aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/iommu.c
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-03-28 18:55:41 -0400
committerDavid S. Miller <davem@davemloft.net>2008-03-28 18:55:41 -0400
commitf08802572965873af97e74337d5740bfa2542941 (patch)
treea28f31926b4f548d662cea2d6b2b1882b0214e24 /arch/sparc64/kernel/iommu.c
parent76cc86ee6b3c261b96ea3ee2f4c6dfd127335881 (diff)
sparc64: add the segment boundary checking to IOMMUs while merging SG entries
Some IOMMUs allocate memory areas spanning LLD's segment boundary limit. It forces low level drivers to have a workaround to adjust scatter lists that the IOMMU builds. We are in the process of making all the IOMMUs respect the segment boundary limits to remove such work around in LLDs. SPARC64 IOMMUs were rewritten to use the IOMMU helper functions and the commit 89c94f2f70d093f59b55d3ea8042d13889169346 made the IOMMUs not allocate memory areas spanning the segment boundary limit. However, SPARC64 IOMMUs allocate memory areas first then try to merge them (while some IOMMUs walk through all the sg entries to see how they can be merged first and allocate memory areas). So SPARC64 IOMMUs also need the boundary limit checking when they try to merge sg entries. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/iommu.c')
-rw-r--r--arch/sparc64/kernel/iommu.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index b781d3d54fb8..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 */