Skip to content

Commit

Permalink
iommu sg merging: sparc64: 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: "David S. Miller" <davem@davemloft.net>
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 7c53664 commit fde6a3c
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 5 deletions.
2 changes: 1 addition & 1 deletion arch/sparc64/kernel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,

/* Step 1: Prepare scatter list. */

npages = prepare_sg(sglist, nelems);
npages = prepare_sg(dev, sglist, nelems);

/* Step 2: Allocate a cluster and context, if necessary. */

Expand Down
8 changes: 6 additions & 2 deletions arch/sparc64/kernel/iommu_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/

#include <linux/dma-mapping.h>
#include "iommu_common.h"

/* You are _strongly_ advised to enable the following debugging code
Expand Down Expand Up @@ -201,21 +202,24 @@ void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int np
}
#endif

unsigned long prepare_sg(struct scatterlist *sg, int nents)
unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
{
struct scatterlist *dma_sg = sg;
unsigned long prev;
u32 dent_addr, dent_len;
unsigned int max_seg_size;

prev = (unsigned long) sg_virt(sg);
prev += (unsigned long) (dent_len = sg->length);
dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
max_seg_size = dma_get_max_seg_size(dev);
while (--nents) {
unsigned long addr;

sg = sg_next(sg);
addr = (unsigned long) sg_virt(sg);
if (! VCONTIG(prev, addr)) {
if (! VCONTIG(prev, addr) ||
dent_len + sg->length > max_seg_size) {
dma_sg->dma_address = dent_addr;
dma_sg->dma_length = dent_len;
dma_sg = sg_next(dma_sg);
Expand Down
3 changes: 2 additions & 1 deletion arch/sparc64/kernel/iommu_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/device.h>

#include <asm/iommu.h>
#include <asm/scatterlist.h>
Expand Down Expand Up @@ -46,4 +47,4 @@ extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int
#define VCONTIG(__X, __Y) (((__X) == (__Y)) || \
(((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)

extern unsigned long prepare_sg(struct scatterlist *sg, int nents);
extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents);
2 changes: 1 addition & 1 deletion arch/sparc64/kernel/pci_sun4v.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
goto bad;

/* Step 1: Prepare scatter list. */
npages = prepare_sg(sglist, nelems);
npages = prepare_sg(dev, sglist, nelems);

/* Step 2: Allocate a cluster and context, if necessary. */
spin_lock_irqsave(&iommu->lock, flags);
Expand Down

0 comments on commit fde6a3c

Please sign in to comment.