From 825fc49497957310e421454fe3fb8b8d8d8e2dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Tue, 21 May 2024 18:22:54 +0200 Subject: [PATCH 01/10] media: mgb4: Fix double debugfs remove MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes an error where debugfs_remove_recursive() is called first on a parent directory and then again on a child which causes a kernel panic. Signed-off-by: Martin Tůma Signed-off-by: Hans Verkuil Fixes: 0ab13674a9bd ("media: pci: mgb4: Added Digiteq Automotive MGB4 driver") Cc: [hverkuil: added Fixes/Cc tags] --- drivers/media/pci/mgb4/mgb4_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/pci/mgb4/mgb4_core.c b/drivers/media/pci/mgb4/mgb4_core.c index 60498a5abebf..ab4f07e2e560 100644 --- a/drivers/media/pci/mgb4/mgb4_core.c +++ b/drivers/media/pci/mgb4/mgb4_core.c @@ -642,9 +642,6 @@ static void mgb4_remove(struct pci_dev *pdev) struct mgb4_dev *mgbdev = pci_get_drvdata(pdev); int i; -#ifdef CONFIG_DEBUG_FS - debugfs_remove_recursive(mgbdev->debugfs); -#endif #if IS_REACHABLE(CONFIG_HWMON) hwmon_device_unregister(mgbdev->hwmon_dev); #endif @@ -659,6 +656,10 @@ static void mgb4_remove(struct pci_dev *pdev) if (mgbdev->vin[i]) mgb4_vin_free(mgbdev->vin[i]); +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(mgbdev->debugfs); +#endif + device_remove_groups(&mgbdev->pdev->dev, mgb4_pci_groups); free_spi(mgbdev); free_i2c(mgbdev); From fd7ccfb112302c6941f03095544c10879ced98be Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 17 May 2024 09:42:04 +0300 Subject: [PATCH 02/10] media: Documentation: v4l: Fix ACTIVE route flag The documentation in one occasion mentions the VIDIOC_SUBDEV_STREAM_FL_ACTIVE flag. This was meant to be V4L2_SUBDEV_STREAM_FL_ACTIVE as it's a flag, not an IOCTL. Fix it. Fixes: cd2c75454d74 ("media: Documentation: Document S_ROUTING behaviour") Reported-by: Samuel Wein PhD Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- Documentation/userspace-api/media/v4l/dev-subdev.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst index 0f9eda3187f3..161b43f1ce66 100644 --- a/Documentation/userspace-api/media/v4l/dev-subdev.rst +++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst @@ -582,7 +582,7 @@ depending on the hardware. In all cases, however, only routes that have the Devices generating the streams may allow enabling and disabling some of the routes or have a fixed routing configuration. If the routes can be disabled, not declaring the routes (or declaring them without -``VIDIOC_SUBDEV_STREAM_FL_ACTIVE`` flag set) in ``VIDIOC_SUBDEV_S_ROUTING`` will +``V4L2_SUBDEV_STREAM_FL_ACTIVE`` flag set) in ``VIDIOC_SUBDEV_S_ROUTING`` will disable the routes. ``VIDIOC_SUBDEV_S_ROUTING`` will still return such routes back to the user in the routes array, with the ``V4L2_SUBDEV_STREAM_FL_ACTIVE`` flag unset. From fe61b2906bd046535f4ef7dfcd69562f531ccd38 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 20 May 2024 11:55:54 +0200 Subject: [PATCH 03/10] media: intel/ipu6: Fix some redundant resources freeing in ipu6_pci_remove() pcim_iomap_regions() and pcim_enable_device() are used in the probe. So the corresponding managed resources don't need to be freed explicitly in the remove function. Remove the incorrect pci_release_regions() and pci_disable_device() calls. Fixes: 25fedc021985 ("media: intel/ipu6: add Intel IPU6 PCI device driver") Signed-off-by: Christophe JAILLET Reviewed-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu6/ipu6.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c index d2bebd208461..f587f609259d 100644 --- a/drivers/media/pci/intel/ipu6/ipu6.c +++ b/drivers/media/pci/intel/ipu6/ipu6.c @@ -727,9 +727,6 @@ static void ipu6_pci_remove(struct pci_dev *pdev) pm_runtime_forbid(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); - pci_release_regions(pdev); - pci_disable_device(pdev); - release_firmware(isp->cpd_fw); ipu6_mmu_cleanup(psys_mmu); From 266b44ec9a26dd2ad5d1dfcbb2f7f4e2c10da3fb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 26 May 2024 09:59:56 +0200 Subject: [PATCH 04/10] media: intel/ipu6: Move isys_remove() close to isys_probe() In preparation to fixing a leak in isys_probe(), move isys_remove(). The fix will introduce a new function that will also be called from isys_remove(). The code needs to be rearranged to avoid a forward declaration. Having the .remove function close to the .probe function is also more standard. Signed-off-by: Christophe JAILLET Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu6/ipu6-isys.c | 70 ++++++++++++------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c index 5992138c7290..7ce2047a09b5 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c @@ -925,41 +925,6 @@ static const struct dev_pm_ops isys_pm_ops = { .resume = isys_resume, }; -static void isys_remove(struct auxiliary_device *auxdev) -{ - struct ipu6_bus_device *adev = auxdev_to_adev(auxdev); - struct ipu6_isys *isys = dev_get_drvdata(&auxdev->dev); - struct ipu6_device *isp = adev->isp; - struct isys_fw_msgs *fwmsg, *safe; - unsigned int i; - - list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head) - dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), - fwmsg, fwmsg->dma_addr, 0); - - list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head) - dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), - fwmsg, fwmsg->dma_addr, 0); - - isys_unregister_devices(isys); - isys_notifier_cleanup(isys); - - cpu_latency_qos_remove_request(&isys->pm_qos); - - if (!isp->secure_mode) { - ipu6_cpd_free_pkg_dir(adev); - ipu6_buttress_unmap_fw_image(adev, &adev->fw_sgt); - release_firmware(adev->fw); - } - - for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) - mutex_destroy(&isys->streams[i].mutex); - - isys_iwake_watermark_cleanup(isys); - mutex_destroy(&isys->stream_mutex); - mutex_destroy(&isys->mutex); -} - static int alloc_fw_msg_bufs(struct ipu6_isys *isys, int amount) { struct device *dev = &isys->adev->auxdev.dev; @@ -1167,6 +1132,41 @@ static int isys_probe(struct auxiliary_device *auxdev, return ret; } +static void isys_remove(struct auxiliary_device *auxdev) +{ + struct ipu6_bus_device *adev = auxdev_to_adev(auxdev); + struct ipu6_isys *isys = dev_get_drvdata(&auxdev->dev); + struct ipu6_device *isp = adev->isp; + struct isys_fw_msgs *fwmsg, *safe; + unsigned int i; + + list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head) + dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), + fwmsg, fwmsg->dma_addr, 0); + + list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head) + dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), + fwmsg, fwmsg->dma_addr, 0); + + isys_unregister_devices(isys); + isys_notifier_cleanup(isys); + + cpu_latency_qos_remove_request(&isys->pm_qos); + + if (!isp->secure_mode) { + ipu6_cpd_free_pkg_dir(adev); + ipu6_buttress_unmap_fw_image(adev, &adev->fw_sgt); + release_firmware(adev->fw); + } + + for (i = 0; i < IPU6_ISYS_MAX_STREAMS; i++) + mutex_destroy(&isys->streams[i].mutex); + + isys_iwake_watermark_cleanup(isys); + mutex_destroy(&isys->stream_mutex); + mutex_destroy(&isys->mutex); +} + struct fwmsg { int type; char *msg; From ab0ed481012811fed052f609b364c118ce8a576e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 26 May 2024 09:59:57 +0200 Subject: [PATCH 05/10] media: intel/ipu6: Fix an error handling path in isys_probe() If an error occurs after a successful alloc_fw_msg_bufs() call, some resources should be released as already done in the remove function. Add a new free_fw_msg_bufs() function that releases what has been allocated by alloc_fw_msg_bufs(). Also use this new function in isys_remove() to avoid some code duplication. Fixes: f50c4ca0a820 ("media: intel/ipu6: add the main input system driver") Signed-off-by: Christophe JAILLET Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu6/ipu6-isys.c | 27 ++++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c index 7ce2047a09b5..1998b72ac07d 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c @@ -925,6 +925,20 @@ static const struct dev_pm_ops isys_pm_ops = { .resume = isys_resume, }; +static void free_fw_msg_bufs(struct ipu6_isys *isys) +{ + struct device *dev = &isys->adev->auxdev.dev; + struct isys_fw_msgs *fwmsg, *safe; + + list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head) + dma_free_attrs(dev, sizeof(struct isys_fw_msgs), fwmsg, + fwmsg->dma_addr, 0); + + list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head) + dma_free_attrs(dev, sizeof(struct isys_fw_msgs), fwmsg, + fwmsg->dma_addr, 0); +} + static int alloc_fw_msg_bufs(struct ipu6_isys *isys, int amount) { struct device *dev = &isys->adev->auxdev.dev; @@ -1105,12 +1119,14 @@ static int isys_probe(struct auxiliary_device *auxdev, ret = isys_register_devices(isys); if (ret) - goto out_remove_pkg_dir_shared_buffer; + goto free_fw_msg_bufs; ipu6_mmu_hw_cleanup(adev->mmu); return 0; +free_fw_msg_bufs: + free_fw_msg_bufs(isys); out_remove_pkg_dir_shared_buffer: if (!isp->secure_mode) ipu6_cpd_free_pkg_dir(adev); @@ -1137,16 +1153,9 @@ static void isys_remove(struct auxiliary_device *auxdev) struct ipu6_bus_device *adev = auxdev_to_adev(auxdev); struct ipu6_isys *isys = dev_get_drvdata(&auxdev->dev); struct ipu6_device *isp = adev->isp; - struct isys_fw_msgs *fwmsg, *safe; unsigned int i; - list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist, head) - dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), - fwmsg, fwmsg->dma_addr, 0); - - list_for_each_entry_safe(fwmsg, safe, &isys->framebuflist_fw, head) - dma_free_attrs(&auxdev->dev, sizeof(struct isys_fw_msgs), - fwmsg, fwmsg->dma_addr, 0); + free_fw_msg_bufs(isys); isys_unregister_devices(isys); isys_notifier_cleanup(isys); From c19fa08c1414644b0d9275d336bdaff90af57d0b Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Mon, 27 May 2024 18:48:57 +0800 Subject: [PATCH 06/10] media: intel/ipu6: fix the buffer flags caused by wrong parentheses The buffer flags is set by wrong due to wrong parentheses, the FL_INCOMING flag is never taken an account. Fix it by wrapping the ternary conditional operation with parentheses. Fixes: 3c1dfb5a69cf ("media: intel/ipu6: input system video nodes and buffer queues") Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu6/ipu6-isys-queue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c index 40a8ebfcfce2..4bd4e324abc9 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-queue.c @@ -301,10 +301,10 @@ static int ipu6_isys_stream_start(struct ipu6_isys_video *av, out_requeue: if (bl && bl->nbufs) ipu6_isys_buffer_list_queue(bl, - (IPU6_ISYS_BUFFER_LIST_FL_INCOMING | - error) ? + IPU6_ISYS_BUFFER_LIST_FL_INCOMING | + (error ? IPU6_ISYS_BUFFER_LIST_FL_SET_STATE : - 0, error ? VB2_BUF_STATE_ERROR : + 0), error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_QUEUED); flush_firmware_streamon_fail(stream); From 328af04b1ac279f17c09ddd5958aa6ec47131c80 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 27 May 2024 23:43:38 +0300 Subject: [PATCH 07/10] media: mei: csi: Put the IPU device reference The mei csi's probe function obtains a reference to the IPU device but never puts that reference. Do that now. Fixes: 33116eb12c6b ("media: ivsc: csi: Use IPU bridge") Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ivsc/mei_csi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c index 89b582a221ab..53151d016188 100644 --- a/drivers/media/pci/intel/ivsc/mei_csi.c +++ b/drivers/media/pci/intel/ivsc/mei_csi.c @@ -677,6 +677,7 @@ static int mei_csi_probe(struct mei_cl_device *cldev, return -ENODEV; ret = ipu_bridge_init(&ipu->dev, ipu_bridge_parse_ssdb); + put_device(&ipu->dev); if (ret < 0) return ret; if (WARN_ON(!dev_fwnode(dev))) From cc864821c7e8b921ebbfb21b17c92f8b3ea3d7ff Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 27 May 2024 23:13:27 +0300 Subject: [PATCH 08/10] media: mei: csi: Warn less verbosely of a missing device fwnode The check for having device fwnode was meant to be a sanity check but this also happens if the ACPI DSDT has graph port nodes on sensor device(s) but not on the IVSC device. Use a more meaningful warning message to tell about this. Fixes: 33116eb12c6b ("media: ivsc: csi: Use IPU bridge") Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ivsc/mei_csi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c index 53151d016188..f04a89584334 100644 --- a/drivers/media/pci/intel/ivsc/mei_csi.c +++ b/drivers/media/pci/intel/ivsc/mei_csi.c @@ -680,8 +680,10 @@ static int mei_csi_probe(struct mei_cl_device *cldev, put_device(&ipu->dev); if (ret < 0) return ret; - if (WARN_ON(!dev_fwnode(dev))) + if (!dev_fwnode(dev)) { + dev_err(dev, "mei-csi probed without device fwnode!\n"); return -ENXIO; + } csi = devm_kzalloc(dev, sizeof(struct mei_csi), GFP_KERNEL); if (!csi) From 54880795b494e6557b47fe3cf3f21f2f54c2aa68 Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 29 May 2024 11:44:32 +0800 Subject: [PATCH 09/10] media: intel/ipu6: update the maximum supported csi2 port number to 6 IPU6EP on Meteor Lake SoC supports maximum 6 csi2 ports instead of 4. Fixes: 25fedc021985 ("media: intel/ipu6: add Intel IPU6 PCI device driver") Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu6/ipu6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c index f587f609259d..bbd646378ab3 100644 --- a/drivers/media/pci/intel/ipu6/ipu6.c +++ b/drivers/media/pci/intel/ipu6/ipu6.c @@ -285,7 +285,7 @@ EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6); #define IPU6_ISYS_CSI2_NPORTS 4 #define IPU6SE_ISYS_CSI2_NPORTS 4 #define IPU6_TGL_ISYS_CSI2_NPORTS 8 -#define IPU6EP_MTL_ISYS_CSI2_NPORTS 4 +#define IPU6EP_MTL_ISYS_CSI2_NPORTS 6 static void ipu6_internal_pdata_init(struct ipu6_device *isp) { From ffb9072bce200a4d004006e8b40c366933cf517b Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Wed, 29 May 2024 14:43:21 +0800 Subject: [PATCH 10/10] media: intel/ipu6: add csi2 port sanity check in notifier bound Invalid csi2 port will break the isys notifier bound ops as it is trying to access an invalid csi2 sub-device instance based on the port. It will trigger a mc warning, and it will cause the sensor driver to unbound an inexistent isys csi2 and crash. Adding a csi2 port sanity check, return error to avoid such case. Fixes: f50c4ca0a820 ("media: intel/ipu6: add the main input system driver") Signed-off-by: Bingbu Cao [Sakari Ailus: Fix spelling of "nports" field.] Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil --- drivers/media/pci/intel/ipu6/ipu6-isys.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c index 1998b72ac07d..8b9b77719bb1 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c @@ -678,6 +678,12 @@ static int isys_notifier_bound(struct v4l2_async_notifier *notifier, container_of(asc, struct sensor_async_sd, asc); int ret; + if (s_asd->csi2.port >= isys->pdata->ipdata->csi2.nports) { + dev_err(&isys->adev->auxdev.dev, "invalid csi2 port %u\n", + s_asd->csi2.port); + return -EINVAL; + } + ret = ipu_bridge_instantiate_vcm(sd->dev); if (ret) { dev_err(&isys->adev->auxdev.dev, "instantiate vcm failed\n");