Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i7300_edac: Fix device reference count

pci_get_device() decrements the reference count of "from" (last
argument) so when we break off the loop successfully we have only one
device reference - and we don't know which device we have. If we want
a reference to each device, we must take them explicitly and let
the pci_get_device() walk complete to avoid duplicate references.

This is serious, as over-putting device references will cause
the device to eventually disappear. Without this fix, the kernel
crashes after a few insmod/rmmod cycles.

Tested on an Intel S7000FC4UR system with a 7300 chipset.

Signed-off-by: Jean Delvare <jdelvare@suse.de>
Link: http://lkml.kernel.org/r/20140224111656.09bbb7ed@endymion.delvare
Cc: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Doug Thompson <dougthompson@xmission.com>
Cc: stable@vger.kernel.org
Signed-off-by: Borislav Petkov <bp@suse.de>

authored by

Jean Delvare and committed by
Borislav Petkov
75135da0 c0f5eeed

+20 -18
+20 -18
drivers/edac/i7300_edac.c
··· 943 943 944 944 /* Attempt to 'get' the MCH register we want */ 945 945 pdev = NULL; 946 - while (!pvt->pci_dev_16_1_fsb_addr_map || 947 - !pvt->pci_dev_16_2_fsb_err_regs) { 948 - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 949 - PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev); 950 - if (!pdev) { 951 - /* End of list, leave */ 952 - i7300_printk(KERN_ERR, 953 - "'system address,Process Bus' " 954 - "device not found:" 955 - "vendor 0x%x device 0x%x ERR funcs " 956 - "(broken BIOS?)\n", 957 - PCI_VENDOR_ID_INTEL, 958 - PCI_DEVICE_ID_INTEL_I7300_MCH_ERR); 959 - goto error; 960 - } 961 - 946 + while ((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 947 + PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, 948 + pdev))) { 962 949 /* Store device 16 funcs 1 and 2 */ 963 950 switch (PCI_FUNC(pdev->devfn)) { 964 951 case 1: 965 - pvt->pci_dev_16_1_fsb_addr_map = pdev; 952 + if (!pvt->pci_dev_16_1_fsb_addr_map) 953 + pvt->pci_dev_16_1_fsb_addr_map = 954 + pci_dev_get(pdev); 966 955 break; 967 956 case 2: 968 - pvt->pci_dev_16_2_fsb_err_regs = pdev; 957 + if (!pvt->pci_dev_16_2_fsb_err_regs) 958 + pvt->pci_dev_16_2_fsb_err_regs = 959 + pci_dev_get(pdev); 969 960 break; 970 961 } 962 + } 963 + 964 + if (!pvt->pci_dev_16_1_fsb_addr_map || 965 + !pvt->pci_dev_16_2_fsb_err_regs) { 966 + /* At least one device was not found */ 967 + i7300_printk(KERN_ERR, 968 + "'system address,Process Bus' device not found:" 969 + "vendor 0x%x device 0x%x ERR funcs (broken BIOS?)\n", 970 + PCI_VENDOR_ID_INTEL, 971 + PCI_DEVICE_ID_INTEL_I7300_MCH_ERR); 972 + goto error; 971 973 } 972 974 973 975 edac_dbg(1, "System Address, processor bus- PCI Bus ID: %s %x:%x\n",