LinuxKPI: implement dmam_free_coherent()
dmam_free_coherent() is used by an updated mt76 driver at v6.19-rc6. We need to surgically find the devres information and destroy it before calling dma_free_coherent. Sponsored by: The FreeBSD Foundation MFC after: 3 days Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D54810
This commit is contained in:
@@ -96,6 +96,8 @@ void *linux_dma_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag);
|
||||
void *linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag);
|
||||
void linuxkpi_dmam_free_coherent(struct device *dev, size_t size,
|
||||
void *addr, dma_addr_t dma_handle);
|
||||
dma_addr_t linux_dma_map_phys(struct device *dev, vm_paddr_t phys, size_t len); /* backward compat */
|
||||
dma_addr_t lkpi_dma_map_phys(struct device *, vm_paddr_t, size_t,
|
||||
enum dma_data_direction, unsigned long);
|
||||
@@ -181,6 +183,13 @@ dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
||||
kmem_free(cpu_addr, size);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dmam_free_coherent(struct device *dev, size_t size, void *addr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
linuxkpi_dmam_free_coherent(dev, size, addr, dma_handle);
|
||||
}
|
||||
|
||||
static inline dma_addr_t
|
||||
dma_map_page_attrs(struct device *dev, struct page *page, size_t offset,
|
||||
size_t size, enum dma_data_direction direction, unsigned long attrs)
|
||||
|
||||
@@ -1796,6 +1796,42 @@ lkpi_dmam_free_coherent(struct device *dev, void *p)
|
||||
dma_free_coherent(dev, dr->size, dr->mem, *dr->handle);
|
||||
}
|
||||
|
||||
static int
|
||||
lkpi_dmam_coherent_match(struct device *dev, void *dr, void *mp)
|
||||
{
|
||||
struct lkpi_devres_dmam_coherent *a, *b;
|
||||
|
||||
a = dr;
|
||||
b = mp;
|
||||
|
||||
if (a->mem != b->mem)
|
||||
return (0);
|
||||
if (a->size != b->size || a->handle != b->handle)
|
||||
dev_WARN(dev, "for mem %p: size %zu != %zu || handle %#jx != %#jx\n",
|
||||
a->mem, a->size, b->size,
|
||||
(uintmax_t)a->handle, (uintmax_t)b->handle);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
linuxkpi_dmam_free_coherent(struct device *dev, size_t size,
|
||||
void *addr, dma_addr_t dma_handle)
|
||||
{
|
||||
struct lkpi_devres_dmam_coherent match = {
|
||||
.size = size,
|
||||
.handle = &dma_handle,
|
||||
.mem = addr
|
||||
};
|
||||
int error;
|
||||
|
||||
error = devres_destroy(dev, lkpi_dmam_free_coherent,
|
||||
lkpi_dmam_coherent_match, &match);
|
||||
if (error != 0)
|
||||
dev_WARN(dev, "devres_destroy returned %d, size %zu addr %p "
|
||||
"dma_handle %#jx\n", error, size, addr, (uintmax_t)dma_handle);
|
||||
dma_free_coherent(dev, size, addr, dma_handle);
|
||||
}
|
||||
|
||||
void *
|
||||
linuxkpi_dmam_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
gfp_t flag)
|
||||
|
||||
Reference in New Issue
Block a user