summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-04-11 22:49:07 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-04-11 22:49:07 -0700
commit8277a1fa5618d97660e8c1de25ce712fa8ae750a (patch)
tree8bf8d13470a0902b2261fbcc249dec936f2a1fd9
parente1df56ff96e6b7be4a651dad58ba38cda5f0d8b3 (diff)
[PATCH] ppc64: change the iSeries virtual device drivers to use the vio infrastructure for DMA mapping
From: Stephen Rothwell <sfr@canb.auug.org.au> This patch changes the iSeries virtual device drivers to use the vio infrastructure for DMA mapping instead of the PCI infrastructure. This is a step along the way to integrating them correctly into the driver model.
-rw-r--r--arch/ppc64/kernel/Makefile4
-rw-r--r--arch/ppc64/kernel/dma.c27
-rw-r--r--arch/ppc64/kernel/iSeries_iommu.c98
-rw-r--r--arch/ppc64/kernel/vio.c74
4 files changed, 97 insertions, 106 deletions
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 922b60f85294..c36dd89a4e3b 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
ptrace32.o signal32.o rtc.o init_task.o \
lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
- iommu.o sysfs.o
+ iommu.o sysfs.o vio.o
obj-$(CONFIG_PPC_OF) += of_device.o
@@ -34,7 +34,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \
open_pic.o xics.o pSeries_htab.o rtas.o \
- chrp_setup.o i8259.o prom.o vio.o pSeries_iommu.o
+ chrp_setup.o i8259.o prom.o pSeries_iommu.o
obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
index 26839a571415..f81dcd1e8da1 100644
--- a/arch/ppc64/kernel/dma.c
+++ b/arch/ppc64/kernel/dma.c
@@ -5,14 +5,11 @@
* the pci and vio busses
*/
-#include <linux/config.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
/* Include the busses we support */
#include <linux/pci.h>
-#ifdef CONFIG_PPC_PSERIES
#include <asm/vio.h>
-#endif
#include <asm/scatterlist.h>
#include <asm/bug.h>
@@ -20,10 +17,8 @@ int dma_supported(struct device *dev, u64 mask)
{
if (dev->bus == &pci_bus_type)
return pci_dma_supported(to_pci_dev(dev), mask);
-#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type)
return vio_dma_supported(to_vio_dev(dev), mask);
-#endif
BUG();
return 0;
}
@@ -33,10 +28,8 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
{
if (dev->bus == &pci_bus_type)
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
-#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type)
return vio_set_dma_mask(to_vio_dev(dev), dma_mask);
-#endif
BUG();
return 0;
}
@@ -47,10 +40,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
{
if (dev->bus == &pci_bus_type)
return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
-#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type)
return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle);
-#endif
BUG();
return 0;
}
@@ -61,10 +52,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
{
if (dev->bus == &pci_bus_type)
pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
-#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type)
vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle);
-#endif
else
BUG();
}
@@ -75,10 +64,8 @@ dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
{
if (dev->bus == &pci_bus_type)
return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type)
return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction);
-#endif
BUG();
return (dma_addr_t)0;
}
@@ -89,10 +76,8 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
{
if (dev->bus == &pci_bus_type)
pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type)
vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction);
-#endif
else
BUG();
}
@@ -104,10 +89,8 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
{
if (dev->bus == &pci_bus_type)
return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type)
return vio_map_page(to_vio_dev(dev), page, offset, size, direction);
-#endif
BUG();
return (dma_addr_t)0;
}
@@ -118,10 +101,8 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
{
if (dev->bus == &pci_bus_type)
pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type)
vio_unmap_page(to_vio_dev(dev), dma_address, size, direction);
-#endif
else
BUG();
}
@@ -132,10 +113,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
{
if (dev->bus == &pci_bus_type)
return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type)
return vio_map_sg(to_vio_dev(dev), sg, nents, direction);
-#endif
BUG();
return 0;
}
@@ -146,10 +125,8 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
{
if (dev->bus == &pci_bus_type)
pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type)
vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction);
-#endif
else
BUG();
}
@@ -160,10 +137,8 @@ void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
{
if (dev->bus == &pci_bus_type)
pci_dma_sync_single(to_pci_dev(dev), dma_handle, size, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type)
vio_dma_sync_single(to_vio_dev(dev), dma_handle, size, direction);
-#endif
else
BUG();
}
@@ -174,10 +149,8 @@ void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
{
if (dev->bus == &pci_bus_type)
pci_dma_sync_sg(to_pci_dev(dev), sg, nelems, (int)direction);
-#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type)
vio_dma_sync_sg(to_vio_dev(dev), sg, nelems, direction);
-#endif
else
BUG();
}
diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c
index ea4ef7497193..c09ea2aaa189 100644
--- a/arch/ppc64/kernel/iSeries_iommu.c
+++ b/arch/ppc64/kernel/iSeries_iommu.c
@@ -2,24 +2,24 @@
* arch/ppc64/kernel/iSeries_iommu.c
*
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
- *
- * Rewrite, cleanup:
+ *
+ * Rewrite, cleanup:
*
* Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
*
* Dynamic DMA mapping support, iSeries-specific parts.
*
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
@@ -44,28 +44,12 @@
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/iSeries/iSeries_pci.h>
-#include <asm/iSeries/vio.h>
#include <asm/machdep.h>
#include "pci.h"
-static struct iommu_table veth_iommu_table; /* Tce table for virtual ethernet */
-static struct iommu_table vio_iommu_table; /* Tce table for virtual I/O */
-
-static struct iSeries_Device_Node veth_dev_node = { .LogicalSlot = 0xFF, .iommu_table = &veth_iommu_table };
-static struct iSeries_Device_Node vio_dev_node = { .LogicalSlot = 0xFF, .iommu_table = &vio_iommu_table };
-
-static struct pci_dev _veth_dev = { .sysdata = &veth_dev_node };
-static struct pci_dev _vio_dev = { .sysdata = &vio_dev_node, .dev.bus = &pci_bus_type };
-
-struct pci_dev *iSeries_veth_dev = &_veth_dev;
-struct device *iSeries_vio_dev = &_vio_dev.dev;
-
-EXPORT_SYMBOL(iSeries_veth_dev);
-EXPORT_SYMBOL(iSeries_vio_dev);
-
extern struct list_head iSeries_Global_Device_List;
@@ -74,7 +58,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
{
u64 rc;
union tce_entry tce;
-
+
while (npages--) {
tce.te_word = 0;
tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT;
@@ -91,9 +75,9 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
if (direction != DMA_TO_DEVICE)
tce.te_bits.tb_pciwr = 1;
}
-
- rc = HvCallXm_setTce((u64)tbl->it_index,
- (u64)index,
+
+ rc = HvCallXm_setTce((u64)tbl->it_index,
+ (u64)index,
tce.te_word);
if (rc)
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc);
@@ -114,7 +98,7 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
(u64)index,
tce.te_word);
- if (rc)
+ if (rc)
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc);
index++;
@@ -122,50 +106,10 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
}
-void __init iommu_vio_init(void)
-{
- struct iommu_table *t;
- struct iommu_table_cb cb;
- unsigned long cbp;
-
- cb.itc_busno = 255; /* Bus 255 is the virtual bus */
- cb.itc_virtbus = 0xff; /* Ask for virtual bus */
-
- cbp = virt_to_abs(&cb);
- HvCallXm_getTceTableParms(cbp);
-
- veth_iommu_table.it_size = cb.itc_size / 2;
- veth_iommu_table.it_busno = cb.itc_busno;
- veth_iommu_table.it_offset = cb.itc_offset;
- veth_iommu_table.it_index = cb.itc_index;
- veth_iommu_table.it_type = TCE_VB;
- veth_iommu_table.it_entrysize = sizeof(union tce_entry);
- veth_iommu_table.it_blocksize = 1;
-
- t = iommu_init_table(&veth_iommu_table);
-
- if (!t)
- printk("Virtual Bus VETH TCE table failed.\n");
-
- vio_iommu_table.it_size = cb.itc_size - veth_iommu_table.it_size;
- vio_iommu_table.it_busno = cb.itc_busno;
- vio_iommu_table.it_offset = cb.itc_offset +
- veth_iommu_table.it_size * (PAGE_SIZE/sizeof(union tce_entry));
- vio_iommu_table.it_index = cb.itc_index;
- vio_iommu_table.it_type = TCE_VB;
- vio_iommu_table.it_entrysize = sizeof(union tce_entry);
- vio_iommu_table.it_blocksize = 1;
-
- t = iommu_init_table(&vio_iommu_table);
-
- if (!t)
- printk("Virtual Bus VIO TCE table failed.\n");
-}
-
/*
* This function compares the known tables to find an iommu_table
- * that has already been built for hardware TCEs.
+ * that has already been built for hardware TCEs.
*/
static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
{
@@ -173,26 +117,26 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
for (dp = (struct iSeries_Device_Node *)iSeries_Global_Device_List.next;
dp != (struct iSeries_Device_Node *)&iSeries_Global_Device_List;
- dp = (struct iSeries_Device_Node *)dp->Device_List.next)
+ dp = (struct iSeries_Device_Node *)dp->Device_List.next)
if (dp->iommu_table != NULL &&
dp->iommu_table->it_type == TCE_PCI &&
dp->iommu_table->it_offset == tbl->it_offset &&
dp->iommu_table->it_index == tbl->it_index &&
- dp->iommu_table->it_size == tbl->it_size)
+ dp->iommu_table->it_size == tbl->it_size)
return dp->iommu_table;
-
+
return NULL;
}
/*
* Call Hv with the architected data structure to get TCE table info.
- * info. Put the returned data into the Linux representation of the
- * TCE table data.
- * The Hardware Tce table comes in three flavors.
- * 1. TCE table shared between Buses.
- * 2. TCE table per Bus.
- * 3. TCE Table per IOA.
+ * info. Put the returned data into the Linux representation of the
+ * TCE table data.
+ * The Hardware Tce table comes in three flavors.
+ * 1. TCE table shared between Buses.
+ * 2. TCE table per Bus.
+ * 3. TCE Table per IOA.
*/
static void iommu_table_getparms(struct iSeries_Device_Node* dn,
struct iommu_table* tbl)
@@ -201,7 +145,7 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL);
- if (parms == NULL)
+ if (parms == NULL)
panic("PCI_DMA: TCE Table Allocation failed.");
memset(parms, 0, sizeof(*parms));
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index c4c16b8cd7a9..817f3152fb41 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -25,6 +25,8 @@
#include <asm/ppcdebug.h>
#include <asm/vio.h>
#include <asm/hvcall.h>
+#include <asm/iSeries/vio.h>
+#include <asm/iSeries/HvCallXm.h>
#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
@@ -32,9 +34,31 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */
struct iommu_table *vio_build_iommu_table(struct vio_dev *dev);
+#ifdef CONFIG_PPC_PSERIES
static int vio_num_address_cells;
+#endif
static struct vio_dev *vio_bus_device; /* fake "parent" device */
+#ifdef CONFIG_PPC_ISERIES
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+static struct vio_dev _veth_dev = {
+ .iommu_table = &veth_iommu_table,
+ .dev.bus = &vio_bus_type
+};
+static struct vio_dev _vio_dev = {
+ .iommu_table = &vio_iommu_table,
+ .dev.bus = &vio_bus_type
+};
+
+struct vio_dev *iSeries_veth_dev = &_veth_dev;
+struct device *iSeries_vio_dev = &_vio_dev.dev;
+
+EXPORT_SYMBOL(iSeries_veth_dev);
+EXPORT_SYMBOL(iSeries_vio_dev);
+#endif
+
/* convert from struct device to struct vio_dev and pass to driver.
* dev->driver has already been set by generic code because vio_bus_match
* succeeded. */
@@ -117,21 +141,67 @@ const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,
{
DBGENTER();
+#ifdef CONFIG_PPC_PSERIES
while (ids->type) {
if ((strncmp(dev->archdata->type, ids->type, strlen(ids->type)) == 0) &&
device_is_compatible((struct device_node*)dev->archdata, ids->compat))
return ids;
ids++;
}
+#endif
return NULL;
}
+#ifdef CONFIG_PPC_ISERIES
+void __init iommu_vio_init(void)
+{
+ struct iommu_table *t;
+ struct iommu_table_cb cb;
+ unsigned long cbp;
+
+ cb.itc_busno = 255; /* Bus 255 is the virtual bus */
+ cb.itc_virtbus = 0xff; /* Ask for virtual bus */
+
+ cbp = virt_to_abs(&cb);
+ HvCallXm_getTceTableParms(cbp);
+
+ veth_iommu_table.it_size = cb.itc_size / 2;
+ veth_iommu_table.it_busno = cb.itc_busno;
+ veth_iommu_table.it_offset = cb.itc_offset;
+ veth_iommu_table.it_index = cb.itc_index;
+ veth_iommu_table.it_type = TCE_VB;
+ veth_iommu_table.it_entrysize = sizeof(union tce_entry);
+ veth_iommu_table.it_blocksize = 1;
+
+ t = iommu_init_table(&veth_iommu_table);
+
+ if (!t)
+ printk("Virtual Bus VETH TCE table failed.\n");
+
+ vio_iommu_table.it_size = cb.itc_size - veth_iommu_table.it_size;
+ vio_iommu_table.it_busno = cb.itc_busno;
+ vio_iommu_table.it_offset = cb.itc_offset +
+ veth_iommu_table.it_size * (PAGE_SIZE/sizeof(union tce_entry));
+ vio_iommu_table.it_index = cb.itc_index;
+ vio_iommu_table.it_type = TCE_VB;
+ vio_iommu_table.it_entrysize = sizeof(union tce_entry);
+ vio_iommu_table.it_blocksize = 1;
+
+ t = iommu_init_table(&vio_iommu_table);
+
+ if (!t)
+ printk("Virtual Bus VIO TCE table failed.\n");
+}
+#endif
+
/**
* vio_bus_init: - Initialize the virtual IO bus
*/
static int __init vio_bus_init(void)
{
+#ifdef CONFIG_PPC_PSERIES
struct device_node *node_vroot, *of_node;
+#endif
int err;
err = bus_register(&vio_bus_type);
@@ -156,6 +226,7 @@ static int __init vio_bus_init(void)
return err;
}
+#ifdef CONFIG_PPC_PSERIES
node_vroot = find_devices("vdevice");
if ((node_vroot == NULL) || (node_vroot->child == NULL)) {
/* this machine doesn't do virtual IO, and that's ok */
@@ -175,6 +246,7 @@ static int __init vio_bus_init(void)
vio_register_device(of_node);
}
+#endif
return 0;
}
@@ -182,6 +254,7 @@ static int __init vio_bus_init(void)
__initcall(vio_bus_init);
+#ifdef CONFIG_PPC_PSERIES
/* vio_dev refcount hit 0 */
static void __devinit vio_dev_release(struct device *dev)
{
@@ -412,6 +485,7 @@ int vio_disable_interrupts(struct vio_dev *dev)
return rc;
}
EXPORT_SYMBOL(vio_disable_interrupts);
+#endif
dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr,
size_t size, enum dma_data_direction direction)