aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 13:09:16 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 13:09:16 -0400
commit92d15c2ccbb3e31a3fc71ad28fdb55e1319383c0 (patch)
tree8d83c0dc3c6b935d8367e331872f242b742f0a8a /arch/x86
parentf20bf6125605acbbc7eb8c9420d7221c91aa83eb (diff)
parent644bd2f048972d75eb1979b1fdca257d528ce687 (diff)
Merge branch 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block
* 'for-linus' of git://git.kernel.dk/data/git/linux-2.6-block: (63 commits) Fix memory leak in dm-crypt SPARC64: sg chaining support SPARC: sg chaining support PPC: sg chaining support PS3: sg chaining support IA64: sg chaining support x86-64: enable sg chaining x86-64: update pci-gart iommu to sg helpers x86-64: update nommu to sg helpers x86-64: update calgary iommu to sg helpers swiotlb: sg chaining support i386: enable sg chaining i386 dma_map_sg: convert to using sg helpers mmc: need to zero sglist on init Panic in blk_rq_map_sg() from CCISS driver remove sglist_len remove blk_queue_max_phys_segments in libata revert sg segment size ifdefs Fixup u14-34f ENABLE_SG_CHAINING qla1280: enable use_sg_chaining option ...
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/pci-calgary_64.c24
-rw-r--r--arch/x86/kernel/pci-gart_64.c65
-rw-r--r--arch/x86/kernel/pci-nommu_64.c5
3 files changed, 52 insertions, 42 deletions
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 71da01e73f03..a50b787b3bfa 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -35,6 +35,7 @@
35#include <linux/pci_ids.h> 35#include <linux/pci_ids.h>
36#include <linux/pci.h> 36#include <linux/pci.h>
37#include <linux/delay.h> 37#include <linux/delay.h>
38#include <linux/scatterlist.h>
38#include <asm/iommu.h> 39#include <asm/iommu.h>
39#include <asm/calgary.h> 40#include <asm/calgary.h>
40#include <asm/tce.h> 41#include <asm/tce.h>
@@ -384,31 +385,32 @@ static void calgary_unmap_sg(struct device *dev,
384 struct scatterlist *sglist, int nelems, int direction) 385 struct scatterlist *sglist, int nelems, int direction)
385{ 386{
386 struct iommu_table *tbl = find_iommu_table(dev); 387 struct iommu_table *tbl = find_iommu_table(dev);
388 struct scatterlist *s;
389 int i;
387 390
388 if (!translate_phb(to_pci_dev(dev))) 391 if (!translate_phb(to_pci_dev(dev)))
389 return; 392 return;
390 393
391 while (nelems--) { 394 for_each_sg(sglist, s, nelems, i) {
392 unsigned int npages; 395 unsigned int npages;
393 dma_addr_t dma = sglist->dma_address; 396 dma_addr_t dma = s->dma_address;
394 unsigned int dmalen = sglist->dma_length; 397 unsigned int dmalen = s->dma_length;
395 398
396 if (dmalen == 0) 399 if (dmalen == 0)
397 break; 400 break;
398 401
399 npages = num_dma_pages(dma, dmalen); 402 npages = num_dma_pages(dma, dmalen);
400 iommu_free(tbl, dma, npages); 403 iommu_free(tbl, dma, npages);
401 sglist++;
402 } 404 }
403} 405}
404 406
405static int calgary_nontranslate_map_sg(struct device* dev, 407static int calgary_nontranslate_map_sg(struct device* dev,
406 struct scatterlist *sg, int nelems, int direction) 408 struct scatterlist *sg, int nelems, int direction)
407{ 409{
410 struct scatterlist *s;
408 int i; 411 int i;
409 412
410 for (i = 0; i < nelems; i++ ) { 413 for_each_sg(sg, s, nelems, i) {
411 struct scatterlist *s = &sg[i];
412 BUG_ON(!s->page); 414 BUG_ON(!s->page);
413 s->dma_address = virt_to_bus(page_address(s->page) +s->offset); 415 s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
414 s->dma_length = s->length; 416 s->dma_length = s->length;
@@ -420,6 +422,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
420 int nelems, int direction) 422 int nelems, int direction)
421{ 423{
422 struct iommu_table *tbl = find_iommu_table(dev); 424 struct iommu_table *tbl = find_iommu_table(dev);
425 struct scatterlist *s;
423 unsigned long vaddr; 426 unsigned long vaddr;
424 unsigned int npages; 427 unsigned int npages;
425 unsigned long entry; 428 unsigned long entry;
@@ -428,8 +431,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
428 if (!translate_phb(to_pci_dev(dev))) 431 if (!translate_phb(to_pci_dev(dev)))
429 return calgary_nontranslate_map_sg(dev, sg, nelems, direction); 432 return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
430 433
431 for (i = 0; i < nelems; i++ ) { 434 for_each_sg(sg, s, nelems, i) {
432 struct scatterlist *s = &sg[i];
433 BUG_ON(!s->page); 435 BUG_ON(!s->page);
434 436
435 vaddr = (unsigned long)page_address(s->page) + s->offset; 437 vaddr = (unsigned long)page_address(s->page) + s->offset;
@@ -454,9 +456,9 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
454 return nelems; 456 return nelems;
455error: 457error:
456 calgary_unmap_sg(dev, sg, nelems, direction); 458 calgary_unmap_sg(dev, sg, nelems, direction);
457 for (i = 0; i < nelems; i++) { 459 for_each_sg(sg, s, nelems, i) {
458 sg[i].dma_address = bad_dma_address; 460 sg->dma_address = bad_dma_address;
459 sg[i].dma_length = 0; 461 sg->dma_length = 0;
460 } 462 }
461 return 0; 463 return 0;
462} 464}
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 4918c575d582..cfcc84e6c350 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -23,6 +23,7 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/bitops.h> 24#include <linux/bitops.h>
25#include <linux/kdebug.h> 25#include <linux/kdebug.h>
26#include <linux/scatterlist.h>
26#include <asm/atomic.h> 27#include <asm/atomic.h>
27#include <asm/io.h> 28#include <asm/io.h>
28#include <asm/mtrr.h> 29#include <asm/mtrr.h>
@@ -278,10 +279,10 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
278 */ 279 */
279static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) 280static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
280{ 281{
282 struct scatterlist *s;
281 int i; 283 int i;
282 284
283 for (i = 0; i < nents; i++) { 285 for_each_sg(sg, s, nents, i) {
284 struct scatterlist *s = &sg[i];
285 if (!s->dma_length || !s->length) 286 if (!s->dma_length || !s->length)
286 break; 287 break;
287 gart_unmap_single(dev, s->dma_address, s->dma_length, dir); 288 gart_unmap_single(dev, s->dma_address, s->dma_length, dir);
@@ -292,14 +293,14 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
292static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, 293static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
293 int nents, int dir) 294 int nents, int dir)
294{ 295{
296 struct scatterlist *s;
295 int i; 297 int i;
296 298
297#ifdef CONFIG_IOMMU_DEBUG 299#ifdef CONFIG_IOMMU_DEBUG
298 printk(KERN_DEBUG "dma_map_sg overflow\n"); 300 printk(KERN_DEBUG "dma_map_sg overflow\n");
299#endif 301#endif
300 302
301 for (i = 0; i < nents; i++ ) { 303 for_each_sg(sg, s, nents, i) {
302 struct scatterlist *s = &sg[i];
303 unsigned long addr = page_to_phys(s->page) + s->offset; 304 unsigned long addr = page_to_phys(s->page) + s->offset;
304 if (nonforced_iommu(dev, addr, s->length)) { 305 if (nonforced_iommu(dev, addr, s->length)) {
305 addr = dma_map_area(dev, addr, s->length, dir); 306 addr = dma_map_area(dev, addr, s->length, dir);
@@ -319,23 +320,23 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
319} 320}
320 321
321/* Map multiple scatterlist entries continuous into the first. */ 322/* Map multiple scatterlist entries continuous into the first. */
322static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, 323static int __dma_map_cont(struct scatterlist *start, int nelems,
323 struct scatterlist *sout, unsigned long pages) 324 struct scatterlist *sout, unsigned long pages)
324{ 325{
325 unsigned long iommu_start = alloc_iommu(pages); 326 unsigned long iommu_start = alloc_iommu(pages);
326 unsigned long iommu_page = iommu_start; 327 unsigned long iommu_page = iommu_start;
328 struct scatterlist *s;
327 int i; 329 int i;
328 330
329 if (iommu_start == -1) 331 if (iommu_start == -1)
330 return -1; 332 return -1;
331 333
332 for (i = start; i < stopat; i++) { 334 for_each_sg(start, s, nelems, i) {
333 struct scatterlist *s = &sg[i];
334 unsigned long pages, addr; 335 unsigned long pages, addr;
335 unsigned long phys_addr = s->dma_address; 336 unsigned long phys_addr = s->dma_address;
336 337
337 BUG_ON(i > start && s->offset); 338 BUG_ON(s != start && s->offset);
338 if (i == start) { 339 if (s == start) {
339 *sout = *s; 340 *sout = *s;
340 sout->dma_address = iommu_bus_base; 341 sout->dma_address = iommu_bus_base;
341 sout->dma_address += iommu_page*PAGE_SIZE + s->offset; 342 sout->dma_address += iommu_page*PAGE_SIZE + s->offset;
@@ -357,17 +358,17 @@ static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
357 return 0; 358 return 0;
358} 359}
359 360
360static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, 361static inline int dma_map_cont(struct scatterlist *start, int nelems,
361 struct scatterlist *sout, 362 struct scatterlist *sout,
362 unsigned long pages, int need) 363 unsigned long pages, int need)
363{ 364{
364 if (!need) { 365 if (!need) {
365 BUG_ON(stopat - start != 1); 366 BUG_ON(nelems != 1);
366 *sout = sg[start]; 367 *sout = *start;
367 sout->dma_length = sg[start].length; 368 sout->dma_length = start->length;
368 return 0; 369 return 0;
369 } 370 }
370 return __dma_map_cont(sg, start, stopat, sout, pages); 371 return __dma_map_cont(start, nelems, sout, pages);
371} 372}
372 373
373/* 374/*
@@ -381,6 +382,7 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
381 int start; 382 int start;
382 unsigned long pages = 0; 383 unsigned long pages = 0;
383 int need = 0, nextneed; 384 int need = 0, nextneed;
385 struct scatterlist *s, *ps, *start_sg, *sgmap;
384 386
385 if (nents == 0) 387 if (nents == 0)
386 return 0; 388 return 0;
@@ -390,8 +392,9 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
390 392
391 out = 0; 393 out = 0;
392 start = 0; 394 start = 0;
393 for (i = 0; i < nents; i++) { 395 start_sg = sgmap = sg;
394 struct scatterlist *s = &sg[i]; 396 ps = NULL; /* shut up gcc */
397 for_each_sg(sg, s, nents, i) {
395 dma_addr_t addr = page_to_phys(s->page) + s->offset; 398 dma_addr_t addr = page_to_phys(s->page) + s->offset;
396 s->dma_address = addr; 399 s->dma_address = addr;
397 BUG_ON(s->length == 0); 400 BUG_ON(s->length == 0);
@@ -400,29 +403,33 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
400 403
401 /* Handle the previous not yet processed entries */ 404 /* Handle the previous not yet processed entries */
402 if (i > start) { 405 if (i > start) {
403 struct scatterlist *ps = &sg[i-1];
404 /* Can only merge when the last chunk ends on a page 406 /* Can only merge when the last chunk ends on a page
405 boundary and the new one doesn't have an offset. */ 407 boundary and the new one doesn't have an offset. */
406 if (!iommu_merge || !nextneed || !need || s->offset || 408 if (!iommu_merge || !nextneed || !need || s->offset ||
407 (ps->offset + ps->length) % PAGE_SIZE) { 409 (ps->offset + ps->length) % PAGE_SIZE) {
408 if (dma_map_cont(sg, start, i, sg+out, pages, 410 if (dma_map_cont(start_sg, i - start, sgmap,
409 need) < 0) 411 pages, need) < 0)
410 goto error; 412 goto error;
411 out++; 413 out++;
414 sgmap = sg_next(sgmap);
412 pages = 0; 415 pages = 0;
413 start = i; 416 start = i;
417 start_sg = s;
414 } 418 }
415 } 419 }
416 420
417 need = nextneed; 421 need = nextneed;
418 pages += to_pages(s->offset, s->length); 422 pages += to_pages(s->offset, s->length);
423 ps = s;
419 } 424 }
420 if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) 425 if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0)
421 goto error; 426 goto error;
422 out++; 427 out++;
423 flush_gart(); 428 flush_gart();
424 if (out < nents) 429 if (out < nents) {
425 sg[out].dma_length = 0; 430 sgmap = sg_next(sgmap);
431 sgmap->dma_length = 0;
432 }
426 return out; 433 return out;
427 434
428error: 435error:
@@ -437,8 +444,8 @@ error:
437 if (panic_on_overflow) 444 if (panic_on_overflow)
438 panic("dma_map_sg: overflow on %lu pages\n", pages); 445 panic("dma_map_sg: overflow on %lu pages\n", pages);
439 iommu_full(dev, pages << PAGE_SHIFT, dir); 446 iommu_full(dev, pages << PAGE_SHIFT, dir);
440 for (i = 0; i < nents; i++) 447 for_each_sg(sg, s, nents, i)
441 sg[i].dma_address = bad_dma_address; 448 s->dma_address = bad_dma_address;
442 return 0; 449 return 0;
443} 450}
444 451
diff --git a/arch/x86/kernel/pci-nommu_64.c b/arch/x86/kernel/pci-nommu_64.c
index 2a34c6c025a9..e85d4360360c 100644
--- a/arch/x86/kernel/pci-nommu_64.c
+++ b/arch/x86/kernel/pci-nommu_64.c
@@ -5,6 +5,7 @@
5#include <linux/pci.h> 5#include <linux/pci.h>
6#include <linux/string.h> 6#include <linux/string.h>
7#include <linux/dma-mapping.h> 7#include <linux/dma-mapping.h>
8#include <linux/scatterlist.h>
8 9
9#include <asm/iommu.h> 10#include <asm/iommu.h>
10#include <asm/processor.h> 11#include <asm/processor.h>
@@ -57,10 +58,10 @@ static void nommu_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
57static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, 58static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
58 int nents, int direction) 59 int nents, int direction)
59{ 60{
61 struct scatterlist *s;
60 int i; 62 int i;
61 63
62 for (i = 0; i < nents; i++ ) { 64 for_each_sg(sg, s, nents, i) {
63 struct scatterlist *s = &sg[i];
64 BUG_ON(!s->page); 65 BUG_ON(!s->page);
65 s->dma_address = virt_to_bus(page_address(s->page) +s->offset); 66 s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
66 if (!check_addr("map_sg", hwdev, s->dma_address, s->length)) 67 if (!check_addr("map_sg", hwdev, s->dma_address, s->length))