[PATCH 21/21] HID: haptic: move FF initialization into .input_configured()

Dmitry Torokhov <[email protected]> Mon, 03 Aug 2026 11:46:46 -0700
Newsgroups org.kernel.vger.linux-input,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Refactor hid_haptic_init() to take a direct pointer to input_dev and
integrate its invocation into hid_haptic_input_configured().

Update hid-multitouch to rely on the refactored callback to perform the
force-feedback initialization during the registration loop. This ensures
that force-feedback capabilities are set up before the input device is
registered and exposed to userspace, closing the registration race.

Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <[email protected]>
---
 drivers/hid/hid-haptic.c     | 45 +++++++++++++++++---------------------------
 drivers/hid/hid-haptic.h     |  6 ++++--
 drivers/hid/hid-multitouch.c | 10 +---------
 3 files changed, 22 insertions(+), 39 deletions(-)

diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c
index deadab28cdbe..5d365a9767dd 100644
--- a/drivers/hid/hid-haptic.c
+++ b/drivers/hid/hid-haptic.c
@@ -82,16 +82,24 @@ int hid_haptic_input_configured(struct hid_device *hdev,
 				struct hid_haptic_device *haptic,
 				struct hid_input *hi)
 {
+	int error;
 
-	if (hi->application == HID_DG_TOUCHPAD) {
-		if (haptic->auto_trigger_report &&
-		    haptic->manual_trigger_report) {
-			__set_bit(INPUT_PROP_PRESSUREPAD, hi->input->propbit);
-			return 1;
-		}
+	if (hi->application != HID_DG_TOUCHPAD)
+		return -1;
+
+	if (!haptic->auto_trigger_report || !haptic->manual_trigger_report)
+		return 0;
+
+	__set_bit(INPUT_PROP_PRESSUREPAD, hi->input->propbit);
+
+	error = hid_haptic_init(hdev, haptic, hi->input);
+	if (error) {
+		dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n",
+			 hdev->name);
 		return 0;
 	}
-	return -1;
+
+	return 1;
 }
 EXPORT_SYMBOL_GPL(hid_haptic_input_configured);
 
@@ -401,11 +409,9 @@ static void hid_haptic_destroy(struct ff_device *ff)
 }
 
 int hid_haptic_init(struct hid_device *hdev,
-		    struct hid_haptic_device **haptic_ptr)
+		    struct hid_haptic_device *haptic,
+		    struct input_dev *dev)
 {
-	struct hid_haptic_device *haptic = *haptic_ptr;
-	struct input_dev *dev = NULL;
-	struct hid_input *hidinput;
 	struct ff_device *ff;
 	int ret = 0, r;
 	struct ff_haptic_effect stop_effect = {
@@ -447,19 +453,6 @@ int hid_haptic_init(struct hid_device *hdev,
 	for (r = 0; r < haptic->auto_trigger_report->maxfield; r++)
 		parse_auto_trigger_field(haptic, haptic->auto_trigger_report->field[r]);
 
-	list_for_each_entry(hidinput, &hdev->inputs, list) {
-		if (hidinput->application == HID_DG_TOUCHPAD) {
-			dev = hidinput->input;
-			break;
-		}
-	}
-
-	if (!dev) {
-		dev_err(&hdev->dev, "Failed to find the input device\n");
-		ret = -ENODEV;
-		goto duration_map;
-	}
-
 	haptic->input_dev = dev;
 	haptic->manual_trigger_report_len =
 		hid_report_len(haptic->manual_trigger_report);
@@ -535,10 +528,6 @@ int hid_haptic_init(struct hid_device *hdev,
 
 input_free:
 	input_ff_destroy(dev);
-	/* Do not let double free happen, input_ff_destroy will call
-	 * hid_haptic_destroy.
-	 */
-	*haptic_ptr = NULL;
 	/* Restore dev flush and event */
 	dev->flush = flush;
 	dev->event = event;
diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h
index c6539ac04c1d..6332991a7844 100644
--- a/drivers/hid/hid-haptic.h
+++ b/drivers/hid/hid-haptic.h
@@ -69,7 +69,8 @@ int hid_haptic_input_mapping(struct hid_device *hdev,
 int hid_haptic_input_configured(struct hid_device *hdev,
 				struct hid_haptic_device *haptic,
 				struct hid_input *hi);
-int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr);
+int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device *haptic,
+		    struct input_dev *dev);
 void hid_haptic_handle_press_release(struct hid_haptic_device *haptic);
 void hid_haptic_pressure_reset(struct hid_haptic_device *haptic);
 void hid_haptic_pressure_increase(struct hid_haptic_device *haptic,
@@ -107,7 +108,8 @@ static inline
 void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic)
 {}
 static inline
-int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr)
+int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device *haptic,
+		    struct input_dev *dev)
 {
 	return 0;
 }
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index edb37b4c867e..15218e92aaa4 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -2189,16 +2189,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL);
 
-	if (td->is_haptic_touchpad) {
-		if (hid_haptic_init(hdev, &td->haptic)) {
-			dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n",
-				 hdev->name);
-			td->is_haptic_touchpad = false;
-			devm_kfree(&hdev->dev, td->haptic);
-		}
-	} else {
+	if (!td->is_haptic_touchpad)
 		devm_kfree(&hdev->dev, td->haptic);
-	}
 
 	return 0;
 }

-- 
2.55.0.629.g250fe7f194-goog