Commit 2edd439a authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] ppc64: create iommu_free_table()

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

The patch below creates iommu_free_table().  Iommu tables are not currently
freed in PPC64.  This could cause a memory leak for DLPAR of an EADS slot. 
The function verifies that there are no outstanding TCE entries for the
range of the table before freeing it.  I added a call to iommu_free_table()
to the code that dynamically removes a device node.  This should be fairly
symmetrical with the table allocation, which happens during dynamic
addition of a device node.
Signed-off-by: default avatarJohn Rose <johnrose@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a62c4a15
...@@ -412,6 +412,38 @@ void iommu_devnode_init(struct device_node *dn) ...@@ -412,6 +412,38 @@ void iommu_devnode_init(struct device_node *dn)
dn->iommu_table = iommu_init_table(tbl); 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) void iommu_setup_pSeries(void)
{ {
......
...@@ -1818,6 +1818,9 @@ int of_remove_node(struct device_node *np) ...@@ -1818,6 +1818,9 @@ int of_remove_node(struct device_node *np)
return -EBUSY; return -EBUSY;
} }
if (np->iommu_table)
iommu_free_table(np);
write_lock(&devtree_lock); write_lock(&devtree_lock);
OF_MARK_STALE(np); OF_MARK_STALE(np);
remove_node_proc_entries(np); remove_node_proc_entries(np);
......
...@@ -113,6 +113,9 @@ extern void iommu_setup_u3(void); ...@@ -113,6 +113,9 @@ extern void iommu_setup_u3(void);
/* Creates table for an individual device node */ /* Creates table for an individual device node */
extern void iommu_devnode_init(struct device_node *dn); extern void iommu_devnode_init(struct device_node *dn);
/* Frees table for an individual device node */
extern void iommu_free_table(struct device_node *dn);
#endif /* CONFIG_PPC_MULTIPLATFORM */ #endif /* CONFIG_PPC_MULTIPLATFORM */
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment