Re: [PATCH v2] media: venus: don't abuse dma_alloc for non-DMA allocations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 19/07/17 13:51, Stanimir Varbanov wrote:
> In venus_boot(), we pass a pointer to a phys_addr_t
> into dmam_alloc_coherent, which the compiler warns about:
> 
> platform/qcom/venus/firmware.c: In function 'venus_boot':
> platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types]
> 
> To avoid the error refactor venus_boot function by discard
> dma_alloc_coherent invocation because we don't want to map the
> memory for the device.  Something more, the usage of
> DMA mapping API is actually wrong and the current 
> implementation relies on several bugs in DMA mapping code.
> When these bugs are fixed that will break firmware loading,
> so fix this now to avoid future troubles.
> 
> The meaning of venus_boot is to copy the content of the
> firmware buffer into reserved (and memblock removed)
> block of memory and pass that physical address to the
> trusted zone for authentication and mapping through iommu
> form the secure world. After iommu mapping is done the iova
> is passed as ane entry point to the remote processor.
> 
> After this change memory-region property is parsed manually 
> and the physical address is memremap to CPU, call mdt_load to
> load firmware segments into proper places and unmap
> reserved memory.
> 
> Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions")
> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@xxxxxxxxxx>

Arnd, is this OK for you?

Regards,

	Hans

