i7core: fix get_devices routine for Xeon55xx
authorMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 18 Jul 2009 13:43:08 +0000 (10:43 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 10 May 2010 14:44:53 +0000 (11:44 -0300)
i7core_get_devices() were preparet to get just the first found device of each type.
Due to that, on Xeon 55xx, only socket 1 were retrived.

Rework i7core_get_devices() to clean it and to properly support Xeon 55xx.

While here, fix a small typo.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/edac/i7core_edac.c

index 9f39d3d..79636b5 100644 (file)
@@ -410,7 +410,7 @@ static int i7core_get_active_channels(u8 socket, unsigned *channels,
                }
        }
 
-       debugf0("Number of active channels on socked %d: %d\n",
+       debugf0("Number of active channels on socket %d: %d\n",
                socket, *channels);
 
        return 0;
@@ -1126,107 +1126,137 @@ static void i7core_put_devices(void)
  *
  *                     Need to 'get' device 16 func 1 and func 2
  */
-static int i7core_get_devices(void)
+int i7core_get_onedevice(struct pci_dev **prev, int devno)
 {
-       int rc, i;
        struct pci_dev *pdev = NULL;
        u8 bus = 0;
        u8 socket = 0;
 
-       for (i = 0; i < N_DEVS; i++) {
+       pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                             pci_devs[devno].dev_id, *prev);
+
+       /*
+        * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
+        * aren't announced by acpi. So, we need to use a legacy scan probing
+        * to detect them
+        */
+       if (unlikely(!pdev && !devno && !prev)) {
+               pcibios_scan_specific_bus(254);
+               pcibios_scan_specific_bus(255);
+
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                       pci_devs[i].dev_id, NULL);
+                                     pci_devs[devno].dev_id, *prev);
+       }
 
-               if (!pdev && !i) {
-                       pcibios_scan_specific_bus(254);
-                       pcibios_scan_specific_bus(255);
+       /*
+        * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+        * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+        * to probe for the alternate address in case of failure
+        */
+       if (pci_devs[devno].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE && !pdev)
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                     PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, *prev);
 
-                       pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                               pci_devs[i].dev_id, NULL);
+       if (!pdev) {
+               if (*prev) {
+                       *prev = pdev;
+                       return 0;
                }
 
                /*
-                * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
-                * is at addr 8086:2c40, instead of 8086:2c41. So, we need
-                * to probe for the alternate address in case of failure
+                * Dev 3 function 2 only exists on chips with RDIMMs
+                * so, it is ok to not found it
                 */
-               if (pci_devs[i].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE
-                                                                   && !pdev)
-                       pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                               PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, NULL);
+               if ((pci_devs[devno].dev == 3) && (pci_devs[devno].func == 2)) {
+                       *prev = pdev;
+                       return 0;
+               }
 
-               if (likely(pdev)) {
-                       bus = pdev->bus->number;
+               i7core_printk(KERN_ERR,
+                       "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+                       pci_devs[devno].dev, pci_devs[devno].func,
+                       PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
 
-                       if (bus == 0x3f)
-                               socket = 0;
-                       else
-                               socket = 255 - bus;
+               /* End of list, leave */
+               return -ENODEV;
+       }
+       bus = pdev->bus->number;
 
-                       if (socket >= NUM_SOCKETS) {
-                               i7core_printk(KERN_ERR,
-                                       "Found unexpected socket for "
-                                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
-                                       bus, pci_devs[i].dev, pci_devs[i].func,
-                                       PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
+       if (bus == 0x3f)
+               socket = 0;
+       else
+               socket = 255 - bus;
+
+       if (socket >= NUM_SOCKETS) {
+               i7core_printk(KERN_ERR,
+                       "Unexpected socket for "
+                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+                       bus, pci_devs[devno].dev, pci_devs[devno].func,
+                       PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+               pci_dev_put(pdev);
+               return -ENODEV;
+       }
 
-                               rc = -ENODEV;
-                               goto error;
-                       }
+       if (pci_devs[devno].pdev[socket]) {
+               i7core_printk(KERN_ERR,
+                       "Duplicated device for "
+                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+                       bus, pci_devs[devno].dev, pci_devs[devno].func,
+                       PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+               pci_dev_put(pdev);
+               return -ENODEV;
+       }
 
-                       pci_devs[i].pdev[socket] = pdev;
-               } else {
-                       i7core_printk(KERN_ERR,
-                               "Device not found: "
-                               "dev %02x:%02x.%d PCI ID %04x:%04x\n",
-                               bus, pci_devs[i].dev, pci_devs[i].func,
-                               PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
+       pci_devs[devno].pdev[socket] = pdev;
+
+       /* Sanity check */
+       if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[devno].dev ||
+                       PCI_FUNC(pdev->devfn) != pci_devs[devno].func)) {
+               i7core_printk(KERN_ERR,
+                       "Device PCI ID %04x:%04x "
+                       "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n",
+                       PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id,
+                       bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+                       bus, pci_devs[devno].dev, pci_devs[devno].func);
+               return -ENODEV;
+       }
 
-                       /* Dev 3 function 2 only exists on chips with RDIMMs */
-                       if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
-                               continue;
+       /* Be sure that the device is enabled */
+       if (unlikely(pci_enable_device(pdev) < 0)) {
+               i7core_printk(KERN_ERR,
+                       "Couldn't enable "
+                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+                       bus, pci_devs[devno].dev, pci_devs[devno].func,
+                       PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+               return -ENODEV;
+       }
 
-                       /* End of list, leave */
-                       rc = -ENODEV;
-                       goto error;
-               }
+       i7core_printk(KERN_INFO,
+                       "Registered socket %d "
+                       "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+                       socket, bus, pci_devs[devno].dev, pci_devs[devno].func,
+                       PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
 
-               /* Sanity check */
-               if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[i].dev ||
-                            PCI_FUNC(pdev->devfn) != pci_devs[i].func)) {
-                       i7core_printk(KERN_ERR,
-                               "Device PCI ID %04x:%04x "
-                               "has fn %d.%d instead of fn %d.%d\n",
-                               PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
-                               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-                               pci_devs[i].dev, pci_devs[i].func);
-                       rc = -EINVAL;
-                       goto error;
-               }
+       *prev = pdev;
 
-               /* Be sure that the device is enabled */
-               rc = pci_enable_device(pdev);
-               if (unlikely(rc < 0)) {
-                       i7core_printk(KERN_ERR,
-                               "Couldn't enable PCI ID %04x:%04x "
-                               "fn %d.%d\n",
-                               PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
-                               PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-                       goto error;
-               }
+       return 0;
+}
 
-               i7core_printk(KERN_INFO,
-                               "Registered socket %d "
-                               "dev %02x:%02x.%d PCI ID %04x:%04x\n",
-                               socket, bus, pci_devs[i].dev, pci_devs[i].func,
-                               PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
-       }
+static int i7core_get_devices(void)
+{
+       int i;
+       struct pci_dev *pdev = NULL;
 
+       for (i = 0; i < N_DEVS; i++) {
+               pdev = NULL;
+               do {
+                       if (i7core_get_onedevice(&pdev, i) < 0) {
+                               i7core_put_devices();
+                               return -ENODEV;
+                       }
+               } while (pdev);
+       }
        return 0;
-
-error:
-       i7core_put_devices();
-       return -EINVAL;
 }
 
 static int mci_bind_devs(struct mem_ctl_info *mci)