Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 2 Apr 2008 14:46:41 +0000 (07:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 2 Apr 2008 14:46:41 +0000 (07:46 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sparc64: remove unused calc_npages() in iommu_common.h
  sparc64: add the segment boundary checking to IOMMUs while merging SG entries
  [SPARC64]: Don't open-code {get,put}_cpu_var() in flush_tlb_pending().

arch/sparc64/kernel/iommu.c
arch/sparc64/kernel/iommu_common.h
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/mm/tlb.c

index b781d3d54fb8f7ac7c69c358d69abcedb6cab199..756fa24eeefa18ae72da4a4825e8ba7f143cf682 100644 (file)
@@ -516,9 +516,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
        unsigned long flags, handle, prot, ctx;
        dma_addr_t dma_next = 0, dma_addr;
        unsigned int max_seg_size;
+       unsigned long seg_boundary_size;
        int outcount, incount, i;
        struct strbuf *strbuf;
        struct iommu *iommu;
+       unsigned long base_shift;
 
        BUG_ON(direction == DMA_NONE);
 
@@ -549,8 +551,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
        outs->dma_length = 0;
 
        max_seg_size = dma_get_max_seg_size(dev);
+       seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+                                 IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
+       base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT;
        for_each_sg(sglist, s, nelems, i) {
-               unsigned long paddr, npages, entry, slen;
+               unsigned long paddr, npages, entry, out_entry = 0, slen;
                iopte_t *base;
 
                slen = s->length;
@@ -593,7 +598,9 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
                         * - allocated dma_addr isn't contiguous to previous allocation
                         */
                        if ((dma_addr != dma_next) ||
-                           (outs->dma_length + s->length > max_seg_size)) {
+                           (outs->dma_length + s->length > max_seg_size) ||
+                           (is_span_boundary(out_entry, base_shift,
+                                             seg_boundary_size, outs, s))) {
                                /* Can't merge: create a new segment */
                                segstart = s;
                                outcount++;
@@ -607,6 +614,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
                        /* This is a new segment, fill entries */
                        outs->dma_address = dma_addr;
                        outs->dma_length = slen;
+                       out_entry = entry;
                }
 
                /* Calculate next page pointer for contiguous check */
index 0713bd58499c1de49d2650877c60f59437b66fd3..f3575a614fa2e643dbcc5f93e3e2e03f26e77e2e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 #include <linux/device.h>
+#include <linux/iommu-helper.h>
 
 #include <asm/iommu.h>
 #include <asm/scatterlist.h>
@@ -45,17 +46,16 @@ static inline unsigned long iommu_num_pages(unsigned long vaddr,
        return npages;
 }
 
-static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
+static inline int is_span_boundary(unsigned long entry,
+                                  unsigned long shift,
+                                  unsigned long boundary_size,
+                                  struct scatterlist *outs,
+                                  struct scatterlist *sg)
 {
-       unsigned long i, npages = 0;
-       struct scatterlist *sg;
+       unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs);
+       int nr = iommu_num_pages(paddr, outs->dma_length + sg->length);
 
-       for_each_sg(sglist, sg, nelems, i) {
-               unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
-               npages += iommu_num_pages(paddr, sg->length);
-       }
-
-       return npages;
+       return iommu_is_span_boundary(entry, nr, shift, boundary_size);
 }
 
 extern unsigned long iommu_range_alloc(struct device *dev,
index ddca6c6c0b492709193e1a3c8a86dcb30f884fbf..01839706bd520b17c73a548d5225e3b1cc238720 100644 (file)
@@ -335,8 +335,10 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
        unsigned long flags, handle, prot;
        dma_addr_t dma_next = 0, dma_addr;
        unsigned int max_seg_size;
+       unsigned long seg_boundary_size;
        int outcount, incount, i;
        struct iommu *iommu;
+       unsigned long base_shift;
        long err;
 
        BUG_ON(direction == DMA_NONE);
@@ -362,8 +364,11 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
        iommu_batch_start(dev, prot, ~0UL);
 
        max_seg_size = dma_get_max_seg_size(dev);
+       seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+                                 IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
+       base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT;
        for_each_sg(sglist, s, nelems, i) {
-               unsigned long paddr, npages, entry, slen;
+               unsigned long paddr, npages, entry, out_entry = 0, slen;
 
                slen = s->length;
                /* Sanity check */
@@ -406,7 +411,9 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
                         * - allocated dma_addr isn't contiguous to previous allocation
                         */
                        if ((dma_addr != dma_next) ||
-                           (outs->dma_length + s->length > max_seg_size)) {
+                           (outs->dma_length + s->length > max_seg_size) ||
+                           (is_span_boundary(out_entry, base_shift,
+                                             seg_boundary_size, outs, s))) {
                                /* Can't merge: create a new segment */
                                segstart = s;
                                outcount++;
@@ -420,6 +427,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
                        /* This is a new segment, fill entries */
                        outs->dma_address = dma_addr;
                        outs->dma_length = slen;
+                       out_entry = entry;
                }
 
                /* Calculate next page pointer for contiguous check */
index a0f000b293de6ab3c26f2267ee8d7d40c0fe1d6f..ae24919cba7cf8bef8a0ad4f8455f5c871e3920f 100644 (file)
@@ -23,11 +23,8 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, };
 
 void flush_tlb_pending(void)
 {
-       struct mmu_gather *mp;
+       struct mmu_gather *mp = &get_cpu_var(mmu_gathers);
 
-       preempt_disable();
-
-       mp = &__get_cpu_var(mmu_gathers);
        if (mp->tlb_nr) {
                flush_tsb_user(mp);
 
@@ -43,7 +40,7 @@ void flush_tlb_pending(void)
                mp->tlb_nr = 0;
        }
 
-       preempt_enable();
+       put_cpu_var(mmu_gathers);
 }
 
 void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig)