From bda142890e6bdd9b1115715e50b0276ea4b9978a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Jun 2010 01:41:35 -0300 Subject: i7core_edac: Properly discover the first QPI device On Nehalem/Nehalem-EP/Westmere, the first QPI device is the last PCI bus. The last bus is generally at 0x3f or 0xff, but there are also other systems using different setups. For example, HP Z800 has 0x7f as the last bus. This patch adds a logic to discover the last bus, dynamically detecting it at runtime. Acked-by: Doug Thompson Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers/edac') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 6b8b7b41ec5f..d7c76800988e 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1233,10 +1233,28 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table) for (i = 0; i < MAX_SOCKET_BUSES; i++) pcibios_scan_specific_bus(255-i); } + pci_dev_put(pdev); table++; } } +static unsigned i7core_pci_lastbus(void) +{ + int last_bus = 0, bus; + struct pci_bus *b = NULL; + + while ((b = pci_find_next_bus(b)) != NULL) { + bus = b->number; + debugf0("Found bus %d\n", bus); + if (bus > last_bus) + last_bus = bus; + } + + debugf0("Last bus %d\n", last_bus); + + return last_bus; +} + /* * i7core_get_devices Find and perform 'get' operation on the MCH's * device/functions we want to reference for this driver @@ -1244,7 +1262,8 @@ static void __init i7core_xeon_pci_fixup(struct pci_id_table *table) * Need to 'get' device 16 func 1 and func 2 */ int i7core_get_onedevice(struct pci_dev **prev, int devno, - struct pci_id_descr *dev_descr, unsigned n_devs) + struct pci_id_descr *dev_descr, unsigned n_devs, + unsigned last_bus) { struct i7core_dev *i7core_dev; @@ -1291,10 +1310,7 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, } bus = pdev->bus->number; - if (bus == 0x3f) - socket = 0; - else - socket = 255 - bus; + socket = last_bus - bus; i7core_dev = get_i7core_dev(socket); if (!i7core_dev) { @@ -1358,17 +1374,21 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, static int i7core_get_devices(struct pci_id_table *table) { - int i, rc; + int i, rc, last_bus; struct pci_dev *pdev = NULL; struct pci_id_descr *dev_descr; + last_bus = i7core_pci_lastbus(); + while (table && table->descr) { dev_descr = table->descr; for (i = 0; i < table->n_devs; i++) { pdev = NULL; do { - rc = i7core_get_onedevice(&pdev, i, &dev_descr[i], - table->n_devs); + rc = i7core_get_onedevice(&pdev, i, + &dev_descr[i], + table->n_devs, + last_bus); if (rc < 0) { if (i == 0) { i = table->n_devs; -- cgit v1.2.3 From 2d95d8158b5ab51339f8482c98c01469c45ff6d7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Jun 2010 01:42:21 -0300 Subject: i7core_edac: Avoid doing multiple probes for the same card As Nehalem/Nehalem-EP/Westmere devices uses several devices for the same functionality (memory controller), the default way of proping devices doesn't work. So, instead of a per-device probe, all devices should be probed at once. This means that we should block any new attempt of probe, otherwise, it will try to register the same device several times. Acked-by: Doug Thompson Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/edac') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index d7c76800988e..cc9357da0e34 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1947,21 +1947,26 @@ fail: * 0 for FOUND a device * < 0 for error code */ + +static int probed = 0; + static int __devinit i7core_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int dev_idx = id->driver_data; int rc; struct i7core_dev *i7core_dev; + /* get the pci devices we want to reserve for our use */ + mutex_lock(&i7core_edac_lock); + /* * All memory controllers are allocated at the first pass. */ - if (unlikely(dev_idx >= 1)) + if (unlikely(probed >= 1)) { + mutex_unlock(&i7core_edac_lock); return -EINVAL; - - /* get the pci devices we want to reserve for our use */ - mutex_lock(&i7core_edac_lock); + } + probed++; rc = i7core_get_devices(pci_dev_table); if (unlikely(rc < 0)) @@ -2033,6 +2038,8 @@ static void __devexit i7core_remove(struct pci_dev *pdev) i7core_dev->socket); } } + probed--; + mutex_unlock(&i7core_edac_lock); } -- cgit v1.2.3