
From: Paul Mackerras <paulus@samba.org>

This patch is from John Rose <johnrose@austin.ibm.com>.

This patch changes the following iommu-related things:

- Renames the [i,p]series versions of iommu_devnode_init(), to keep
  things logically separate where possible.

- Moves iommu_free_table() to generic iommu.c

- Creates of_cleanup_node(), which will directly precede the dynamic
  removal of any device node

Signed-off-by: John Rose <johnrose@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ppc64/kernel/iSeries_iommu.c |    2 -
 25-akpm/arch/ppc64/kernel/iSeries_pci.c   |    2 -
 25-akpm/arch/ppc64/kernel/iommu.c         |   33 ++++++++++++++++++++++++
 25-akpm/arch/ppc64/kernel/pSeries_iommu.c |   40 ++----------------------------
 25-akpm/arch/ppc64/kernel/prom.c          |   19 ++++++++------
 25-akpm/include/asm-ppc64/iommu.h         |   20 ++++++---------
 6 files changed, 57 insertions(+), 59 deletions(-)

diff -puN arch/ppc64/kernel/iommu.c~ppc64-iommu-fixes-round-3 arch/ppc64/kernel/iommu.c
--- 25/arch/ppc64/kernel/iommu.c~ppc64-iommu-fixes-round-3	Thu Nov  4 14:38:43 2004
+++ 25-akpm/arch/ppc64/kernel/iommu.c	Thu Nov  4 14:38:43 2004
@@ -425,6 +425,39 @@ struct iommu_table *iommu_init_table(str
 	return tbl;
 }
 
+void iommu_free_table(struct device_node *dn)
+{
+	struct iommu_table *tbl = dn->iommu_table;
+	unsigned long bitmap_sz, i;
+	unsigned int order;
+
+	if (!tbl || !tbl->it_map) {
+		printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
+				dn->full_name);
+		return;
+	}
+
+	/* verify that table contains no entries */
+	/* it_mapsize is in entries, and we're examining 64 at a time */
+	for (i = 0; i < (tbl->it_mapsize/64); i++) {
+		if (tbl->it_map[i] != 0) {
+			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
+				__FUNCTION__, dn->full_name);
+			break;
+		}
+	}
+
+	/* calculate bitmap size in bytes */
+	bitmap_sz = (tbl->it_mapsize + 7) / 8;
+
+	/* free bitmap */
+	order = get_order(bitmap_sz);
+	free_pages((unsigned long) tbl->it_map, order);
+
+	/* free table */
+	kfree(tbl);
+}
+
 /* Creates TCEs for a user provided buffer.  The user buffer must be
  * contiguous real kernel storage (not vmalloc).  The address of the buffer
  * passed here is the kernel (virtual) address of the buffer.  The buffer
diff -puN arch/ppc64/kernel/iSeries_iommu.c~ppc64-iommu-fixes-round-3 arch/ppc64/kernel/iSeries_iommu.c
--- 25/arch/ppc64/kernel/iSeries_iommu.c~ppc64-iommu-fixes-round-3	Thu Nov  4 14:38:43 2004
+++ 25-akpm/arch/ppc64/kernel/iSeries_iommu.c	Thu Nov  4 14:39:27 2004
@@ -144,7 +144,7 @@ static void iommu_table_getparms(struct 
 }
 
 
-void iommu_devnode_init(struct iSeries_Device_Node *dn)
+void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
 {
 	struct iommu_table *tbl;
 
diff -puN arch/ppc64/kernel/iSeries_pci.c~ppc64-iommu-fixes-round-3 arch/ppc64/kernel/iSeries_pci.c
--- 25/arch/ppc64/kernel/iSeries_pci.c~ppc64-iommu-fixes-round-3	Thu Nov  4 14:38:43 2004
+++ 25-akpm/arch/ppc64/kernel/iSeries_pci.c	Thu Nov  4 14:38:43 2004
@@ -329,7 +329,7 @@ void __init iSeries_pci_final_fixup(void
 			iSeries_Device_Information(pdev, Buffer,
 					sizeof(Buffer));
 			printk("%d. %s\n", DeviceCount, Buffer);
-			iommu_devnode_init(node);
+			iommu_devnode_init_iSeries(node);
 		} else
 			printk("PCI: Device Tree not found for 0x%016lX\n",
 					(unsigned long)pdev);
diff -puN arch/ppc64/kernel/prom.c~ppc64-iommu-fixes-round-3 arch/ppc64/kernel/prom.c
--- 25/arch/ppc64/kernel/prom.c~ppc64-iommu-fixes-round-3	Thu Nov  4 14:38:43 2004
+++ 25-akpm/arch/ppc64/kernel/prom.c	Thu Nov  4 14:38:43 2004
@@ -1740,7 +1740,7 @@ static int of_finish_dynamic_node(struct
 	if (strcmp(node->name, "pci") == 0 &&
 	    get_property(node, "ibm,dma-window", NULL)) {
 		node->bussubno = node->busno;
-		iommu_devnode_init(node);
+		iommu_devnode_init_pSeries(node);
 	} else
 		node->iommu_table = parent->iommu_table;
 #endif /* CONFIG_PPC_PSERIES */
