lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <facbd20d-15ac-4aed-a95c-dacc0076ae5f@ti.com>
Date: Mon, 29 Dec 2025 15:37:20 +0530
From: Rishikesh Donadkar <r-donadkar@...com>
To: Jai Luthra <jai.luthra@...asonboard.com>, Tomi Valkeinen
	<tomi.valkeinen@...asonboard.com>, <jai.luthra@...ux.dev>,
	<laurent.pinchart@...asonboard.com>, <mripard@...nel.org>, "Vignesh
 Raghavendra" <vigneshr@...com>
CC: <y-abhilashchandra@...com>, <devarsht@...com>, <s-jain1@...com>,
	<mchehab@...nel.org>, <robh@...nel.org>, <krzk+dt@...nel.org>,
	<p.zabel@...gutronix.de>, <conor+dt@...nel.org>,
	<sakari.ailus@...ux.intel.com>, <hverkuil-cisco@...all.nl>,
	<changhuang.liang@...rfivetech.com>, <jack.zhu@...rfivetech.com>,
	<sjoerd@...labora.com>, <dan.carpenter@...aro.org>,
	<hverkuil+cisco@...nel.org>, <linux-kernel@...r.kernel.org>,
	<linux-media@...r.kernel.org>, <devicetree@...r.kernel.org>
Subject: Re: [PATCH v8 17/18] media: ti: j721e-csi2rx: Support runtime suspend


On 08/12/25 13:06, Jai Luthra wrote:
> Hi Tomi,


Hi Jai, Tomi,

