Re: [PATCH v2 RESEND 5/6] rtsx_usb: hold runtime PM during transfers
From: Ulf Hansson
Date: Tue Mar 24 2026 - 08:17:21 EST
+ Matthew
On Thu, 12 Mar 2026 at 13:16, Sean Rhodes <sean@starlabs.systems> wrote:
>
> Hold a runtime-PM reference across bulk transfers, and mark the device
> busy afterwards.
>
> When runtime PM is already in progress (e.g. from rtsx_usb_suspend()),
> avoid forcing a runtime resume from within the PM path by using
> usb_autopm_get_interface_no_resume() unless the interface is already
> runtime-suspended.
Can you please clarify the problem further? It's unclear to me what
you mean by "runtime PM is already in progress."
>
> Signed-off-by: Sean Rhodes <sean@starlabs.systems>
> ---
> drivers/misc/cardreader/rtsx_usb.c | 38 ++++++++++++++++++++++++------
> 1 file changed, 31 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
> index 1830e9ed2521..5d818b632788 100644
> --- a/drivers/misc/cardreader/rtsx_usb.c
> +++ b/drivers/misc/cardreader/rtsx_usb.c
> @@ -12,6 +12,7 @@
> #include <linux/usb.h>
> #include <linux/platform_device.h>
> #include <linux/mfd/core.h>
> +#include <linux/pm_runtime.h>
> #include <linux/rtsx_usb.h>
>
> static int polling_pipe = 1;
> @@ -65,19 +66,42 @@ static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
> }
>
> int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
> - void *buf, unsigned int len, int num_sg,
> - unsigned int *act_len, int timeout)
> + void *buf, unsigned int len, int num_sg,
> + unsigned int *act_len, int timeout)
> {
> + int ret;
> + struct device *dev = &ucr->pusb_intf->dev;
> +
> if (timeout < 600)
> timeout = 600;
>
> + /*
> + * During runtime suspend/resume callbacks, avoid forcing a runtime resume
> + * from within the PM path. The device is still active when
> + * rtsx_usb_suspend() runs, but usb_autopm_get_interface() can block when
> + * runtime PM is already in progress.
> + */
Thanks for adding a comment here! Yet it's unfortunately not clear
enough to me what is happening.
Can you please elaborate a bit more?
> + if (pm_runtime_status_suspended(dev)) {
> + ret = usb_autopm_get_interface(ucr->pusb_intf);
> + } else {
> + usb_autopm_get_interface_no_resume(ucr->pusb_intf);
> + ret = 0;
> + }
> + if (ret)
> + return ret;
> +
> if (num_sg)
> - return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
> - (struct scatterlist *)buf, num_sg, len, act_len,
> - timeout);
> + ret = rtsx_usb_bulk_transfer_sglist(ucr, pipe,
> + (struct scatterlist *)buf,
> + num_sg, len, act_len,
> + timeout);
> else
> - return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
> - timeout);
> + ret = usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
> + timeout);
> +
> + usb_mark_last_busy(ucr->pusb_dev);
> + usb_autopm_put_interface(ucr->pusb_intf);
> + return ret;
> }
> EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
>
> --
> 2.51.0
Kind regards
Uffe