> ---
> this is v2 of the patch 2/4 form this [1] patchset. The only
> change is rewording in the patch description.
> 
> [1] http://www.mail-archive.com/linux-media@xxxxxxxxxxxxxxx/msg115717.html
> 
>  drivers/media/platform/qcom/venus/core.c     | 10 ++--
>  drivers/media/platform/qcom/venus/core.h     |  1 -
>  drivers/media/platform/qcom/venus/firmware.c | 74 ++++++++++++----------------
>  drivers/media/platform/qcom/venus/firmware.h |  5 +-
>  4 files changed, 39 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
> index 694f57a78288..a70368cb713f 100644
> --- a/drivers/media/platform/qcom/venus/core.c
> +++ b/drivers/media/platform/qcom/venus/core.c
> @@ -76,7 +76,7 @@ static void venus_sys_error_handler(struct work_struct *work)
>  	hfi_core_deinit(core, true);
>  	hfi_destroy(core);
>  	mutex_lock(&core->lock);
> -	venus_shutdown(&core->dev_fw);
> +	venus_shutdown(core->dev);
>  
>  	pm_runtime_put_sync(core->dev);
>  
> @@ -84,7 +84,7 @@ static void venus_sys_error_handler(struct work_struct *work)
>  
>  	pm_runtime_get_sync(core->dev);
>  
> -	ret |= venus_boot(core->dev, &core->dev_fw, core->res->fwname);
> +	ret |= venus_boot(core->dev, core->res->fwname);
>  
>  	ret |= hfi_core_resume(core, true);
>  
> @@ -207,7 +207,7 @@ static int venus_probe(struct platform_device *pdev)
>  	if (ret < 0)
>  		goto err_runtime_disable;
>  
> -	ret = venus_boot(dev, &core->dev_fw, core->res->fwname);
> +	ret = venus_boot(dev, core->res->fwname);
>  	if (ret)
>  		goto err_runtime_disable;
>  
> @@ -238,7 +238,7 @@ static int venus_probe(struct platform_device *pdev)
>  err_core_deinit:
>  	hfi_core_deinit(core, false);
>  err_venus_shutdown:
> -	venus_shutdown(&core->dev_fw);
> +	venus_shutdown(dev);
>  err_runtime_disable:
>  	pm_runtime_set_suspended(dev);
>  	pm_runtime_disable(dev);
> @@ -259,7 +259,7 @@ static int venus_remove(struct platform_device *pdev)
>  	WARN_ON(ret);
>  
>  	hfi_destroy(core);
> -	venus_shutdown(&core->dev_fw);
> +	venus_shutdown(dev);
>  	of_platform_depopulate(dev);
>  
>  	pm_runtime_put_sync(dev);
> diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h
> index e542700eee32..cba092bcb76d 100644
> --- a/drivers/media/platform/qcom/venus/core.h
> +++ b/drivers/media/platform/qcom/venus/core.h
> @@ -101,7 +101,6 @@ struct venus_core {
>  	struct device *dev;
>  	struct device *dev_dec;
>  	struct device *dev_enc;
> -	struct device dev_fw;
>  	struct mutex lock;
>  	struct list_head instances;
>  	atomic_t insts_count;
> diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
> index 1b1a4f355918..d6d9560c1c19 100644
> --- a/drivers/media/platform/qcom/venus/firmware.c
> +++ b/drivers/media/platform/qcom/venus/firmware.c
> @@ -12,29 +12,27 @@
>   *
>   */
>  
> -#include <linux/dma-mapping.h>
> +#include <linux/device.h>
>  #include <linux/firmware.h>
>  #include <linux/kernel.h>
> +#include <linux/io.h>
>  #include <linux/of.h>
> -#include <linux/of_reserved_mem.h>
> -#include <linux/slab.h>
> +#include <linux/of_address.h>
>  #include <linux/qcom_scm.h>
> +#include <linux/sizes.h>
>  #include <linux/soc/qcom/mdt_loader.h>
>  
>  #include "firmware.h"
>  
>  #define VENUS_PAS_ID			9
> -#define VENUS_FW_MEM_SIZE		SZ_8M
> +#define VENUS_FW_MEM_SIZE		(6 * SZ_1M)
>  
> -static void device_release_dummy(struct device *dev)
> -{
> -	of_reserved_mem_device_release(dev);
> -}
> -
> -int venus_boot(struct device *parent, struct device *fw_dev, const char *fwname)
> +int venus_boot(struct device *dev, const char *fwname)
>  {
>  	const struct firmware *mdt;
> +	struct device_node *node;
>  	phys_addr_t mem_phys;
> +	struct resource r;
>  	ssize_t fw_size;
>  	size_t mem_size;
>  	void *mem_va;
> @@ -43,66 +41,58 @@ int venus_boot(struct device *parent, struct device *fw_dev, const char *fwname)
>  	if (!qcom_scm_is_available())
>  		return -EPROBE_DEFER;
>  
> -	fw_dev->parent = parent;
> -	fw_dev->release = device_release_dummy;
> +	node = of_parse_phandle(dev->of_node, "memory-region", 0);
> +	if (!node) {
> +		dev_err(dev, "no memory-region specified\n");
> +		return -EINVAL;
> +	}
>  
> -	ret = dev_set_name(fw_dev, "%s:%s", dev_name(parent), "firmware");
> +	ret = of_address_to_resource(node, 0, &r);
>  	if (ret)
>  		return ret;
>  
> -	ret = device_register(fw_dev);
> -	if (ret < 0)
> -		return ret;
> +	mem_phys = r.start;
> +	mem_size = resource_size(&r);
>  
> -	ret = of_reserved_mem_device_init_by_idx(fw_dev, parent->of_node, 0);
> -	if (ret)
> -		goto err_unreg_device;
> +	if (mem_size < VENUS_FW_MEM_SIZE)
> +		return -EINVAL;
>  
> -	mem_size = VENUS_FW_MEM_SIZE;
> -
> -	mem_va = dmam_alloc_coherent(fw_dev, mem_size, &mem_phys, GFP_KERNEL);
> +	mem_va = memremap(r.start, mem_size, MEMREMAP_WC);
>  	if (!mem_va) {
> -		ret = -ENOMEM;
> -		goto err_unreg_device;
> +		dev_err(dev, "unable to map memory region: %pa+%zx\n",
> +			&r.start, mem_size);
> +		return -ENOMEM;
>  	}
>  
> -	ret = request_firmware(&mdt, fwname, fw_dev);
> +	ret = request_firmware(&mdt, fwname, dev);
>  	if (ret < 0)
> -		goto err_unreg_device;
> +		goto err_unmap;
>  
>  	fw_size = qcom_mdt_get_size(mdt);
>  	if (fw_size < 0) {
>  		ret = fw_size;
>  		release_firmware(mdt);
> -		goto err_unreg_device;
> +		goto err_unmap;
>  	}
>  
> -	ret = qcom_mdt_load(fw_dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
> +	ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
>  			    mem_size);
>  
>  	release_firmware(mdt);
>  
>  	if (ret)
> -		goto err_unreg_device;
> +		goto err_unmap;
>  
>  	ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
>  	if (ret)
> -		goto err_unreg_device;
> -
> -	return 0;
> +		goto err_unmap;
>  
> -err_unreg_device:
> -	device_unregister(fw_dev);
> +err_unmap:
> +	memunmap(mem_va);
>  	return ret;
>  }
>  
> -int venus_shutdown(struct device *fw_dev)
> +int venus_shutdown(struct device *dev)
>  {
> -	int ret;
> -
> -	ret = qcom_scm_pas_shutdown(VENUS_PAS_ID);
> -	device_unregister(fw_dev);
> -	memset(fw_dev, 0, sizeof(*fw_dev));
> -
> -	return ret;
> +	return qcom_scm_pas_shutdown(VENUS_PAS_ID);
>  }
> diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h
> index f81a98979798..428efb56d339 100644
> --- a/drivers/media/platform/qcom/venus/firmware.h
> +++ b/drivers/media/platform/qcom/venus/firmware.h
> @@ -16,8 +16,7 @@
>  
>  struct device;
>  
> -int venus_boot(struct device *parent, struct device *fw_dev,
> -	       const char *fwname);
> -int venus_shutdown(struct device *fw_dev);
> +int venus_boot(struct device *dev, const char *fwname);
> +int venus_shutdown(struct device *dev);
>  
>  #endif
> 




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux