Re: [PATCH v2 1/7] HID: sensor: hub: Synchronize callback removal with raw events
From: Jonathan Cameron
Date: Sat Nov 07 2026 - 15:14:46 EST
On Wed, 4 Nov 2026 12:13:57 -0800
Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx> wrote:
> Raw-event processing holds pdata->lock across callback lookup and
> invocation, and takes dyn_callback_lock during lookup. Removal must
> prevent both active callbacks and future lookups before client state can
> be released.
>
> Take pdata->lock before dyn_callback_lock, matching raw-event order,
> and unlink the callback while holding both locks. This ensures active
> raw-event callbacks have finished and prevents future lookups.
>
> Fixes: 401ca24fb34a ("HID: sensors: introduce sensor framework")
> Reported-by: Семён Марьясин <simeon@xxxxxxxxxxxxx>
> Closes: https://lore.kernel.org/all/CAM2dg7ewfVJSP4rFyhkCB1Rmd1+X56sAg=eUdbPthG2xrLqwQQ@xxxxxxxxxxxxxx/
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx>
Maybe a minimal fix is good for now, but I do note that we can
make this code nicer with some guard() magic.
Perhaps a follow up series to tidy this up.
Things are getting very messy around this driver wrt to fix vs
cleanup. Hopefully it won't cause too much of a problem in next
until I can merge the fixes back after they go upstream.
> ---
> drivers/hid/hid-sensor-hub.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> index 6470a290ebfc..0c4884c5821f 100644
> --- a/drivers/hid/hid-sensor-hub.c
> +++ b/drivers/hid/hid-sensor-hub.c
> @@ -173,7 +173,9 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
> struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);
> unsigned long flags;
>
> - spin_lock_irqsave(&pdata->dyn_callback_lock, flags);
> + /* Serialize callback removal with raw-event callback execution. */
> + spin_lock_irqsave(&pdata->lock, flags);
> + spin_lock(&pdata->dyn_callback_lock);
Do both of those with appropriate guard()
> list_for_each_entry(callback, &pdata->dyn_callback_list, list)
> if (callback->usage_id == usage_id &&
> callback->hsdev == hsdev) {
I'd just go long!
if (callback->usage_id == usage_id && callback->hsdev == hsdev) {
> @@ -181,7 +183,8 @@ int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
> kfree(callback);
> break;
And we can return here.
> }
> - spin_unlock_irqrestore(&pdata->dyn_callback_lock, flags);
> + spin_unlock(&pdata->dyn_callback_lock);
> + spin_unlock_irqrestore(&pdata->lock, flags);
>
> return 0;
> }