diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-05-11 08:56:18 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-10-16 05:26:01 -0400 |
commit | dbfd49fe9dd7d234a4e195c6ed422cafa25813f2 (patch) | |
tree | 56e393bc6df0e7f7f660be50d9c60183fde5e689 /lib/swiotlb.c | |
parent | 38d375561f0f89e76f28ed9e69706bb2c980200f (diff) |
swiotlb: sg chaining support
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'lib/swiotlb.c')
-rw-r--r-- | lib/swiotlb.c | 19 |
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 | */ |
679 | int | 679 | int |
680 | swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, | 680 | swiotlb_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 | */ |
714 | void | 715 | void |
715 | swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems, | 716 | swiotlb_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 | */ |
737 | static void | 740 | static void |
738 | swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg, | 741 | swiotlb_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 | ||
753 | void | 758 | void |