aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/iommu.c')
-rw-r--r--arch/sparc64/kernel/iommu.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index fbaab3497bfd..756fa24eeefa 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -516,9 +516,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
516 unsigned long flags, handle, prot, ctx; 516 unsigned long flags, handle, prot, ctx;
517 dma_addr_t dma_next = 0, dma_addr; 517 dma_addr_t dma_next = 0, dma_addr;
518 unsigned int max_seg_size; 518 unsigned int max_seg_size;
519 unsigned long seg_boundary_size;
519 int outcount, incount, i; 520 int outcount, incount, i;
520 struct strbuf *strbuf; 521 struct strbuf *strbuf;
521 struct iommu *iommu; 522 struct iommu *iommu;
523 unsigned long base_shift;
522 524
523 BUG_ON(direction == DMA_NONE); 525 BUG_ON(direction == DMA_NONE);
524 526
@@ -549,8 +551,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
549 outs->dma_length = 0; 551 outs->dma_length = 0;
550 552
551 max_seg_size = dma_get_max_seg_size(dev); 553 max_seg_size = dma_get_max_seg_size(dev);
554 seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
555 IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
556 base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT;
552 for_each_sg(sglist, s, nelems, i) { 557 for_each_sg(sglist, s, nelems, i) {
553 unsigned long paddr, npages, entry, slen; 558 unsigned long paddr, npages, entry, out_entry = 0, slen;
554 iopte_t *base; 559 iopte_t *base;
555 560
556 slen = s->length; 561 slen = s->length;
@@ -593,7 +598,9 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
593 * - allocated dma_addr isn't contiguous to previous allocation 598 * - allocated dma_addr isn't contiguous to previous allocation
594 */ 599 */
595 if ((dma_addr != dma_next) || 600 if ((dma_addr != dma_next) ||
596 (outs->dma_length + s->length > max_seg_size)) { 601 (outs->dma_length + s->length > max_seg_size) ||
602 (is_span_boundary(out_entry, base_shift,
603 seg_boundary_size, outs, s))) {
597 /* Can't merge: create a new segment */ 604 /* Can't merge: create a new segment */
598 segstart = s; 605 segstart = s;
599 outcount++; 606 outcount++;
@@ -607,6 +614,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
607 /* This is a new segment, fill entries */ 614 /* This is a new segment, fill entries */
608 outs->dma_address = dma_addr; 615 outs->dma_address = dma_addr;
609 outs->dma_length = slen; 616 outs->dma_length = slen;
617 out_entry = entry;
610 } 618 }
611 619
612 /* Calculate next page pointer for contiguous check */ 620 /* Calculate next page pointer for contiguous check */
@@ -626,7 +634,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
626iommu_map_failed: 634iommu_map_failed:
627 for_each_sg(sglist, s, nelems, i) { 635 for_each_sg(sglist, s, nelems, i) {
628 if (s->dma_length != 0) { 636 if (s->dma_length != 0) {
629 unsigned long vaddr, npages, entry, i; 637 unsigned long vaddr, npages, entry, j;
630 iopte_t *base; 638 iopte_t *base;
631 639
632 vaddr = s->dma_address & IO_PAGE_MASK; 640 vaddr = s->dma_address & IO_PAGE_MASK;
@@ -637,8 +645,8 @@ iommu_map_failed:
637 >> IO_PAGE_SHIFT; 645 >> IO_PAGE_SHIFT;
638 base = iommu->page_table + entry; 646 base = iommu->page_table + entry;
639 647
640 for (i = 0; i < npages; i++) 648 for (j = 0; j < npages; j++)
641 iopte_make_dummy(iommu, base + i); 649 iopte_make_dummy(iommu, base + j);
642 650
643 s->dma_address = DMA_ERROR_CODE; 651 s->dma_address = DMA_ERROR_CODE;
644 s->dma_length = 0; 652 s->dma_length = 0;
@@ -803,7 +811,7 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
803 spin_unlock_irqrestore(&iommu->lock, flags); 811 spin_unlock_irqrestore(&iommu->lock, flags);
804} 812}
805 813
806const struct dma_ops sun4u_dma_ops = { 814static const struct dma_ops sun4u_dma_ops = {
807 .alloc_coherent = dma_4u_alloc_coherent, 815 .alloc_coherent = dma_4u_alloc_coherent,
808 .free_coherent = dma_4u_free_coherent, 816 .free_coherent = dma_4u_free_coherent,
809 .map_single = dma_4u_map_single, 817 .map_single = dma_4u_map_single,