forked from Minki/linux
iommu sg merging: ppc: make iommu respect the segment size limits
This patch makes iommu respect segment size limits when merging sg lists. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Jeff Garzik <jeff@garzik.org> Cc: James Bottomley <James.Bottomley@steeleye.com> Acked-by: Jens Axboe <jens.axboe@oracle.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
42d00284e1
commit
740c3ce667
@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
|
||||
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
|
||||
int nelems, enum dma_data_direction direction)
|
||||
{
|
||||
return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
|
||||
return iommu_map_sg(dev, sglist, nelems,
|
||||
device_to_mask(dev), direction);
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
@ -79,7 +79,7 @@ extern void iommu_free_table(struct iommu_table *tbl, const char *node_name);
|
||||
extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
|
||||
int nid);
|
||||
|
||||
extern int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
||||
extern int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
|
||||
int nelems, unsigned long mask,
|
||||
enum dma_data_direction direction);
|
||||
extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
|
||||
|
Loading…
Reference in New Issue
Block a user