aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2009-05-26 20:43:03 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2009-05-29 08:27:05 -0400
commit88f3907f6f447899544beadf491dccb32015dacb (patch)
tree65566b6711d85b951d55982d3bcc0c7393d6ad73 /lib
parent884d05970bfbc3db368f23460dc4ce63257f240d (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>
Diffstat (limited to 'lib')
-rw-r--r--lib/dma-debug.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 51f95e5b626..1abed176d35 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}
856EXPORT_SYMBOL(debug_dma_map_sg); 856EXPORT_SYMBOL(debug_dma_map_sg);
857 857
858static 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
858void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, 879void 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 }