diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-04-11 22:49:07 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-11 22:49:07 -0700 |
| commit | 8277a1fa5618d97660e8c1de25ce712fa8ae750a (patch) | |
| tree | 8bf8d13470a0902b2261fbcc249dec936f2a1fd9 | |
| parent | e1df56ff96e6b7be4a651dad58ba38cda5f0d8b3 (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/Makefile | 4 | ||||
| -rw-r--r-- | arch/ppc64/kernel/dma.c | 27 | ||||
| -rw-r--r-- | arch/ppc64/kernel/iSeries_iommu.c | 98 | ||||
| -rw-r--r-- | arch/ppc64/kernel/vio.c | 74 |
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) |
