summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 17:25:02 +1100
committerPaul Mackerras <paulus@samba.org>2006-12-04 20:38:40 +1100
commit12d04eef927bf61328af2c7cbe756c96f98ac3bf (patch)
tree18865369100e9059c7e883dec93ea67f7b52a287 /arch/powerpc/platforms
parent7c719871ff4d5f15b71f0138d08b758281b58631 (diff)
[POWERPC] Refactor 64 bits DMA operations
This patch completely refactors DMA operations for 64 bits powerpc. 32 bits is untouched for now. We use the new dev_archdata structure to add the dma operations pointer and associated data to struct device. While at it, we also add the OF node pointer and numa node. In the future, we might want to look into merging that with pci_dn as well. The old vio, pci-iommu and pci-direct DMA ops are gone. They are now replaced by a set of generic iommu and direct DMA ops (non PCI specific) that can be used by bus types. The toplevel implementation is now inline. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r--arch/powerpc/platforms/cell/iommu.c21
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c12
-rw-r--r--arch/powerpc/platforms/iseries/pci.c2
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c16
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c90
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c4
6 files changed, 63 insertions, 82 deletions
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index aca4c3db0dde..0e6ab8a55ef7 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -255,9 +255,6 @@ static void enable_mapping(void __iomem *base, void __iomem *mmio_base)
set_iost_origin(mmio_base);
}
-static void iommu_dev_setup_null(struct pci_dev *d) { }
-static void iommu_bus_setup_null(struct pci_bus *b) { }
-
struct cell_iommu {
unsigned long base;
unsigned long mmio_base;
@@ -306,12 +303,15 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
}
}
-static void iommu_devnode_setup(struct device_node *d)
+static void pci_dma_cell_bus_setup(struct pci_bus *b)
{
const unsigned int *ioid;
unsigned long map_start, map_size, token;
const unsigned long *dma_window;
struct cell_iommu *iommu;
+ struct device_node *d;
+
+ d = pci_bus_to_OF_node(b);
ioid = get_property(d, "ioid", NULL);
if (!ioid)
@@ -330,12 +330,6 @@ static void iommu_devnode_setup(struct device_node *d)
cell_do_map_iommu(iommu, *ioid, map_start, map_size);
}
-static void iommu_bus_setup(struct pci_bus *b)
-{
- struct device_node *d = (struct device_node *)b->sysdata;
- iommu_devnode_setup(d);
-}
-
static int cell_map_iommu_hardcoded(int num_nodes)
{
@@ -499,16 +493,13 @@ void cell_init_iommu(void)
if (setup_bus) {
pr_debug("%s: IOMMU mapping activated\n", __FUNCTION__);
- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
- ppc_md.iommu_bus_setup = iommu_bus_setup;
+ ppc_md.pci_dma_bus_setup = pci_dma_cell_bus_setup;
} else {
pr_debug("%s: IOMMU mapping activated, "
"no device action necessary\n", __FUNCTION__);
/* Direct I/O, IOMMU off */
- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
}
}
- pci_dma_ops = cell_iommu_ops;
+ pci_dma_ops = &cell_iommu_ops;
}
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 218817d13c5c..ee0a4e42e4f0 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -27,6 +27,7 @@
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/list.h>
+#include <linux/pci.h>
#include <asm/iommu.h>
#include <asm/tce.h>
@@ -168,7 +169,7 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
}
-void iommu_devnode_init_iSeries(struct device_node *dn)
+void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
{
struct iommu_table *tbl;
struct pci_dn *pdn = PCI_DN(dn);
@@ -186,19 +187,14 @@ void iommu_devnode_init_iSeries(struct device_node *dn)
pdn->iommu_table = iommu_init_table(tbl, -1);
else
kfree(tbl);
+ pdev->dev.archdata.dma_data = pdn->iommu_table;
}
#endif
-static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
-static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
-
void iommu_init_early_iSeries(void)
{
ppc_md.tce_build = tce_build_iSeries;
ppc_md.tce_free = tce_free_iSeries;
- ppc_md.iommu_dev_setup = iommu_dev_setup_iSeries;
- ppc_md.iommu_bus_setup = iommu_bus_setup_iSeries;
-
- pci_iommu_init();
+ pci_dma_ops = &dma_iommu_ops;
}
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 4aa165e010d9..a90ae42a7bc2 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -253,7 +253,7 @@ void __init iSeries_pci_final_fixup(void)
PCI_DN(node)->pcidev = pdev;
allocate_device_bars(pdev);
iSeries_Device_Information(pdev, DeviceCount);
- iommu_devnode_init_iSeries(node);
+ iommu_devnode_init_iSeries(pdev, node);
} else
printk("PCI: Device Tree not found for 0x%016lX\n",
(unsigned long)pdev);
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index eb2457567f8a..89d6e295dbf7 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/console.h>
+#include <linux/pci.h>
#include <asm/prom.h>
#include <asm/system.h>
@@ -71,6 +72,9 @@ void __init pas_setup_arch(void)
/* Setup SMP callback */
smp_ops = &pas_smp_ops;
#endif
+ /* no iommu yet */
+ pci_dma_ops = &dma_direct_ops;
+
/* Lookup PCI hosts */
pas_pci_init();
@@ -81,17 +85,6 @@ void __init pas_setup_arch(void)
printk(KERN_DEBUG "Using default idle loop\n");
}
-static void iommu_dev_setup_null(struct pci_dev *dev) { }
-static void iommu_bus_setup_null(struct pci_bus *bus) { }
-
-static void __init pas_init_early(void)
-{
- /* No iommu code yet */
- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
- pci_direct_iommu_init();
-}
-
/* No legacy IO on our parts */
static int pas_check_legacy_ioport(unsigned int baseport)
{
@@ -173,7 +166,6 @@ define_machine(pas) {
.name = "PA Semi PA6T-1682M",
.probe = pas_probe,
.setup_arch = pas_setup_arch,
- .init_early = pas_init_early,
.init_IRQ = pas_init_IRQ,
.get_irq = mpic_get_irq,
.restart = pas_restart,
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 556c279a789d..3c95392f4f41 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -309,7 +309,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
tbl->it_size = size >> IOMMU_PAGE_SHIFT;
}
-static void iommu_bus_setup_pSeries(struct pci_bus *bus)
+static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
{
struct device_node *dn;
struct iommu_table *tbl;
@@ -318,10 +318,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
struct pci_dn *pci;
int children;
- DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
-
dn = pci_bus_to_OF_node(bus);
- pci = PCI_DN(dn);
+
+ DBG("pci_dma_bus_setup_pSeries: setting up bus %s\n", dn->full_name);
if (bus->self) {
/* This is not a root bus, any setup will be done for the
@@ -329,6 +328,7 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
*/
return;
}
+ pci = PCI_DN(dn);
/* Check if the ISA bus on the system is under
* this PHB.
@@ -390,17 +390,17 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus)
}
-static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
+static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
{
struct iommu_table *tbl;
struct device_node *dn, *pdn;
struct pci_dn *ppci;
const void *dma_window = NULL;
- DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
-
dn = pci_bus_to_OF_node(bus);
+ DBG("pci_dma_bus_setup_pSeriesLP: setting up bus %s\n", dn->full_name);
+
/* Find nearest ibm,dma-window, walking up the device tree */
for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
dma_window = get_property(pdn, "ibm,dma-window", NULL);
@@ -409,11 +409,15 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
}
if (dma_window == NULL) {
- DBG("iommu_bus_setup_pSeriesLP: bus %s seems to have no ibm,dma-window property\n", dn->full_name);
+ DBG(" no ibm,dma-window property !\n");
return;
}
ppci = PCI_DN(pdn);
+
+ DBG(" parent is %s, iommu_table: 0x%p\n",
+ pdn->full_name, ppci->iommu_table);
+
if (!ppci->iommu_table) {
/* Bussubno hasn't been copied yet.
* Do it now because iommu_table_setparms_lpar needs it.
@@ -427,6 +431,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
+ DBG(" created table: %p\n", ppci->iommu_table);
}
if (pdn != dn)
@@ -434,27 +439,27 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
}
-static void iommu_dev_setup_pSeries(struct pci_dev *dev)
+static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
{
- struct device_node *dn, *mydn;
+ struct device_node *dn;
struct iommu_table *tbl;
- DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, pci_name(dev));
+ DBG("pci_dma_dev_setup_pSeries: %s\n", pci_name(dev));
- mydn = dn = pci_device_to_OF_node(dev);
+ dn = dev->dev.archdata.of_node;
/* If we're the direct child of a root bus, then we need to allocate
* an iommu table ourselves. The bus setup code should have setup
* the window sizes already.
*/
if (!dev->bus->self) {
+ struct pci_controller *phb = PCI_DN(dn)->phb;
+
DBG(" --> first child, no bridge. Allocating iommu table.\n");
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
- PCI_DN(dn)->phb->node);
- iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
- PCI_DN(dn)->iommu_table = iommu_init_table(tbl,
- PCI_DN(dn)->phb->node);
-
+ phb->node);
+ iommu_table_setparms(phb, dn, tbl);
+ dev->dev.archdata.dma_data = iommu_init_table(tbl, phb->node);
return;
}
@@ -465,11 +470,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev)
while (dn && PCI_DN(dn) && PCI_DN(dn)->iommu_table == NULL)
dn = dn->parent;
- if (dn && PCI_DN(dn)) {
- PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
- } else {
- DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, pci_name(dev));
- }
+ if (dn && PCI_DN(dn))
+ dev->dev.archdata.dma_data = PCI_DN(dn)->iommu_table;
+ else
+ printk(KERN_WARNING "iommu: Device %s has no iommu table\n",
+ pci_name(dev));
}
static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
@@ -495,13 +500,15 @@ static struct notifier_block iommu_reconfig_nb = {
.notifier_call = iommu_reconfig_notifier,
};
-static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
+static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
{
struct device_node *pdn, *dn;
struct iommu_table *tbl;
const void *dma_window = NULL;
struct pci_dn *pci;
+ DBG("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
+
/* dev setup for LPAR is a little tricky, since the device tree might
* contain the dma-window properties per-device and not neccesarily
* for the bus. So we need to search upwards in the tree until we
@@ -509,9 +516,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
* already allocated.
*/
dn = pci_device_to_OF_node(dev);
-
- DBG("iommu_dev_setup_pSeriesLP, dev %p (%s) %s\n",
- dev, pci_name(dev), dn->full_name);
+ DBG(" node is %s\n", dn->full_name);
for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
pdn = pdn->parent) {
@@ -520,16 +525,17 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
break;
}
+ DBG(" parent is %s\n", pdn->full_name);
+
/* Check for parent == NULL so we don't try to setup the empty EADS
* slots on POWER4 machines.
*/
if (dma_window == NULL || pdn->parent == NULL) {
- DBG("No dma window for device, linking to parent\n");
- PCI_DN(dn)->iommu_table = PCI_DN(pdn)->iommu_table;
+ DBG(" no dma window for device, linking to parent\n");
+ dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
return;
- } else {
- DBG("Found DMA window, allocating table\n");
}
+ DBG(" found DMA window, table: %p\n", pci->iommu_table);
pci = PCI_DN(pdn);
if (!pci->iommu_table) {
@@ -542,24 +548,20 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev)
iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
+ DBG(" created table: %p\n", pci->iommu_table);
}
- if (pdn != dn)
- PCI_DN(dn)->iommu_table = pci->iommu_table;
+ dev->dev.archdata.dma_data = pci->iommu_table;
}
-static void iommu_bus_setup_null(struct pci_bus *b) { }
-static void iommu_dev_setup_null(struct pci_dev *d) { }
-
/* These are called very early. */
void iommu_init_early_pSeries(void)
{
if (of_chosen && get_property(of_chosen, "linux,iommu-off", NULL)) {
/* Direct I/O, IOMMU off */
- ppc_md.iommu_dev_setup = iommu_dev_setup_null;
- ppc_md.iommu_bus_setup = iommu_bus_setup_null;
- pci_direct_iommu_init();
-
+ ppc_md.pci_dma_dev_setup = NULL;
+ ppc_md.pci_dma_bus_setup = NULL;
+ pci_dma_ops = &dma_direct_ops;
return;
}
@@ -572,19 +574,19 @@ void iommu_init_early_pSeries(void)
ppc_md.tce_free = tce_free_pSeriesLP;
}
ppc_md.tce_get = tce_get_pSeriesLP;
- ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
- ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
+ ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
} else {
ppc_md.tce_build = tce_build_pSeries;
ppc_md.tce_free = tce_free_pSeries;
ppc_md.tce_get = tce_get_pseries;
- ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
- ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
+ ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeries;
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeries;
}
pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
- pci_iommu_init();
+ pci_dma_ops = &dma_iommu_ops;
}
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 6bfacc217085..bb0cb5c5b565 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -93,8 +93,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
if (list_empty(&dev->global_list)) {
int i;
- /* Need to setup IOMMU tables */
- ppc_md.iommu_dev_setup(dev);
+ /* Fill device archdata and setup iommu table */
+ pcibios_setup_new_device(dev);
if(fix_bus)
pcibios_fixup_device_resources(dev, bus);