Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2856

kernel-2.6.18-194.11.1.el5.src.rpm

From: Scott Moser <smoser@redhat.com>
Subject: [PATCH RHEL5u1] bz249617 [ppc] DLPAR REMOVE I/O resource failed
Date: Thu, 26 Jul 2007 14:13:33 -0400 (EDT)
Bugzilla: 249617
Message-Id: <Pine.LNX.4.64.0707261411410.30310@squad5-lp1.lab.boston.redhat.com>
Changelog: [ppc] DLPAR REMOVE I/O resource failed


RHBZ#: 249617
------
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=249617

Description:
------------
Hotplug remove of the IDE CDROM in power5 systems fails.  This is because
pci_iounmap does not do anything.  This results in IO memory used by the
driver never being returned.  

The bug stops the feature bug 184774 from working properly.

The patch below is developed by Ben Herrenschmidt of IBM.  It simply calls
iounmap appropriately if the address is an io port.

RHEL Version Found:
-------------------
This is a bug found in RHEL5u1 kernel 2.6.18-36.el5

Upstream Status:
----------------
These changes are not presently upstream.  Ben is working on a patch for
upstream inclusion.

Test Status:
------------
To ensure cross-platform build, this code has been built with brew
--scratch against a 2.6.18-36.el5 kernel and is available at [1].

I have booted this kernel and verified that the device can be added, removed,
re-added, and re-removed via the hmc.

Proposed Patch:
----------------
Please review and ACK for RHEL5.1

-- 
[1] http://brewweb.devel.redhat.com/brew/taskinfo?taskID=888478

---
 arch/powerpc/kernel/iomap.c      |    5 ++++-
 arch/powerpc/kernel/pci_64.c     |   17 +++++++++++++++++
 include/asm-powerpc/pci-bridge.h |    6 ++++++
 3 files changed, 27 insertions(+), 1 deletion(-)

Index: b/arch/powerpc/kernel/iomap.c
===================================================================
--- a/arch/powerpc/kernel/iomap.c
+++ b/arch/powerpc/kernel/iomap.c
@@ -136,7 +136,10 @@ void __iomem *pci_iomap(struct pci_dev *
 
 void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
 {
-	/* Nothing to do */
+#ifdef CONFIG_PPC64
+	if (!pcibios_vaddr_is_ioport(addr))
+		iounmap(addr);
+#endif
 }
 EXPORT_SYMBOL(pci_iomap);
 EXPORT_SYMBOL(pci_iounmap);
Index: b/arch/powerpc/kernel/pci_64.c
===================================================================
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1439,3 +1439,20 @@ int pcibus_to_node(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pcibus_to_node);
 #endif
+
+int pcibios_vaddr_is_ioport(void __iomem *address)
+{
+	int ret = 0;
+	struct pci_controller *hose;
+
+	spin_lock(&hose_spinlock);
+	list_for_each_entry(hose, &hose_list, list_node) {
+		if (address >= hose->io_base_virt &&
+		    address < (hose->io_base_virt + hose->pci_io_size)) {
+			ret = 1;
+			break;
+		}
+	}
+	spin_unlock(&hose_spinlock);
+	return ret;
+}
Index: b/include/asm-powerpc/pci-bridge.h
===================================================================
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -157,13 +157,19 @@ extern void pcibios_free_controller(stru
 
 #ifdef CONFIG_PCI
 extern unsigned long pci_address_to_pio(phys_addr_t address);
+extern int pcibios_vaddr_is_ioport(void __iomem *address);
 #else
 static inline unsigned long pci_address_to_pio(phys_addr_t address)
 {
 	return (unsigned long)-1;
 }
+static inline int pcibios_vaddr_is_ioport(void __iomem *address)
+{
+	return 0;
+}
 #endif
 
+
 /* Return values for ppc_md.pci_probe_mode function */
 #define PCI_PROBE_NONE		-1	/* Don't look at this bus at all */
 #define PCI_PROBE_NORMAL	0	/* Do normal PCI probing */