Commit 88f3907f authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by Joerg Roedel

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: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: default avatarJoerg Roedel <joerg.roedel@amd.com>
parent 884d0597
...@@ -855,13 +855,32 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg, ...@@ -855,13 +855,32 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
} }
EXPORT_SYMBOL(debug_dma_map_sg); EXPORT_SYMBOL(debug_dma_map_sg);
static int get_nr_mapped_entries(struct device *dev, struct scatterlist *s)
{
struct dma_debug_entry *entry;
struct hash_bucket *bucket;
unsigned long flags;
int mapped_ents = 0;
struct dma_debug_entry ref;
ref.dev = dev;
ref.dev_addr = sg_dma_address(s);
ref.size = sg_dma_len(s),
bucket = get_hash_bucket(&ref, &flags);
entry = hash_bucket_find(bucket, &ref);
if (entry)
mapped_ents = entry->sg_mapped_ents;
put_hash_bucket(bucket, &flags);
return mapped_ents;
}
void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, int dir) int nelems, int dir)
{ {
struct dma_debug_entry *entry;
struct scatterlist *s; struct scatterlist *s;
int mapped_ents = 0, i; int mapped_ents = 0, i;
unsigned long flags;
if (unlikely(global_disable)) if (unlikely(global_disable))
return; return;
...@@ -881,14 +900,9 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, ...@@ -881,14 +900,9 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
if (mapped_ents && i >= mapped_ents) if (mapped_ents && i >= mapped_ents)
break; break;
if (mapped_ents == 0) { if (!i) {
struct hash_bucket *bucket;
ref.sg_call_ents = nelems; ref.sg_call_ents = nelems;
bucket = get_hash_bucket(&ref, &flags); mapped_ents = get_nr_mapped_entries(dev, s);
entry = hash_bucket_find(bucket, &ref);
if (entry)
mapped_ents = entry->sg_mapped_ents;
put_hash_bucket(bucket, &flags);
} }
check_unmap(&ref); check_unmap(&ref);
...@@ -990,12 +1004,18 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, ...@@ -990,12 +1004,18 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
int nelems, int direction) int nelems, int direction)
{ {
struct scatterlist *s; struct scatterlist *s;
int i; int mapped_ents = 0, i;
if (unlikely(global_disable)) if (unlikely(global_disable))
return; return;
for_each_sg(sg, s, nelems, i) { for_each_sg(sg, s, nelems, i) {
if (!i)
mapped_ents = get_nr_mapped_entries(dev, s);
if (i >= mapped_ents)
break;
check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0,
direction, true); direction, true);
} }
...@@ -1006,12 +1026,18 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, ...@@ -1006,12 +1026,18 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
int nelems, int direction) int nelems, int direction)
{ {
struct scatterlist *s; struct scatterlist *s;
int i; int mapped_ents = 0, i;
if (unlikely(global_disable)) if (unlikely(global_disable))
return; return;
for_each_sg(sg, s, nelems, i) { for_each_sg(sg, s, nelems, i) {
if (!i)
mapped_ents = get_nr_mapped_entries(dev, s);
if (i >= mapped_ents)
break;
check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0,
direction, false); direction, false);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment