diff options
Diffstat (limited to 'arch/sparc64/kernel/pci_sun4v.c')
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index ddca6c6c0b49..01839706bd52 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -335,8 +335,10 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, | |||
335 | unsigned long flags, handle, prot; | 335 | unsigned long flags, handle, prot; |
336 | dma_addr_t dma_next = 0, dma_addr; | 336 | dma_addr_t dma_next = 0, dma_addr; |
337 | unsigned int max_seg_size; | 337 | unsigned int max_seg_size; |
338 | unsigned long seg_boundary_size; | ||
338 | int outcount, incount, i; | 339 | int outcount, incount, i; |
339 | struct iommu *iommu; | 340 | struct iommu *iommu; |
341 | unsigned long base_shift; | ||
340 | long err; | 342 | long err; |
341 | 343 | ||
342 | BUG_ON(direction == DMA_NONE); | 344 | BUG_ON(direction == DMA_NONE); |
@@ -362,8 +364,11 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, | |||
362 | iommu_batch_start(dev, prot, ~0UL); | 364 | iommu_batch_start(dev, prot, ~0UL); |
363 | 365 | ||
364 | max_seg_size = dma_get_max_seg_size(dev); | 366 | max_seg_size = dma_get_max_seg_size(dev); |
367 | seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, | ||
368 | IO_PAGE_SIZE) >> IO_PAGE_SHIFT; | ||
369 | base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT; | ||
365 | for_each_sg(sglist, s, nelems, i) { | 370 | for_each_sg(sglist, s, nelems, i) { |
366 | unsigned long paddr, npages, entry, slen; | 371 | unsigned long paddr, npages, entry, out_entry = 0, slen; |
367 | 372 | ||
368 | slen = s->length; | 373 | slen = s->length; |
369 | /* Sanity check */ | 374 | /* Sanity check */ |
@@ -406,7 +411,9 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, | |||
406 | * - allocated dma_addr isn't contiguous to previous allocation | 411 | * - allocated dma_addr isn't contiguous to previous allocation |
407 | */ | 412 | */ |
408 | if ((dma_addr != dma_next) || | 413 | if ((dma_addr != dma_next) || |
409 | (outs->dma_length + s->length > max_seg_size)) { | 414 | (outs->dma_length + s->length > max_seg_size) || |
415 | (is_span_boundary(out_entry, base_shift, | ||
416 | seg_boundary_size, outs, s))) { | ||
410 | /* Can't merge: create a new segment */ | 417 | /* Can't merge: create a new segment */ |
411 | segstart = s; | 418 | segstart = s; |
412 | outcount++; | 419 | outcount++; |
@@ -420,6 +427,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, | |||
420 | /* This is a new segment, fill entries */ | 427 | /* This is a new segment, fill entries */ |
421 | outs->dma_address = dma_addr; | 428 | outs->dma_address = dma_addr; |
422 | outs->dma_length = slen; | 429 | outs->dma_length = slen; |
430 | out_entry = entry; | ||
423 | } | 431 | } |
424 | 432 | ||
425 | /* Calculate next page pointer for contiguous check */ | 433 | /* Calculate next page pointer for contiguous check */ |