From: sashiko-bot@kernel.org
To: "Fenglin Wu" <fenglin.wu@oss.qualcomm.com>
Cc: linux-input@vger.kernel.org, robh@kernel.org,
devicetree@vger.kernel.org, conor+dt@kernel.org,
dmitry.torokhov@gmail.com
Subject: Re: [PATCH v5 3/3] input: misc: Add Qualcomm SPMI PMIC haptics driver
Date: Wed, 05 Aug 2026 06:28:57 +0000 [thread overview]
Message-ID: <20260805062858.67D3B1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260804-qcom-spmi-haptics-v5-3-77128ebbdd2d@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Multiplexing play_work for both playback requests and duration timers causes race conditions where active effect duration timers are overwritten, leading to indefinite playback.
- [High] The driver permanently disables the playback workqueue in `qcom_haptics_close()` but lacks an `open` callback to re-enable it, rendering the device inoperable after the first close.
- [High] Manually disabling the hardware module in `close()` desynchronizes the runtime PM state, causing subsequent playbacks to silently fail if started quickly.
--
--- Patch [3]: [PATCH v5 3/3] input: misc: Add Qualcomm SPMI PMIC haptics driver ---
commit 64b23ca2ca86ee295bdc5ad669c51fb6d603b0fc
Author: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
input: misc: Add Qualcomm SPMI PMIC haptics driver
Add an initial driver for the Qualcomm PMIH0108 PMIC haptics module,
named as HAP530_HV. This module supports several play modes, including
DIRECT_PLAY, FIFO, PAT_MEM, and SWR, each with distinct data sourcing
and hardware data handling logic. Currently, the driver provides support
for two play modes using the input force-feedback framework: FF_CONSTANT
effect for DIRECT_PLAY mode and FF_PERIODIC effect with FF_CUSTOM
waveform for FIFO mode.
diff --git a/drivers/input/misc/qcom-spmi-haptics.c b/drivers/input/misc/qcom-spmi-haptics.c
--- /dev/null
+++ b/drivers/input/misc/qcom-spmi-haptics.c
[ ... ]
> +static void haptics_play_work(struct work_struct *work)
> +{
> + struct qcom_haptics *h = container_of(to_delayed_work(work),
> + struct qcom_haptics, play_work);
> + struct haptics_play_req *req = haptics_dequeue_play_req(h);
> + bool rearmed = false;
> + u32 length_us;
> + int ret;
> +
> + guard(mutex)(&h->play_lock);
> +
> + if (!req) {
> + /*
> + * Not a new request: the play-duration re-arm timer fired
> + * so stop the play
> + */
> + if (h->active_effect_id != -1)
> + haptics_stop(h, false);
> + } else if (req->play) {
> + ret = haptics_start(h, req->effect_id);
> + if (ret) {
> + dev_err(h->dev, "play haptics failed, ret=%d\n", ret);
> + } else {
> + /*
> + * Re-arm the work to stop the play or advance
> + * to next play after the play duration
> + */
> + length_us = h->effects[req->effect_id].length_us;
> + if (length_us) {
> + schedule_delayed_work(&h->play_work,
> + usecs_to_jiffies(length_us));
> + rearmed = true;
> + }
> + }
> + } else {
> + if (req->effect_id == h->active_effect_id)
> + haptics_stop(h, false);
> + }
> +
> + kfree(req);
> +
> + /* Wait for the re-arm to stop the play */
> + if (rearmed)
> + return;
> +
> + /* Handle the remaining requests if the queue is not empty */
> + guard(spinlock_irqsave)(&h->play_queue_lock);
> + if (!list_empty(&h->play_queue))
> + schedule_delayed_work(&h->play_work, 0);
> +}
[Severity: High]
Does this code handle the active effect's stop timer correctly when a STOP
request for a different effect arrives?
If an effect is currently playing with a scheduled stop timer, and userspace
sends a STOP request for a different inactive effect, the worker sees that the
STOP request is for an inactive effect and drops it.
However, it appears it fails to re-arm the duration timer for the active
effect, which could result in the active effect vibrating indefinitely.
[ ... ]
> +static int haptics_playback(struct input_dev *dev, int effect_id, int val)
> +{
> + struct qcom_haptics *h = input_get_drvdata(dev);
> + int ret;
> +
> + ret = haptics_enqueue_play_req(h, effect_id, val > 0);
> + if (ret)
> + return ret;
> +
> + if (val > 0)
> + /*
> + * Queue the play. If a duration re-arm is already pending this
> + * is a no-op, so the new play waits for the current effect to
> + * finish before the worker dequeues it.
> + */
> + schedule_delayed_work(&h->play_work, 0);
> + else
> + /*
> + * Run the worker now, cancelling any pending duration re-arm,
> + * so an explicit stop takes effect immediately.
> + */
> + mod_delayed_work(system_percpu_wq, &h->play_work, 0);
> +
> + return 0;
> +}
[Severity: High]
Can calling mod_delayed_work() here overwrite an active duration timer?
If userspace sends a STOP request for a different inactive effect,
mod_delayed_work() is called unconditionally, cancelling the active effect's
duration timer before the worker gets a chance to process the inactive STOP
request.
[ ... ]
> +static void qcom_haptics_close(struct input_dev *input)
> +{
> + struct qcom_haptics *h = input_get_drvdata(input);
> +
> + cancel_work_sync(&h->gain_work);
> + haptics_enable_play_work(h, false);
> + scoped_guard(mutex, &h->play_lock) {
> + haptics_queue_flush(h);
> + haptics_stop(h, false);
> + }
> +
> + haptics_enable_module(h, false);
> +}
[Severity: High]
Does disabling play_work here permanently render the device inoperable?
When the input device is closed, haptics_enable_play_work() uses
disable_delayed_work_sync() which sets the WORK_STRUCT_DISABLE bit on the
play_work item.
Because there is no corresponding open() callback registered to re-enable it,
subsequent playback requests will fail to schedule the work after the device
is opened again.
[Severity: High]
Can manually disabling the hardware module here desynchronize the runtime PM
state?
Calling haptics_enable_module() directly bypasses the PM runtime framework.
Earlier in the close sequence, haptics_stop() calls
pm_runtime_put_autosuspend() which leaves the PM state as RPM_ACTIVE for the
1000ms autosuspend delay.
If userspace reopens the device and requests playback within this window,
haptics_start() will see the device as already active and skip calling
qcom_haptics_runtime_resume(). The hardware module will remain disabled,
causing subsequent register writes to be silently ignored.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260804-qcom-spmi-haptics-v5-0-77128ebbdd2d@oss.qualcomm.com?part=3
prev parent reply other threads:[~2026-08-05 6:28 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-05 6:18 [PATCH v5 0/3] input: misc: Add an initial driver for haptics inside Qcom PMIH010x PMIC Fenglin Wu
2026-08-05 6:18 ` [PATCH v5 1/3] dt-bindings: input: Add Qualcomm SPMI PMIC haptics Fenglin Wu
2026-08-05 6:18 ` [PATCH v5 2/3] dt-bindings: mfd: qcom,spmi-pmic: Document haptics device Fenglin Wu
2026-08-06 13:22 ` (subset) " Lee Jones
2026-08-05 6:18 ` [PATCH v5 3/3] input: misc: Add Qualcomm SPMI PMIC haptics driver Fenglin Wu
2026-08-05 6:28 ` sashiko-bot [this message]
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=20260805062858.67D3B1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=fenglin.wu@oss.qualcomm.com \
--cc=linux-input@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.