@@ -63,6 +63,7 @@ enum map_err_types {
6363 * @sg_mapped_ents: 'mapped_ents' from dma_map_sg
6464 * @paddr: physical start address of the mapping
6565 * @map_err_type: track whether dma_mapping_error() was checked
66+ * @is_cache_clean: driver promises not to write to buffer while mapped
6667 * @stack_len: number of backtrace entries in @stack_entries
6768 * @stack_entries: stack of backtrace history
6869 */
@@ -76,7 +77,8 @@ struct dma_debug_entry {
7677 int sg_call_ents ;
7778 int sg_mapped_ents ;
7879 phys_addr_t paddr ;
79- enum map_err_types map_err_type ;
80+ enum map_err_types map_err_type ;
81+ bool is_cache_clean ;
8082#ifdef CONFIG_STACKTRACE
8183 unsigned int stack_len ;
8284 unsigned long stack_entries [DMA_DEBUG_STACKTRACE_ENTRIES ];
@@ -472,12 +474,15 @@ static int active_cacheline_dec_overlap(phys_addr_t cln)
472474 return active_cacheline_set_overlap (cln , -- overlap );
473475}
474476
475- static int active_cacheline_insert (struct dma_debug_entry * entry )
477+ static int active_cacheline_insert (struct dma_debug_entry * entry ,
478+ bool * overlap_cache_clean )
476479{
477480 phys_addr_t cln = to_cacheline_number (entry );
478481 unsigned long flags ;
479482 int rc ;
480483
484+ * overlap_cache_clean = false;
485+
481486 /* If the device is not writing memory then we don't have any
482487 * concerns about the cpu consuming stale data. This mitigates
483488 * legitimate usages of overlapping mappings.
@@ -487,8 +492,16 @@ static int active_cacheline_insert(struct dma_debug_entry *entry)
487492
488493 spin_lock_irqsave (& radix_lock , flags );
489494 rc = radix_tree_insert (& dma_active_cacheline , cln , entry );
490- if (rc == - EEXIST )
495+ if (rc == - EEXIST ) {
496+ struct dma_debug_entry * existing ;
497+
491498 active_cacheline_inc_overlap (cln );
499+ existing = radix_tree_lookup (& dma_active_cacheline , cln );
500+ /* A lookup failure here after we got -EEXIST is unexpected. */
501+ WARN_ON (!existing );
502+ if (existing )
503+ * overlap_cache_clean = existing -> is_cache_clean ;
504+ }
492505 spin_unlock_irqrestore (& radix_lock , flags );
493506
494507 return rc ;
@@ -583,20 +596,24 @@ DEFINE_SHOW_ATTRIBUTE(dump);
583596 */
584597static void add_dma_entry (struct dma_debug_entry * entry , unsigned long attrs )
585598{
599+ bool overlap_cache_clean ;
586600 struct hash_bucket * bucket ;
587601 unsigned long flags ;
588602 int rc ;
589603
604+ entry -> is_cache_clean = !!(attrs & DMA_ATTR_CPU_CACHE_CLEAN );
605+
590606 bucket = get_hash_bucket (entry , & flags );
591607 hash_bucket_add (bucket , entry );
592608 put_hash_bucket (bucket , flags );
593609
594- rc = active_cacheline_insert (entry );
610+ rc = active_cacheline_insert (entry , & overlap_cache_clean );
595611 if (rc == - ENOMEM ) {
596612 pr_err_once ("cacheline tracking ENOMEM, dma-debug disabled\n" );
597613 global_disable = true;
598614 } else if (rc == - EEXIST &&
599- !(attrs & (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_CPU_CACHE_CLEAN )) &&
615+ !(attrs & DMA_ATTR_SKIP_CPU_SYNC ) &&
616+ !(entry -> is_cache_clean && overlap_cache_clean ) &&
600617 !(IS_ENABLED (CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC ) &&
601618 is_swiotlb_active (entry -> dev ))) {
602619 err_printk (entry -> dev , entry ,
0 commit comments