From: Greg KH <gregkh@linuxfoundation.org>
To: Guan-Yu Lin <guanyulin@google.com>
Cc: mathias.nyman@intel.com, perex@perex.cz, tiwai@suse.com,
quic_wcheng@quicinc.com, broonie@kernel.org, arnd@arndb.de,
christophe.jaillet@wanadoo.fr, xiaopei01@kylinos.cn,
wesley.cheng@oss.qualcomm.com, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-sound@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH v2 2/2] ALSA: usb: qcom: manage offload device usage
Date: Wed, 11 Mar 2026 13:31:31 +0100 [thread overview]
Message-ID: <2026031115-unboxed-spouse-1dcd@gregkh> (raw)
In-Reply-To: <20260309022205.28136-3-guanyulin@google.com>
On Mon, Mar 09, 2026 at 02:22:05AM +0000, Guan-Yu Lin wrote:
> The Qualcomm USB audio offload driver currently does not report its offload
> activity to the USB core. This prevents the USB core from properly tracking
> active offload sessions, which could allow the device to auto-suspend while
> audio offloading is in progress.
>
> Integrate usb_offload_get() and usb_offload_put() calls into the offload
> stream setup and teardown paths. Specifically, call usb_offload_get() when
> initializing the event ring and usb_offload_put() when freeing it.
>
> Since the updated usb_offload_get() and usb_offload_put() APIs require the
> caller to hold the USB device lock, add the necessary device locking in
> handle_uaudio_stream_req() and qmi_stop_session() to satisfy this
> requirement.
>
> Cc: stable@vger.kernel.org
> Fixes: ef82a4803aab ("xhci: sideband: add api to trace sideband usage")
> Signed-off-by: Guan-Yu Lin <guanyulin@google.com>
> ---
> sound/usb/qcom/qc_audio_offload.c | 102 ++++++++++++++++++------------
> 1 file changed, 60 insertions(+), 42 deletions(-)
>
> diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c
> index cfb30a195364..1da243662327 100644
> --- a/sound/usb/qcom/qc_audio_offload.c
> +++ b/sound/usb/qcom/qc_audio_offload.c
> @@ -699,6 +699,7 @@ static void uaudio_event_ring_cleanup_free(struct uaudio_dev *dev)
> uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE,
> PAGE_SIZE);
> xhci_sideband_remove_interrupter(uadev[dev->chip->card->number].sb);
> + usb_offload_put(dev->udev);
> }
> }
>
> @@ -750,6 +751,7 @@ static void qmi_stop_session(void)
> struct snd_usb_substream *subs;
> struct usb_host_endpoint *ep;
> struct snd_usb_audio *chip;
> + struct usb_device *udev;
> struct intf_info *info;
> int pcm_card_num;
> int if_idx;
> @@ -791,8 +793,13 @@ static void qmi_stop_session(void)
> disable_audio_stream(subs);
> }
> atomic_set(&uadev[idx].in_use, 0);
> - guard(mutex)(&chip->mutex);
> - uaudio_dev_cleanup(&uadev[idx]);
> +
> + udev = uadev[idx].udev;
> + if (udev) {
> + guard(device)(&udev->dev);
> + guard(mutex)(&chip->mutex);
> + uaudio_dev_cleanup(&uadev[idx]);
Two locks? For one structure? Is this caller verifying that those
locks are held?
> + }
> }
> }
>
> @@ -1183,11 +1190,15 @@ static int uaudio_event_ring_setup(struct snd_usb_substream *subs,
> er_pa = 0;
>
> /* event ring */
> + ret = usb_offload_get(subs->dev);
> + if (ret < 0)
> + goto exit;
Where is the lock being held here?
This pushing the lock for USB calls "higher" up the call chain is rough,
and almost impossible to audit, given changes like this:
> @@ -1597,50 +1612,53 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle,
>
> uadev[pcm_card_num].ctrl_intf = chip->ctrl_intf;
>
> - if (req_msg->enable) {
> - ret = enable_audio_stream(subs,
> - map_pcm_format(req_msg->audio_format),
> - req_msg->number_of_ch, req_msg->bit_rate,
> - datainterval);
> -
> - if (!ret)
> - ret = prepare_qmi_response(subs, req_msg, &resp,
> - info_idx);
> - if (ret < 0) {
> - guard(mutex)(&chip->mutex);
> - subs->opened = 0;
> - }
> - } else {
> - info = &uadev[pcm_card_num].info[info_idx];
> - if (info->data_ep_pipe) {
> - ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
> - info->data_ep_pipe);
> - if (ep) {
> - xhci_sideband_stop_endpoint(uadev[pcm_card_num].sb,
> - ep);
> - xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb,
> - ep);
> + udev = subs->dev;
> + scoped_guard(device, &udev->dev) {
> + if (req_msg->enable) {
> + ret = enable_audio_stream(subs,
> + map_pcm_format(req_msg->audio_format),
> + req_msg->number_of_ch, req_msg->bit_rate,
> + datainterval);
> +
> + if (!ret)
> + ret = prepare_qmi_response(subs, req_msg, &resp,
> + info_idx);
> + if (ret < 0) {
> + guard(mutex)(&chip->mutex);
> + subs->opened = 0;
> + }
> + } else {
> + info = &uadev[pcm_card_num].info[info_idx];
> + if (info->data_ep_pipe) {
> + ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
> + info->data_ep_pipe);
> + if (ep) {
> + xhci_sideband_stop_endpoint(uadev[pcm_card_num].sb,
> + ep);
> + xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb,
> + ep);
> + }
> +
> + info->data_ep_pipe = 0;
> }
>
> - info->data_ep_pipe = 0;
> - }
> -
> - if (info->sync_ep_pipe) {
> - ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
> - info->sync_ep_pipe);
> - if (ep) {
> - xhci_sideband_stop_endpoint(uadev[pcm_card_num].sb,
> - ep);
> - xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb,
> - ep);
> + if (info->sync_ep_pipe) {
> + ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
> + info->sync_ep_pipe);
> + if (ep) {
> + xhci_sideband_stop_endpoint(uadev[pcm_card_num].sb,
> + ep);
> + xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb,
> + ep);
> + }
> +
> + info->sync_ep_pipe = 0;
> }
>
> - info->sync_ep_pipe = 0;
> + disable_audio_stream(subs);
> + guard(mutex)(&chip->mutex);
> + subs->opened = 0;
> }
> -
> - disable_audio_stream(subs);
> - guard(mutex)(&chip->mutex);
> - subs->opened = 0;
You have multiple levels of locks here, which is always a sign that
something has gone really wrong. This looks even more fragile and easy
to get wrong than before. Are you _SURE_ this is the only way to solve
this? The whole usb_offload_get() api seems more wrong to me than
before (and I didn't like it even then...)
In other words, this patch set feels rough, and adds more complexity
overall, requiring a reviewer to "know" where locks are held and not
held while before they did not. That's a lot to push onto us for
something that feels like is due to a broken hardware design?
thanks,
greg k-h
next prev parent reply other threads:[~2026-03-11 12:31 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260309022205.28136-1-guanyulin@google.com>
2026-03-09 2:22 ` [PATCH v2 1/2] usb: offload: move device locking to callers in offload.c Guan-Yu Lin
2026-03-11 12:26 ` Greg KH
2026-03-12 17:23 ` Guan-Yu Lin
2026-03-17 21:17 ` Wesley Cheng
2026-03-18 23:21 ` Guan-Yu Lin
2026-03-19 0:24 ` Wesley Cheng
2026-03-09 2:22 ` [PATCH v2 2/2] ALSA: usb: qcom: manage offload device usage Guan-Yu Lin
2026-03-11 12:31 ` Greg KH [this message]
2026-03-12 17:24 ` Guan-Yu Lin
2026-03-17 20:45 ` Guan-Yu Lin
2026-03-18 5:58 ` Greg KH
2026-03-18 23:29 ` Guan-Yu Lin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2026031115-unboxed-spouse-1dcd@gregkh \
--to=gregkh@linuxfoundation.org \
--cc=arnd@arndb.de \
--cc=broonie@kernel.org \
--cc=christophe.jaillet@wanadoo.fr \
--cc=guanyulin@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
--cc=perex@perex.cz \
--cc=quic_wcheng@quicinc.com \
--cc=stable@vger.kernel.org \
--cc=tiwai@suse.com \
--cc=wesley.cheng@oss.qualcomm.com \
--cc=xiaopei01@kylinos.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox