From: Paul Mackerras The EEH code currently can end up doing an extra pci_dev_put() in the case where we hot-unplug a card for which we are ignoring EEH errors (e.g. a graphics card). This patch fixes that problem by only maintaining a reference to the PCI device if we have entered any of its resource addresses into our address -> PCI device cache. This patch is based on an earlier patch by Linas Vepstas. Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc64/kernel/eeh.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletion(-) diff -puN arch/ppc64/kernel/eeh.c~ppc64-fix-unbalanced-pci_dev_put-in-eeh-code arch/ppc64/kernel/eeh.c --- 25/arch/ppc64/kernel/eeh.c~ppc64-fix-unbalanced-pci_dev_put-in-eeh-code 2004-08-17 23:47:42.060575440 -0700 +++ 25-akpm/arch/ppc64/kernel/eeh.c 2004-08-17 23:47:42.064574832 -0700 @@ -209,6 +209,7 @@ static void __pci_addr_cache_insert_devi { struct device_node *dn; int i; + int inserted = 0; dn = pci_device_to_OF_node(dev); if (!dn) { @@ -242,7 +243,12 @@ static void __pci_addr_cache_insert_devi if (start == 0 || ~start == 0 || end == 0 || ~end == 0) continue; pci_addr_cache_insert(dev, start, end, flags); + inserted = 1; } + + /* If there was nothing to add, the cache has no reference... */ + if (!inserted) + pci_dev_put(dev); } /** @@ -265,6 +271,7 @@ void pci_addr_cache_insert_device(struct static inline void __pci_addr_cache_remove_device(struct pci_dev *dev) { struct rb_node *n; + int removed = 0; restart: n = rb_first(&pci_io_addr_cache_root.rb_root); @@ -274,6 +281,7 @@ restart: if (piar->pcidev == dev) { rb_erase(n, &pci_io_addr_cache_root.rb_root); + removed = 1; kfree(piar); goto restart; } @@ -281,7 +289,8 @@ restart: } /* The cache no longer holds its reference to this device... */ - pci_dev_put(dev); + if (removed) + pci_dev_put(dev); } /** _