Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / arch / sparc64 / kernel / pci_iommu.c
index 82e5455134c67719c9cafbdf7dc107a187c56302..dfd6f9f4790b852035a5143f77559163d7e587ad 100644 (file)
@@ -1,7 +1,6 @@
-/* $Id: pci_iommu.c,v 1.17 2001/12/17 07:05:09 davem Exp $
- * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
+/* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
  *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
  */
 
@@ -9,10 +8,12 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/pci.h>
 
-#include <asm/pbm.h>
+#include <asm/oplib.h>
 
 #include "iommu_common.h"
+#include "pci_impl.h"
 
 #define PCI_STC_CTXMATCH_ADDR(STC, CTX)        \
        ((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
                               "i" (ASI_PHYS_BYPASS_EC_E))
 
 /* Must be invoked under the IOMMU lock. */
-static void __iommu_flushall(struct pci_iommu *iommu)
+static void __iommu_flushall(struct iommu *iommu)
 {
-       unsigned long tag;
-       int entry;
+       if (iommu->iommu_flushinv) {
+               pci_iommu_write(iommu->iommu_flushinv, ~(u64)0);
+       } else {
+               unsigned long tag;
+               int entry;
 
-       tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
-       for (entry = 0; entry < 16; entry++) {
-               pci_iommu_write(tag, 0);
-               tag += 8;
-       }
+               tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
+               for (entry = 0; entry < 16; entry++) {
+                       pci_iommu_write(tag, 0);
+                       tag += 8;
+               }
 
-       /* Ensure completion of previous PIO writes. */
-       (void) pci_iommu_read(iommu->write_complete_reg);
+               /* Ensure completion of previous PIO writes. */
+               (void) pci_iommu_read(iommu->write_complete_reg);
+       }
 }
 
 #define IOPTE_CONSISTENT(CTX) \
@@ -64,7 +69,7 @@ static void __iommu_flushall(struct pci_iommu *iommu)
 #define IOPTE_IS_DUMMY(iommu, iopte)   \
        ((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa)
 
-static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
+static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
 {
        unsigned long val = iopte_val(*iopte);
 
@@ -75,9 +80,9 @@ static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
 }
 
 /* Based largely upon the ppc64 iommu allocator.  */
-static long pci_arena_alloc(struct pci_iommu *iommu, unsigned long npages)
+static long pci_arena_alloc(struct iommu *iommu, unsigned long npages)
 {
-       struct pci_iommu_arena *arena = &iommu->arena;
+       struct iommu_arena *arena = &iommu->arena;
        unsigned long n, i, start, end, limit;
        int pass;
 
@@ -116,7 +121,7 @@ again:
        return n;
 }
 
-static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, unsigned long npages)
+static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
 {
        unsigned long i;
 
@@ -124,7 +129,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un
                __clear_bit(i, arena->map);
 }
 
-void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask)
+void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask)
 {
        unsigned long i, tsbbase, order, sz, num_tsb_entries;
 
@@ -170,7 +175,7 @@ void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize, u32 dma_offset,
                iopte_make_dummy(iommu, &iommu->page_table[i]);
 }
 
