diff options
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/iommu.c | 13 | ||||
-rw-r--r-- | arch/sparc64/kernel/iommu_common.c | 51 | ||||
-rw-r--r-- | arch/sparc64/kernel/iommu_common.h | 1 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 16 |
4 files changed, 46 insertions, 35 deletions
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index db3ffcf7a120..29af777d7ac9 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/device.h> | 10 | #include <linux/device.h> |
11 | #include <linux/dma-mapping.h> | 11 | #include <linux/dma-mapping.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/scatterlist.h> | ||
14 | 13 | ||
15 | #ifdef CONFIG_PCI | 14 | #ifdef CONFIG_PCI |
16 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
@@ -476,12 +475,11 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr, | |||
476 | #define SG_ENT_PHYS_ADDRESS(SG) \ | 475 | #define SG_ENT_PHYS_ADDRESS(SG) \ |
477 | (__pa(page_address((SG)->page)) + (SG)->offset) | 476 | (__pa(page_address((SG)->page)) + (SG)->offset) |
478 | 477 | ||
479 | static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | 478 | static void fill_sg(iopte_t *iopte, struct scatterlist *sg, |
480 | int nused, int nelems, | 479 | int nused, int nelems, |
481 | unsigned long iopte_protection) | 480 | unsigned long iopte_protection) |
482 | { | 481 | { |
483 | struct scatterlist *dma_sg = sg; | 482 | struct scatterlist *dma_sg = sg; |
484 | struct scatterlist *sg_end = sg_last(sg, nelems); | ||
485 | int i; | 483 | int i; |
486 | 484 | ||
487 | for (i = 0; i < nused; i++) { | 485 | for (i = 0; i < nused; i++) { |
@@ -517,6 +515,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | |||
517 | break; | 515 | break; |
518 | } | 516 | } |
519 | sg = sg_next(sg); | 517 | sg = sg_next(sg); |
518 | nelems--; | ||
520 | } | 519 | } |
521 | 520 | ||
522 | pteval = iopte_protection | (pteval & IOPTE_PAGE); | 521 | pteval = iopte_protection | (pteval & IOPTE_PAGE); |
@@ -530,18 +529,20 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, | |||
530 | 529 | ||
531 | pteval = (pteval & IOPTE_PAGE) + len; | 530 | pteval = (pteval & IOPTE_PAGE) + len; |
532 | sg = sg_next(sg); | 531 | sg = sg_next(sg); |
532 | nelems--; | ||
533 | 533 | ||
534 | /* Skip over any tail mappings we've fully mapped, | 534 | /* Skip over any tail mappings we've fully mapped, |
535 | * adjusting pteval along the way. Stop when we | 535 | * adjusting pteval along the way. Stop when we |
536 | * detect a page crossing event. | 536 | * detect a page crossing event. |
537 | */ | 537 | */ |
538 | while (sg != sg_end && | 538 | while (nelems && |
539 | (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && | 539 | (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && |
540 | (pteval == SG_ENT_PHYS_ADDRESS(sg)) && | 540 | (pteval == SG_ENT_PHYS_ADDRESS(sg)) && |
541 | ((pteval ^ | 541 | ((pteval ^ |
542 | (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { | 542 | (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { |
543 | pteval += sg->length; | 543 | pteval += sg->length; |
544 | sg = sg_next(sg); | 544 | sg = sg_next(sg); |
545 | nelems--; | ||
545 | } | 546 | } |
546 | if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) | 547 | if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) |
547 | pteval = ~0UL; | 548 | pteval = ~0UL; |
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c index 12c93a3eee26..d7ca900ec51d 100644 --- a/arch/sparc64/kernel/iommu_common.c +++ b/arch/sparc64/kernel/iommu_common.c | |||
@@ -12,18 +12,22 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifdef VERIFY_SG | 14 | #ifdef VERIFY_SG |
15 | static int verify_lengths(struct scatterlist *sg, int nents, int npages) | 15 | static int verify_lengths(struct scatterlist *sglist, int nents, int npages) |
16 | { | 16 | { |
17 | int sg_len, dma_len; | 17 | int sg_len, dma_len; |
18 | int i, pgcount; | 18 | int i, pgcount; |
19 | struct scatterlist *sg; | ||
19 | 20 | ||
20 | sg_len = 0; | 21 | sg_len = 0; |
21 | for (i = 0; i < nents; i++) | 22 | for_each_sg(sglist, sg, nents, i) |
22 | sg_len += sg[i].length; | 23 | sg_len += sg->length; |
23 | 24 | ||
24 | dma_len = 0; | 25 | dma_len = 0; |
25 | for (i = 0; i < nents && sg[i].dma_length; i++) | 26 | for_each_sg(sglist, sg, nents, i) { |
26 | dma_len += sg[i].dma_length; | 27 | if (!sg->dma_length) |
28 | break; | ||
29 | dma_len += sg->dma_length; | ||
30 | } | ||
27 | 31 | ||
28 | if (sg_len != dma_len) { | 32 | if (sg_len != dma_len) { |
29 | printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", | 33 | printk("verify_lengths: Error, different, sg[%d] dma[%d]\n", |
@@ -32,13 +36,16 @@ static int verify_lengths(struct scatterlist *sg, int nents, int npages) | |||
32 | } | 36 | } |
33 | 37 | ||
34 | pgcount = 0; | 38 | pgcount = 0; |
35 | for (i = 0; i < nents && sg[i].dma_length; i++) { | 39 | for_each_sg(sglist, sg, nents, i) { |
36 | unsigned long start, end; | 40 | unsigned long start, end; |
37 | 41 | ||
38 | start = sg[i].dma_address; | 42 | if (!sg->dma_length) |
43 | break; | ||
44 | |||
45 | start = sg->dma_address; | ||
39 | start = start & IO_PAGE_MASK; | 46 | start = start & IO_PAGE_MASK; |
40 | 47 | ||
41 | end = sg[i].dma_address + sg[i].dma_length; | 48 | end = sg->dma_address + sg->dma_length; |
42 | end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; | 49 | end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK; |
43 | 50 | ||
44 | pgcount += ((end - start) >> IO_PAGE_SHIFT); | 51 | pgcount += ((end - start) >> IO_PAGE_SHIFT); |
@@ -113,7 +120,7 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, | |||
113 | if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) | 120 | if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0)) |
114 | iopte++; | 121 | iopte++; |
115 | 122 | ||
116 | sg++; | 123 | sg = sg_next(sg); |
117 | if (--nents <= 0) | 124 | if (--nents <= 0) |
118 | break; | 125 | break; |
119 | sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); | 126 | sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); |
@@ -147,7 +154,7 @@ static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) | |||
147 | nents = verify_one_map(dma_sg, &sg, nents, &iopte); | 154 | nents = verify_one_map(dma_sg, &sg, nents, &iopte); |
148 | if (nents <= 0) | 155 | if (nents <= 0) |
149 | break; | 156 | break; |
150 | dma_sg++; | 157 | dma_sg = sg_next(dma_sg); |
151 | if (dma_sg->dma_length == 0) | 158 | if (dma_sg->dma_length == 0) |
152 | break; | 159 | break; |
153 | } | 160 | } |
@@ -169,22 +176,24 @@ static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte) | |||
169 | return 0; | 176 | return 0; |
170 | } | 177 | } |
171 | 178 | ||
172 | void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages) | 179 | void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages) |
173 | { | 180 | { |
174 | if (verify_lengths(sg, nents, npages) < 0 || | 181 | struct scatterlist *sg; |
175 | verify_maps(sg, nents, iopte) < 0) { | 182 | |
183 | if (verify_lengths(sglist, nents, npages) < 0 || | ||
184 | verify_maps(sglist, nents, iopte) < 0) { | ||
176 | int i; | 185 | int i; |
177 | 186 | ||
178 | printk("verify_sglist: Crap, messed up mappings, dumping, iodma at "); | 187 | printk("verify_sglist: Crap, messed up mappings, dumping, iodma at "); |
179 | printk("%016lx.\n", sg->dma_address & IO_PAGE_MASK); | 188 | printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK); |
180 | 189 | ||
181 | for (i = 0; i < nents; i++) { | 190 | for_each_sg(sglist, sg, nents, i) { |
182 | printk("sg(%d): page_addr(%p) off(%x) length(%x) " | 191 | printk("sg(%d): page_addr(%p) off(%x) length(%x) " |
183 | "dma_address[%016lx] dma_length[%016lx]\n", | 192 | "dma_address[%016x] dma_length[%016x]\n", |
184 | i, | 193 | i, |
185 | page_address(sg[i].page), sg[i].offset, | 194 | page_address(sg->page), sg->offset, |
186 | sg[i].length, | 195 | sg->length, |
187 | sg[i].dma_address, sg[i].dma_length); | 196 | sg->dma_address, sg->dma_length); |
188 | } | 197 | } |
189 | } | 198 | } |
190 | 199 | ||
@@ -205,12 +214,12 @@ unsigned long prepare_sg(struct scatterlist *sg, int nents) | |||
205 | while (--nents) { | 214 | while (--nents) { |
206 | unsigned long addr; | 215 | unsigned long addr; |
207 | 216 | ||
208 | sg++; | 217 | sg = sg_next(sg); |
209 | addr = (unsigned long) (page_address(sg->page) + sg->offset); | 218 | addr = (unsigned long) (page_address(sg->page) + sg->offset); |
210 | if (! VCONTIG(prev, addr)) { | 219 | if (! VCONTIG(prev, addr)) { |
211 | dma_sg->dma_address = dent_addr; | 220 | dma_sg->dma_address = dent_addr; |
212 | dma_sg->dma_length = dent_len; | 221 | dma_sg->dma_length = dent_len; |
213 | dma_sg++; | 222 | dma_sg = sg_next(dma_sg); |
214 | 223 | ||
215 | dent_addr = ((dent_addr + | 224 | dent_addr = ((dent_addr + |
216 | dent_len + | 225 | dent_len + |
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h index ad791014419c..75b5a5814522 100644 --- a/arch/sparc64/kernel/iommu_common.h +++ b/arch/sparc64/kernel/iommu_common.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/scatterlist.h> | ||
11 | 12 | ||
12 | #include <asm/iommu.h> | 13 | #include <asm/iommu.h> |
13 | #include <asm/scatterlist.h> | 14 | #include <asm/scatterlist.h> |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index cacacfae5451..fe46ace3e59f 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/msi.h> | 14 | #include <linux/msi.h> |
15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
16 | #include <linux/scatterlist.h> | ||
17 | 16 | ||
18 | #include <asm/iommu.h> | 17 | #include <asm/iommu.h> |
19 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
@@ -369,12 +368,11 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr, | |||
369 | #define SG_ENT_PHYS_ADDRESS(SG) \ | 368 | #define SG_ENT_PHYS_ADDRESS(SG) \ |
370 | (__pa(page_address((SG)->page)) + (SG)->offset) | 369 | (__pa(page_address((SG)->page)) + (SG)->offset) |
371 | 370 | ||
372 | static inline long fill_sg(long entry, struct device *dev, | 371 | static long fill_sg(long entry, struct device *dev, |
373 | struct scatterlist *sg, | 372 | struct scatterlist *sg, |
374 | int nused, int nelems, unsigned long prot) | 373 | int nused, int nelems, unsigned long prot) |
375 | { | 374 | { |
376 | struct scatterlist *dma_sg = sg; | 375 | struct scatterlist *dma_sg = sg; |
377 | struct scatterlist *sg_end = sg_last(sg, nelems); | ||
378 | unsigned long flags; | 376 | unsigned long flags; |
379 | int i; | 377 | int i; |
380 | 378 | ||
@@ -415,6 +413,7 @@ static inline long fill_sg(long entry, struct device *dev, | |||
415 | break; | 413 | break; |
416 | } | 414 | } |
417 | sg = sg_next(sg); | 415 | sg = sg_next(sg); |
416 | nelems--; | ||
418 | } | 417 | } |
419 | 418 | ||
420 | pteval = (pteval & IOPTE_PAGE); | 419 | pteval = (pteval & IOPTE_PAGE); |
@@ -433,19 +432,20 @@ static inline long fill_sg(long entry, struct device *dev, | |||
433 | 432 | ||
434 | pteval = (pteval & IOPTE_PAGE) + len; | 433 | pteval = (pteval & IOPTE_PAGE) + len; |
435 | sg = sg_next(sg); | 434 | sg = sg_next(sg); |
435 | nelems--; | ||
436 | 436 | ||
437 | /* Skip over any tail mappings we've fully mapped, | 437 | /* Skip over any tail mappings we've fully mapped, |
438 | * adjusting pteval along the way. Stop when we | 438 | * adjusting pteval along the way. Stop when we |
439 | * detect a page crossing event. | 439 | * detect a page crossing event. |
440 | */ | 440 | */ |
441 | while ((pteval << (64 - IO_PAGE_SHIFT)) != 0UL && | 441 | while (nelems && |
442 | (pteval << (64 - IO_PAGE_SHIFT)) != 0UL && | ||
442 | (pteval == SG_ENT_PHYS_ADDRESS(sg)) && | 443 | (pteval == SG_ENT_PHYS_ADDRESS(sg)) && |
443 | ((pteval ^ | 444 | ((pteval ^ |
444 | (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { | 445 | (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) { |
445 | pteval += sg->length; | 446 | pteval += sg->length; |
446 | if (sg == sg_end) | ||
447 | break; | ||
448 | sg = sg_next(sg); | 447 | sg = sg_next(sg); |
448 | nelems--; | ||
449 | } | 449 | } |
450 | if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) | 450 | if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL) |
451 | pteval = ~0UL; | 451 | pteval = ~0UL; |