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

[PATCH] ppc64: iommu fixes, round 3

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: 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 0c8af7c7
......@@ -144,7 +144,7 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
}
void iommu_devnode_init(struct iSeries_Device_Node *dn)
void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
{
struct iommu_table *tbl;
......
......@@ -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);
......
......@@ -425,6 +425,39 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
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
......
......@@ -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 list_head *bus_list)
* 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(struct pci_controller *phb,
}
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_node *dn)
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)
{
......
......@@ -1740,7 +1740,7 @@ static int of_finish_dynamic_node(struct device_node *node)
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 */
......@@ -1801,6 +1801,15 @@ int of_add_node(const char *path, struct property *proplist)
return 0;
}
/*
* 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 *np)
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);
......
......@@ -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 */
......
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