public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Jie Deng <dengjie03@kylinos.cn>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Sasha Levin <sashal@kernel.org>,
	corbet@lwn.net, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
Subject: [PATCH AUTOSEL 6.19-6.1] usb: core: new quirk to handle devices with zero configurations
Date: Tue, 17 Mar 2026 07:32:40 -0400	[thread overview]
Message-ID: <20260317113249.117771-9-sashal@kernel.org> (raw)
In-Reply-To: <20260317113249.117771-1-sashal@kernel.org>

From: Jie Deng <dengjie03@kylinos.cn>

[ Upstream commit 9f6a983cfa22ac662c86e60816d3a357d4b551e9 ]

Some USB devices incorrectly report bNumConfigurations as 0 in their
device descriptor, which causes the USB core to reject them during
enumeration.
logs:
usb 1-2: device descriptor read/64, error -71
usb 1-2: no configurations
usb 1-2: can't read configurations, error -22

However, these devices actually work correctly when
treated as having a single configuration.

Add a new quirk USB_QUIRK_FORCE_ONE_CONFIG to handle such devices.
When this quirk is set, assume the device has 1 configuration instead
of failing with -EINVAL.

This quirk is applied to the device with VID:PID 5131:2007 which
exhibits this behavior.

Signed-off-by: Jie Deng <dengjie03@kylinos.cn>
Link: https://patch.msgid.link/20260227084931.1527461-1-dengjie03@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

## Analysis

### What the commit does

This commit introduces a new USB quirk `USB_QUIRK_FORCE_ONE_CONFIG`
(BIT(18)) for devices that incorrectly report `bNumConfigurations = 0`
in their device descriptor. Without this quirk, such devices are
rejected during enumeration with `-EINVAL` ("no configurations"). The
quirk forces the configuration count to 1, allowing the device to
enumerate normally.

It's applied to the Noji-MCS SmartCard Reader (VID:PID 5131:2007).

### Changes across files:
1. **`include/linux/usb/quirks.h`**: Adds `USB_QUIRK_FORCE_ONE_CONFIG`
   as BIT(18) — the next available bit
2. **`drivers/usb/core/config.c`**: Modifies `usb_get_configuration()`
   to force `ncfg=1` when the quirk is set, instead of returning
   `-EINVAL`
3. **`drivers/usb/core/quirks.c`**: Adds the device entry and 'q' case
   in the module parameter parser
4. **`Documentation/admin-guide/kernel-parameters.txt`**: Documents the
   'q' character mapping

### Bug classification: Hardware quirk

This is a textbook USB hardware quirk — a specific device reports broken
descriptors, and a per-device quirk makes it work. The stable kernel
rules explicitly allow hardware quirks as exceptions because they:
- Fix real hardware for real users
- Are narrowly scoped to specific VID:PID
- Use established, well-tested infrastructure
- Carry near-zero risk to other devices

### Code quality concerns

**Missing `break` in case 'q'**: The new case 'q' in
`quirks_param_set()` lacks a `break` statement (every other case a-p has
one). However, since 'q' is the **last case** before the switch closing
brace `}`, this is functionally harmless — fall-through hits the end of
the switch. It's a style issue, not a functional bug.

**Operator precedence in config.c**: The condition `ncfg < 1 &&
dev->quirks & USB_QUIRK_FORCE_ONE_CONFIG` is correct due to C
precedence: `<` (6) > `&` (8) > `&&` (11), so it evaluates as `(ncfg <
1) && (dev->quirks & USB_QUIRK_FORCE_ONE_CONFIG)`.

### Risk assessment

- **Scope**: Only affects VID:PID 5131:2007 — zero risk to other devices
- **Mechanism**: The quirk check in `usb_get_configuration()` is gated
  by the device-specific quirk flag
- **Timing**: `usb_detect_quirks()` is called in `hub_port_init()`
  before `usb_get_configuration()` is called in
  `usb_enumerate_device()`, so the quirk is available when needed
- **Size**: Small (~16 insertions), well-contained
- **Maintainer**: Signed off by Greg KH (USB subsystem maintainer)
- **Review**: Went through 3 versions (v1, v2, v3), with review from
  Alan Stern and Greg KH

### Considerations for stable

This is slightly more than a typical "add device ID to existing quirk"
because it introduces a new quirk type with new logic in
`usb_get_configuration()`. However:
- The new logic is 4 lines, guarded by the quirk flag
- It follows established patterns exactly
- Without it, the specific SmartCard reader is completely non-functional
- The USB quirk infrastructure is identical across stable trees

### Verification

- **Verified current code**: Read `drivers/usb/core/config.c:925-944`
  confirming the existing `ncfg < 1` check at line 930 that returns
  `-EINVAL`
- **Verified quirk bit allocation**: Read `include/linux/usb/quirks.h` —
  BIT(17) is `USB_QUIRK_NO_BOS`, BIT(18) is the next available
- **Verified missing break**: Read `drivers/usb/core/quirks.c:130-149` —
  confirmed all other cases (a-p) have `break` statements; the `}` at
  line 145 closes the switch, making the missing break harmless
- **Verified operator precedence**: C precedence rules make `ncfg < 1 &&
  dev->quirks & USB_QUIRK_FORCE_ONE_CONFIG` evaluate correctly