>
> Quoting Tomi Valkeinen (2025-12-01 18:52:36)
>> Hi,
>>
>> On 12/11/2025 13:54, Rishikesh Donadkar wrote:
>>> From: Jai Luthra <jai.luthra@...asonboard.com>
>>>
>>> Add support for runtime power-management to enable powering off the
>>> shared power domain between Cadence CSI2RX and TI CSI2RX wrapper when
>>> the device(s) are not in use.
>>>
>>> When powering off the IP, the PSI-L endpoint loses the paired DMA
>>> channels. Thus we have to release the DMA channels at runtime suspend
>>> and request them again at resume.
>> I'm not an expert on the dmaengine, but to me this sounds like a bug in
>> the dma driver. It just sounds very wrong...
>>
> Cc: Vignesh
>
> IIRC this was done because on AM62 the CSI2RX is on a separate power domain
> and it uses DMA channels from the system-wide DMA engine.
>
> And as those two drivers have different set of users, we have situations
> where CSI2RX goes to runtime suspend state and turns off the power and
> clocks, while the DMA engine remains on as it has other users. This leads
> to the paired PSIL channels to become invalid, and needs a re-pairing.
>
> I am not an expert on DMA engine APIs to know how feasible it would be to
> do the book-keeping of the power state of various devices in the DMA driver
> and manage the re-pairing entirely there.
>
> On AM62A and later devices, there is a dedicated instance of the BCDMA
> engine for camera pipeline on the same power domain as CSI2RX, so this is
> not a problem. Rishikesh/Vignesh please correct me if I'm wrong, as it has
> been a while since I looked at this in depth.
>
>
>>> Tested-by: Rishikesh Donadkar <r-donadkar@...com>
>>> Reviewed-by: Rishikesh Donadkar <r-donadkar@...com>
>>> Signed-off-by: Jai Luthra <jai.luthra@...asonboard.com>
>>> Signed-off-by: Rishikesh Donadkar <r-donadkar@...com>
>>> ---
>>>   drivers/media/platform/ti/Kconfig             |  1 +
>>>   .../platform/ti/j721e-csi2rx/j721e-csi2rx.c   | 55 ++++++++++++++++++-
>>>   2 files changed, 54 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
>>> index 3bc4aa35887e6..a808063e24779 100644
>>> --- a/drivers/media/platform/ti/Kconfig
>>> +++ b/drivers/media/platform/ti/Kconfig
>>> @@ -70,6 +70,7 @@ config VIDEO_TI_J721E_CSI2RX
>>>        depends on VIDEO_CADENCE_CSI2RX
>>>        depends on PHY_CADENCE_DPHY_RX || COMPILE_TEST
>>>        depends on ARCH_K3 || COMPILE_TEST
>>> +     depends on PM
>>>        select VIDEOBUF2_DMA_CONTIG
>>>        select V4L2_FWNODE
>>>        help
>>> diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
>>> index 528041ee78cf3..21e032c64b901 100644
>>> --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
>>> +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
>>> @@ -13,6 +13,7 @@
>>>   #include <linux/module.h>
>>>   #include <linux/of_platform.h>
>>>   #include <linux/platform_device.h>
>>> +#include <linux/pm_runtime.h>
>>>   #include <linux/property.h>
>>>   
>>>   #include <media/cadence/cdns-csi2rx.h>
>>> @@ -963,12 +964,16 @@ static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count)
>>>        unsigned long flags;
>>>        int ret = 0;
>>>   
>>> +     ret = pm_runtime_resume_and_get(csi->dev);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>>        spin_lock_irqsave(&dma->lock, flags);
>>>        if (list_empty(&dma->queue))
>>>                ret = -EIO;
>>>        spin_unlock_irqrestore(&dma->lock, flags);
>>>        if (ret)
>>> -             return ret;
>>> +             goto err;
>>>   
>>>        ret = video_device_pipeline_start(&ctx->vdev, &csi->pipe);
>>>        if (ret)
>>> @@ -1024,6 +1029,8 @@ static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count)
>>>        writel(0, csi->shim + SHIM_DMACNTX(ctx->idx));
>>>   err:
>>>        ti_csi2rx_cleanup_buffers(ctx, VB2_BUF_STATE_QUEUED);
>>> +     pm_runtime_put(csi->dev);
>>> +
>>>        return ret;
>>>   }
>>>   
>>> @@ -1055,6 +1062,7 @@ static void ti_csi2rx_stop_streaming(struct vb2_queue *vq)
>>>   
>>>        ti_csi2rx_stop_dma(ctx);
>>>        ti_csi2rx_cleanup_buffers(ctx, VB2_BUF_STATE_ERROR);
>>> +     pm_runtime_put(csi->dev);
>>>   }
>>>   
>>>   static const struct vb2_ops csi_vb2_qops = {
>>> @@ -1261,7 +1269,9 @@ static void ti_csi2rx_cleanup_notifier(struct ti_csi2rx_dev *csi)
>>>   
>>>   static void ti_csi2rx_cleanup_ctx(struct ti_csi2rx_ctx *ctx)
>>>   {
>>> -     dma_release_channel(ctx->dma.chan);
>>> +     if (!pm_runtime_status_suspended(ctx->csi->dev))
>>> +             dma_release_channel(ctx->dma.chan);
>>> +
>>>        vb2_queue_release(&ctx->vidq);
>>>   
>>>        video_unregister_device(&ctx->vdev);
>>> @@ -1512,6 +1522,39 @@ static int ti_csi2rx_init_ctx(struct ti_csi2rx_ctx *ctx)
>>>        return ret;
>>>   }
>>>   
>>> +static int ti_csi2rx_runtime_suspend(struct device *dev)
>>> +{
>>> +     struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
>>> +     int i;
>>> +
>>> +     if (csi->enable_count != 0)
>>> +             return -EBUSY;
>>> +
>>> +     for (i = 0; i < csi->num_ctx; i++)
>>> +             dma_release_channel(csi->ctx[i].dma.chan);
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static int ti_csi2rx_runtime_resume(struct device *dev)
>>> +{
>>> +     struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
>>> +     int ret, i;
>>> +
>>> +     for (i = 0; i < csi->num_ctx; i++) {
>>> +             ret = ti_csi2rx_init_dma(&csi->ctx[i]);
>> If runtime_resume always requests the dma channels, is the call to
>> ti_csi2rx_init_dma() in ti_csi2rx_init_ctx() needed? If not, you could
>> inline the code from ti_csi2rx_init_dma() to here and also drop the
>> dma_release_channel() call from ti_csi2rx_cleanup_ctx(), making the flow
>> more understandable.
>>
> Makes sense.
>
>>> +             if (ret)
>>> +                     return ret;
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +static const struct dev_pm_ops ti_csi2rx_pm_ops = {
>>> +     RUNTIME_PM_OPS(ti_csi2rx_runtime_suspend, ti_csi2rx_runtime_resume,
>>> +                    NULL)
>>> +};
>>> +
>>>   static int ti_csi2rx_probe(struct platform_device *pdev)
>>>   {
>>>        struct device_node *np = pdev->dev.of_node;
>>> @@ -1579,6 +1622,10 @@ static int ti_csi2rx_probe(struct platform_device *pdev)
>>>                goto err_notifier;
>>>        }
>>>   
>>> +     pm_runtime_set_active(csi->dev);
>>> +     pm_runtime_enable(csi->dev);
>>> +     pm_request_idle(csi->dev);
>> I always forget what exactly the runtime_pm funcs do. What's the idea
>> here? If you do something else than the plain standard
>> pm_runtime_enable(), I think it's good to mention what/why in a comment.
>>
> https://docs.kernel.org/power/runtime_pm.html#runtime-pm-initialization-device-probing-and-removal
>
> The pm_request_idle() is done to queue up a job to suspend the hardware
> until userspace starts streaming, to save power.
>
> The runtime_set_active() is used because the power domain for CSI is by
> default turned on when system boots up. But Rishikesh, please double check
> that before v9 on AM62.


I checked with AM62 when booting up, with CSI drivers being probed/not 
probed. The device state was OFF by default on boot in both cases. So, 
plain pm_runtime_enable() should work. That will simplify the 
dma_request/release_chan() callsĀ  in the runtime suspend/resume flow.


Thanks & Regards,

Rishikesh

>
>>>        return 0;
>>>   
>>>   err_notifier:
>>> @@ -1609,6 +1656,9 @@ static void ti_csi2rx_remove(struct platform_device *pdev)
>>>        mutex_destroy(&csi->mutex);
>>>        dma_free_coherent(csi->dev, csi->drain.len, csi->drain.vaddr,
>>>                          csi->drain.paddr);
>>> +     pm_runtime_disable(&pdev->dev);
>>> +     pm_runtime_set_suspended(&pdev->dev);
>>> +
>>>   }
>>>   
>>>   static const struct of_device_id ti_csi2rx_of_match[] = {
>>> @@ -1623,6 +1673,7 @@ static struct platform_driver ti_csi2rx_pdrv = {
>>>        .driver = {
>>>                .name = TI_CSI2RX_MODULE_NAME,
>>>                .of_match_table = ti_csi2rx_of_match,
>>> +             .pm             = &ti_csi2rx_pm_ops,
>>>        },
>>>   };
>>>   

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