]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64: fix unbalanced dev_get/put calls in EEH code
authorPaul Mackerras <paulus@samba.org>
Sun, 11 Jul 2004 02:29:14 +0000 (19:29 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sun, 11 Jul 2004 02:29:14 +0000 (19:29 -0700)
This patch fixes some unbalanced usage of pci_dev_get()/pci_dev_put() calls
in the eeh code.  The old code had too many calls to dev_put, which could
cause memory structs to be freed prematurely, possibly leading to bad bad
pointer derefs in certain cases.

Signed-off-by: Linas Vepstas <linas@linas.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/ppc64/kernel/eeh.c

index 7bd687cfabe70005ba3b9e7f2f0a9eb98d0379a2..fb98b183bc2a1d84df59e76d5e4f6774001c9323 100644 (file)
@@ -214,7 +214,6 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
        if (!dn) {
                printk(KERN_WARNING "PCI: no pci dn found for dev=%s %s\n",
                        pci_name(dev), pci_pretty_name(dev));
-               pci_dev_put(dev);
                return;
        }
 
@@ -225,10 +224,12 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
                printk(KERN_INFO "PCI: skip building address cache for=%s %s\n",
                       pci_name(dev), pci_pretty_name(dev));
 #endif
-               pci_dev_put(dev);
                return;
        }
 
+       /* The cache holds a reference to the device... */
+       pci_dev_get(dev);
+
        /* Walk resources on this device, poke them into the tree */
        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
                unsigned long start = pci_resource_start(dev,i);
@@ -278,6 +279,8 @@ restart:
                }
                n = rb_next(n);
        }
+
+       /* The cache no longer holds its reference to this device... */
        pci_dev_put(dev);
 }
 
@@ -317,7 +320,6 @@ void __init pci_addr_cache_build(void)
        while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
                /* Ignore PCI bridges ( XXX why ??) */
                if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
-                       pci_dev_put(dev);
                        continue;
                }
                pci_addr_cache_insert_device(dev);