diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2007-10-17 03:22:14 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-10-17 03:22:14 -0400 |
commit | 24c31eede658c30e4fcc93505589fd519c3aa4b8 (patch) | |
tree | 492e257d2cd9b57bdb804a84738283dd95b86cbe | |
parent | 2428427e49beddd8ebc53054219fac2cc9ffee23 (diff) |
SPARC64: fix iommu sg chaining
Commit 2c941a204070ab32d92d40318a3196a7fb994c00 looks incomplete. The
helper functions like prepare_sg() need to support sg chaining too.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | arch/sparc64/kernel/iommu.c | 1 | ||||
-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 | 1 |
4 files changed, 31 insertions, 23 deletions
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index db3ffcf7a120..5d4e96dba412 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> |
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..119f8efa03d2 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> |