diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2009-05-26 20:43:03 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2009-05-29 08:27:05 -0400 |
commit | 88f3907f6f447899544beadf491dccb32015dacb (patch) | |
tree | 65566b6711d85b951d55982d3bcc0c7393d6ad73 | |
parent | 884d05970bfbc3db368f23460dc4ce63257f240d (diff) |
dma-debug: fix debug_dma_sync_sg_for_cpu and debug_dma_sync_sg_for_device
DMA-mapping.txt says that debug_dma_sync_sg family must be called with
the _same_ one you passed into the dma_map_sg call, it should _NOT_ be
the 'count' value _returned_ from the dma_map_sg call.
debug_dma_sync_sg_for_cpu and debug_dma_sync_sg_for_device can't
handle this properly; they need to use the sg_mapped_ents in struct
dma_debug_entry as debug_dma_unmap_sg() does.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r-- | lib/dma-debug.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 51f95e5b6265..1abed176d35a 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -855,13 +855,32 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg, | |||
855 | } | 855 | } |
856 | EXPORT_SYMBOL(debug_dma_map_sg); | 856 | EXPORT_SYMBOL(debug_dma_map_sg); |
857 | 857 | ||
858 | static int get_nr_mapped_entries(struct device *dev, struct scatterlist *s) | ||
859 | { | ||
860 | struct dma_debug_entry *entry; | ||
861 | struct hash_bucket *bucket; | ||
862 | unsigned long flags; | ||
863 | int mapped_ents = 0; | ||
864 | struct dma_debug_entry ref; | ||
865 | |||
866 | ref.dev = dev; | ||
867 | ref.dev_addr = sg_dma_address(s); | ||
868 | ref.size = sg_dma_len(s), | ||
869 | |||
870 | bucket = get_hash_bucket(&ref, &flags); | ||
871 | entry = hash_bucket_find(bucket, &ref); | ||
872 | if (entry) | ||
873 | mapped_ents = entry->sg_mapped_ents; | ||
874 | put_hash_bucket(bucket, &flags); | ||
875 | |||
876 | return mapped_ents; | ||
877 | } | ||
878 | |||
858 | void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, | 879 | void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, |
859 | int nelems, int dir) | 880 | int nelems, int dir) |
860 | { | 881 | { |
861 | struct dma_debug_entry *entry; | ||
862 | struct scatterlist *s; | 882 | struct scatterlist *s; |
863 | int mapped_ents = 0, i; | 883 | int mapped_ents = 0, i; |
864 | unsigned long flags; | ||
865 | 884 | ||
866 | if (unlikely(global_disable)) | 885 | if (unlikely(global_disable)) |
867 | return; | 886 | return; |
@@ -881,14 +900,9 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, | |||
881 | if (mapped_ents && i >= mapped_ents) | 900 | if (mapped_ents && i >= mapped_ents) |
882 | break; | 901 | break; |
883 | 902 | ||
884 | if (mapped_ents == 0) { | 903 | if (!i) { |
885 | struct hash_bucket *bucket; | ||
886 | ref.sg_call_ents = nelems; | 904 | ref.sg_call_ents = nelems; |
887 | bucket = get_hash_bucket(&ref, &flags); | 905 | mapped_ents = get_nr_mapped_entries(dev, s); |
888 | entry = hash_bucket_find(bucket, &ref); | ||
889 | if (entry) | ||
890 | mapped_ents = entry->sg_mapped_ents; | ||
891 | put_hash_bucket(bucket, &flags); | ||
892 | } | 906 | } |
893 | 907 | ||
894 | check_unmap(&ref); | 908 | check_unmap(&ref); |
@@ -990,12 +1004,18 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | |||
990 | int nelems, int direction) | 1004 | int nelems, int direction) |
991 | { | 1005 | { |
992 | struct scatterlist *s; | 1006 | struct scatterlist *s; |
993 | int i; | 1007 | int mapped_ents = 0, i; |
994 | 1008 | ||
995 | if (unlikely(global_disable)) | 1009 | if (unlikely(global_disable)) |
996 | return; | 1010 | return; |
997 | 1011 | ||
998 | for_each_sg(sg, s, nelems, i) { | 1012 | for_each_sg(sg, s, nelems, i) { |
1013 | if (!i) | ||
1014 | mapped_ents = get_nr_mapped_entries(dev, s); | ||
1015 | |||
1016 | if (i >= mapped_ents) | ||
1017 | break; | ||
1018 | |||
999 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, | 1019 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, |
1000 | direction, true); | 1020 | direction, true); |
1001 | } | 1021 | } |
@@ -1006,12 +1026,18 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
1006 | int nelems, int direction) | 1026 | int nelems, int direction) |
1007 | { | 1027 | { |
1008 | struct scatterlist *s; | 1028 | struct scatterlist *s; |
1009 | int i; | 1029 | int mapped_ents = 0, i; |
1010 | 1030 | ||
1011 | if (unlikely(global_disable)) | 1031 | if (unlikely(global_disable)) |
1012 | return; | 1032 | return; |
1013 | 1033 | ||
1014 | for_each_sg(sg, s, nelems, i) { | 1034 | for_each_sg(sg, s, nelems, i) { |
1035 | if (!i) | ||
1036 | mapped_ents = get_nr_mapped_entries(dev, s); | ||
1037 | |||
1038 | if (i >= mapped_ents) | ||
1039 | break; | ||
1040 | |||
1015 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, | 1041 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, |
1016 | direction, false); | 1042 | direction, false); |
1017 | } | 1043 | } |