Re: [RFC PATCH 1/2] rtsx_usb: hold runtime PM during transfers

From: Ulf Hansson

Date: Mon Jul 06 2026 - 07:19:22 EST


On Mon, Apr 13, 2026 at 1:42 PM 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()),

What do you mean by "runtime PM is already in progress"? Is the device
in the process of being runtime resumed?

> 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.
>
> 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 f65acf4d1164..c8badd0db87b 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

Sorry, but I don't understand the above. Can you please elaborate?

> + * rtsx_usb_suspend() runs, but usb_autopm_get_interface() can block when
> + * runtime PM is already in progress.
> + */
> + if (pm_runtime_status_suspended(dev)) {

This looks odd to me. Should it not be the responsibility of the
caller to make sure the device's runtime is resumed before this
function gets called?

> + 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);

Kind regards
Uffe