Re: [PATCH v2 40/44] media: ipu6: Map ipu7 firmware

Sakari Ailus <[email protected]>
Newsgroups org.kernel.vger.linux-media
Organization Intel Finland Oy - BIC 0357606-4 - c/o Alberga Business Park, 6 krs, Bertel Jungin Aukio 5, 02600 Espoo
Message-ID <[email protected]>
Moi,

On Fri, Aug 21, 2026 at 02:42:58PM +0300, Antti Laakso wrote:
> Mapping of ipu7 firmware is slightly different compared to ipu6. Add
> helpers for it and call them similar to ipu6.
> 
> Signed-off-by: Antti Laakso <[email protected]>
> ---
>  drivers/media/pci/intel/ipu6/ipu6.c | 75 ++++++++++++++++++++++++++---
>  drivers/media/pci/intel/ipu6/ipu6.h |  1 +
>  2 files changed, 70 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c
> index d27ffd7ac6f0..93f28ec9a74d 100644
> --- a/drivers/media/pci/intel/ipu6/ipu6.c
> +++ b/drivers/media/pci/intel/ipu6/ipu6.c
> @@ -19,6 +19,7 @@
>  #include <linux/scatterlist.h>
>  #include <linux/slab.h>
>  #include <linux/types.h>
> +#include <linux/vmalloc.h>
>  
>  #include <media/ipu-bridge.h>
>  #include <media/ipu6-pci-table.h>
> @@ -27,6 +28,7 @@
>  #include "ipu6-bus.h"
>  #include "ipu6-buttress.h"
>  #include "ipu6-cpd.h"
> +#include "ipu6-dma.h"
>  #include "ipu6-isys.h"
>  #include "ipu6-mmu.h"
>  #include "ipu6-platform-buttress-regs.h"
> @@ -514,6 +516,57 @@ static int ipu6_map_fw(struct ipu6_device *isp)
>  	return 0;
>  }
>  
> +static int __ipu7_map_fw_non_secure(struct ipu6_device *isp)
> +{
> +	int ret;
> +
> +	/*
> +	 * Allocate and map memory for running the firmware. Not
> +	 * required in secure mode, in which firmware runs in IMR.
> +	 */
> +	isp->fw_code_region = vmalloc(IPU7_FW_CODE_REGION_SIZE);
> +	if (!isp->fw_code_region)
> +		return -ENOMEM;
> +
> +	ret = ipu7_cpd_copy_binary(isp->cpd_fw->data, "isys",
> +				   isp->fw_code_region, &isp->isys->fw_entry);
> +	if (ret)
> +		return ret;
> +
> +	ret = ipu6_map_fw_region(isp->isys, isp->fw_code_region,
> +				 IPU7_FW_CODE_REGION_SIZE, DMA_BIDIRECTIONAL,
> +				 DMA_ATTR_RESERVE_REGION);
> +	if (ret)
> +		return ret;
> +
> +	ret = ipu7_cpd_copy_binary(isp->cpd_fw->data, "psys",
> +				   isp->fw_code_region, &isp->psys->fw_entry);
> +	if (ret)
> +		return ret;
> +
> +	return ipu6_map_fw_region(isp->psys, isp->fw_code_region,
> +				  IPU7_FW_CODE_REGION_SIZE, DMA_BIDIRECTIONAL,
> +				  DMA_ATTR_RESERVE_REGION);
> +}
> +
> +static int ipu7_map_fw(struct ipu6_device *isp)
> +{
> +	int ret;
> +
> +	ret = isp->secure_mode ?
> +		ipu6_map_fw_region(isp->psys, isp->cpd_fw->data,
> +				   isp->cpd_fw->size, DMA_BIDIRECTIONAL, 0) :
> +		__ipu7_map_fw_non_secure(isp);
> +

No newline needed here.

> +	if (ret) {
> +		dev_err_probe(&isp->pdev->dev, ret,
> +			      "Failed to init ipu7 firmware region\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  {
>  	const struct ipu6_buttress_ctrl *isys_ctrl, *psys_ctrl;
> @@ -523,6 +576,7 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  	struct ipu6_device *isp;
>  	phys_addr_t phys;
>  	u32 val, version, sku_id;
> +	unsigned long dir;
>  	int ret;
>  
>  	isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
> @@ -658,7 +712,7 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  		goto out_ipu6_rpm_put;
>  	}
>  
> -	ret = ipu6_map_fw(isp);
> +	ret = IS_IPU7(isp) ? ipu7_map_fw(isp) : ipu6_map_fw(isp);
>  	if (ret)
>  		goto out_ipu6_rpm_put;
>  
> @@ -701,15 +755,20 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  out_ipu6_rpm_put:
>  	pm_runtime_put_sync(&isp->psys->auxdev.dev);
>  out_ipu6_bus_del_devices:
> +	dir = IS_IPU7(isp) ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
>  	if (!IS_ERR_OR_NULL(isp->psys)) {
>  		ipu6_cpd_free_pkg_dir(isp->psys);
>  		if (isp->psys->fw_sgt.nents)
> -			ipu6_unmap_fw_region(isp->psys, DMA_TO_DEVICE);
> +			ipu6_unmap_fw_region(isp->psys, dir);
>  	}
>  	if (!IS_ERR_OR_NULL(isp->isys)) {
>  		ipu6_cpd_free_pkg_dir(isp->isys);
>  		if (isp->isys->fw_sgt.nents)
> -			ipu6_unmap_fw_region(isp->isys, DMA_TO_DEVICE);
> +			ipu6_unmap_fw_region(isp->isys, dir);
> +	}
> +	if (isp->fw_code_region) {
> +		vfree(isp->fw_code_region);
> +		isp->fw_code_region = NULL;

This can be done unconditionally -- as in the remove callback.

>  	}
>  	if (!IS_ERR_OR_NULL(isp->psys) && !IS_ERR_OR_NULL(isp->psys->mmu))
>  		ipu6_mmu_cleanup(isp->psys->mmu);
> @@ -728,18 +787,22 @@ static void ipu6_pci_remove(struct pci_dev *pdev)
>  	struct ipu6_device *isp = pci_get_drvdata(pdev);
>  	struct ipu6_mmu *isys_mmu = isp->isys->mmu;
>  	struct ipu6_mmu *psys_mmu = isp->psys->mmu;
> +	unsigned long dir;
>  
>  	devm_free_irq(&pdev->dev, pdev->irq, isp);
> -	ipu6_cpd_free_pkg_dir(isp->psys);
>  
> -	ipu6_unmap_fw_region(isp->psys, DMA_TO_DEVICE);
> +	dir = IS_IPU7(isp) ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;

Why is there a need for a bi-directional mapping for ipu7?

> +	ipu6_cpd_free_pkg_dir(isp->psys);
> +	ipu6_unmap_fw_region(isp->psys, dir);
>  
>  	if (isp->isys) {
>  		ipu6_cpd_free_pkg_dir(isp->isys);
>  		if (isp->isys->fw_sgt.nents)
> -			ipu6_unmap_fw_region(isp->isys, DMA_TO_DEVICE);
> +			ipu6_unmap_fw_region(isp->isys, dir);
>  	}
>  
> +	vfree(isp->fw_code_region);
> +
>  	ipu6_buttress_exit(isp);
>  
>  	ipu6_bus_del_devices(pdev);
> diff --git a/drivers/media/pci/intel/ipu6/ipu6.h b/drivers/media/pci/intel/ipu6/ipu6.h
> index 6bef45a02c2b..a2992ffe8e3c 100644
> --- a/drivers/media/pci/intel/ipu6/ipu6.h
> +++ b/drivers/media/pci/intel/ipu6/ipu6.h
> @@ -70,6 +70,7 @@ struct ipu6_device {
>  	bool secure_mode;
>  	u8 hw_ver;
>  	bool bus_ready_to_probe;
> +	u32 *fw_code_region;
>  };
>  
>  #define IPU_PSYS	0

-- 
Terveisin,

Sakari Ailus
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.