From 53a2fe5804e849f39d9723dfdaaea527ec9d1eac Mon Sep 17 00:00:00 2001 From: Vladislav Bogdanov Date: Wed, 15 Oct 2008 22:04:26 -0700 Subject: edac: make i82443bxgx_edac coexist with intel_agp Fix 443BX/GX MCH suppport in a EDAC. It makes i82443bxgx_edac coexist with intel_agp using the same approach as several other EDAC drivers. Tested on Intel's L443GX with redhat's 2.6.18 with whole EDAC subsystem backported a while ago. [root@host ~]# dmesg|grep -iE '(AGP|EDAC)' Linux agpgart interface v0.101 (c) Dave Jones agpgart: Detected an Intel 440GX Chipset. agpgart: AGP aperture is 64M @ 0xf8000000 EDAC MC: Ver: 2.1.0 Jun 27 2008 EDAC MC0: Giving out device to 'i82443bxgx_edac' 'I82443BXGX': DEV 0000:00:00.0 EDAC PCI0: Giving out device to module 'i82443bxgx_edac' controller 'EDAC PCI controller': DEV '0000:00:00.0' (POLLED) Signed-off-by: Vladislav Bogdanov Cc: Doug Thompson Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i82443bxgx_edac.c | 63 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'drivers/edac') diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index c5305e3ee43..577760a82a0 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c @@ -114,6 +114,12 @@ struct i82443bxgx_edacmc_error_info { static struct edac_pci_ctl_info *i82443bxgx_pci; +static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has + * already registered driver + */ + +static int i82443bxgx_registered = 1; + static void i82443bxgx_edacmc_get_error_info(struct mem_ctl_info *mci, struct i82443bxgx_edacmc_error_info *info) @@ -345,10 +351,17 @@ EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1); static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { + int rc; + debugf0("MC: " __FILE__ ": %s()\n", __func__); /* don't need to call pci_device_enable() */ - return i82443bxgx_edacmc_probe1(pdev, ent->driver_data); + rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); + + if (mci_pdev == NULL) + mci_pdev = pci_dev_get(pdev); + + return rc; } static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) @@ -387,15 +400,61 @@ static struct pci_driver i82443bxgx_edacmc_driver = { static int __init i82443bxgx_edacmc_init(void) { + int pci_rc; /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); - return pci_register_driver(&i82443bxgx_edacmc_driver); + pci_rc = pci_register_driver(&i82443bxgx_edacmc_driver); + if (pci_rc < 0) + goto fail0; + + if (mci_pdev == NULL) { + const struct pci_device_id *id = &i82443bxgx_pci_tbl[0]; + int i = 0; + i82443bxgx_registered = 0; + + while (mci_pdev == NULL && id->vendor != 0) { + mci_pdev = pci_get_device(id->vendor, + id->device, NULL); + i++; + id = &i82443bxgx_pci_tbl[i]; + } + if (!mci_pdev) { + debugf0("i82443bxgx pci_get_device fail\n"); + pci_rc = -ENODEV; + goto fail1; + } + + pci_rc = i82443bxgx_edacmc_init_one(mci_pdev, i82443bxgx_pci_tbl); + + if (pci_rc < 0) { + debugf0("i82443bxgx init fail\n"); + pci_rc = -ENODEV; + goto fail1; + } + } + + return 0; + +fail1: + pci_unregister_driver(&i82443bxgx_edacmc_driver); + +fail0: + if (mci_pdev != NULL) + pci_dev_put(mci_pdev); + + return pci_rc; } static void __exit i82443bxgx_edacmc_exit(void) { pci_unregister_driver(&i82443bxgx_edacmc_driver); + + if (!i82443bxgx_registered) + i82443bxgx_edacmc_remove_one(mci_pdev); + + if (mci_pdev) + pci_dev_put(mci_pdev); } module_init(i82443bxgx_edacmc_init); -- cgit v1.2.3