- **Verified timing**: Agent traced the call chain `hub_port_connect()`
  → `hub_port_init()` (calls `usb_detect_quirks()`) → `usb_new_device()`
  → `usb_enumerate_device()` → `usb_get_configuration()` — quirks are
  set before config reading
- **Verified mailing list**: lore.kernel.org shows 3 patch versions with
  review from Alan Stern and Greg KH; could not access full discussion
  content to determine specific reviewer concerns (unverified whether
  break issue was discussed)
- **Verified recent history**: `git log` shows `usb_quirk_list` and
  `quirks.h` are regularly updated with new quirks (e.g.,
  `USB_QUIRK_NO_BOS` was recently added following the same pattern)

### Conclusion

This is a hardware quirk that makes a completely broken USB SmartCard
reader functional. It follows the established USB quirk pattern, is
narrowly scoped to one device, carries near-zero risk, and was reviewed
and accepted by the USB subsystem maintainer. Hardware quirks are
explicitly listed as stable-worthy exceptions. The minor style issue
(missing `break`) does not affect functionality.

**YES**

 Documentation/admin-guide/kernel-parameters.txt | 3 +++
 drivers/usb/core/config.c                       | 6 +++++-
 drivers/usb/core/quirks.c                       | 5 +++++
 include/linux/usb/quirks.h                      | 3 +++
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index aa0031108bc1d..f31e9e4c598fc 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8090,6 +8090,9 @@ Kernel parameters
 				p = USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT
 					(Reduce timeout of the SET_ADDRESS
 					request from 5000 ms to 500 ms);
+				q = USB_QUIRK_FORCE_ONE_CONFIG (Device
+					claims zero configurations,
+					forcing to 1);
 			Example: quirks=0781:5580:bk,0a5c:5834:gij
 
 	usbhid.mousepoll=
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 2bb1ceb9d621a..3067e18ec4d8a 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -927,7 +927,11 @@ int usb_get_configuration(struct usb_device *dev)
 		dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
 	}
 
-	if (ncfg < 1) {
+	if (ncfg < 1 && dev->quirks & USB_QUIRK_FORCE_ONE_CONFIG) {
+		dev_info(ddev, "Device claims zero configurations, forcing to 1\n");
+		dev->descriptor.bNumConfigurations = 1;
+		ncfg = 1;
+	} else if (ncfg < 1) {
 		dev_err(ddev, "no configurations\n");
 		return -EINVAL;
 	}
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index c4d85089d19b1..53380296c94c6 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -141,6 +141,8 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp)
 			case 'p':
 				flags |= USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT;
 				break;
+			case 'q':
+				flags |= USB_QUIRK_FORCE_ONE_CONFIG;
 			/* Ignore unrecognized flag characters */
 			}
 		}
@@ -581,6 +583,9 @@ static const struct usb_device_id usb_quirk_list[] = {
 	/* VCOM device */
 	{ USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS },
 
+	/* Noji-MCS SmartCard Reader */
+	{ USB_DEVICE(0x5131, 0x2007), .driver_info = USB_QUIRK_FORCE_ONE_CONFIG },
+
 	/* INTEL VALUE SSD */
 	{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
 
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 2f7bd2fdc6164..b3cc7beab4a3c 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -78,4 +78,7 @@
 /* skip BOS descriptor request */
 #define USB_QUIRK_NO_BOS			BIT(17)
 
+/* Device claims zero configurations, forcing to 1 */
+#define USB_QUIRK_FORCE_ONE_CONFIG		BIT(18)
+
 #endif /* __LINUX_USB_QUIRKS_H */
-- 
2.51.0


  parent reply	other threads:[~2026-03-17 11:33 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-17 11:32 [PATCH AUTOSEL 6.19-6.1] ALSA: hda/realtek: add HP Laptop 14s-dr5xxx mute LED quirk Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.6] spi: intel-pci: Add support for Nova Lake mobile SPI flash Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19] objtool: Use HOSTCFLAGS for HAVE_XXHASH test Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.18] powerpc64/ftrace: fix OOL stub count with clang Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] nvmet: move async event work off nvmet-wq Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] drm/amdgpu: fix gpu idle power consumption issue for gfx v12 Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19] objtool/klp: Disable unsupported pr_debug() usage Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19] ALSA: usb-audio: Add iface reset and delay quirk for SPACETOUCH USB Audio Sasha Levin
2026-03-17 11:32 ` Sasha Levin [this message]
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] ALSA: hda/realtek: add quirk for ASUS UM6702RC Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.6] objtool: Handle Clang RSP musical chairs Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] sched_ext: Use WRITE_ONCE() for the write side of dsq->seq update Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.1] btrfs: set BTRFS_ROOT_ORPHAN_CLEANUP during subvol create Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.18] ALSA: hda/realtek: Add quirk for Gigabyte Technology to fix headphone Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] i3c: master: dw-i3c: Fix missing of_node for virtual I2C adapter Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-5.10] ALSA: hda/realtek: Add headset jack quirk for Thinkpad X390 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=20260317113249.117771-9-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=corbet@lwn.net \
    --cc=dengjie03@kylinos.cn \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    /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