-static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npages)
+static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
 {
        long entry;
 
@@ -181,12 +186,12 @@ static inline iopte_t *alloc_npages(struct pci_iommu *iommu, unsigned long npage
        return iommu->page_table + entry;
 }
 
-static inline void free_npages(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages)
+static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
 {
        pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
 }
 
-static int iommu_alloc_ctx(struct pci_iommu *iommu)
+static int iommu_alloc_ctx(struct iommu *iommu)
 {
        int lowest = iommu->ctx_lowest_free;
        int sz = IOMMU_NUM_CTXS - lowest;
@@ -205,7 +210,7 @@ static int iommu_alloc_ctx(struct pci_iommu *iommu)
        return n;
 }
 
-static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
+static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
 {
        if (likely(ctx)) {
                __clear_bit(ctx, iommu->ctx_bitmap);
@@ -220,8 +225,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
  */
 static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
+       struct iommu *iommu;
        iopte_t *iopte;
        unsigned long flags, order, first_page;
        void *ret;
@@ -237,8 +241,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
                return NULL;
        memset((char *)first_page, 0, PAGE_SIZE << order);
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
+       iommu = pdev->dev.archdata.iommu;
 
        spin_lock_irqsave(&iommu->lock, flags);
        iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
@@ -268,20 +271,18 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 /* Free and unmap a consistent DMA translation. */
 static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
+       struct iommu *iommu;
        iopte_t *iopte;
        unsigned long flags, order, npages;
 
        npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
+       iommu = pdev->dev.archdata.iommu;
        iopte = iommu->page_table +
                ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       free_npages(iommu, dvma, npages);
+       free_npages(iommu, dvma - iommu->page_table_map_base, npages);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -295,18 +296,16 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
  */
 static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
-       struct pci_strbuf *strbuf;
+       struct iommu *iommu;
+       struct strbuf *strbuf;
        iopte_t *base;
        unsigned long flags, npages, oaddr;
        unsigned long i, base_paddr, ctx;
        u32 bus_addr, ret;
        unsigned long iopte_protection;
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
-       strbuf = &pcp->pbm->stc;
+       iommu = pdev->dev.archdata.iommu;
+       strbuf = pdev->dev.archdata.stc;
 
        if (unlikely(direction == PCI_DMA_NONE))
                goto bad_no_ctx;
@@ -349,7 +348,7 @@ bad_no_ctx:
        return PCI_DMA_ERROR_CODE;
 }
 
-static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
+static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
 {
        int limit;
 
@@ -416,9 +415,8 @@ do_flush_sync:
 /* Unmap a single streaming mode DMA translation. */
 static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
-       struct pci_strbuf *strbuf;
+       struct iommu *iommu;
+       struct strbuf *strbuf;
        iopte_t *base;
        unsigned long flags, npages, ctx, i;
 
@@ -428,9 +426,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
                return;
        }
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
-       strbuf = &pcp->pbm->stc;
+       iommu = pdev->dev.archdata.iommu;
+       strbuf = pdev->dev.archdata.stc;
 
        npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
        npages >>= IO_PAGE_SHIFT;
@@ -549,9 +546,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
  */
 static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
-       struct pci_strbuf *strbuf;
+       struct iommu *iommu;
+       struct strbuf *strbuf;
        unsigned long flags, ctx, npages, iopte_protection;
        iopte_t *base;
        u32 dma_base;
@@ -570,9 +566,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
                return 1;
        }
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
-       strbuf = &pcp->pbm->stc;
+       iommu = pdev->dev.archdata.iommu;
+       strbuf = pdev->dev.archdata.stc;
        
        if (unlikely(direction == PCI_DMA_NONE))
                goto bad_no_ctx;
@@ -636,9 +631,8 @@ bad_no_ctx:
 /* Unmap a set of streaming mode DMA translations. */
 static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
-       struct pci_strbuf *strbuf;
+       struct iommu *iommu;
+       struct strbuf *strbuf;
        iopte_t *base;
        unsigned long flags, ctx, i, npages;
        u32 bus_addr;
@@ -648,9 +642,8 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
                        WARN_ON(1);
        }
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
-       strbuf = &pcp->pbm->stc;
+       iommu = pdev->dev.archdata.iommu;
+       strbuf = pdev->dev.archdata.stc;
        
        bus_addr = sglist->dma_address & IO_PAGE_MASK;
 
@@ -696,14 +689,12 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
  */
 static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
-       struct pci_strbuf *strbuf;
+       struct iommu *iommu;
+       struct strbuf *strbuf;
        unsigned long flags, ctx, npages;
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
-       strbuf = &pcp->pbm->stc;
+       iommu = pdev->dev.archdata.iommu;
+       strbuf = pdev->dev.archdata.stc;
 
        if (!strbuf->strbuf_enabled)
                return;
@@ -736,15 +727,13 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_
  */
 static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
 {
-       struct pcidev_cookie *pcp;
-       struct pci_iommu *iommu;
-       struct pci_strbuf *strbuf;
+       struct iommu *iommu;
+       struct strbuf *strbuf;
        unsigned long flags, ctx, npages, i;
        u32 bus_addr;
 
-       pcp = pdev->sysdata;
-       iommu = pcp->pbm->iommu;
-       strbuf = &pcp->pbm->stc;
+       iommu = pdev->dev.archdata.iommu;
+       strbuf = pdev->dev.archdata.stc;
 
        if (!strbuf->strbuf_enabled)
                return;
@@ -775,7 +764,7 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-struct pci_iommu_ops pci_sun4u_iommu_ops = {
+const struct pci_iommu_ops pci_sun4u_iommu_ops = {
        .alloc_consistent               = pci_4u_alloc_consistent,
        .free_consistent                = pci_4u_free_consistent,
        .map_single                     = pci_4u_map_single,
@@ -809,13 +798,12 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
 
 int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
 {
-       struct pcidev_cookie *pcp = pdev->sysdata;
        u64 dma_addr_mask;
 
        if (pdev == NULL) {
                dma_addr_mask = 0xffffffff;
        } else {
-               struct pci_iommu *iommu = pcp->pbm->iommu;
+               struct iommu *iommu = pdev->dev.archdata.iommu;
 
                dma_addr_mask = iommu->dma_addr_mask;