vserver 1.9.5.x5
[linux-2.6.git] / arch / ppc64 / kernel / iSeries_iommu.c
index c09ea2a..4e1a47c 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <linux/config.h>
-#include <linux/init.h>
 #include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/pci.h>
 #include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/rtas.h>
-#include <asm/ppcdebug.h>
+#include <linux/list.h>
 
-#include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iommu.h>
-#include <asm/pci-bridge.h>
-#include <asm/iSeries/iSeries_pci.h>
-
 #include <asm/machdep.h>
-
-#include "pci.h"
-
+#include <asm/iSeries/HvCallXm.h>
+#include <asm/iSeries/iSeries_pci.h>
 
 extern struct list_head iSeries_Global_Device_List;
 
@@ -76,12 +60,11 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
                                tce.te_bits.tb_pciwr = 1;
                }
 
-               rc = HvCallXm_setTce((u64)tbl->it_index,
-                                    (u64)index,
-                                    tce.te_word);
+               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);
-
+                       panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
+                                       rc);
                index++;
                uaddr += PAGE_SIZE;
        }
@@ -90,20 +73,14 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
 static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
 {
        u64 rc;
-       union tce_entry tce;
 
        while (npages--) {
-               tce.te_word = 0;
-               rc = HvCallXm_setTce((u64)tbl->it_index,
-                                    (u64)index,
-                                    tce.te_word);
-
+               rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, 0);
                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++;
        }
-
 }
 
 
@@ -115,17 +92,14 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
 {
        struct iSeries_Device_Node *dp;
 
-       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)
-               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)
+       list_for_each_entry(dp, &iSeries_Global_Device_List, Device_List) {
+               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))
                        return dp->iommu_table;
-
-
+       }
        return NULL;
 }
 
@@ -143,15 +117,14 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
 {
        struct iommu_table_cb *parms;
 
-       parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL);
-
+       parms = kmalloc(sizeof(*parms), GFP_KERNEL);
        if (parms == NULL)
                panic("PCI_DMA: TCE Table Allocation failed.");
 
        memset(parms, 0, sizeof(*parms));
 
-       parms->itc_busno   = ISERIES_BUS(dn);
-       parms->itc_slotno  = dn->LogicalSlot;
+       parms->itc_busno = ISERIES_BUS(dn);
+       parms->itc_slotno = dn->LogicalSlot;
        parms->itc_virtbus = 0;
 
        HvCallXm_getTceTableParms(ISERIES_HV_ADDR(parms));
@@ -159,41 +132,44 @@ static void iommu_table_getparms(struct iSeries_Device_Node* dn,
        if (parms->itc_size == 0)
                panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms);
 
-       tbl->it_size        = parms->itc_size;
-       tbl->it_busno       = parms->itc_busno;
-       tbl->it_offset      = parms->itc_offset;
-       tbl->it_index       = parms->itc_index;
-       tbl->it_entrysize   = sizeof(union tce_entry);
-       tbl->it_blocksize   = 1;
-       tbl->it_type        = TCE_PCI;
+       /* itc_size is in pages worth of table, it_size is in # of entries */
+       tbl->it_size = (parms->itc_size * PAGE_SIZE) / sizeof(union tce_entry);
+       tbl->it_busno = parms->itc_busno;
+       tbl->it_offset = parms->itc_offset;
+       tbl->it_index = parms->itc_index;
+       tbl->it_blocksize = 1;
+       tbl->it_type = TCE_PCI;
 
        kfree(parms);
 }
 
 
-void iommu_devnode_init(struct iSeries_Device_Node *dn) {
+void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
+{
        struct iommu_table *tbl;
 
-       tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
        iommu_table_getparms(dn, tbl);
 
        /* Look for existing tce table */
        dn->iommu_table = iommu_table_find(tbl);
-
        if (dn->iommu_table == NULL)
                dn->iommu_table = iommu_init_table(tbl);
        else
                kfree(tbl);
-
-       return;
 }
 
+static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
+static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
 
-void tce_init_iSeries(void)
+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();
 }