diff options
Diffstat (limited to 'arch/sparc64/kernel/iommu.c')
-rw-r--r-- | arch/sparc64/kernel/iommu.c | 20 |
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, | |||
626 | iommu_map_failed: | 634 | iommu_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 | ||
806 | const struct dma_ops sun4u_dma_ops = { | 814 | static 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, |