aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <tomof@acm.org>2008-02-05 01:27:56 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:10 -0500
commit42d00284e16bf998f8f93ce5d061df81b0ff283e (patch)
tree1318ceca16b25b16080040f3639da885cf3135ac
parent4d57cdfacaa1c207bf4c071f89835e0368766a50 (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.c7
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;