dma-debug: store a phys_addr_t in struct dma_debug_entry
authorChristoph Hellwig <hch@lst.de>
Sun, 6 Oct 2024 07:20:01 +0000 (09:20 +0200)
committerChristoph Hellwig <hch@lst.de>
Tue, 29 Oct 2024 07:53:37 +0000 (08:53 +0100)
dma-debug goes to great length to split incoming physical addresses into
a PFN and offset to store them in struct dma_debug_entry, just to
recombine those for all meaningful uses.  Just store a phys_addr_t
instead.

Signed-off-by: Christoph Hellwig <hch@lst.de>
kernel/dma/debug.c

index f6f0387..4e3692a 100644 (file)
@@ -59,8 +59,7 @@ enum map_err_types {
  * @direction: enum dma_data_direction
  * @sg_call_ents: 'nents' from dma_map_sg
  * @sg_mapped_ents: 'mapped_ents' from dma_map_sg
- * @pfn: page frame of the start address
- * @offset: offset of mapping relative to pfn
+ * @paddr: physical start address of the mapping
  * @map_err_type: track whether dma_mapping_error() was checked
  * @stack_len: number of backtrace entries in @stack_entries
  * @stack_entries: stack of backtrace history
@@ -74,8 +73,7 @@ struct dma_debug_entry {
        int              direction;
        int              sg_call_ents;
        int              sg_mapped_ents;
-       unsigned long    pfn;
-       size_t           offset;
+       phys_addr_t      paddr;
        enum map_err_types  map_err_type;
 #ifdef CONFIG_STACKTRACE
        unsigned int    stack_len;
@@ -389,14 +387,6 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
        list_del(&entry->list);
 }
 
-static unsigned long long phys_addr(struct dma_debug_entry *entry)
-{
-       if (entry->type == dma_debug_resource)
-               return __pfn_to_phys(entry->pfn) + entry->offset;
-
-       return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
-}
-
 /*
  * For each mapping (initial cacheline in the case of
  * dma_alloc_coherent/dma_map_page, initial cacheline in each page of a
@@ -428,8 +418,8 @@ static DEFINE_SPINLOCK(radix_lock);
 
 static phys_addr_t to_cacheline_number(struct dma_debug_entry *entry)
 {
-       return (entry->pfn << CACHELINE_PER_PAGE_SHIFT) +
-               (entry->offset >> L1_CACHE_SHIFT);
+       return ((entry->paddr >> PAGE_SHIFT) << CACHELINE_PER_PAGE_SHIFT) +
+               (offset_in_page(entry->paddr) >> L1_CACHE_SHIFT);
 }
 
 static int active_cacheline_read_overlap(phys_addr_t cln)
@@ -538,11 +528,11 @@ 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=%llx N=%lx D=%llx L=%llx cln=%pa %s %s\n",
+                                        "%s idx %d P=%pa D=%llx L=%llx cln=%pa %s %s\n",
                                         type2name[entry->type], idx,
-                                        phys_addr(entry), entry->pfn,
-                                        entry->dev_addr, entry->size,
-                                        &cln, dir2name[entry->direction],
+                                        &entry->paddr, entry->dev_addr,
+                                        entry->size, &cln,
+                                        dir2name[entry->direction],
                                         maperr2str[entry->map_err_type]);
                        }
                }
@@ -569,13 +559,13 @@ 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=%llx N=%lx D=%llx L=%llx cln=%pa %s %s\n",
+                                  "%s %s %s idx %d P=%pa D=%llx L=%llx cln=%pa %s %s\n",
                                   dev_driver_string(entry->dev),
                                   dev_name(entry->dev),
                                   type2name[entry->type], idx,
-                                  phys_addr(entry), entry->pfn,
-                                  entry->dev_addr, entry->size,
-                                  &cln, dir2name[entry->direction],
+                                  &entry->paddr, entry->dev_addr,
+                                  entry->size, &cln,
+                                  dir2name[entry->direction],
                                   maperr2str[entry->map_err_type]);
                }
                spin_unlock_irqrestore(&bucket->lock, flags);
@@ -1003,16 +993,16 @@ static void check_unmap(struct dma_debug_entry *ref)
                           "[mapped as %s] [unmapped as %s]\n",
                           ref->dev_addr, ref->size,
                           type2name[entry->type], type2name[ref->type]);
-       } else if ((entry->type == dma_debug_coherent) &&
-                  (phys_addr(ref) != phys_addr(entry))) {
+       } else if (entry->type == dma_debug_coherent &&
+                  ref->paddr != entry->paddr) {
                err_printk(ref->dev, entry, "device driver frees "
                           "DMA memory with different CPU address "
                           "[device address=0x%016llx] [size=%llu bytes] "
-                          "[cpu alloc address=0x%016llx] "
-                          "[cpu free address=0x%016llx]",
+                          "[cpu alloc address=0x%pa] "
+                          "[cpu free address=0x%pa]",
                           ref->dev_addr, ref->size,
-                          phys_addr(entry),
-                          phys_addr(ref));
+                          &entry->paddr,
+                          &ref->paddr);
        }
 
        if (ref->sg_call_ents && ref->type == dma_debug_sg &&
@@ -1231,8 +1221,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
 
        entry->dev       = dev;
        entry->type      = dma_debug_single;
-       entry->pfn       = page_to_pfn(page);
-       entry->offset    = offset;
+       entry->paddr     = page_to_phys(page);
        entry->dev_addr  = dma_addr;
        entry->size      = size;
        entry->direction = direction;
@@ -1327,8 +1316,7 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
 
                entry->type           = dma_debug_sg;
                entry->dev            = dev;
-               entry->pfn            = page_to_pfn(sg_page(s));
-               entry->offset         = s->offset;
+               entry->paddr          = sg_phys(s);
                entry->size           = sg_dma_len(s);
                entry->dev_addr       = sg_dma_address(s);
                entry->direction      = direction;
@@ -1374,8 +1362,7 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
                struct dma_debug_entry ref = {
                        .type           = dma_debug_sg,
                        .dev            = dev,
-                       .pfn            = page_to_pfn(sg_page(s)),
-                       .offset         = s->offset,
+                       .paddr          = sg_phys(s),
                        .dev_addr       = sg_dma_address(s),
                        .size           = sg_dma_len(s),
                        .direction      = dir,
@@ -1414,16 +1401,12 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
 
        entry->type      = dma_debug_coherent;
        entry->dev       = dev;
-       entry->offset    = offset_in_page(virt);
+       entry->paddr     = page_to_phys((is_vmalloc_addr(virt) ?
+                               vmalloc_to_page(virt) : virt_to_page(virt)));
        entry->size      = size;
        entry->dev_addr  = dma_addr;
        entry->direction = DMA_BIDIRECTIONAL;
 
-       if (is_vmalloc_addr(virt))
-               entry->pfn = vmalloc_to_pfn(virt);
-       else
-               entry->pfn = page_to_pfn(virt_to_page(virt));
-
        add_dma_entry(entry, attrs);
 }
 
@@ -1433,7 +1416,6 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
        struct dma_debug_entry ref = {
                .type           = dma_debug_coherent,
                .dev            = dev,
-               .offset         = offset_in_page(virt),
                .dev_addr       = dma_addr,
                .size           = size,
                .direction      = DMA_BIDIRECTIONAL,
@@ -1443,10 +1425,8 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
        if (!is_vmalloc_addr(virt) && !virt_addr_valid(virt))
                return;
 
-       if (is_vmalloc_addr(virt))
-               ref.pfn = vmalloc_to_pfn(virt);
-       else
-               ref.pfn = page_to_pfn(virt_to_page(virt));
+       ref.paddr = page_to_phys((is_vmalloc_addr(virt) ?
+                       vmalloc_to_page(virt) : virt_to_page(virt)));
 
        if (unlikely(dma_debug_disabled()))
                return;
@@ -1469,8 +1449,7 @@ void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
 
        entry->type             = dma_debug_resource;
        entry->dev              = dev;
-       entry->pfn              = PHYS_PFN(addr);
-       entry->offset           = offset_in_page(addr);
+       entry->paddr            = addr;
        entry->size             = size;
        entry->dev_addr         = dma_addr;
        entry->direction        = direction;
@@ -1547,8 +1526,7 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
                struct dma_debug_entry ref = {
                        .type           = dma_debug_sg,
                        .dev            = dev,
-                       .pfn            = page_to_pfn(sg_page(s)),
-                       .offset         = s->offset,
+                       .paddr          = sg_phys(s),
                        .dev_addr       = sg_dma_address(s),
                        .size           = sg_dma_len(s),
                        .direction      = direction,
@@ -1579,8 +1557,7 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
                struct dma_debug_entry ref = {
                        .type           = dma_debug_sg,
                        .dev            = dev,
-                       .pfn            = page_to_pfn(sg_page(s)),
-                       .offset         = s->offset,
+                       .paddr          = sg_phys(sg),
                        .dev_addr       = sg_dma_address(s),
                        .size           = sg_dma_len(s),
                        .direction      = direction,