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 /lib | |
| 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>
Diffstat (limited to 'lib')
| -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 | } |
