From nobody Mon Jun 8 04:11:21 2026 Received: from mail-dl1-f48.google.com (mail-dl1-f48.google.com [74.125.82.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A46E34071F5 for ; Sun, 7 Jun 2026 03:42:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780803744; cv=none; b=atKpMpv4c7LI6UfKRjcX3Vt3A79mx0ZNcp+LHm7P91ZKWihVrADJdI5bqEzThHrXhYhsJmGDKYdLV40EBFqXxVkSsaDjSBrYl2Jn8MTDJ5PbJDyVtXEP7FO2HPSftuyegZVhznE37hMIhUMWW1YivqY1A05MvtJ7qfBG0xoZvXo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780803744; c=relaxed/simple; bh=kPkBkM1Qtum7gCtRCRF0MmOLnxVYx6bjsFk60lfIDXo=; h=Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition; b=sDfPaQR9pXdSJF77mlGROlpCyaJLTDrHZW13GNpHGwNAhNGpr+W0H5e2j1Vg3Iv1AVNq58JJxq6rCxY9/suRuDEjJRy9jf7BLx8vdXVRYlUtJ7gxpaCiTJFdcbXaWp4+y3YeFDeKQLmv9jmde6RDD4WewXFmwmDKHtq8Owdn3ug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=pEtnSGzw; arc=none smtp.client-ip=74.125.82.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="pEtnSGzw" Received: by mail-dl1-f48.google.com with SMTP id a92af1059eb24-138129a622dso3489487c88.0 for ; Sat, 06 Jun 2026 20:42:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780803743; x=1781408543; darn=vger.kernel.org; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=LWaAnOrRSrm5ZXZjuybNvtusfLNLd0nfqfGYSdEQrmU=; b=pEtnSGzw1/OSy3pDV7+Bh4UNOgvct+wfCTp5aFFmjmEMCRQqYAPBKPj6blChyGqT8K CbIlBnI4q3U3QPdyWgY/gU+UnS2W5b5DO7zfEzZlzeph24dgbB4ZrFSlFfbSvMT2WibT HG/M79CVoBp9uOP3M92dYcnDaPrsEoVq5jWLLd/rstLUIInNx0oo6p446F08yKTUJxu2 oqCjHyu9gMKGF52SJvVUZZWO8n0/+tIhx+8JxyGDkEpUkiAJ9DIAVKEOn3pCeTVJyJ2s NQ5x+/giYm18klh1akC1/06NPuetT2ogJxWS/7CLgGiBISo5W/3A5iuS54WBaPWxmraV QYEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780803743; x=1781408543; h=content-disposition:mime-version:message-id:subject:cc:to:from:date :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=LWaAnOrRSrm5ZXZjuybNvtusfLNLd0nfqfGYSdEQrmU=; b=FZNvGZ7Ur44Qf2e1gWF9I8fdoQEibAOhh6dEchsFNB9MHCjYtt3f5xAzOLDyfzts+K S4GRh8/fIzamQAfaKuS8teCuqZVcRtijzwWpRrbmu5Cn584EXH8g96VxTi/ktUOxEyy0 DSTRcwmqAgiri1rPUQKgCz8xOhFSZU5h4bINumrELygOrCOHGy78yZKygJdsxHoky234 SsUakRAowABIEzAldXUWqwN+NVM0pAWqSvQnZ65lI8rUYEByaqBtMUBZaymu11HX8O8I 6mBXjtSMRXA40d7z4N/3cG7dKZhp6XJRz/NBKqBWr7IhNU89jLHaUBhD+RmNdGbUpZJk a5EA== X-Gm-Message-State: AOJu0Yx0gpcmjUjZWiVDeGvbiVAL/1KdmbXRiByJbz0HNZE6gJMhH0bp 3Y2Y4Jw7y/U556ZS4fiFPF89EaAXVn9RW8/VONhtLfk28bF+fjSMMqjP X-Gm-Gg: Acq92OEa9IIAst1LaJNX6itc5ODhj0cTuuFZZevZ2XU+mo2x/plCuysFShE6m6cqAQm A/1eRz0k/CkhW5cCSS8FGleE9Xlh1IVn1AJGV7xRC0gwcwjLkp0VQFJrou2WkEengMgrjAd/mzv NrbjnW1E+9XP3il1dvUy/uUG24TCm5EBpf12Q1D8CW2qQkg1VuvnKYAaQMQZfmX3eqhRHLZAU/3 rSL9v6XzIrtYzrK4ykjr/m0qFjQx8j1NlWrAR08oMILFVBzkPwRpWo7ZOo44gMV+V29YConSPFW hy/GYkxyDZi/xsjG+L2VY+IAnAqvpysrt0zeHLR5hSFWA82aS5y6dcrnQoAO/6vA+J7Aedn2M0Z lyygRZ6D0lwNxRtwQgsD2085A5b83XUZZ/P4+fBiESdxVi+TWogc/BkkyD5f7M3PLCJr5NWO2DK DHNLD7cxYt0U1FdFwqj51dvAlKeBmtZX8+tJUKOCEsq9HXGVsoVIspWV8Yccq8PGlwNNmAS3IuA So= X-Received: by 2002:a05:7022:3d04:b0:137:eda3:e5a9 with SMTP id a92af1059eb24-13806720e38mr5616462c88.28.1780803742463; Sat, 06 Jun 2026 20:42:22 -0700 (PDT) Received: from google.com ([2a00:79e0:2ebe:8:bb2f:1c0b:386d:8909]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-1381495bb00sm2869442c88.3.2026.06.06.20.42.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 06 Jun 2026 20:42:21 -0700 (PDT) Date: Sat, 6 Jun 2026 20:42:19 -0700 From: Dmitry Torokhov To: linux-input@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Benjamin Tissoires , Jiri Kosina Subject: [PATCH] Input: stop force-feedback timer when unregistering input devices Message-ID: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Memoryless force-feedback devices use a timer to manage playback of effects. When a driver for such a device is unbound (or the device is unregistered for other reasons), the driver typically frees its private data synchronously. However, the input_dev structure (and its associated force-feedback structures, including the timer) is only freed when the last user closes the corresponding device node. If userspace keeps the device node open while the device is unregistered (e.g., during driver unbind), the force-feedback timer can still fire after the driver's private data has been freed. Introduce a new 'stop' callback to struct ff_device, and call it from input_unregister_device() before the device is deleted. Implement this callback for memoryless devices and synchronously shut down the timer to ensure it is stopped and cannot be rearmed once unregistration happens. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 27 +++++++++++++++++++++------ drivers/input/input.c | 3 +++ include/linux/input.h | 3 +++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 937370d04928..d1fefd1dfc0d 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -484,17 +484,31 @@ static void ml_ff_destroy(struct ff_device *ff) struct ml_device *ml =3D ff->private; =20 /* - * Even though we stop all playing effects when tearing down - * an input device (via input_device_flush() that calls into - * input_ff_flush() that stops and erases all effects), we - * do not actually stop the timer, and therefore we should - * do it here. + * The timer is normally shut down in ml_ff_stop() when the device + * is unregistered. However, we still shut it down here as a safety + * net and for cases where the device was never registered (e.g. + * error paths during probe). */ - timer_delete_sync(&ml->timer); + timer_shutdown_sync(&ml->timer); =20 kfree(ml->private); } =20 +static void ml_ff_stop(struct ff_device *ff) +{ + struct ml_device *ml =3D ff->private; + + /* + * Even though we stop all playing effects when tearing down an + * input device (by the way of evdev calling input_flush_device() + * that calls into input_ff_flush() that stops and erases all + * effects), we do not actually shutdown the timer, and therefore + * we should do it here to prevent it firing after the input + * device is unregistered and its associated resources are freed. + */ + timer_shutdown_sync(&ml->timer); +} + /** * input_ff_create_memless() - create memoryless force-feedback device * @dev: input device supporting force-feedback @@ -529,6 +543,7 @@ int input_ff_create_memless(struct input_dev *dev, void= *data, ff->playback =3D ml_ff_playback; ff->set_gain =3D ml_ff_set_gain; ff->destroy =3D ml_ff_destroy; + ff->stop =3D ml_ff_stop; =20 /* we can emulate periodic effects with RUMBLE */ if (test_bit(FF_RUMBLE, ff->ffbit)) { diff --git a/drivers/input/input.c b/drivers/input/input.c index 39d9d2b1e3ca..cf6fecea79b8 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -2212,6 +2212,9 @@ static void __input_unregister_device(struct input_de= v *dev) input_wakeup_procfs_readers(); } =20 + if (dev->ff && dev->ff->stop) + dev->ff->stop(dev->ff); + device_del(&dev->dev); } =20 diff --git a/include/linux/input.h b/include/linux/input.h index 06ca62328db1..3022bb730898 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -543,6 +543,8 @@ extern const struct class input_class; * @set_autocenter: Called to auto-center device * @destroy: called by input core when parent input device is being * destroyed + * @stop: called by input core when parent input device is being + * unregistered * @private: driver-specific data, will be freed automatically * @ffbit: bitmap of force feedback capabilities truly supported by * device (not emulated like ones in input_dev->ffbit) @@ -571,6 +573,7 @@ struct ff_device { void (*set_autocenter)(struct input_dev *dev, u16 magnitude); =20 void (*destroy)(struct ff_device *); + void (*stop)(struct ff_device *); =20 void *private; =20 --=20 2.54.0.1032.g2f8565e1d1-goog --=20 Dmitry