Commit 7d62cb2a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dma-mapping-6.9-2024-03-11' of git://git.infradead.org/users/hch/dma-mapping

Pull dma-mapping updates from Christoph Hellwig:

 - fix leaked pages on dma_set_decrypted() failure (Rick Edgecombe)

 - add a new swiotlb debugfs file (ZhangPeng)

* tag 'dma-mapping-6.9-2024-03-11' of git://git.infradead.org/users/hch/dma-mapping:
  dma-direct: Leak pages on dma_set_decrypted() failure
  swiotlb: add debugfs to track swiotlb transient pool usage
parents 8c9c2f85 b9fa1694
...@@ -120,6 +120,8 @@ struct io_tlb_pool { ...@@ -120,6 +120,8 @@ struct io_tlb_pool {
* debugfs. * debugfs.
* @used_hiwater: The high water mark for total_used. Used only for reporting * @used_hiwater: The high water mark for total_used. Used only for reporting
* in debugfs. * in debugfs.
* @transient_nslabs: The total number of slots in all transient pools that
* are currently used across all areas.
*/ */
struct io_tlb_mem { struct io_tlb_mem {
struct io_tlb_pool defpool; struct io_tlb_pool defpool;
...@@ -137,6 +139,7 @@ struct io_tlb_mem { ...@@ -137,6 +139,7 @@ struct io_tlb_mem {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
atomic_long_t total_used; atomic_long_t total_used;
atomic_long_t used_hiwater; atomic_long_t used_hiwater;
atomic_long_t transient_nslabs;
#endif #endif
}; };
......
...@@ -286,7 +286,7 @@ void *dma_direct_alloc(struct device *dev, size_t size, ...@@ -286,7 +286,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
} else { } else {
ret = page_address(page); ret = page_address(page);
if (dma_set_decrypted(dev, ret, size)) if (dma_set_decrypted(dev, ret, size))
goto out_free_pages; goto out_leak_pages;
} }
memset(ret, 0, size); memset(ret, 0, size);
...@@ -307,6 +307,8 @@ void *dma_direct_alloc(struct device *dev, size_t size, ...@@ -307,6 +307,8 @@ void *dma_direct_alloc(struct device *dev, size_t size,
out_free_pages: out_free_pages:
__dma_direct_free_pages(dev, page, size); __dma_direct_free_pages(dev, page, size);
return NULL; return NULL;
out_leak_pages:
return NULL;
} }
void dma_direct_free(struct device *dev, size_t size, void dma_direct_free(struct device *dev, size_t size,
...@@ -367,12 +369,11 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size, ...@@ -367,12 +369,11 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
ret = page_address(page); ret = page_address(page);
if (dma_set_decrypted(dev, ret, size)) if (dma_set_decrypted(dev, ret, size))
goto out_free_pages; goto out_leak_pages;
memset(ret, 0, size); memset(ret, 0, size);
*dma_handle = phys_to_dma_direct(dev, page_to_phys(page)); *dma_handle = phys_to_dma_direct(dev, page_to_phys(page));
return page; return page;
out_free_pages: out_leak_pages:
__dma_direct_free_pages(dev, page, size);
return NULL; return NULL;
} }
......
...@@ -956,6 +956,28 @@ static void dec_used(struct io_tlb_mem *mem, unsigned int nslots) ...@@ -956,6 +956,28 @@ static void dec_used(struct io_tlb_mem *mem, unsigned int nslots)
} }
#endif /* CONFIG_DEBUG_FS */ #endif /* CONFIG_DEBUG_FS */
#ifdef CONFIG_SWIOTLB_DYNAMIC
#ifdef CONFIG_DEBUG_FS
static void inc_transient_used(struct io_tlb_mem *mem, unsigned int nslots)
{
atomic_long_add(nslots, &mem->transient_nslabs);
}
static void dec_transient_used(struct io_tlb_mem *mem, unsigned int nslots)
{
atomic_long_sub(nslots, &mem->transient_nslabs);
}
#else /* !CONFIG_DEBUG_FS */
static void inc_transient_used(struct io_tlb_mem *mem, unsigned int nslots)
{
}
static void dec_transient_used(struct io_tlb_mem *mem, unsigned int nslots)
{
}
#endif /* CONFIG_DEBUG_FS */
#endif /* CONFIG_SWIOTLB_DYNAMIC */
/** /**
* swiotlb_search_pool_area() - search one memory area in one pool * swiotlb_search_pool_area() - search one memory area in one pool
* @dev: Device which maps the buffer. * @dev: Device which maps the buffer.
...@@ -1170,6 +1192,7 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr, ...@@ -1170,6 +1192,7 @@ static int swiotlb_find_slots(struct device *dev, phys_addr_t orig_addr,
spin_lock_irqsave(&dev->dma_io_tlb_lock, flags); spin_lock_irqsave(&dev->dma_io_tlb_lock, flags);
list_add_rcu(&pool->node, &dev->dma_io_tlb_pools); list_add_rcu(&pool->node, &dev->dma_io_tlb_pools);
spin_unlock_irqrestore(&dev->dma_io_tlb_lock, flags); spin_unlock_irqrestore(&dev->dma_io_tlb_lock, flags);
inc_transient_used(mem, pool->nslabs);
found: found:
WRITE_ONCE(dev->dma_uses_io_tlb, true); WRITE_ONCE(dev->dma_uses_io_tlb, true);
...@@ -1415,6 +1438,7 @@ static bool swiotlb_del_transient(struct device *dev, phys_addr_t tlb_addr) ...@@ -1415,6 +1438,7 @@ static bool swiotlb_del_transient(struct device *dev, phys_addr_t tlb_addr)
dec_used(dev->dma_io_tlb_mem, pool->nslabs); dec_used(dev->dma_io_tlb_mem, pool->nslabs);
swiotlb_del_pool(dev, pool); swiotlb_del_pool(dev, pool);
dec_transient_used(dev->dma_io_tlb_mem, pool->nslabs);
return true; return true;
} }
...@@ -1557,6 +1581,23 @@ phys_addr_t default_swiotlb_limit(void) ...@@ -1557,6 +1581,23 @@ phys_addr_t default_swiotlb_limit(void)
} }
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_SWIOTLB_DYNAMIC
static unsigned long mem_transient_used(struct io_tlb_mem *mem)
{
return atomic_long_read(&mem->transient_nslabs);
}
static int io_tlb_transient_used_get(void *data, u64 *val)
{
struct io_tlb_mem *mem = data;
*val = mem_transient_used(mem);
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_io_tlb_transient_used, io_tlb_transient_used_get,
NULL, "%llu\n");
#endif /* CONFIG_SWIOTLB_DYNAMIC */
static int io_tlb_used_get(void *data, u64 *val) static int io_tlb_used_get(void *data, u64 *val)
{ {
...@@ -1605,6 +1646,11 @@ static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem, ...@@ -1605,6 +1646,11 @@ static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem,
&fops_io_tlb_used); &fops_io_tlb_used);
debugfs_create_file("io_tlb_used_hiwater", 0600, mem->debugfs, mem, debugfs_create_file("io_tlb_used_hiwater", 0600, mem->debugfs, mem,
&fops_io_tlb_hiwater); &fops_io_tlb_hiwater);
#ifdef CONFIG_SWIOTLB_DYNAMIC
atomic_long_set(&mem->transient_nslabs, 0);
debugfs_create_file("io_tlb_transient_nslabs", 0400, mem->debugfs,
mem, &fops_io_tlb_transient_used);
#endif
} }
static int __init swiotlb_create_default_debugfs(void) static int __init swiotlb_create_default_debugfs(void)
......
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