diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-05-14 09:44:38 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-10-16 05:27:32 -0400 |
commit | 0912a5db0ea45d8aef3ee99a882e093285e32c3c (patch) | |
tree | eef222f8bce729c7bf0fa988e0c77918032f55a3 | |
parent | 78bdc3106a877cfa50439fa66b52acbc4e7868df (diff) |
SPARC: sg chaining support
This updates the sparc iommu/pci dma mappers to sg chaining.
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | arch/sparc/kernel/ioport.c | 25 | ||||
-rw-r--r-- | arch/sparc/mm/io-unit.c | 12 | ||||
-rw-r--r-- | arch/sparc/mm/iommu.c | 10 | ||||
-rw-r--r-- | arch/sparc/mm/sun4c.c | 10 | ||||
-rw-r--r-- | include/asm-sparc/scatterlist.h | 2 |
5 files changed, 33 insertions, 26 deletions
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 62182d2d7b0d..9c3ed88853f3 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/pci.h> /* struct pci_dev */ | 36 | #include <linux/pci.h> /* struct pci_dev */ |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/scatterlist.h> | ||
38 | 39 | ||
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
40 | #include <asm/vaddrs.h> | 41 | #include <asm/vaddrs.h> |
@@ -717,19 +718,19 @@ void pci_unmap_page(struct pci_dev *hwdev, | |||
717 | * Device ownership issues as mentioned above for pci_map_single are | 718 | * Device ownership issues as mentioned above for pci_map_single are |
718 | * the same here. | 719 | * the same here. |
719 | */ | 720 | */ |
720 | int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, | 721 | int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, |
721 | int direction) | 722 | int direction) |
722 | { | 723 | { |
724 | struct scatterlist *sg; | ||
723 | int n; | 725 | int n; |
724 | 726 | ||
725 | BUG_ON(direction == PCI_DMA_NONE); | 727 | BUG_ON(direction == PCI_DMA_NONE); |
726 | /* IIep is write-through, not flushing. */ | 728 | /* IIep is write-through, not flushing. */ |
727 | for (n = 0; n < nents; n++) { | 729 | for_each_sg(sgl, sg, nents, n) { |
728 | BUG_ON(page_address(sg->page) == NULL); | 730 | BUG_ON(page_address(sg->page) == NULL); |
729 | sg->dvma_address = | 731 | sg->dvma_address = |
730 | virt_to_phys(page_address(sg->page)) + sg->offset; | 732 | virt_to_phys(page_address(sg->page)) + sg->offset; |
731 | sg->dvma_length = sg->length; | 733 | sg->dvma_length = sg->length; |
732 | sg++; | ||
733 | } | 734 | } |
734 | return nents; | 735 | return nents; |
735 | } | 736 | } |
@@ -738,19 +739,19 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, | |||
738 | * Again, cpu read rules concerning calls here are the same as for | 739 | * Again, cpu read rules concerning calls here are the same as for |
739 | * pci_unmap_single() above. | 740 | * pci_unmap_single() above. |
740 | */ | 741 | */ |
741 | void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, | 742 | void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, |
742 | int direction) | 743 | int direction) |
743 | { | 744 | { |
745 | struct scatterlist *sg; | ||
744 | int n; | 746 | int n; |
745 | 747 | ||
746 | BUG_ON(direction == PCI_DMA_NONE); | 748 | BUG_ON(direction == PCI_DMA_NONE); |
747 | if (direction != PCI_DMA_TODEVICE) { | 749 | if (direction != PCI_DMA_TODEVICE) { |
748 | for (n = 0; n < nents; n++) { | 750 | for_each_sg(sgl, sg, nents, n) { |
749 | BUG_ON(page_address(sg->page) == NULL); | 751 | BUG_ON(page_address(sg->page) == NULL); |
750 | mmu_inval_dma_area( | 752 | mmu_inval_dma_area( |
751 | (unsigned long) page_address(sg->page), | 753 | (unsigned long) page_address(sg->page), |
752 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | 754 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); |
753 | sg++; | ||
754 | } | 755 | } |
755 | } | 756 | } |
756 | } | 757 | } |
@@ -789,34 +790,34 @@ void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t | |||
789 | * The same as pci_dma_sync_single_* but for a scatter-gather list, | 790 | * The same as pci_dma_sync_single_* but for a scatter-gather list, |
790 | * same rules and usage. | 791 | * same rules and usage. |
791 | */ | 792 | */ |
792 | void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) | 793 | void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction) |
793 | { | 794 | { |
795 | struct scatterlist *sg; | ||
794 | int n; | 796 | int n; |
795 | 797 | ||
796 | BUG_ON(direction == PCI_DMA_NONE); | 798 | BUG_ON(direction == PCI_DMA_NONE); |
797 | if (direction != PCI_DMA_TODEVICE) { | 799 | if (direction != PCI_DMA_TODEVICE) { |
798 | for (n = 0; n < nents; n++) { | 800 | for_each_sg(sgl, sg, nents, n) { |
799 | BUG_ON(page_address(sg->page) == NULL); | 801 | BUG_ON(page_address(sg->page) == NULL); |
800 | mmu_inval_dma_area( | 802 | mmu_inval_dma_area( |
801 | (unsigned long) page_address(sg->page), | 803 | (unsigned long) page_address(sg->page), |
802 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | 804 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); |
803 | sg++; | ||
804 | } | 805 | } |
805 | } | 806 | } |
806 | } | 807 | } |
807 | 808 | ||
808 | void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) | 809 | void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction) |
809 | { | 810 | { |
811 | struct scatterlist *sg; | ||
810 | int n; | 812 | int n; |
811 | 813 | ||
812 | BUG_ON(direction == PCI_DMA_NONE); | 814 | BUG_ON(direction == PCI_DMA_NONE); |
813 | if (direction != PCI_DMA_TODEVICE) { | 815 | if (direction != PCI_DMA_TODEVICE) { |
814 | for (n = 0; n < nents; n++) { | 816 | for_each_sg(sgl, sg, nents, n) { |
815 | BUG_ON(page_address(sg->page) == NULL); | 817 | BUG_ON(page_address(sg->page) == NULL); |
816 | mmu_inval_dma_area( | 818 | mmu_inval_dma_area( |
817 | (unsigned long) page_address(sg->page), | 819 | (unsigned long) page_address(sg->page), |
818 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); | 820 | (sg->length + PAGE_SIZE-1) & PAGE_MASK); |
819 | sg++; | ||
820 | } | 821 | } |
821 | } | 822 | } |
822 | } | 823 | } |
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 7c89893b1fe8..375b4db63704 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c | |||
@@ -11,8 +11,8 @@ | |||
11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
12 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ | 12 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ |
13 | #include <linux/bitops.h> | 13 | #include <linux/bitops.h> |
14 | #include <linux/scatterlist.h> | ||
14 | 15 | ||
15 | #include <asm/scatterlist.h> | ||
16 | #include <asm/pgalloc.h> | 16 | #include <asm/pgalloc.h> |
17 | #include <asm/pgtable.h> | 17 | #include <asm/pgtable.h> |
18 | #include <asm/sbus.h> | 18 | #include <asm/sbus.h> |
@@ -144,8 +144,9 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus | |||
144 | spin_lock_irqsave(&iounit->lock, flags); | 144 | spin_lock_irqsave(&iounit->lock, flags); |
145 | while (sz != 0) { | 145 | while (sz != 0) { |
146 | --sz; | 146 | --sz; |
147 | sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); | 147 | sg->dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg->page) + sg->offset, sg->length); |
148 | sg[sz].dvma_length = sg[sz].length; | 148 | sg->dvma_length = sg->length; |
149 | sg = sg_next(sg); | ||
149 | } | 150 | } |
150 | spin_unlock_irqrestore(&iounit->lock, flags); | 151 | spin_unlock_irqrestore(&iounit->lock, flags); |
151 | } | 152 | } |
@@ -173,11 +174,12 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_ | |||
173 | spin_lock_irqsave(&iounit->lock, flags); | 174 | spin_lock_irqsave(&iounit->lock, flags); |
174 | while (sz != 0) { | 175 | while (sz != 0) { |
175 | --sz; | 176 | --sz; |
176 | len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT; | 177 | len = ((sg->dvma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT; |
177 | vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; | 178 | vaddr = (sg->dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT; |
178 | IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); | 179 | IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr)); |
179 | for (len += vaddr; vaddr < len; vaddr++) | 180 | for (len += vaddr; vaddr < len; vaddr++) |
180 | clear_bit(vaddr, iounit->bmap); | 181 | clear_bit(vaddr, iounit->bmap); |
182 | sg = sg_next(sg); | ||
181 | } | 183 | } |
182 | spin_unlock_irqrestore(&iounit->lock, flags); | 184 | spin_unlock_irqrestore(&iounit->lock, flags); |
183 | } | 185 | } |
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 52e907af9d29..283656d9f6ea 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c | |||
@@ -12,8 +12,8 @@ | |||
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ | 14 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ |
15 | #include <linux/scatterlist.h> | ||
15 | 16 | ||
16 | #include <asm/scatterlist.h> | ||
17 | #include <asm/pgalloc.h> | 17 | #include <asm/pgalloc.h> |
18 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
19 | #include <asm/sbus.h> | 19 | #include <asm/sbus.h> |
@@ -240,7 +240,7 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sb | |||
240 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; | 240 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; |
241 | sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; | 241 | sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; |
242 | sg->dvma_length = (__u32) sg->length; | 242 | sg->dvma_length = (__u32) sg->length; |
243 | sg++; | 243 | sg = sg_next(sg); |
244 | } | 244 | } |
245 | } | 245 | } |
246 | 246 | ||
@@ -254,7 +254,7 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu | |||
254 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; | 254 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; |
255 | sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; | 255 | sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; |
256 | sg->dvma_length = (__u32) sg->length; | 256 | sg->dvma_length = (__u32) sg->length; |
257 | sg++; | 257 | sg = sg_next(sg); |
258 | } | 258 | } |
259 | } | 259 | } |
260 | 260 | ||
@@ -285,7 +285,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu | |||
285 | 285 | ||
286 | sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; | 286 | sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; |
287 | sg->dvma_length = (__u32) sg->length; | 287 | sg->dvma_length = (__u32) sg->length; |
288 | sg++; | 288 | sg = sg_next(sg); |
289 | } | 289 | } |
290 | } | 290 | } |
291 | 291 | ||
@@ -325,7 +325,7 @@ static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b | |||
325 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; | 325 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; |
326 | iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus); | 326 | iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus); |
327 | sg->dvma_address = 0x21212121; | 327 | sg->dvma_address = 0x21212121; |
328 | sg++; | 328 | sg = sg_next(sg); |
329 | } | 329 | } |
330 | } | 330 | } |
331 | 331 | ||
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 005a3e72d4f2..ee6708fc4492 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/seq_file.h> | 19 | #include <linux/seq_file.h> |
20 | #include <linux/scatterlist.h> | ||
20 | 21 | ||
21 | #include <asm/scatterlist.h> | ||
22 | #include <asm/page.h> | 22 | #include <asm/page.h> |
23 | #include <asm/pgalloc.h> | 23 | #include <asm/pgalloc.h> |
24 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
@@ -1228,8 +1228,9 @@ static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus * | |||
1228 | { | 1228 | { |
1229 | while (sz != 0) { | 1229 | while (sz != 0) { |
1230 | --sz; | 1230 | --sz; |
1231 | sg[sz].dvma_address = (__u32)sun4c_lockarea(page_address(sg[sz].page) + sg[sz].offset, sg[sz].length); | 1231 | sg->dvma_address = (__u32)sun4c_lockarea(page_address(sg->page) + sg->offset, sg->length); |
1232 | sg[sz].dvma_length = sg[sz].length; | 1232 | sg->dvma_length = sg->length; |
1233 | sg = sg_next(sg); | ||
1233 | } | 1234 | } |
1234 | } | 1235 | } |
1235 | 1236 | ||
@@ -1244,7 +1245,8 @@ static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b | |||
1244 | { | 1245 | { |
1245 | while (sz != 0) { | 1246 | while (sz != 0) { |
1246 | --sz; | 1247 | --sz; |
1247 | sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length); | 1248 | sun4c_unlockarea((char *)sg->dvma_address, sg->length); |
1249 | sg = sg_next(sg); | ||
1248 | } | 1250 | } |
1249 | } | 1251 | } |
1250 | 1252 | ||
diff --git a/include/asm-sparc/scatterlist.h b/include/asm-sparc/scatterlist.h index a4fcf9ac9649..4055af90ad7e 100644 --- a/include/asm-sparc/scatterlist.h +++ b/include/asm-sparc/scatterlist.h | |||
@@ -19,4 +19,6 @@ struct scatterlist { | |||
19 | 19 | ||
20 | #define ISA_DMA_THRESHOLD (~0UL) | 20 | #define ISA_DMA_THRESHOLD (~0UL) |
21 | 21 | ||
22 | #define ARCH_HAS_SG_CHAIN | ||
23 | |||
22 | #endif /* !(_SPARC_SCATTERLIST_H) */ | 24 | #endif /* !(_SPARC_SCATTERLIST_H) */ |