Received: by 2002:a05:6358:1087:b0:cb:c9d3:cd90 with SMTP id j7csp58269rwi; Sun, 9 Oct 2022 18:26:47 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7lkR0AMy8B2E0qMSzPQCEvrQqFYuGXpxfMI5p4Zq7WfNw2vzF7l43uUVdgI84zZLO6iUi0 X-Received: by 2002:a17:90b:1b06:b0:20d:3b10:3817 with SMTP id nu6-20020a17090b1b0600b0020d3b103817mr3878738pjb.43.1665365206988; Sun, 09 Oct 2022 18:26:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665365206; cv=none; d=google.com; s=arc-20160816; b=DsMEEXqrMdN2u/7MqeGK82k3u7sZCSe/8XEr08uTb1ygi2E7eXOJvWLuU8CEyTTRLL 0stjaDSOAF0kNXFMgKDEuSlGYGoo+CQPSNc9PSfk0EsDHBFcdbdUG0J03fNSk2tKb4+X uDSWpGTxR9FLS9O1BzUfJRf410jo1unz/UEJdEGXQlDyvvT50sB1eP1UtxoPraL4qAzz E46+Q590JuOhmhZODj/ESYLkGRSnX23mOhXOIN3N10FkpJHPcsmlMK3FU5AE7SuS6Lb6 greOP1kTv3t8c7unUsMzTp8thzRQ5RENPJ0VZZyzc/M8ITM9vUe6BN7ICvsMnZnXIk9J z+iQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ez3LiAF9/bGxAoUBFlFi35Nmd+PeI6Efg2mzqXfCmNg=; b=0zCbVeA+e98v/IYMxPGOYB0+Xo9cNpdRBxTao8AyGY/t6/OlEHdfIzeWZ1d2PT+vI0 DP4FgpqgX9x5Jq1lHYEHGGoS9I+SFKnG/6c0+gWK8IIFwXfCYP3mcardSHxLkpKPwWx6 7Awli/j8Jl9PrKQLP3B+KrXraLbzZMLIpyqKXbj6C1De5P5GlzhSLgW15QYkJ8XgyVcv iHmnKqPRtl8SBpNxYJU2R5+3TYaaqpSzemww+ypzlHtHmeoMPvsn2GTGy799zL5ir6h2 C5z3RkKcKrXePkxNailtjCvnobkb/1wuJOtH+337U5jR9D0WyAjvI+2ILl6YPAoU+6od 9rgw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Z+UbWONW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i15-20020a63130f000000b0045fc63bf52csi8304286pgl.764.2022.10.09.18.26.35; Sun, 09 Oct 2022 18:26:46 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Z+UbWONW; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232575AbiJJAWO (ORCPT + 99 others); Sun, 9 Oct 2022 20:22:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232564AbiJJAUm (ORCPT ); Sun, 9 Oct 2022 20:20:42 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0777D1F2F5; Sun, 9 Oct 2022 16:55:02 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id D81CEB80DEA; Sun, 9 Oct 2022 23:55:00 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4607AC433C1; Sun, 9 Oct 2022 23:54:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1665359699; bh=eDeBSiIKixe6Te7PK8P1+e7QjUkM90YCHsUhK7/2fM8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z+UbWONWr3ti3tfeUJQCm7qtIwU6HLWrXt74+Zzvi7RviEgAEFkZyMBLqSM8iIDPE v4myRFsSgF4tGckxGlDm5o2e9guEa9CetA1fh3M2OeExJXK4O+23M2GSiiXcYUwLe0 yJBx3XTPQ5ei3d2qWRXRpd0iCnFJBzhBbMDqfF7ORAWoJ81DR/N28ii6uFsGQ19HSO NufFhy9GH1jF/W+IAlot+0JrPjGdMZ0KMtAZp1LoKRV8LIDxKvgCGTsmj+GHLHaCFi yDhOF76B3eEjcsFXz5i0BLx5yvikjdO9LrEOzt6SBG2IMbXSmIfsO+jzkuVCQM85rD fJ3ryWECN1QhA== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Takashi Iwai , Sasha Levin , perex@perex.cz, tiwai@suse.com, sdoregor@sdore.me, cyrozap@gmail.com, connerknoxpublic@gmail.com, giun7a@gmail.com, gregkh@linuxfoundation.org, bp@suse.de, alsa-devel@alsa-project.org Subject: [PATCH AUTOSEL 5.15 11/25] ALSA: usb-audio: Register card at the last interface Date: Sun, 9 Oct 2022 19:54:11 -0400 Message-Id: <20221009235426.1231313-11-sashal@kernel.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221009235426.1231313-1-sashal@kernel.org> References: <20221009235426.1231313-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Takashi Iwai [ Upstream commit 6392dcd1d0c7034ccf630ec55fc9e5810ecadf3b ] The USB-audio driver matches per interface, and as default, it registers the card instance at the very first instance. This can be a problem for the devices that have multiple interfaces to be probed, as the udev rule isn't applied properly for the later appearing interfaces. Although we introduced the delayed_register option and the quirks for covering those shortcomings, it's nothing but a workaround for specific devices. This patch is an another attempt to fix the problem in a more generic way. Now the driver checks the whole USB device descriptor at the very first time when an interface is attached to a sound card. It looks at each matching interface in the descriptor and remembers the last matching one. The snd_card_register() is invoked only when this last interface is probed. After this change, the quirks for the delayed registration become superfluous, hence they are removed along with the patch. OTOH, the delayed_register option is still kept, as it might be useful for some corner cases (e.g. a special driver overtakes the interface probe from the standard driver, and the last interface probe may miss). Link: https://lore.kernel.org/r/20220904161247.16461-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/card.c | 32 +++++++++++++++++++++++++------- sound/usb/quirks.c | 42 ------------------------------------------ sound/usb/quirks.h | 2 -- sound/usb/usbaudio.h | 1 + 4 files changed, 26 insertions(+), 51 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 713b84d8d42f..207c212eabde 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -689,7 +689,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id) return false; } -static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) +static int check_delayed_register_option(struct snd_usb_audio *chip) { int i; unsigned int id, inum; @@ -698,14 +698,31 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) if (delayed_register[i] && sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 && id == chip->usb_id) - return iface < inum; + return inum; } - return false; + return -1; } static const struct usb_device_id usb_audio_ids[]; /* defined below */ +/* look for the last interface that matches with our ids and remember it */ +static void find_last_interface(struct snd_usb_audio *chip) +{ + struct usb_host_config *config = chip->dev->actconfig; + struct usb_interface *intf; + int i; + + if (!config) + return; + for (i = 0; i < config->desc.bNumInterfaces; i++) { + intf = config->interface[i]; + if (usb_match_id(intf, usb_audio_ids)) + chip->last_iface = intf->altsetting[0].desc.bInterfaceNumber; + } + usb_audio_dbg(chip, "Found last interface = %d\n", chip->last_iface); +} + /* look for the corresponding quirk */ static const struct snd_usb_audio_quirk * get_alias_quirk(struct usb_device *dev, unsigned int id) @@ -812,6 +829,7 @@ static int usb_audio_probe(struct usb_interface *intf, err = -ENODEV; goto __error; } + find_last_interface(chip); } if (chip->num_interfaces >= MAX_CARD_INTERFACES) { @@ -861,11 +879,11 @@ static int usb_audio_probe(struct usb_interface *intf, chip->need_delayed_register = false; /* clear again */ } - /* we are allowed to call snd_card_register() many times, but first - * check to see if a device needs to skip it or do anything special + /* register card if we reach to the last interface or to the specified + * one given via option */ - if (!snd_usb_registration_quirk(chip, ifnum) && - !check_delayed_register_option(chip, ifnum)) { + if (check_delayed_register_option(chip) == ifnum || + chip->last_iface == ifnum) { err = snd_card_register(chip->card); if (err < 0) goto __error; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 194c75c45628..eadac586bcc8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2030,48 +2030,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, } } -/* - * registration quirk: - * the registration is skipped if a device matches with the given ID, - * unless the interface reaches to the defined one. This is for delaying - * the registration until the last known interface, so that the card and - * devices appear at the same time. - */ - -struct registration_quirk { - unsigned int usb_id; /* composed via USB_ID() */ - unsigned int interface; /* the interface to trigger register */ -}; - -#define REG_QUIRK_ENTRY(vendor, product, iface) \ - { .usb_id = USB_ID(vendor, product), .interface = (iface) } - -static const struct registration_quirk registration_quirks[] = { - REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ - REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ - REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */ - { 0 } /* terminator */ -}; - -/* return true if skipping registration */ -bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface) -{ - const struct registration_quirk *q; - - for (q = registration_quirks; q->usb_id; q++) - if (chip->usb_id == q->usb_id) - return iface < q->interface; - - /* Register as normal */ - return false; -} - /* * driver behavior quirk flags */ diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 31abb7cb01a5..f9bfd5ac7bab 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -48,8 +48,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, struct audioformat *fp, int stream); -bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface); - void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); #endif /* __USBAUDIO_QUIRKS_H */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 044cd7ab27cb..39c3c61a7e49 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,6 +37,7 @@ struct snd_usb_audio { unsigned int quirk_flags; unsigned int need_delayed_register:1; /* warn for delayed registration */ int num_interfaces; + int last_iface; int num_suspended_intf; int sample_rate_read_error; -- 2.35.1