diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2013-05-02 17:37:49 +0200 | 
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2013-05-02 17:54:19 +0200 | 
| commit | c032862fba51a3ca504752d3a25186b324c5ce83 (patch) | |
| tree | 955dc2ba4ab3df76ecc2bb780ee84aca04967e8d /lib/dma-debug.c | |
| parent | fda76e074c7737fc57855dd17c762e50ed526052 (diff) | |
| parent | 8700c95adb033843fc163d112b9d21d4fda78018 (diff) | |
| download | olio-linux-3.10-c032862fba51a3ca504752d3a25186b324c5ce83.tar.xz olio-linux-3.10-c032862fba51a3ca504752d3a25186b324c5ce83.zip  | |
Merge commit '8700c95adb03' into timers/nohz
The full dynticks tree needs the latest RCU and sched
upstream updates in order to fix some dependencies.
Merge a common upstream merge point that has these
updates.
Conflicts:
	include/linux/perf_event.h
	kernel/rcutree.h
	kernel/rcutree_plugin.h
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'lib/dma-debug.c')
| -rw-r--r-- | lib/dma-debug.c | 45 | 
1 files changed, 31 insertions, 14 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 5e396accd3d..d87a17a819d 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -862,17 +862,21 @@ static void check_unmap(struct dma_debug_entry *ref)  	entry = bucket_find_exact(bucket, ref);  	if (!entry) { +		/* must drop lock before calling dma_mapping_error */ +		put_hash_bucket(bucket, &flags); +  		if (dma_mapping_error(ref->dev, ref->dev_addr)) {  			err_printk(ref->dev, NULL, -				   "DMA-API: device driver tries " -				   "to free an invalid DMA memory address\n"); -			return; +				   "DMA-API: device driver tries to free an " +				   "invalid DMA memory address\n"); +		} else { +			err_printk(ref->dev, NULL, +				   "DMA-API: device driver tries to free DMA " +				   "memory it has not allocated [device " +				   "address=0x%016llx] [size=%llu bytes]\n", +				   ref->dev_addr, ref->size);  		} -		err_printk(ref->dev, NULL, "DMA-API: device driver tries " -			   "to free DMA memory it has not allocated " -			   "[device address=0x%016llx] [size=%llu bytes]\n", -			   ref->dev_addr, ref->size); -		goto out; +		return;  	}  	if (ref->size != entry->size) { @@ -936,7 +940,6 @@ static void check_unmap(struct dma_debug_entry *ref)  	hash_bucket_del(entry);  	dma_entry_free(entry); -out:  	put_hash_bucket(bucket, &flags);  } @@ -1082,13 +1085,27 @@ void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)  	ref.dev = dev;  	ref.dev_addr = dma_addr;  	bucket = get_hash_bucket(&ref, &flags); -	entry = bucket_find_exact(bucket, &ref); -	if (!entry) -		goto out; +	list_for_each_entry(entry, &bucket->list, list) { +		if (!exact_match(&ref, entry)) +			continue; + +		/* +		 * The same physical address can be mapped multiple +		 * times. Without a hardware IOMMU this results in the +		 * same device addresses being put into the dma-debug +		 * hash multiple times too. This can result in false +		 * positives being reported. Therefore we implement a +		 * best-fit algorithm here which updates the first entry +		 * from the hash which fits the reference value and is +		 * not currently listed as being checked. +		 */ +		if (entry->map_err_type == MAP_ERR_NOT_CHECKED) { +			entry->map_err_type = MAP_ERR_CHECKED; +			break; +		} +	} -	entry->map_err_type = MAP_ERR_CHECKED; -out:  	put_hash_bucket(bucket, &flags);  }  EXPORT_SYMBOL(debug_dma_mapping_error);  |