diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-02-12 06:21:34 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-21 14:22:49 -0400 |
commit | 0142877aa4e54dd9943fb727e9b386c36c8e3ab7 (patch) | |
tree | a417008857f8bb421052bf22b2ce03be49053f5e /drivers/edac | |
parent | df95e42e1f20a561f2fe0a632d5b8fd6c26f1bb9 (diff) |
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: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/i5400_edac.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index 74d6ec342afb..b44a5de1c22c 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c | |||
@@ -735,7 +735,7 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) | |||
735 | 735 | ||
736 | /* Attempt to 'get' the MCH register we want */ | 736 | /* Attempt to 'get' the MCH register we want */ |
737 | pdev = NULL; | 737 | pdev = NULL; |
738 | while (!pvt->branchmap_werrors || !pvt->fsb_error_regs) { | 738 | while (1) { |
739 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 739 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
740 | PCI_DEVICE_ID_INTEL_5400_ERR, pdev); | 740 | PCI_DEVICE_ID_INTEL_5400_ERR, pdev); |
741 | if (!pdev) { | 741 | if (!pdev) { |
@@ -743,23 +743,42 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) | |||
743 | i5400_printk(KERN_ERR, | 743 | i5400_printk(KERN_ERR, |
744 | "'system address,Process Bus' " | 744 | "'system address,Process Bus' " |
745 | "device not found:" | 745 | "device not found:" |
746 | "vendor 0x%x device 0x%x ERR funcs " | 746 | "vendor 0x%x device 0x%x ERR func 1 " |
747 | "(broken BIOS?)\n", | 747 | "(broken BIOS?)\n", |
748 | PCI_VENDOR_ID_INTEL, | 748 | PCI_VENDOR_ID_INTEL, |
749 | PCI_DEVICE_ID_INTEL_5400_ERR); | 749 | PCI_DEVICE_ID_INTEL_5400_ERR); |
750 | goto error; | 750 | return -ENODEV; |
751 | } | 751 | } |
752 | 752 | ||
753 | /* Store device 16 funcs 1 and 2 */ | 753 | /* Store device 16 func 1 */ |
754 | switch (PCI_FUNC(pdev->devfn)) { | 754 | if (PCI_FUNC(pdev->devfn) == 1) |
755 | case 1: | ||
756 | pvt->branchmap_werrors = pdev; | ||
757 | break; | ||
758 | case 2: | ||
759 | pvt->fsb_error_regs = pdev; | ||
760 | break; | 755 | break; |
756 | } | ||
757 | pvt->branchmap_werrors = pdev; | ||
758 | |||
759 | pdev = NULL; | ||
760 | while (1) { | ||
761 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
762 | PCI_DEVICE_ID_INTEL_5400_ERR, pdev); | ||
763 | if (!pdev) { | ||
764 | /* End of list, leave */ | ||
765 | i5400_printk(KERN_ERR, | ||
766 | "'system address,Process Bus' " | ||
767 | "device not found:" | ||
768 | "vendor 0x%x device 0x%x ERR func 2 " | ||
769 | "(broken BIOS?)\n", | ||
770 | PCI_VENDOR_ID_INTEL, | ||
771 | PCI_DEVICE_ID_INTEL_5400_ERR); | ||
772 | |||
773 | pci_dev_put(pvt->branchmap_werrors); | ||
774 | return -ENODEV; | ||
761 | } | 775 | } |
776 | |||
777 | /* Store device 16 func 2 */ | ||
778 | if (PCI_FUNC(pdev->devfn) == 2) | ||
779 | break; | ||
762 | } | 780 | } |
781 | pvt->fsb_error_regs = pdev; | ||
763 | 782 | ||
764 | debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", | 783 | debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n", |
765 | pci_name(pvt->system_address), | 784 | pci_name(pvt->system_address), |
@@ -778,7 +797,10 @@ static int i5400_get_devices(struct mem_ctl_info *mci, int dev_idx) | |||
778 | "MC: 'BRANCH 0' device not found:" | 797 | "MC: 'BRANCH 0' device not found:" |
779 | "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", | 798 | "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n", |
780 | PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0); | 799 | PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_FBD0); |
781 | goto error; | 800 | |
801 | pci_dev_put(pvt->fsb_error_regs); | ||
802 | pci_dev_put(pvt->branchmap_werrors); | ||
803 | return -ENODEV; | ||
782 | } | 804 | } |
783 | 805 | ||
784 | /* If this device claims to have more than 2 channels then | 806 | /* 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 | "(broken BIOS?)\n", | 818 | "(broken BIOS?)\n", |
797 | PCI_VENDOR_ID_INTEL, | 819 | PCI_VENDOR_ID_INTEL, |
798 | PCI_DEVICE_ID_INTEL_5400_FBD1); | 820 | PCI_DEVICE_ID_INTEL_5400_FBD1); |
799 | goto error; | 821 | |
822 | pci_dev_put(pvt->branch_0); | ||
823 | pci_dev_put(pvt->fsb_error_regs); | ||
824 | pci_dev_put(pvt->branchmap_werrors); | ||
825 | return -ENODEV; | ||
800 | } | 826 | } |
801 | 827 | ||
802 | return 0; | 828 | return 0; |
803 | |||
804 | error: | ||
805 | i5400_put_devices(mci); | ||
806 | return -ENODEV; | ||
807 | } | 829 | } |
808 | 830 | ||
809 | /* | 831 | /* |