From: Paul Mackerras This patch is from John Rose . 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 Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton --- 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 */ _