|
@@ -270,16 +270,18 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
|
|
|
spin_unlock_irqrestore(&(tbl->it_lock), flags);
|
|
|
}
|
|
|
|
|
|
-int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
|
|
+int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
|
|
|
int nelems, unsigned long mask,
|
|
|
enum dma_data_direction direction)
|
|
|
{
|
|
|
+ struct iommu_table *tbl = dev->archdata.dma_data;
|
|
|
dma_addr_t dma_next = 0, dma_addr;
|
|
|
unsigned long flags;
|
|
|
struct scatterlist *s, *outs, *segstart;
|
|
|
int outcount, incount, i;
|
|
|
unsigned int align;
|
|
|
unsigned long handle;
|
|
|
+ unsigned int max_seg_size;
|
|
|
|
|
|
BUG_ON(direction == DMA_NONE);
|
|
|
|
|
@@ -298,6 +300,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
|
|
|
|
|
spin_lock_irqsave(&(tbl->it_lock), flags);
|
|
|
|
|
|
+ max_seg_size = dma_get_max_seg_size(dev);
|
|
|
for_each_sg(sglist, s, nelems, i) {
|
|
|
unsigned long vaddr, npages, entry, slen;
|
|
|
|
|
@@ -344,7 +347,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
|
|
/* We cannot merge if:
|
|
|
* - allocated dma_addr isn't contiguous to previous allocation
|
|
|
*/
|
|
|
- if (novmerge || (dma_addr != dma_next)) {
|
|
|
+ if (novmerge || (dma_addr != dma_next) ||
|
|
|
+ (outs->dma_length + s->length > max_seg_size)) {
|
|
|
/* Can't merge: create a new segment */
|
|
|
segstart = s;
|
|
|
outcount++;
|