mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 10:02:02 +02:00
dma-debug: Record DMA attributes in debug entry
To enable reliable comparison of DMA attributes between map and unmap operations, store the attribute value in dma_debug_entry. Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Link: https://lore.kernel.org/r/20260501-dma-attrs-debug-v2-4-8dbac75cd501@nvidia.com
This commit is contained in:
parent
5da80b8fb3
commit
04d492ab96
|
|
@ -63,7 +63,7 @@ enum map_err_types {
|
|||
* @sg_mapped_ents: 'mapped_ents' from dma_map_sg
|
||||
* @paddr: physical start address of the mapping
|
||||
* @map_err_type: track whether dma_mapping_error() was checked
|
||||
* @is_cache_clean: driver promises not to write to buffer while mapped
|
||||
* @attrs: dma attributes
|
||||
* @stack_len: number of backtrace entries in @stack_entries
|
||||
* @stack_entries: stack of backtrace history
|
||||
*/
|
||||
|
|
@ -78,7 +78,7 @@ struct dma_debug_entry {
|
|||
int sg_mapped_ents;
|
||||
phys_addr_t paddr;
|
||||
enum map_err_types map_err_type;
|
||||
bool is_cache_clean;
|
||||
unsigned long attrs;
|
||||
#ifdef CONFIG_STACKTRACE
|
||||
unsigned int stack_len;
|
||||
unsigned long stack_entries[DMA_DEBUG_STACKTRACE_ENTRIES];
|
||||
|
|
@ -478,6 +478,9 @@ static int active_cacheline_insert(struct dma_debug_entry *entry,
|
|||
bool *overlap_cache_clean)
|
||||
{
|
||||
phys_addr_t cln = to_cacheline_number(entry);
|
||||
bool is_cache_clean = entry->attrs &
|
||||
(DMA_ATTR_DEBUGGING_IGNORE_CACHELINES |
|
||||
DMA_ATTR_REQUIRE_COHERENT);
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
|
|
@ -495,12 +498,15 @@ static int active_cacheline_insert(struct dma_debug_entry *entry,
|
|||
if (rc == -EEXIST) {
|
||||
struct dma_debug_entry *existing;
|
||||
|
||||
active_cacheline_inc_overlap(cln, entry->is_cache_clean);
|
||||
active_cacheline_inc_overlap(cln, is_cache_clean);
|
||||
existing = radix_tree_lookup(&dma_active_cacheline, cln);
|
||||
/* A lookup failure here after we got -EEXIST is unexpected. */
|
||||
WARN_ON(!existing);
|
||||
if (existing)
|
||||
*overlap_cache_clean = existing->is_cache_clean;
|
||||
*overlap_cache_clean =
|
||||
existing->attrs &
|
||||
(DMA_ATTR_DEBUGGING_IGNORE_CACHELINES |
|
||||
DMA_ATTR_REQUIRE_COHERENT);
|
||||
}
|
||||
spin_unlock_irqrestore(&radix_lock, flags);
|
||||
|
||||
|
|
@ -544,12 +550,13 @@ void debug_dma_dump_mappings(struct device *dev)
|
|||
if (!dev || dev == entry->dev) {
|
||||
cln = to_cacheline_number(entry);
|
||||
dev_info(entry->dev,
|
||||
"%s idx %d P=%pa D=%llx L=%llx cln=%pa %s %s\n",
|
||||
"%s idx %d P=%pa D=%llx L=%llx cln=%pa %s %s attrs=0x%lx\n",
|
||||
type2name[entry->type], idx,
|
||||
&entry->paddr, entry->dev_addr,
|
||||
entry->size, &cln,
|
||||
dir2name[entry->direction],
|
||||
maperr2str[entry->map_err_type]);
|
||||
maperr2str[entry->map_err_type],
|
||||
entry->attrs);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&bucket->lock, flags);
|
||||
|
|
@ -575,14 +582,15 @@ static int dump_show(struct seq_file *seq, void *v)
|
|||
list_for_each_entry(entry, &bucket->list, list) {
|
||||
cln = to_cacheline_number(entry);
|
||||
seq_printf(seq,
|
||||
"%s %s %s idx %d P=%pa D=%llx L=%llx cln=%pa %s %s\n",
|
||||
"%s %s %s idx %d P=%pa D=%llx L=%llx cln=%pa %s %s attrs=0x%lx\n",
|
||||
dev_driver_string(entry->dev),
|
||||
dev_name(entry->dev),
|
||||
type2name[entry->type], idx,
|
||||
&entry->paddr, entry->dev_addr,
|
||||
entry->size, &cln,
|
||||
dir2name[entry->direction],
|
||||
maperr2str[entry->map_err_type]);
|
||||
maperr2str[entry->map_err_type],
|
||||
entry->attrs);
|
||||
}
|
||||
spin_unlock_irqrestore(&bucket->lock, flags);
|
||||
}
|
||||
|
|
@ -594,16 +602,14 @@ DEFINE_SHOW_ATTRIBUTE(dump);
|
|||
* Wrapper function for adding an entry to the hash.
|
||||
* This function takes care of locking itself.
|
||||
*/
|
||||
static void add_dma_entry(struct dma_debug_entry *entry, unsigned long attrs)
|
||||
static void add_dma_entry(struct dma_debug_entry *entry)
|
||||
{
|
||||
unsigned long attrs = entry->attrs;
|
||||
bool overlap_cache_clean;
|
||||
struct hash_bucket *bucket;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
entry->is_cache_clean = attrs & (DMA_ATTR_DEBUGGING_IGNORE_CACHELINES |
|
||||
DMA_ATTR_REQUIRE_COHERENT);
|
||||
|
||||
bucket = get_hash_bucket(entry, &flags);
|
||||
hash_bucket_add(bucket, entry);
|
||||
put_hash_bucket(bucket, flags);
|
||||
|
|
@ -612,9 +618,10 @@ static void add_dma_entry(struct dma_debug_entry *entry, unsigned long attrs)
|
|||
if (rc == -ENOMEM) {
|
||||
pr_err_once("cacheline tracking ENOMEM, dma-debug disabled\n");
|
||||
global_disable = true;
|
||||
} else if (rc == -EEXIST &&
|
||||
!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
|
||||
!(entry->is_cache_clean && overlap_cache_clean) &&
|
||||
} else if (rc == -EEXIST && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
|
||||
!(attrs & (DMA_ATTR_DEBUGGING_IGNORE_CACHELINES |
|
||||
DMA_ATTR_REQUIRE_COHERENT) &&
|
||||
overlap_cache_clean) &&
|
||||
dma_get_cache_alignment() >= L1_CACHE_BYTES &&
|
||||
!(IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) &&
|
||||
is_swiotlb_active(entry->dev))) {
|
||||
|
|
@ -1250,6 +1257,7 @@ void debug_dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
|
|||
entry->size = size;
|
||||
entry->direction = direction;
|
||||
entry->map_err_type = MAP_ERR_NOT_CHECKED;
|
||||
entry->attrs = attrs;
|
||||
|
||||
if (!(attrs & DMA_ATTR_MMIO)) {
|
||||
check_for_stack(dev, phys);
|
||||
|
|
@ -1258,7 +1266,7 @@ void debug_dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
|
|||
check_for_illegal_area(dev, phys_to_virt(phys), size);
|
||||
}
|
||||
|
||||
add_dma_entry(entry, attrs);
|
||||
add_dma_entry(entry);
|
||||
}
|
||||
|
||||
void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
|
|
@ -1345,10 +1353,11 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
|
|||
entry->direction = direction;
|
||||
entry->sg_call_ents = nents;
|
||||
entry->sg_mapped_ents = mapped_ents;
|
||||
entry->attrs = attrs;
|
||||
|
||||
check_sg_segment(dev, s);
|
||||
|
||||
add_dma_entry(entry, attrs);
|
||||
add_dma_entry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1440,8 +1449,9 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
|
|||
entry->size = size;
|
||||
entry->dev_addr = dma_addr;
|
||||
entry->direction = DMA_BIDIRECTIONAL;
|
||||
entry->attrs = attrs;
|
||||
|
||||
add_dma_entry(entry, attrs);
|
||||
add_dma_entry(entry);
|
||||
}
|
||||
|
||||
void debug_dma_free_coherent(struct device *dev, size_t size,
|
||||
|
|
@ -1585,7 +1595,7 @@ void debug_dma_alloc_pages(struct device *dev, struct page *page,
|
|||
entry->dev_addr = dma_addr;
|
||||
entry->direction = direction;
|
||||
|
||||
add_dma_entry(entry, 0);
|
||||
add_dma_entry(entry);
|
||||
}
|
||||
|
||||
void debug_dma_free_pages(struct device *dev, struct page *page,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user