From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AADA2E06E4; Tue, 25 Aug 2026 13:38:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787665112; cv=none; b=VjNfxwvNBZKJ8vcyzHcfA66hmnMvtA1fW4h+xZrkkFWqYKvPTQXSNfRgm22O0sdYveNMFciZ84IABYaXSBKc3LyWJizGMwIelZyyoW4ZoIxWszvm/og5pdpwAT2eLmUJ3htgkQeoC+vW7EZCaB7X2YBvmiG+0nUWjwF8aBRv6Sk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787665112; c=relaxed/simple; bh=lqcuM2EQv/lzG24QUBQCRykZFU3x2EzysGelYl0kCHY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LUCDMo6cN4nchTmOj9mOHRuaQkMJuOBPGShfr5FNGIlUqWwGUhvrm1g//uorO+EhJW4ZWU7vaSccfFxmfhoryC4tIDg7N3JM5QrLX+UfiiIucy8f0S/rbbk/9U6cpdOwjqSTf0k3xr1BKqjuRKh24aqcgSmUcAkkbW0qrWz+zo0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=1vwyUxCm; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="1vwyUxCm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D82F31F000E9; Tue, 25 Aug 2026 13:38:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1787665111; bh=U+Ajowpl6xyxPKSlmPdtJ+DOLi8VS9XRMTLyWxB3LpA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=1vwyUxCmyYv+X0QLtnkkpP2UafN1k1eUWw7u+PlOlvakovLnAyYI63FO6jJKLPDcp tmCy6mIXIJtOdUEODEKRCDRZnrRJFViz+5S58q5Ciq49I+Uv6KldAZt+s2J1fQIYB1 CtTzEWhtS/ACE5kteiMMIshNBdvM05AqkKHZxun4= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, "Geoffrey D. Bennett" , Takashi Iwai Subject: [PATCH 6.18 12/94] ALSA: FCP: Use a private URB for the notification endpoint Date: Tue, 25 Aug 2026 15:25:08 +0200 Message-ID: <20260825132542.364465122@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825132541.887883084@linuxfoundation.org> References: <20260825132541.887883084@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Geoffrey D. Bennett commit 918b8d231c571c50a00efe92ffc8404a537a0490 upstream. fcp_init_notify() used mixer->urb, which snd_usb_mixer_status_create() allocates for the optional UAC2 status interrupt endpoint and mixer.c kills, resubmits and frees. On a device with that endpoint, fcp_init_notify()'s "already set up" early return fires on the status URB and returns success without doing anything. No FCP notification URB is submitted, and cmd_done is left zeroed because it is initialised past that early return and nowhere else. fcp_init() then issues init1_opcode and wait_for_completion_timeout() would crash adding to the zeroed wait.head. fcp_cleanup_urb() would also kill and free mixer.c's status URB. Use a separate URB in fcp_data, and initialise cmd_done in fcp_init_private() where fcp_data is allocated. fcp_init_notify() is reached again after suspend via fcp_reinit(), and the URB kill path in fcp_notify() completes cmd_done, leaving a stale count that would satisfy the next command's wait before the device ACKs. Use reinit_completion() to clear it. Fixes: 46757a3e7d50 ("ALSA: FCP: Add Focusrite Control Protocol driver") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Geoffrey D. Bennett Signed-off-by: Takashi Iwai Link: https://patch.msgid.link/2cad281e6434024ca48a9ecc94fa19d6777e9be7.1786290885.git.g@b4.vu Signed-off-by: Greg Kroah-Hartman --- sound/usb/fcp.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) --- a/sound/usb/fcp.c +++ b/sound/usb/fcp.c @@ -82,6 +82,7 @@ struct fcp_data { struct mutex mutex; /* serialise access to the device */ struct completion cmd_done; /* wait for command completion */ struct file *file; /* hwdep file */ + struct urb *urb; /* FCP notification endpoint */ struct fcp_notify notify; @@ -194,7 +195,7 @@ static int fcp_usb(struct usb_mixer_inte const int max_retries = 5; int err; - if (!mixer->urb) + if (!private->urb) return -ENODEV; req = kmalloc(req_buf_size, GFP_KERNEL); @@ -307,7 +308,7 @@ static int fcp_reinit(struct usb_mixer_i void *step0_resp __free(kfree) = NULL; void *step2_resp __free(kfree) = NULL; - if (mixer->urb) + if (private->urb) return 0; step0_resp = kmalloc(private->step0_resp_size, GFP_KERNEL); @@ -901,13 +902,15 @@ static int fcp_hwdep_init(struct usb_mix static void fcp_cleanup_urb(struct usb_mixer_interface *mixer) { - if (!mixer->urb) + struct fcp_data *private = mixer->private_data; + + if (!private->urb) return; - usb_kill_urb(mixer->urb); - kfree(mixer->urb->transfer_buffer); - usb_free_urb(mixer->urb); - mixer->urb = NULL; + usb_kill_urb(private->urb); + kfree(private->urb->transfer_buffer); + usb_free_urb(private->urb); + private->urb = NULL; } static void fcp_private_free(struct usb_mixer_interface *mixer) @@ -978,37 +981,37 @@ static int fcp_init_notify(struct usb_mi int err; /* Already set up */ - if (mixer->urb) + if (private->urb) return 0; if (usb_pipe_type_check(dev, pipe)) return -EINVAL; - mixer->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mixer->urb) + private->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!private->urb) return -ENOMEM; transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL); if (!transfer_buffer) { - usb_free_urb(mixer->urb); - mixer->urb = NULL; + usb_free_urb(private->urb); + private->urb = NULL; return -ENOMEM; } - usb_fill_int_urb(mixer->urb, dev, pipe, + usb_fill_int_urb(private->urb, dev, pipe, transfer_buffer, private->wMaxPacketSize, fcp_notify, mixer, private->bInterval); - init_completion(&private->cmd_done); + reinit_completion(&private->cmd_done); - err = usb_submit_urb(mixer->urb, GFP_KERNEL); + err = usb_submit_urb(private->urb, GFP_KERNEL); if (err) { usb_audio_err(mixer->chip, "%s: usb_submit_urb failed: %d\n", __func__, err); kfree(transfer_buffer); - usb_free_urb(mixer->urb); - mixer->urb = NULL; + usb_free_urb(private->urb); + private->urb = NULL; } return err; @@ -1059,6 +1062,7 @@ static int fcp_init_private(struct usb_m return -ENOMEM; mutex_init(&private->mutex); + init_completion(&private->cmd_done); init_waitqueue_head(&private->notify.queue); spin_lock_init(&private->notify.lock);