aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJens Axboe <jens.axboe@oracle.com>2007-05-11 08:56:18 -0400
committerJens Axboe <jens.axboe@oracle.com>2007-10-16 05:26:01 -0400
commitdbfd49fe9dd7d234a4e195c6ed422cafa25813f2 (patch)
tree56e393bc6df0e7f7f660be50d9c60183fde5e689 /lib
parent38d375561f0f89e76f28ed9e69706bb2c980200f (diff)
swiotlb: sg chaining support
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/swiotlb.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 30c1400e749e..c419ecf334c3 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -677,16 +677,17 @@ swiotlb_sync_single_range_for_device(struct device *hwdev, dma_addr_t dev_addr,
677 * same here. 677 * same here.
678 */ 678 */
679int 679int
680swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, 680swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
681 int dir) 681 int dir)
682{ 682{
683 struct scatterlist *sg;
683 void *addr; 684 void *addr;
684 dma_addr_t dev_addr; 685 dma_addr_t dev_addr;
685 int i; 686 int i;
686 687
687 BUG_ON(dir == DMA_NONE); 688 BUG_ON(dir == DMA_NONE);
688 689
689 for (i = 0; i < nelems; i++, sg++) { 690 for_each_sg(sgl, sg, nelems, i) {
690 addr = SG_ENT_VIRT_ADDRESS(sg); 691 addr = SG_ENT_VIRT_ADDRESS(sg);
691 dev_addr = virt_to_bus(addr); 692 dev_addr = virt_to_bus(addr);
692 if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) { 693 if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
@@ -696,7 +697,7 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
696 to do proper error handling. */ 697 to do proper error handling. */
697 swiotlb_full(hwdev, sg->length, dir, 0); 698 swiotlb_full(hwdev, sg->length, dir, 0);
698 swiotlb_unmap_sg(hwdev, sg - i, i, dir); 699 swiotlb_unmap_sg(hwdev, sg - i, i, dir);
699 sg[0].dma_length = 0; 700 sgl[0].dma_length = 0;
700 return 0; 701 return 0;
701 } 702 }
702 sg->dma_address = virt_to_bus(map); 703 sg->dma_address = virt_to_bus(map);
@@ -712,19 +713,21 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
712 * concerning calls here are the same as for swiotlb_unmap_single() above. 713 * concerning calls here are the same as for swiotlb_unmap_single() above.
713 */ 714 */
714void 715void
715swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems, 716swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
716 int dir) 717 int dir)
717{ 718{
719 struct scatterlist *sg;
718 int i; 720 int i;
719 721
720 BUG_ON(dir == DMA_NONE); 722 BUG_ON(dir == DMA_NONE);
721 723
722 for (i = 0; i < nelems; i++, sg++) 724 for_each_sg(sgl, sg, nelems, i) {
723 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) 725 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
724 unmap_single(hwdev, bus_to_virt(sg->dma_address), 726 unmap_single(hwdev, bus_to_virt(sg->dma_address),
725 sg->dma_length, dir); 727 sg->dma_length, dir);
726 else if (dir == DMA_FROM_DEVICE) 728 else if (dir == DMA_FROM_DEVICE)
727 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); 729 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
730 }
728} 731}
729 732
730/* 733/*
@@ -735,19 +738,21 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
735 * and usage. 738 * and usage.
736 */ 739 */
737static void 740static void
738swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg, 741swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl,
739 int nelems, int dir, int target) 742 int nelems, int dir, int target)
740{ 743{
744 struct scatterlist *sg;
741 int i; 745 int i;
742 746
743 BUG_ON(dir == DMA_NONE); 747 BUG_ON(dir == DMA_NONE);
744 748
745 for (i = 0; i < nelems; i++, sg++) 749 for_each_sg(sgl, sg, nelems, i) {
746 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) 750 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
747 sync_single(hwdev, bus_to_virt(sg->dma_address), 751 sync_single(hwdev, bus_to_virt(sg->dma_address),
748 sg->dma_length, dir, target); 752 sg->dma_length, dir, target);
749 else if (dir == DMA_FROM_DEVICE) 753 else if (dir == DMA_FROM_DEVICE)
750 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); 754 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
755 }
751} 756}
752 757
753void 758void