Commit 8277a1fa authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: change the iSeries virtual device drivers to use the vio...

[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.
parent e1df56ff
...@@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \ ...@@ -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 \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
ptrace32.o signal32.o rtc.o init_task.o \ ptrace32.o signal32.o rtc.o init_task.o \
lmb.o cputable.o cpu_setup_power4.o idle_power4.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 obj-$(CONFIG_PPC_OF) += of_device.o
...@@ -34,7 +34,7 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.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 \ obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \ eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \
open_pic.o xics.o pSeries_htab.o rtas.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_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
......
...@@ -5,14 +5,11 @@ ...@@ -5,14 +5,11 @@
* the pci and vio busses * the pci and vio busses
*/ */
#include <linux/config.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
/* Include the busses we support */ /* Include the busses we support */
#include <linux/pci.h> #include <linux/pci.h>
#ifdef CONFIG_PPC_PSERIES
#include <asm/vio.h> #include <asm/vio.h>
#endif
#include <asm/scatterlist.h> #include <asm/scatterlist.h>
#include <asm/bug.h> #include <asm/bug.h>
...@@ -20,10 +17,8 @@ int dma_supported(struct device *dev, u64 mask) ...@@ -20,10 +17,8 @@ int dma_supported(struct device *dev, u64 mask)
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
return pci_dma_supported(to_pci_dev(dev), mask); return pci_dma_supported(to_pci_dev(dev), mask);
#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return vio_dma_supported(to_vio_dev(dev), mask); return vio_dma_supported(to_vio_dev(dev), mask);
#endif
BUG(); BUG();
return 0; return 0;
} }
...@@ -33,10 +28,8 @@ int dma_set_mask(struct device *dev, u64 dma_mask) ...@@ -33,10 +28,8 @@ int dma_set_mask(struct device *dev, u64 dma_mask)
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
return pci_set_dma_mask(to_pci_dev(dev), dma_mask); return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return vio_set_dma_mask(to_vio_dev(dev), dma_mask); return vio_set_dma_mask(to_vio_dev(dev), dma_mask);
#endif
BUG(); BUG();
return 0; return 0;
} }
...@@ -47,10 +40,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size, ...@@ -47,10 +40,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle); return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle);
#endif
BUG(); BUG();
return 0; return 0;
} }
...@@ -61,10 +52,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, ...@@ -61,10 +52,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type) else if (dev->bus == &vio_bus_type)
vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle); vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle);
#endif
else else
BUG(); BUG();
} }
...@@ -75,10 +64,8 @@ dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size, ...@@ -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) if (dev->bus == &pci_bus_type)
return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction); return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction);
#endif
BUG(); BUG();
return (dma_addr_t)0; return (dma_addr_t)0;
} }
...@@ -89,10 +76,8 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, ...@@ -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) if (dev->bus == &pci_bus_type)
pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type) else if (dev->bus == &vio_bus_type)
vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction); vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction);
#endif
else else
BUG(); BUG();
} }
...@@ -104,10 +89,8 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, ...@@ -104,10 +89,8 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction); return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return vio_map_page(to_vio_dev(dev), page, offset, size, direction); return vio_map_page(to_vio_dev(dev), page, offset, size, direction);
#endif
BUG(); BUG();
return (dma_addr_t)0; return (dma_addr_t)0;
} }
...@@ -118,10 +101,8 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, ...@@ -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) if (dev->bus == &pci_bus_type)
pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction); pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type) else if (dev->bus == &vio_bus_type)
vio_unmap_page(to_vio_dev(dev), dma_address, size, direction); vio_unmap_page(to_vio_dev(dev), dma_address, size, direction);
#endif
else else
BUG(); BUG();
} }
...@@ -132,10 +113,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, ...@@ -132,10 +113,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
#ifdef CONFIG_PPC_PSERIES
if (dev->bus == &vio_bus_type) if (dev->bus == &vio_bus_type)
return vio_map_sg(to_vio_dev(dev), sg, nents, direction); return vio_map_sg(to_vio_dev(dev), sg, nents, direction);
#endif
BUG(); BUG();
return 0; return 0;
} }
...@@ -146,10 +125,8 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, ...@@ -146,10 +125,8 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type) else if (dev->bus == &vio_bus_type)
vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction); vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction);
#endif
else else
BUG(); BUG();
} }
...@@ -160,10 +137,8 @@ void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, ...@@ -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) if (dev->bus == &pci_bus_type)
pci_dma_sync_single(to_pci_dev(dev), dma_handle, size, (int)direction); pci_dma_sync_single(to_pci_dev(dev), dma_handle, size, (int)direction);
#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type) else if (dev->bus == &vio_bus_type)
vio_dma_sync_single(to_vio_dev(dev), dma_handle, size, direction); vio_dma_sync_single(to_vio_dev(dev), dma_handle, size, direction);
#endif
else else
BUG(); BUG();
} }
...@@ -174,10 +149,8 @@ void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, ...@@ -174,10 +149,8 @@ void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
{ {
if (dev->bus == &pci_bus_type) if (dev->bus == &pci_bus_type)
pci_dma_sync_sg(to_pci_dev(dev), sg, nelems, (int)direction); pci_dma_sync_sg(to_pci_dev(dev), sg, nelems, (int)direction);
#ifdef CONFIG_PPC_PSERIES
else if (dev->bus == &vio_bus_type) else if (dev->bus == &vio_bus_type)
vio_dma_sync_sg(to_vio_dev(dev), sg, nelems, direction); vio_dma_sync_sg(to_vio_dev(dev), sg, nelems, direction);
#endif
else else
BUG(); BUG();
} }
......
...@@ -2,24 +2,24 @@ ...@@ -2,24 +2,24 @@
* arch/ppc64/kernel/iSeries_iommu.c * arch/ppc64/kernel/iSeries_iommu.c
* *
* Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
* *
* Rewrite, cleanup: * Rewrite, cleanup:
* *
* Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation * Copyright (C) 2004 Olof Johansson <olof@austin.ibm.com>, IBM Corporation
* *
* Dynamic DMA mapping support, iSeries-specific parts. * Dynamic DMA mapping support, iSeries-specific parts.
* *
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
...@@ -44,28 +44,12 @@ ...@@ -44,28 +44,12 @@
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/iSeries/iSeries_pci.h> #include <asm/iSeries/iSeries_pci.h>
#include <asm/iSeries/vio.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include "pci.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; 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, ...@@ -74,7 +58,7 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
{ {
u64 rc; u64 rc;
union tce_entry tce; union tce_entry tce;
while (npages--) { while (npages--) {
tce.te_word = 0; tce.te_word = 0;
tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> PAGE_SHIFT; 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, ...@@ -91,9 +75,9 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
if (direction != DMA_TO_DEVICE) if (direction != DMA_TO_DEVICE)
tce.te_bits.tb_pciwr = 1; tce.te_bits.tb_pciwr = 1;
} }
rc = HvCallXm_setTce((u64)tbl->it_index, rc = HvCallXm_setTce((u64)tbl->it_index,
(u64)index, (u64)index,
tce.te_word); tce.te_word);
if (rc) if (rc)
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", 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) ...@@ -114,7 +98,7 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
(u64)index, (u64)index,
tce.te_word); tce.te_word);
if (rc) if (rc)
panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc);
index++; index++;
...@@ -122,50 +106,10 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) ...@@ -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 * 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) 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) ...@@ -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; 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 *)&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 && if (dp->iommu_table != NULL &&
dp->iommu_table->it_type == TCE_PCI && dp->iommu_table->it_type == TCE_PCI &&
dp->iommu_table->it_offset == tbl->it_offset && dp->iommu_table->it_offset == tbl->it_offset &&
dp->iommu_table->it_index == tbl->it_index && 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 dp->iommu_table;
return NULL; return NULL;
} }
/* /*
* Call Hv with the architected data structure to get TCE table info. * Call Hv with the architected data structure to get TCE table info.
* info. Put the returned data into the Linux representation of the * info. Put the returned data into the Linux representation of the
* TCE table data. * TCE table data.
* The Hardware Tce table comes in three flavors. * The Hardware Tce table comes in three flavors.
* 1. TCE table shared between Buses. * 1. TCE table shared between Buses.
* 2. TCE table per Bus. * 2. TCE table per Bus.
* 3. TCE Table per IOA. * 3. TCE Table per IOA.
*/ */
static void iommu_table_getparms(struct iSeries_Device_Node* dn, static void iommu_table_getparms(struct iSeries_Device_Node* dn,
struct iommu_table* tbl) struct iommu_table* tbl)
...@@ -201,7 +145,7 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn, ...@@ -201,7 +145,7 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL); parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL);
if (parms == NULL) if (parms == NULL)
panic("PCI_DMA: TCE Table Allocation failed."); panic("PCI_DMA: TCE Table Allocation failed.");
memset(parms, 0, sizeof(*parms)); memset(parms, 0, sizeof(*parms));
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/vio.h> #include <asm/vio.h>
#include <asm/hvcall.h> #include <asm/hvcall.h>
#include <asm/iSeries/vio.h>
#include <asm/iSeries/HvCallXm.h>
#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__) #define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
...@@ -32,9 +34,31 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */ ...@@ -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); struct iommu_table *vio_build_iommu_table(struct vio_dev *dev);
#ifdef CONFIG_PPC_PSERIES
static int vio_num_address_cells; static int vio_num_address_cells;
#endif
static struct vio_dev *vio_bus_device; /* fake "parent" device */ 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. /* 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 * dev->driver has already been set by generic code because vio_bus_match
* succeeded. */ * succeeded. */
...@@ -117,21 +141,67 @@ const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, ...@@ -117,21 +141,67 @@ const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,
{ {
DBGENTER(); DBGENTER();
#ifdef CONFIG_PPC_PSERIES
while (ids->type) { while (ids->type) {
if ((strncmp(dev->archdata->type, ids->type, strlen(ids->type)) == 0) && if ((strncmp(dev->archdata->type, ids->type, strlen(ids->type)) == 0) &&
device_is_compatible((struct device_node*)dev->archdata, ids->compat)) device_is_compatible((struct device_node*)dev->archdata, ids->compat))
return ids; return ids;
ids++; ids++;
} }
#endif
return NULL; 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 * vio_bus_init: - Initialize the virtual IO bus
*/ */
static int __init vio_bus_init(void) static int __init vio_bus_init(void)
{ {
#ifdef CONFIG_PPC_PSERIES
struct device_node *node_vroot, *of_node; struct device_node *node_vroot, *of_node;
#endif
int err; int err;
err = bus_register(&vio_bus_type); err = bus_register(&vio_bus_type);
...@@ -156,6 +226,7 @@ static int __init vio_bus_init(void) ...@@ -156,6 +226,7 @@ static int __init vio_bus_init(void)
return err; return err;
} }
#ifdef CONFIG_PPC_PSERIES
node_vroot = find_devices("vdevice"); node_vroot = find_devices("vdevice");
if ((node_vroot == NULL) || (node_vroot->child == NULL)) { if ((node_vroot == NULL) || (node_vroot->child == NULL)) {
/* this machine doesn't do virtual IO, and that's ok */ /* this machine doesn't do virtual IO, and that's ok */
...@@ -175,6 +246,7 @@ static int __init vio_bus_init(void) ...@@ -175,6 +246,7 @@ static int __init vio_bus_init(void)
vio_register_device(of_node); vio_register_device(of_node);
} }
#endif
return 0; return 0;
} }
...@@ -182,6 +254,7 @@ static int __init vio_bus_init(void) ...@@ -182,6 +254,7 @@ static int __init vio_bus_init(void)
__initcall(vio_bus_init); __initcall(vio_bus_init);
#ifdef CONFIG_PPC_PSERIES
/* vio_dev refcount hit 0 */ /* vio_dev refcount hit 0 */
static void __devinit vio_dev_release(struct device *dev) static void __devinit vio_dev_release(struct device *dev)
{ {
...@@ -412,6 +485,7 @@ int vio_disable_interrupts(struct vio_dev *dev) ...@@ -412,6 +485,7 @@ int vio_disable_interrupts(struct vio_dev *dev)
return rc; return rc;
} }
EXPORT_SYMBOL(vio_disable_interrupts); EXPORT_SYMBOL(vio_disable_interrupts);
#endif
dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr, dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr,
size_t size, enum dma_data_direction direction) size_t size, enum dma_data_direction direction)
......
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