diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 5f61235439e054d9155418a3dc236922a53eac69..584e9a2bfdecd89cc86aa2898d099abeee1e4fd9 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -129,7 +129,7 @@ struct firmware_buf { phys_addr_t dest_addr; size_t dest_size; void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data); - void (*unmap_fw_mem)(void *virt, void *data); + void (*unmap_fw_mem)(void *virt, size_t size, void *data); void *map_data; #ifdef CONFIG_FW_LOADER_USER_HELPER bool is_paged_buf; @@ -161,7 +161,7 @@ struct fw_desc { phys_addr_t dest_addr; size_t dest_size; void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data); - void (*unmap_fw_mem)(void *virt, void *data); + void (*unmap_fw_mem)(void *virt, size_t size, void *data); void *map_data; struct module *module; void *context; @@ -336,7 +336,8 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf return false; if (kernel_read(file, 0, buf, size) != size) { if (fw_buf->dest_addr) - fw_buf->unmap_fw_mem(buf, fw_buf->map_data); + fw_buf->unmap_fw_mem(buf, fw_buf->dest_size, + fw_buf->map_data); else vfree(buf); return false; @@ -344,7 +345,7 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf fw_buf->data = buf; fw_buf->size = size; if (fw_buf->dest_addr) - fw_buf->unmap_fw_mem(buf, fw_buf->map_data); + fw_buf->unmap_fw_mem(buf, fw_buf->size, fw_buf->map_data); return true; } @@ -709,7 +710,7 @@ static int __firmware_data_rw(struct firmware_priv *fw_priv, char *buffer, memcpy(fw_buf, buffer, count); *offset += count; - buf->unmap_fw_mem(fw_buf, buf->map_data); + buf->unmap_fw_mem(fw_buf, count, buf->map_data); out: return retval; @@ -1271,7 +1272,8 @@ request_firmware_direct(const char *name, struct device *device, phys_addr_t dest_addr, size_t dest_size, void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data), - void (*unmap_fw_mem)(void *virt, void *data), + void (*unmap_fw_mem)(void *virt, size_t size, + void *data), void *map_data) { struct fw_desc desc; @@ -1339,7 +1341,7 @@ _request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context), bool nocache, phys_addr_t dest_addr, size_t dest_size, void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data), - void (*unmap_fw_mem)(void *virt, void *data), + void (*unmap_fw_mem)(void *virt, size_t size, void *data), void *map_data) { struct fw_desc *desc; @@ -1429,7 +1431,7 @@ request_firmware_nowait_direct( void (*cont)(const struct firmware *fw, void *context), phys_addr_t dest_addr, size_t dest_size, void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data), - void (*unmap_fw_mem)(void *virt, void *data), + void (*unmap_fw_mem)(void *virt, size_t size, void *data), void *map_data) { return _request_firmware_nowait(module, uevent, name, device, gfp, diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index b9853300cb472a67c5ff2df4cea4cbeb20f054e8..06fcccfdd3c159b471f47800afa512be5713a4ed 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -363,7 +363,6 @@ static int pil_alloc_region(struct pil_priv *priv, phys_addr_t min_addr, void *region; size_t size = max_addr - min_addr; size_t aligned_size; - DEFINE_DMA_ATTRS(attrs); /* Don't reallocate due to fragmentation concerns, just sanity check */ if (priv->region) { @@ -378,9 +377,12 @@ static int pil_alloc_region(struct pil_priv *priv, phys_addr_t min_addr, else aligned_size = ALIGN(size, SZ_1M); - dma_set_attr(DMA_ATTR_SKIP_ZEROING, &attrs); + dma_set_attr(DMA_ATTR_SKIP_ZEROING, &priv->desc->attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &priv->desc->attrs); + region = dma_alloc_attrs(priv->desc->dev, aligned_size, - &priv->region_start, GFP_KERNEL, &attrs); + &priv->region_start, GFP_KERNEL, + &priv->desc->attrs); if (region == NULL) { pil_err(priv->desc, "Failed to allocate relocatable region of size %zx\n", @@ -523,29 +525,25 @@ static void pil_release_mmap(struct pil_desc *desc) #define IOMAP_SIZE SZ_1M struct pil_map_fw_info { - int relocated; void *region; + struct dma_attrs attrs; phys_addr_t base_addr; + struct device *dev; }; static void *map_fw_mem(phys_addr_t paddr, size_t size, void *data) { struct pil_map_fw_info *info = data; - if (info && info->relocated && info->region) - return info->region + (paddr - info->base_addr); - - return ioremap(paddr, size); + return dma_remap(info->dev, info->region, paddr, size, + &info->attrs); } -static void unmap_fw_mem(void *vaddr, void *data) +static void unmap_fw_mem(void *vaddr, size_t size, void *data) { struct pil_map_fw_info *info = data; - if (info && info->relocated && info->region) - return; - - iounmap(vaddr); + dma_unremap(info->dev, vaddr, size); } static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg) @@ -555,9 +553,10 @@ static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg) char fw_name[30]; int num = seg->num; struct pil_map_fw_info map_fw_info = { - .relocated = seg->relocated, + .attrs = desc->attrs, .region = desc->priv->region, .base_addr = desc->priv->region_start, + .dev = desc->dev, }; void *map_data = desc->map_data ? desc->map_data : &map_fw_info; @@ -612,7 +611,7 @@ static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg) memset(buf, 0, size); - desc->unmap_fw_mem(buf, map_data); + desc->unmap_fw_mem(buf, size, map_data); count -= orig_size; paddr += orig_size; @@ -714,6 +713,8 @@ int pil_boot(struct pil_desc *desc) goto release_fw; } + init_dma_attrs(&desc->attrs); + ret = pil_init_mmap(desc, mdt); if (ret) goto release_fw; @@ -765,8 +766,9 @@ out: up_read(&pil_pm_rwsem); if (ret) { if (priv->region) { - dma_free_coherent(desc->dev, priv->region_size, - priv->region, priv->region_start); + dma_free_attrs(desc->dev, priv->region_size, + priv->region, priv->region_start, + &desc->attrs); priv->region = NULL; } pil_release_mmap(desc); @@ -796,8 +798,8 @@ void pil_shutdown(struct pil_desc *desc) flush_delayed_work(&priv->proxy); if (priv->region) { - dma_free_coherent(desc->dev, priv->region_size, - priv->region, priv->region_start); + dma_free_attrs(desc->dev, priv->region_size, + priv->region, priv->region_start, &desc->attrs); priv->region = NULL; } } diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h index 68b3659e14b3f750aa5cb63087fadac8f9e8993f..9cb791fc32ef1de1a4d96d674083706405650059 100644 --- a/drivers/soc/qcom/peripheral-loader.h +++ b/drivers/soc/qcom/peripheral-loader.h @@ -12,6 +12,8 @@ #ifndef __MSM_PERIPHERAL_LOADER_H #define __MSM_PERIPHERAL_LOADER_H +#include <linux/dma-attrs.h> + struct device; struct module; struct pil_priv; @@ -25,6 +27,7 @@ struct pil_priv; * @proxy_timeout: delay in ms until proxy vote is removed * @flags: bitfield for image flags * @priv: DON'T USE - internal only + * @attrs: DMA attributes to be used during dma allocation. * @proxy_unvote_irq: IRQ to trigger a proxy unvote. proxy_timeout * is ignored if this is set. * @map_fw_mem: Custom function used to map physical address space to virtual. @@ -41,9 +44,10 @@ struct pil_desc { unsigned long flags; #define PIL_SKIP_ENTRY_CHECK BIT(0) struct pil_priv *priv; + struct dma_attrs attrs; unsigned int proxy_unvote_irq; void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data); - void (*unmap_fw_mem)(void *virt, void *data); + void (*unmap_fw_mem)(void *virt, size_t size, void *data); void *map_data; }; diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 89b23a831ce70518445aad9c1331ba557c6b84e6..56672339c6cf4af2a6c13b7a5161fe619bac35b7 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -49,7 +49,8 @@ int request_firmware_direct(const char *name, struct device *device, phys_addr_t dest_addr, size_t dest_size, void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data), - void (*unmap_fw_mem)(void *virt, void *data), + void (*unmap_fw_mem)(void *virt, size_t size, + void *data), void *data); int request_firmware_nowait_direct( struct module *module, bool uevent, @@ -57,7 +58,7 @@ int request_firmware_nowait_direct( void (*cont)(const struct firmware *fw, void *context), phys_addr_t dest_addr, size_t dest_size, void * (*map_fw_mem)(phys_addr_t phys, size_t size, void *data), - void (*unmap_fw_mem)(void *virt, void *data), void *data); + void (*unmap_fw_mem)(void *virt, size_t size, void *data), void *data); void release_firmware(const struct firmware *fw); int cache_firmware(const char *name); int uncache_firmware(const char *name);