public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Takashi Iwai <tiwai@suse.de>, Sasha Levin <sashal@kernel.org>,
	perex@perex.cz, tiwai@suse.com, sdoregor@sdore.me,
	giun7a@gmail.com, connerknoxpublic@gmail.com, cyrozap@gmail.com,
	bp@suse.de, alsa-devel@alsa-project.org
Subject: [PATCH AUTOSEL 5.19 14/36] ALSA: usb-audio: Register card at the last interface
Date: Sun,  9 Oct 2022 19:52:00 -0400	[thread overview]
Message-ID: <20221009235222.1230786-14-sashal@kernel.org> (raw)
In-Reply-To: <20221009235222.1230786-1-sashal@kernel.org>

From: Takashi Iwai <tiwai@suse.de>

[ 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 <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 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 706d249a9ad6..3aea241435fb 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -690,7 +690,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;
@@ -699,14 +699,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)
@@ -813,6 +830,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) {
@@ -862,11 +880,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 ffbb4b0d09a0..2c6575029b1c 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


  parent reply	other threads:[~2022-10-10  0:19 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-09 23:51 [PATCH AUTOSEL 5.19 01/36] drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc() Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 02/36] drm: Use size_t type for len variable in drm_copy_field() Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 03/36] drm: Prevent drm_copy_field() to attempt copying a NULL pointer Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 04/36] drm/komeda: Fix handling of atomic commits in the atomic_commit_tail hook Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 05/36] gpu: lontium-lt9611: Fix NULL pointer dereference in lt9611_connector_init() Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 06/36] drm/amd/display: fix overflow on MIN_I64 definition Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 07/36] ALSA: usb-audio: Add quirk to enable Avid Mbox 3 support Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 08/36] udmabuf: Set ubuf->sg = NULL if the creation of sg table fails Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 09/36] platform/x86: pmc_atom: Improve quirk message to be less cryptic Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 10/36] drm: bridge: dw_hdmi: only trigger hotplug event on link change Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 11/36] drm/amdgpu: Skip the program of MMMC_VM_AGP_* in SRIOV on MMHUB v3_0_0 Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 12/36] drm/admgpu: Skip CG/PG on SOC21 under SRIOV VF Sasha Levin
2022-10-09 23:51 ` [PATCH AUTOSEL 5.19 13/36] drm: hide unregistered connectors from GETCONNECTOR IOCTL Sasha Levin
2022-10-09 23:52 ` Sasha Levin [this message]
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 15/36] drm/vc4: vec: Fix timings for VEC modes Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 16/36] ACPI: video: Change disable_backlight_sysfs_if quirks to acpi_backlight=native Sasha Levin
2022-10-10  7:35   ` Hans de Goede
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 17/36] drm: panel-orientation-quirks: Add quirk for Anbernic Win600 Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 18/36] drm: panel-orientation-quirks: Add quirk for Aya Neo Air Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 19/36] platform/chrome: cros_ec: Notify the PM of wake events during resume Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 20/36] platform/x86: hp-wmi: Setting thermal profile fails with 0x06 Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 21/36] platform/x86: msi-laptop: Change DMI match / alias strings to fix module autoloading Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 22/36] ALSA: intel-dspconfig: add ES8336 support for AlderLake-PS Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 23/36] ASoC: SOF: pci: Change DMI match info to support all Chrome platforms Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 24/36] ASoC: SOF: add quirk to override topology mclk_id Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 25/36] drm/amdgpu: SDMA update use unlocked iterator Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 26/36] drm/amd/display: correct hostvm flag Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 27/36] drm/amdgpu: fix initial connector audio value Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 28/36] drm/meson: reorder driver deinit sequence to fix use-after-free bug Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 29/36] drm/meson: explicitly remove aggregate driver at module unload time Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 30/36] drm/meson: remove drm bridges at aggregate driver unbind time Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 31/36] drm/exynos: Fix return type for mixer_mode_valid and hdmi_mode_valid Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 32/36] drm/dp: Don't rewrite link config when setting phy test pattern Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 33/36] drm/amd/display: Remove interface for periodic interrupt 1 Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 34/36] drm/amd/display: polling vid stream status in hpo dp blank Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 35/36] drm/amd/display: fix array-bounds error in dc_stream_remove_writeback() Sasha Levin
2022-10-09 23:52 ` [PATCH AUTOSEL 5.19 36/36] drm/amdkfd: Fix UBSAN shift-out-of-bounds warning Sasha Levin

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=20221009235222.1230786-14-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=alsa-devel@alsa-project.org \
    --cc=bp@suse.de \
    --cc=connerknoxpublic@gmail.com \
    --cc=cyrozap@gmail.com \
    --cc=giun7a@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=sdoregor@sdore.me \
    --cc=stable@vger.kernel.org \
    --cc=tiwai@suse.com \
    --cc=tiwai@suse.de \
    /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