Commit 88f3907f6f447899544beadf491dccb32015dacb
Committed by
Joerg Roedel
1 parent
884d05970b
Exists in
master
and in
4 other branches
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>
Showing 1 changed file with 37 additions and 11 deletions Side-by-side Diff
lib/dma-debug.c
... | ... | @@ -855,13 +855,32 @@ |
855 | 855 | } |
856 | 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 | 879 | void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, |
859 | 880 | int nelems, int dir) |
860 | 881 | { |
861 | - struct dma_debug_entry *entry; | |
862 | 882 | struct scatterlist *s; |
863 | 883 | int mapped_ents = 0, i; |
864 | - unsigned long flags; | |
865 | 884 | |
866 | 885 | if (unlikely(global_disable)) |
867 | 886 | return; |
868 | 887 | |
... | ... | @@ -881,14 +900,9 @@ |
881 | 900 | if (mapped_ents && i >= mapped_ents) |
882 | 901 | break; |
883 | 902 | |
884 | - if (mapped_ents == 0) { | |
885 | - struct hash_bucket *bucket; | |
903 | + if (!i) { | |
886 | 904 | ref.sg_call_ents = nelems; |
887 | - bucket = get_hash_bucket(&ref, &flags); | |
888 | - entry = hash_bucket_find(bucket, &ref); | |
889 | - if (entry) | |
890 | - mapped_ents = entry->sg_mapped_ents; | |
891 | - put_hash_bucket(bucket, &flags); | |
905 | + mapped_ents = get_nr_mapped_entries(dev, s); | |
892 | 906 | } |
893 | 907 | |
894 | 908 | check_unmap(&ref); |
895 | 909 | |
... | ... | @@ -990,12 +1004,18 @@ |
990 | 1004 | int nelems, int direction) |
991 | 1005 | { |
992 | 1006 | struct scatterlist *s; |
993 | - int i; | |
1007 | + int mapped_ents = 0, i; | |
994 | 1008 | |
995 | 1009 | if (unlikely(global_disable)) |
996 | 1010 | return; |
997 | 1011 | |
998 | 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 | 1019 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, |
1000 | 1020 | direction, true); |
1001 | 1021 | } |
1002 | 1022 | |
... | ... | @@ -1006,12 +1026,18 @@ |
1006 | 1026 | int nelems, int direction) |
1007 | 1027 | { |
1008 | 1028 | struct scatterlist *s; |
1009 | - int i; | |
1029 | + int mapped_ents = 0, i; | |
1010 | 1030 | |
1011 | 1031 | if (unlikely(global_disable)) |
1012 | 1032 | return; |
1013 | 1033 | |
1014 | 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 | 1041 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, |
1016 | 1042 | direction, false); |
1017 | 1043 | } |