Thread (74 messages) flat view 74 messages, 3 authors, 2d ago

Re: [RFC PATCH v3 1/2] HID: topping-m62: driver for the M62's vendor controls

From: sashiko-bot@kernel.org
Date: 2026-09-04 14:57:53

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Lockless access to newly initialized ALSA controls (m62->kctl) without memory barriers causing a data race.
- [Low] Mixing goto-based error handling with scope-based cleanup helpers (`scoped_guard`) in the same function.
--

commit 0bcb87ac2e7106ce707298feca287dd58398496f
Author: Mikhail Gavrilov [off-list ref]

HID: topping-m62: driver for the M62's vendor controls

This commit adds a driver for the Topping M62 USB audio interface to expose
vendor controls (such as analogue input gains, output volumes, and output
source selectors) through a HID-class interface. It registers a component
that interacts with the snd-usb-audio driver to add the controls to the
master sound card.
quoted hunk ↗ jump to hunk
diff --git a/drivers/hid/hid-topping-m62.c b/drivers/hid/hid-topping-m62.c
new file mode 100644
index 0000000000000..3c1b8e7626f69
--- /dev/null
+++ b/drivers/hid/hid-topping-m62.c
[ ... ]
+static int topping_raw_event(struct hid_device *hdev,
+			     struct hid_report *report, u8 *data, int size)
+{
[ ... ]
+	guard(spinlock_irqsave)(&m62->lock);
+
+	if (m62->val[idx] == value)
+		return 0;
+	m62->val[idx] = value;
+
+	if (m62->card && m62->kctl[idx])
+		snd_ctl_notify(m62->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &m62->kctl[idx]->id);
[Severity: High]
Can this lockless read of m62->kctl[idx] race with the initialization
in topping_add_kctl()?

Because hid_device_io_start() is called in topping_probe() before the
component binds, USB interrupts can arrive while topping_bind() is running.

In topping_bind(), m62->card is set early under a lock:

        scoped_guard(spinlock_irqsave, &m62->lock)
                m62->card = card;

This exposes it to the interrupt handler. When topping_bind() subsequently
allocates controls, it publishes them to m62->kctl locklessly in
topping_add_kctl():

        m62->kctl[slot] = kctl;

Without memory barriers or lock synchronization here, could the CPU reorder
the initialization, causing this interrupt handler to observe a non-NULL
pointer but crash or misbehave when snd_ctl_notify() dereferences it?
+
+	return 0;
+}
[ ... ]
+static int topping_bind(struct device *comp, struct device *master,
+			void *master_data)
+{
+	struct hid_device *hdev = to_hid_device(comp);
+	struct topping_m62 *m62 = hid_get_drvdata(hdev);
+	struct snd_card *card = master_data;
+	int i, err;
+
+	scoped_guard(spinlock_irqsave, &m62->lock)
+		m62->card = card;
+
+	for (i = 0; i < TOPPING_NUM_CTLS; i++) {
+		err = topping_add_kctl(m62, &topping_ctl,
+				       topping_m62_ctls[i].name, i, i,
+				       topping_m62_ctls[i].tlv);
+		if (err < 0)
+			goto err_drop;
[Severity: Low]
This is a stylistic issue, but does this function mix goto-based error
handling with scope-based cleanup helpers?

According to the kernel's cleanup subsystem guidelines, functions should not
mix goto labels (like err_drop) with scope-based cleanups (like
scoped_guard). This is to prevent confusing ownership semantics and fragile
cleanup paths. Should this function be converted entirely to scope-based
cleanups or revert to traditional locking?
+	}
-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260904144300.529289-1-mikhail.v.gavrilov@gmail.com?part=1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help