Commit 0142877a authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

i5400_edac: Avoid calling pci_put_device() twice

When i5400_edac driver is removed and re-loaded a few times, it causes
an OOPS, as it is currently decrementing some PCI device usage two
times.

When called inside a loop, pci_get_device() will call
pci_put_device(). That mangles the error count. In this specific
case, it seems easier to just duplicate the call.

Also fixes the error logic when pci_get_device fails.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent df95e42e
...@@ -735,7 +735,7 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) ...@@ -735,7 +735,7 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
/* Attempt to 'get' the MCH register we want */ /* Attempt to 'get' the MCH register we want */
pdev = NULL; pdev = NULL;
while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) { while (1) {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR, pdev); PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
if (!pdev) { if (!pdev) {
...@@ -743,23 +743,42 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) ...@@ -743,23 +743,42 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
i5400_printk(KERN_ERR, i5400_printk(KERN_ERR,
"'system address,Process Bus' " "'system address,Process Bus' "
"device not found:" "device not found:"
"vendor 0x%x device 0x%x ERR funcs " "vendor 0x%x device 0x%x ERR func 1 "
"(broken BIOS?)\n", "(broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR); PCI_DEVICE_ID_INTEL_5400_ERR);
goto error; return -ENODEV;
} }
/* Store device 16 funcs 1 and 2 */ /* Store device 16 func 1 */
switch (PCI_FUNC(pdev->devfn)) { if (PCI_FUNC(pdev->devfn) == 1)
case 1:
pvt->branchmap_werrors = pdev;
break;
case 2:
pvt->fsb_error_regs = pdev;
break; break;
}
pvt->branchmap_werrors = pdev;
pdev = NULL;
while (1) {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR, pdev);
if (!pdev) {
/* End of list, leave */
i5400_printk(KERN_ERR,
"'system address,Process Bus' "
"device not found:"
"vendor 0x%x device 0x%x ERR func 2 "
"(broken BIOS?)\n",
PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_ERR);
pci_dev_put(pvt->branchmap_werrors);
return -ENODEV;
} }
/* Store device 16 func 2 */
if (PCI_FUNC(pdev->devfn) == 2)
break;
} }
pvt->fsb_error_regs = pdev;
debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n",
pci_name(pvt->system_address), pci_name(pvt->system_address),
...@@ -778,7 +797,10 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) ...@@ -778,7 +797,10 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
"MC: 'BRANCH 0' device not found:" "MC: 'BRANCH 0' device not found:"
"vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0); PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0);
goto error;
pci_dev_put(pvt->fsb_error_regs);
pci_dev_put(pvt->branchmap_werrors);
return -ENODEV;
} }
/* If this device claims to have more than 2 channels then /* If this device claims to have more than 2 channels then
...@@ -796,14 +818,14 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) ...@@ -796,14 +818,14 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx)
"(broken BIOS?)\n", "(broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_5400_FBD1); PCI_DEVICE_ID_INTEL_5400_FBD1);
goto error;
pci_dev_put(pvt->branch_0);
pci_dev_put(pvt->fsb_error_regs);
pci_dev_put(pvt->branchmap_werrors);
return -ENODEV;
} }
return 0; return 0;
error:
i5400_put_devices(mci);
return -ENODEV;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment