|
@@ -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 */
|