diff options
author | FUJITA Tomonori <tomof@acm.org> | 2008-02-05 01:27:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-05 12:44:10 -0500 |
commit | 42d00284e16bf998f8f93ce5d061df81b0ff283e (patch) | |
tree | 1318ceca16b25b16080040f3639da885cf3135ac | |
parent | 4d57cdfacaa1c207bf4c071f89835e0368766a50 (diff) |
iommu sg merging: x86: make pci-gart iommu respect the segment size limits
This patch makes pci-gart 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: Dave Airlie <airlied@linux.ie>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 845cbecd68e9..5ee700f0844d 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -416,6 +416,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) | |||
416 | struct scatterlist *s, *ps, *start_sg, *sgmap; | 416 | struct scatterlist *s, *ps, *start_sg, *sgmap; |
417 | int need = 0, nextneed, i, out, start; | 417 | int need = 0, nextneed, i, out, start; |
418 | unsigned long pages = 0; | 418 | unsigned long pages = 0; |
419 | unsigned int seg_size; | ||
420 | unsigned int max_seg_size; | ||
419 | 421 | ||
420 | if (nents == 0) | 422 | if (nents == 0) |
421 | return 0; | 423 | return 0; |
@@ -426,6 +428,8 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) | |||
426 | out = 0; | 428 | out = 0; |
427 | start = 0; | 429 | start = 0; |
428 | start_sg = sgmap = sg; | 430 | start_sg = sgmap = sg; |
431 | seg_size = 0; | ||
432 | max_seg_size = dma_get_max_seg_size(dev); | ||
429 | ps = NULL; /* shut up gcc */ | 433 | ps = NULL; /* shut up gcc */ |
430 | for_each_sg(sg, s, nents, i) { | 434 | for_each_sg(sg, s, nents, i) { |
431 | dma_addr_t addr = sg_phys(s); | 435 | dma_addr_t addr = sg_phys(s); |
@@ -443,11 +447,13 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) | |||
443 | * offset. | 447 | * offset. |
444 | */ | 448 | */ |
445 | if (!iommu_merge || !nextneed || !need || s->offset || | 449 | if (!iommu_merge || !nextneed || !need || s->offset || |
450 | (s->length + seg_size > max_seg_size) || | ||
446 | (ps->offset + ps->length) % PAGE_SIZE) { | 451 | (ps->offset + ps->length) % PAGE_SIZE) { |
447 | if (dma_map_cont(start_sg, i - start, sgmap, | 452 | if (dma_map_cont(start_sg, i - start, sgmap, |
448 | pages, need) < 0) | 453 | pages, need) < 0) |
449 | goto error; | 454 | goto error; |
450 | out++; | 455 | out++; |
456 | seg_size = 0; | ||
451 | sgmap = sg_next(sgmap); | 457 | sgmap = sg_next(sgmap); |
452 | pages = 0; | 458 | pages = 0; |
453 | start = i; | 459 | start = i; |
@@ -455,6 +461,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) | |||
455 | } | 461 | } |
456 | } | 462 | } |
457 | 463 | ||
464 | seg_size += s->length; | ||
458 | need = nextneed; | 465 | need = nextneed; |
459 | pages += to_pages(s->offset, s->length); | 466 | pages += to_pages(s->offset, s->length); |
460 | ps = s; | 467 | ps = s; |