]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/sparc64/kernel/pci_sun4v.c
[SPARC64]: check fork_idle() error
[linux-2.6-omap-h63xx.git] / arch / sparc64 / kernel / pci_sun4v.c
index ce46b04716932a048a93ca0d1f4bab33944eaba1..da724b13e89e45eaf567bdfb380268bbd7fcecf9 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/percpu.h>
 #include <linux/irq.h>
 #include <linux/msi.h>
+#include <linux/log2.h>
 
-#include <asm/pbm.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/upa.h>
 
 #include "pci_sun4v.h"
 
+static unsigned long vpci_major = 1;
+static unsigned long vpci_minor = 1;
+
 #define PGLIST_NENTS   (PAGE_SIZE / sizeof(u64))
 
 struct iommu_batch {
-       struct pci_dev  *pdev;          /* Device mapping is for.       */
+       struct device   *dev;           /* Device mapping is for.       */
        unsigned long   prot;           /* IOMMU page protections       */
        unsigned long   entry;          /* Index into IOTSB.            */
        u64             *pglist;        /* List of physical pages       */
        unsigned long   npages;         /* Number of pages in list.     */
 };
 
-static DEFINE_PER_CPU(struct iommu_batch, pci_iommu_batch);
+static DEFINE_PER_CPU(struct iommu_batch, iommu_batch);
 
 /* Interrupts must be disabled.  */
-static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long prot, unsigned long entry)
+static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry)
 {
-       struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
+       struct iommu_batch *p = &__get_cpu_var(iommu_batch);
 
-       p->pdev         = pdev;
+       p->dev          = dev;
        p->prot         = prot;
        p->entry        = entry;
        p->npages       = 0;
 }
 
 /* Interrupts must be disabled.  */
