From 7c1645c59af34735c271de90ddda27b0c9002331 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 22 Aug 2004 22:32:41 -0700 Subject: [PATCH] [PATCH] ppc64 Fix unbalanced pci_dev_put in EEH code 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 Signed-off-by: Linus Torvalds --- arch/ppc64/kernel/eeh.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c index 5fdcce2db45e4..8a64dc7c3cc9a 100644 --- a/arch/ppc64/kernel/eeh.c +++ b/arch/ppc64/kernel/eeh.c @@ -209,6 +209,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev) { 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_device(struct pci_dev *dev) 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 pci_dev *dev) 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); } /** -- 2.53.0