@@ -1802,6 +1802,15 @@ int of_add_node(const char *path, struct
 }
 
 /*
+ * Prepare an OF node for removal from system
+ */
+static void of_cleanup_node(struct device_node *np)
+{
+	if (np->iommu_table && get_property(np, "ibm,dma-window", NULL))
+		iommu_free_table(np);
+}
+
+/*
  * Remove an OF device node from the system.
  * Caller should have already "gotten" np.
  */
@@ -1818,13 +1827,7 @@ int of_remove_node(struct device_node *n
 		return -EBUSY;
 	}
 
-	/* XXX This is a layering violation, should be moved to the caller
-	 * --BenH.
-	 */
-#ifdef CONFIG_PPC_PSERIES
-	if (np->iommu_table)
-		iommu_free_table(np);
-#endif /* CONFIG_PPC_PSERIES */
+	of_cleanup_node(np);
 
 	write_lock(&devtree_lock);
 	OF_MARK_STALE(np);
diff -puN arch/ppc64/kernel/pSeries_iommu.c~ppc64-iommu-fixes-round-3 arch/ppc64/kernel/pSeries_iommu.c
--- 25/arch/ppc64/kernel/pSeries_iommu.c~ppc64-iommu-fixes-round-3	Thu Nov  4 14:38:43 2004
+++ 25-akpm/arch/ppc64/kernel/pSeries_iommu.c	Thu Nov  4 14:38:43 2004
@@ -276,7 +276,7 @@ static void iommu_buses_init(void)
 		first_phb = 0;
 
 		for (dn = first_dn; dn != NULL; dn = dn->sibling)
-			iommu_devnode_init(dn);
+			iommu_devnode_init_pSeries(dn);
 	}
 }
 
@@ -298,7 +298,7 @@ static void iommu_buses_init_lpar(struct
 			 * Do it now because iommu_table_setparms_lpar needs it.
 			 */
 			busdn->bussubno = bus->number;
-			iommu_devnode_init(busdn);
+			iommu_devnode_init_pSeries(busdn);
 		}
 
 		/* look for a window on a bridge even if the PHB had one */
@@ -397,7 +397,7 @@ static void iommu_table_setparms_lpar(st
 }
 
 
-void iommu_devnode_init(struct device_node *dn)
+void iommu_devnode_init_pSeries(struct device_node *dn)
 {
 	struct iommu_table *tbl;
 
@@ -412,39 +412,6 @@ void iommu_devnode_init(struct device_no
 	dn->iommu_table = iommu_init_table(tbl);
 }
 
-void iommu_free_table(struct device_node *dn)
-{
-	struct iommu_table *tbl = dn->iommu_table;
-	unsigned long bitmap_sz, i;
-	unsigned int order;
-
-	if (!tbl || !tbl->it_map) {
-		printk(KERN_ERR "%s: expected TCE map for %s\n", __FUNCTION__,
-				dn->full_name);
-		return;
-	}
-
-	/* verify that table contains no entries */
-	/* it_mapsize is in entries, and we're examining 64 at a time */
-	for (i = 0; i < (tbl->it_mapsize/64); i++) {
-		if (tbl->it_map[i] != 0) {
-			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
-				__FUNCTION__, dn->full_name);
-			break;
-		}
-	}
-
-	/* calculate bitmap size in bytes */
-	bitmap_sz = (tbl->it_mapsize + 7) / 8;
-
-	/* free bitmap */
-	order = get_order(bitmap_sz);
-	free_pages((unsigned long) tbl->it_map, order);
-
-	/* free table */
-	kfree(tbl);
-}
-
 void iommu_setup_pSeries(void)
 {
 	struct pci_dev *dev = NULL;
@@ -469,7 +436,6 @@ void iommu_setup_pSeries(void)
 	}
 }
 
-
 /* These are called very early. */
 void tce_init_pSeries(void)
 {
diff -puN include/asm-ppc64/iommu.h~ppc64-iommu-fixes-round-3 include/asm-ppc64/iommu.h
--- 25/include/asm-ppc64/iommu.h~ppc64-iommu-fixes-round-3	Thu Nov  4 14:38:43 2004
+++ 25-akpm/include/asm-ppc64/iommu.h	Thu Nov  4 14:38:43 2004
@@ -110,22 +110,18 @@ struct scatterlist;
 extern void iommu_setup_pSeries(void);
 extern void iommu_setup_u3(void);
 
-/* Creates table for an individual device node */
-/* XXX: This isn't generic, please name it accordingly or add
- * some ppc_md. hooks for iommu implementations to do what they
- * need to do. --BenH.
- */
-extern void iommu_devnode_init(struct device_node *dn);
-
 /* Frees table for an individual device node */
-/* XXX: This isn't generic, please name it accordingly or add
- * some ppc_md. hooks for iommu implementations to do what they
- * need to do. --BenH.
- */
 extern void iommu_free_table(struct device_node *dn);
 
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 
+#ifdef CONFIG_PPC_PSERIES
+
+/* Creates table for an individual device node */
+extern void iommu_devnode_init_pSeries(struct device_node *dn);
+
+#endif /* CONFIG_PPC_PSERIES */
+
 #ifdef CONFIG_PPC_ISERIES
 
 /* Walks all buses and creates iommu tables */
@@ -136,7 +132,7 @@ extern void __init iommu_vio_init(void);
 
 struct iSeries_Device_Node;
 /* Creates table for an individual device node */
-extern void iommu_devnode_init(struct iSeries_Device_Node *dn);
+extern void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn);
 
 #endif /* CONFIG_PPC_ISERIES */
 
_