-static long pci_iommu_batch_flush(struct iommu_batch *p)
+static long iommu_batch_flush(struct iommu_batch *p)
 {
-       struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller;
+       struct pci_pbm_info *pbm = p->dev->archdata.host_controller;
        unsigned long devhandle = pbm->devhandle;
        unsigned long prot = p->prot;
        unsigned long entry = p->entry;
@@ -67,7 +70,7 @@ static long pci_iommu_batch_flush(struct iommu_batch *p)
                                          npages, prot, __pa(pglist));
                if (unlikely(num < 0)) {
                        if (printk_ratelimit())
-                               printk("pci_iommu_batch_flush: IOMMU map of "
+                               printk("iommu_batch_flush: IOMMU map of "
                                       "[%08lx:%08lx:%lx:%lx:%lx] failed with "
                                       "status %ld\n",
                                       devhandle, HV_PCI_TSBID(0, entry),
@@ -87,30 +90,30 @@ static long pci_iommu_batch_flush(struct iommu_batch *p)
 }
 
 /* Interrupts must be disabled.  */
-static inline long pci_iommu_batch_add(u64 phys_page)
+static inline long iommu_batch_add(u64 phys_page)
 {
-       struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
+       struct iommu_batch *p = &__get_cpu_var(iommu_batch);
 
        BUG_ON(p->npages >= PGLIST_NENTS);
 
        p->pglist[p->npages++] = phys_page;
        if (p->npages == PGLIST_NENTS)
-               return pci_iommu_batch_flush(p);
+               return iommu_batch_flush(p);
 
        return 0;
 }
 
 /* Interrupts must be disabled.  */
-static inline long pci_iommu_batch_end(void)
+static inline long iommu_batch_end(void)
 {
-       struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
+       struct iommu_batch *p = &__get_cpu_var(iommu_batch);
 
        BUG_ON(p->npages >= PGLIST_NENTS);
 
-       return pci_iommu_batch_flush(p);
+       return iommu_batch_flush(p);
 }
 
-static long pci_arena_alloc(struct iommu_arena *arena, unsigned long npages)
+static long arena_alloc(struct iommu_arena *arena, unsigned long npages)
 {
        unsigned long n, i, start, end, limit;
        int pass;
@@ -149,7 +152,8 @@ again:
        return n;
 }
 
-static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
+static void arena_free(struct iommu_arena *arena, unsigned long base,
+                      unsigned long npages)
 {
        unsigned long i;
 
@@ -157,7 +161,8 @@ static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsign
                __clear_bit(i, arena->map);
 }
 
-static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
+static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
+                                  dma_addr_t *dma_addrp, gfp_t gfp)
 {
        struct iommu *iommu;
        unsigned long flags, order, first_page, npages, n;
@@ -177,10 +182,10 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 
        memset((char *)first_page, 0, PAGE_SIZE << order);
 
-       iommu = pdev->dev.archdata.iommu;
+       iommu = dev->archdata.iommu;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       entry = pci_arena_alloc(&iommu->arena, npages);
+       entry = arena_alloc(&iommu->arena, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        if (unlikely(entry < 0L))
@@ -193,18 +198,18 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 
        local_irq_save(flags);
 
-       pci_iommu_batch_start(pdev,
-                             (HV_PCI_MAP_ATTR_READ |
-                              HV_PCI_MAP_ATTR_WRITE),
-                             entry);
+       iommu_batch_start(dev,
+                         (HV_PCI_MAP_ATTR_READ |
+                          HV_PCI_MAP_ATTR_WRITE),
+                         entry);
 
        for (n = 0; n < npages; n++) {
-               long err = pci_iommu_batch_add(first_page + (n * PAGE_SIZE));
+               long err = iommu_batch_add(first_page + (n * PAGE_SIZE));
                if (unlikely(err < 0L))
                        goto iommu_map_fail;
        }
 
-       if (unlikely(pci_iommu_batch_end() < 0L))
+       if (unlikely(iommu_batch_end() < 0L))
                goto iommu_map_fail;
 
        local_irq_restore(flags);
@@ -214,7 +219,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 iommu_map_fail:
        /* Interrupts are disabled.  */
        spin_lock(&iommu->lock);
-       pci_arena_free(&iommu->arena, entry, npages);
+       arena_free(&iommu->arena, entry, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
 arena_alloc_fail:
@@ -222,7 +227,8 @@ arena_alloc_fail:
        return NULL;
 }
 
-static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
+static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
+                                dma_addr_t dvma)
 {
        struct pci_pbm_info *pbm;
        struct iommu *iommu;
@@ -230,14 +236,14 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
        u32 devhandle;
 
        npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
-       iommu = pdev->dev.archdata.iommu;
-       pbm = pdev->dev.archdata.host_controller;
+       iommu = dev->archdata.iommu;
+       pbm = dev->archdata.host_controller;
        devhandle = pbm->devhandle;
        entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       pci_arena_free(&iommu->arena, entry, npages);
+       arena_free(&iommu->arena, entry, npages);
 
        do {
                unsigned long num;
@@ -255,7 +261,8 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
                free_pages((unsigned long)cpu, order);
 }
 
-static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
+static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
+                                   enum dma_data_direction direction)
 {
        struct iommu *iommu;
        unsigned long flags, npages, oaddr;
@@ -264,9 +271,9 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
        unsigned long prot;
        long entry;
 
-       iommu = pdev->dev.archdata.iommu;
+       iommu = dev->archdata.iommu;
 
-       if (unlikely(direction == PCI_DMA_NONE))
+       if (unlikely(direction == DMA_NONE))
                goto bad;
 
        oaddr = (unsigned long)ptr;
@@ -274,7 +281,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
        npages >>= IO_PAGE_SHIFT;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       entry = pci_arena_alloc(&iommu->arena, npages);
+       entry = arena_alloc(&iommu->arena, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        if (unlikely(entry < 0L))
@@ -285,19 +292,19 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
        ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
        base_paddr = __pa(oaddr & IO_PAGE_MASK);
        prot = HV_PCI_MAP_ATTR_READ;
-       if (direction != PCI_DMA_TODEVICE)
+       if (direction != DMA_TO_DEVICE)
                prot |= HV_PCI_MAP_ATTR_WRITE;
 
        local_irq_save(flags);
 
-       pci_iommu_batch_start(pdev, prot, entry);
+       iommu_batch_start(dev, prot, entry);
 
        for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) {
-               long err = pci_iommu_batch_add(base_paddr);
+               long err = iommu_batch_add(base_paddr);
                if (unlikely(err < 0L))
                        goto iommu_map_fail;
        }
-       if (unlikely(pci_iommu_batch_end() < 0L))
+       if (unlikely(iommu_batch_end() < 0L))
                goto iommu_map_fail;
 
        local_irq_restore(flags);
@@ -307,18 +314,19 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 bad:
        if (printk_ratelimit())
                WARN_ON(1);
-       return PCI_DMA_ERROR_CODE;
+       return DMA_ERROR_CODE;
 
 iommu_map_fail:
        /* Interrupts are disabled.  */
        spin_lock(&iommu->lock);
-       pci_arena_free(&iommu->arena, entry, npages);
+       arena_free(&iommu->arena, entry, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
-       return PCI_DMA_ERROR_CODE;
+       return DMA_ERROR_CODE;
 }
 
-static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
+static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
+                               size_t sz, enum dma_data_direction direction)
 {
        struct pci_pbm_info *pbm;
        struct iommu *iommu;
@@ -326,14 +334,14 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
        long entry;
        u32 devhandle;
 
-       if (unlikely(direction == PCI_DMA_NONE)) {
+       if (unlikely(direction == DMA_NONE)) {
                if (printk_ratelimit())
                        WARN_ON(1);
                return;
        }
 
-       iommu = pdev->dev.archdata.iommu;
-       pbm = pdev->dev.archdata.host_controller;
+       iommu = dev->archdata.iommu;
+       pbm = dev->archdata.host_controller;
        devhandle = pbm->devhandle;
 
        npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
@@ -343,7 +351,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
        spin_lock_irqsave(&iommu->lock, flags);
 
        entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
-       pci_arena_free(&iommu->arena, entry, npages);
+       arena_free(&iommu->arena, entry, npages);
 
        do {
                unsigned long num;
@@ -360,7 +368,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
 #define SG_ENT_PHYS_ADDRESS(SG)        \
        (__pa(page_address((SG)->page)) + (SG)->offset)
 
-static inline long fill_sg(long entry, struct pci_dev *pdev,
+static inline long fill_sg(long entry, struct device *dev,
                           struct scatterlist *sg,
                           int nused, int nelems, unsigned long prot)
 {
@@ -371,7 +379,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
 
        local_irq_save(flags);
 
-       pci_iommu_batch_start(pdev, prot, entry);
+       iommu_batch_start(dev, prot, entry);
 
        for (i = 0; i < nused; i++) {
                unsigned long pteval = ~0UL;
@@ -412,7 +420,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
                        while (len > 0) {
                                long err;
 
-                               err = pci_iommu_batch_add(pteval);
+                               err = iommu_batch_add(pteval);
                                if (unlikely(err < 0L))
                                        goto iommu_map_failed;
 
@@ -443,7 +451,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
                dma_sg++;
        }
 
-       if (unlikely(pci_iommu_batch_end() < 0L))
+       if (unlikely(iommu_batch_end() < 0L))
                goto iommu_map_failed;
 
        local_irq_restore(flags);
@@ -454,7 +462,8 @@ iommu_map_failed:
        return -1L;
 }
 
-static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
+                        int nelems, enum dma_data_direction direction)
 {
        struct iommu *iommu;
        unsigned long flags, npages, prot;
@@ -466,18 +475,19 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
        /* Fast path single entry scatterlists. */
        if (nelems == 1) {
                sglist->dma_address =
-                       pci_4v_map_single(pdev,
-                                         (page_address(sglist->page) + sglist->offset),
+                       dma_4v_map_single(dev,
+                                         (page_address(sglist->page) +
+                                          sglist->offset),
                                          sglist->length, direction);
-               if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE))
+               if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
                        return 0;
                sglist->dma_length = sglist->length;
                return 1;
        }
 
-       iommu = pdev->dev.archdata.iommu;
+       iommu = dev->archdata.iommu;
        
-       if (unlikely(direction == PCI_DMA_NONE))
+       if (unlikely(direction == DMA_NONE))
                goto bad;
 
        /* Step 1: Prepare scatter list. */
@@ -485,7 +495,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 
        /* Step 2: Allocate a cluster and context, if necessary. */
        spin_lock_irqsave(&iommu->lock, flags);
-       entry = pci_arena_alloc(&iommu->arena, npages);
+       entry = arena_alloc(&iommu->arena, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        if (unlikely(entry < 0L))
@@ -507,10 +517,10 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 
        /* Step 4: Create the mappings. */
        prot = HV_PCI_MAP_ATTR_READ;
-       if (direction != PCI_DMA_TODEVICE)
+       if (direction != DMA_TO_DEVICE)
                prot |= HV_PCI_MAP_ATTR_WRITE;
 
-       err = fill_sg(entry, pdev, sglist, used, nelems, prot);
+       err = fill_sg(entry, dev, sglist, used, nelems, prot);
        if (unlikely(err < 0L))
                goto iommu_map_failed;
 
@@ -523,13 +533,14 @@ bad:
 
 iommu_map_failed:
        spin_lock_irqsave(&iommu->lock, flags);
-       pci_arena_free(&iommu->arena, entry, npages);
+       arena_free(&iommu->arena, entry, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        return 0;
 }
 
-static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
+                           int nelems, enum dma_data_direction direction)
 {
        struct pci_pbm_info *pbm;
        struct iommu *iommu;
@@ -537,13 +548,13 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
        long entry;
        u32 devhandle, bus_addr;
 
-       if (unlikely(direction == PCI_DMA_NONE)) {
+       if (unlikely(direction == DMA_NONE)) {
                if (printk_ratelimit())
                        WARN_ON(1);
        }
 
-       iommu = pdev->dev.archdata.iommu;
-       pbm = pdev->dev.archdata.host_controller;
+       iommu = dev->archdata.iommu;
+       pbm = dev->archdata.host_controller;
        devhandle = pbm->devhandle;
        
        bus_addr = sglist->dma_address & IO_PAGE_MASK;
@@ -559,7 +570,7 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       pci_arena_free(&iommu->arena, entry, npages);
+       arena_free(&iommu->arena, entry, npages);
 
        do {
                unsigned long num;
@@ -573,110 +584,31 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-static void pci_4v_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
+static void dma_4v_sync_single_for_cpu(struct device *dev,
+                                      dma_addr_t bus_addr, size_t sz,
+                                      enum dma_data_direction direction)
 {
        /* Nothing to do... */
 }
 
-static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static void dma_4v_sync_sg_for_cpu(struct device *dev,
+                                  struct scatterlist *sglist, int nelems,
+                                  enum dma_data_direction direction)
 {
        /* Nothing to do... */
 }
 
-const struct pci_iommu_ops pci_sun4v_iommu_ops = {
-       .alloc_consistent               = pci_4v_alloc_consistent,
-       .free_consistent                = pci_4v_free_consistent,
-       .map_single                     = pci_4v_map_single,
-       .unmap_single                   = pci_4v_unmap_single,
-       .map_sg                         = pci_4v_map_sg,
-       .unmap_sg                       = pci_4v_unmap_sg,
-       .dma_sync_single_for_cpu        = pci_4v_dma_sync_single_for_cpu,
-       .dma_sync_sg_for_cpu            = pci_4v_dma_sync_sg_for_cpu,
+const struct dma_ops sun4v_dma_ops = {
+       .alloc_coherent                 = dma_4v_alloc_coherent,
+       .free_coherent                  = dma_4v_free_coherent,
+       .map_single                     = dma_4v_map_single,
+       .unmap_single                   = dma_4v_unmap_single,
+       .map_sg                         = dma_4v_map_sg,
+       .unmap_sg                       = dma_4v_unmap_sg,
+       .sync_single_for_cpu            = dma_4v_sync_single_for_cpu,
+       .sync_sg_for_cpu                = dma_4v_sync_sg_for_cpu,
 };
 
-static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
-{
-       if (bus < pbm->pci_first_busno ||
-           bus > pbm->pci_last_busno)
-               return 1;
-       return 0;
-}
-
-static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-                                 int where, int size, u32 *value)
-{
-       struct pci_pbm_info *pbm = bus_dev->sysdata;
-       u32 devhandle = pbm->devhandle;
-       unsigned int bus = bus_dev->number;
-       unsigned int device = PCI_SLOT(devfn);
-       unsigned int func = PCI_FUNC(devfn);
-       unsigned long ret;
-
-       if (bus_dev == pbm->pci_bus && devfn == 0x00)
-               return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
-                                                   size, value);
-       if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
-               ret = ~0UL;
-       } else {
-               ret = pci_sun4v_config_get(devhandle,
-                               HV_PCI_DEVICE_BUILD(bus, device, func),
-                               where, size);
-#if 0
-               printk("rcfg: [%x:%x:%x:%d]=[%lx]\n",
-                      devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
-                      where, size, ret);
-#endif
-       }
-       switch (size) {
-       case 1:
-               *value = ret & 0xff;
-               break;
-       case 2:
-               *value = ret & 0xffff;
-               break;
-       case 4:
-               *value = ret & 0xffffffff;
-               break;
-       };
-
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-                                  int where, int size, u32 value)
-{
-       struct pci_pbm_info *pbm = bus_dev->sysdata;
-       u32 devhandle = pbm->devhandle;
-       unsigned int bus = bus_dev->number;
-       unsigned int device = PCI_SLOT(devfn);
-       unsigned int func = PCI_FUNC(devfn);
-       unsigned long ret;
-
-       if (bus_dev == pbm->pci_bus && devfn == 0x00)
-               return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
-                                                    size, value);
-       if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
-               /* Do nothing. */
-       } else {
-               ret = pci_sun4v_config_put(devhandle,
-                               HV_PCI_DEVICE_BUILD(bus, device, func),
-                               where, size, value);
-#if 0
-               printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n",
-                      devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
-                      where, size, value, ret);
-#endif
-       }
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_sun4v_ops = {
-       .read =         pci_sun4v_read_pci_cfg,
-       .write =        pci_sun4v_write_pci_cfg,
-};
-
-
 static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
 {
        struct property *prop;
@@ -722,9 +654,8 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 {
        struct iommu *iommu = pbm->iommu;
        struct property *prop;
-       unsigned long num_tsb_entries, sz;
+       unsigned long num_tsb_entries, sz, tsbsize;
        u32 vdma[2], dma_mask, dma_offset;
-       int tsbsize;
 
        prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
        if (prop) {
@@ -738,31 +669,15 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
                vdma[1] = 0x80000000;
        }
 
-       dma_mask = vdma[0];
-       switch (vdma[1]) {
-               case 0x20000000:
-                       dma_mask |= 0x1fffffff;
-                       tsbsize = 64;
-                       break;
-
-               case 0x40000000:
-                       dma_mask |= 0x3fffffff;
-                       tsbsize = 128;
-                       break;
-
-               case 0x80000000:
-                       dma_mask |= 0x7fffffff;
-                       tsbsize = 256;
-                       break;
-
-               default:
-                       prom_printf("PCI-SUN4V: strange virtual-dma size.\n");
-                       prom_halt();
+       if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) {
+               prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n",
+                           vdma[0], vdma[1]);
+               prom_halt();
        };
 
-       tsbsize *= (8 * 1024);
-
-       num_tsb_entries = tsbsize / sizeof(iopte_t);
+       dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
+       num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
+       tsbsize = num_tsb_entries * sizeof(iopte_t);
 
        dma_offset = vdma[0];
 
@@ -773,7 +688,7 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
        iommu->dma_addr_mask = dma_mask;
 
        /* Allocate and initialize the free area map.  */
-       sz = num_tsb_entries / 8;
+       sz = (num_tsb_entries + 7) / 8;
        sz = (sz + 7UL) & ~7UL;
        iommu->arena.map = kzalloc(sz, GFP_KERNEL);
        if (!iommu->arena.map) {
@@ -815,7 +730,7 @@ struct pci_sun4v_msiq_entry {
 
        u64             msi_address;
 
-       /* The format of this value is message type dependant.
+       /* The format of this value is message type dependent.
         * For MSI bits 15:0 are the data from the MSI packet.
         * For MSI-X bits 31:0 are the data from the MSI packet.
         * For MSG, the message code and message routing code where:
@@ -1025,13 +940,13 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
        if (msi_num < 0)
                return msi_num;
 
-       devino = sun4v_build_msi(pbm->devhandle, virt_irq_p,
-                                pbm->msiq_first_devino,
-                                (pbm->msiq_first_devino +
-                                 pbm->msiq_num));
-       err = -ENOMEM;
-       if (!devino)
+       err = sun4v_build_msi(pbm->devhandle, virt_irq_p,
+                             pbm->msiq_first_devino,
+                             (pbm->msiq_first_devino +
+                              pbm->msiq_num));
+       if (err < 0)
                goto out_err;
+       devino = err;
 
        msiqid = ((devino - pbm->msiq_first_devino) +
                  pbm->msiq_first);
@@ -1056,7 +971,7 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
        if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID))
                goto out_err;
 
-       pdev->dev.archdata.msi_num = msi_num;
+       sparc64_set_msi(*virt_irq_p, msi_num);
 
        if (entry->msi_attrib.is_64) {
                msg.address_hi = pbm->msi64_start >> 32;
@@ -1078,8 +993,6 @@ static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p,
 
 out_err:
        free_msi(pbm, msi_num);
-       sun4v_destroy_msi(*virt_irq_p);
-       *virt_irq_p = 0;
        return err;
 
 }
@@ -1091,7 +1004,7 @@ static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq,
        unsigned long msiqid, err;
        unsigned int msi_num;
 
-       msi_num = pdev->dev.archdata.msi_num;
+       msi_num = sparc64_get_msi(virt_irq);
        err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid);
        if (err) {
                printk(KERN_ERR "%s: getmsiq gives error %lu\n",
@@ -1226,7 +1139,7 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm)
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
-static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
+static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
 {
        struct pci_pbm_info *pbm;
 
@@ -1239,7 +1152,8 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
        pci_pbm_root = pbm;
 
        pbm->scan_bus = pci_sun4v_scan_bus;
-       pbm->pci_ops = &pci_sun4v_ops;
+       pbm->pci_ops = &sun4v_pci_ops;
+       pbm->config_space_reg_bits = 12;
 
        pbm->index = pci_num_pbms++;
 
@@ -1259,8 +1173,9 @@ static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node
        pci_sun4v_msi_init(pbm);
 }
 
-void sun4v_pci_init(struct device_node *dp, char *model_name)
+void __init sun4v_pci_init(struct device_node *dp, char *model_name)
 {
+       static int hvapi_negotiated = 0;
        struct pci_controller_info *p;
        struct pci_pbm_info *pbm;
        struct iommu *iommu;
@@ -1269,6 +1184,22 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
        u32 devhandle;
        int i;
 
+       if (!hvapi_negotiated++) {
+               int err = sun4v_hvapi_register(HV_GRP_PCI,
+                                              vpci_major,
+                                              &vpci_minor);
+
+               if (err) {
+                       prom_printf("SUN4V_PCI: Could not register hvapi, "
+                                   "err=%d\n", err);
+                       prom_halt();
+               }
+               printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n",
+                      vpci_major, vpci_minor);
+
+               dma_ops = &sun4v_dma_ops;
+       }
+
        prop = of_find_property(dp, "reg", NULL);
        regs = prop->value;
 
@@ -1287,7 +1218,7 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
                if (!page)
                        goto fatal_memory_error;
 
-               per_cpu(pci_iommu_batch, i).pglist = (u64 *) page;
+               per_cpu(iommu_batch, i).pglist = (u64 *) page;
        }
 
        p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);