Skip to content

Commit

Permalink
iommu sg merging: ppc: make iommu respect the segment size limits
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
FUJITA Tomonori authored and Linus Torvalds committed Feb 5, 2008
1 parent 42d0028 commit 740c3ce
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 4 deletions.
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/dma_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
8 changes: 6 additions & 2 deletions arch/powerpc/kernel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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;

Expand Down Expand Up @@ -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++;
Expand Down
2 changes: 1 addition & 1 deletion include/asm-powerpc/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 740c3ce

Please sign in to comment.