mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 1/3] Input: wacom_w8001 - fix teardown order and device lifetime
@ 2026-10-09 19:07 Dmitry Torokhov
  2026-10-09 19:07 ` [PATCH 2/3] Input: wacom_w8001 - assign distinct phys paths to pen and touch devices Dmitry Torokhov
  2026-10-09 19:07 ` [PATCH 3/3] Input: wacom_w8001 - use ACQUIRE() for interruptible mutex in w8001_open() Dmitry Torokhov
  0 siblings, 2 replies; 3+ messages in thread
From: Dmitry Torokhov @ 2026-10-09 19:07 UTC (permalink / raw)
  To: linux-input
  Cc: Ping Cheng, Jason Gerecke, Peter Hutterer, linux-kernel, sashiko-bot

In w8001_disconnect(), serio_close() was called before unregistering
the input devices. When input_unregister_device() calls w8001_close()
to shut down the hardware, w8001_command() fails because the serio
port is already closed, preventing W8001_CMD_STOP from reaching the
controller.

Additionally, w8001_connect() pre-allocated both pen_dev and touch_dev
upfront before serio_open() so w8001_interrupt() could dereference
them unconditionally, and then freed unused input devices mid-probe
without synchronizing with w8001_interrupt() when pen or touch was
absent. That created a race and use-after-free hazard with
w8001_interrupt(), as well as a double-free on the fail4 error path.

Fix these issues by guarding event reporting in w8001_interrupt()
against NULL device pointers, allocating and registering input devices
on demand after querying capabilities, synchronizing device pointer
publication and teardown with serio_pause_rx, and unregistering input
devices before closing the serio port in both disconnect and probe
error unwind paths.

Fixes: 66fd9385ee9c ("Input: wacom_w8001 - simplify w8001_remove")
Fixes: e0361b70175f ("Input: wacom_w8001 - split the touch and pen devices into two devices")
Reported-by: sashiko-bot@kernel.org
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/touchscreen/wacom_w8001.c | 341 +++++++++++++-----------
 1 file changed, 186 insertions(+), 155 deletions(-)

diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index d8d1cdc3f09e..1c48e2775214 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -302,7 +302,8 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
 
 		if (w8001->pktlen == w8001->idx) {
 			w8001->idx = 0;
-			if (w8001->type != BTN_TOOL_PEN &&
+			if (w8001->touch_dev &&
+			    w8001->type != BTN_TOOL_PEN &&
 			    w8001->type != BTN_TOOL_RUBBER) {
 				parse_single_touch(w8001->data, &coord);
 				report_single_touch(w8001, &coord);
@@ -321,8 +322,10 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
 			break;
 
 		w8001->idx = 0;
-		parse_pen_data(w8001->data, &coord);
-		report_pen_events(w8001, &coord);
+		if (w8001->pen_dev) {
+			parse_pen_data(w8001->data, &coord);
+			report_pen_events(w8001, &coord);
+		}
 		break;
 
 	/* control packet */
@@ -340,7 +343,8 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
 	/* 2 finger touch packet */
 	case W8001_PKTLEN_TOUCH2FG - 1:
 		w8001->idx = 0;
-		parse_multi_touch(w8001);
+		if (w8001->touch_dev)
+			parse_multi_touch(w8001);
 		break;
 
 	default:
@@ -349,7 +353,9 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
 		 * sends invalid data packets that are larger than
 		 * W8001_PKTLEN_TPCPEN. Let's start over again.
 		 */
-		if (!w8001->touch_dev && w8001->idx > W8001_PKTLEN_TPCPEN - 1)
+		if (!w8001->touch_dev &&
+		    (w8001->data[0] & W8001_TAB_MASK) != W8001_TAB_BYTE &&
+		    w8001->idx > W8001_PKTLEN_TPCPEN - 1)
 			w8001->idx = 0;
 	}
 
@@ -404,19 +410,6 @@ static void w8001_close(struct input_dev *dev)
 		w8001_command(w8001, W8001_CMD_STOP, false);
 }
 
-static int w8001_detect(struct w8001 *w8001)
-{
-	int error;
-
-	error = w8001_command(w8001, W8001_CMD_STOP, false);
-	if (error)
-		return error;
-
-	msleep(250);	/* wait 250ms before querying the device */
-
-	return 0;
-}
-
 static void w8001_append_suffix(char *dest, const char *suffix, size_t dest_sz)
 {
 	size_t used = strnlen(dest, dest_sz);
@@ -424,88 +417,54 @@ static void w8001_append_suffix(char *dest, const char *suffix, size_t dest_sz)
 	strscpy(dest + used, suffix, dest_sz - used);
 }
 
-static int w8001_setup_pen(struct w8001 *w8001, char *basename,
-			   size_t basename_sz)
+static bool w8001_detect_pen(struct w8001 *w8001,
+			     char *basename, size_t basename_sz,
+			     struct w8001_coord *coord)
 {
-	struct input_dev *dev = w8001->pen_dev;
-	struct w8001_coord coord;
 	int error;
 
-	/* penabled? */
 	error = w8001_command(w8001, W8001_CMD_QUERY, true);
 	if (error)
-		return error;
-
-	__set_bit(EV_KEY, dev->evbit);
-	__set_bit(EV_ABS, dev->evbit);
-	__set_bit(BTN_TOUCH, dev->keybit);
-	__set_bit(BTN_TOOL_PEN, dev->keybit);
-	__set_bit(BTN_TOOL_RUBBER, dev->keybit);
-	__set_bit(BTN_STYLUS, dev->keybit);
-	__set_bit(BTN_STYLUS2, dev->keybit);
-	__set_bit(INPUT_PROP_DIRECT, dev->propbit);
-
-	parse_pen_data(w8001->response, &coord);
-	w8001->max_pen_x = coord.x;
-	w8001->max_pen_y = coord.y;
-
-	input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
-	input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
-	input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION);
-	input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION);
-	input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
-	if (coord.tilt_x && coord.tilt_y) {
-		input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
-		input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
-	}
+		return false;
 
+	parse_pen_data(w8001->response, coord);
+	w8001->max_pen_x = coord->x;
+	w8001->max_pen_y = coord->y;
 	w8001->id = 0x90;
 	w8001_append_suffix(basename, " Penabled", basename_sz);
 
-	return 0;
+	return true;
 }
 
-static int w8001_setup_touch(struct w8001 *w8001, char *basename,
-			     size_t basename_sz)
+static bool w8001_detect_touch(struct w8001 *w8001,
+			       char *basename, size_t basename_sz,
+			       struct w8001_touch_query *touch)
 {
-	struct input_dev *dev = w8001->touch_dev;
-	struct w8001_touch_query touch;
 	int error;
 
-
-	/* Touch enabled? */
 	error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
 	if (error)
-		return error;
+		return false;
+
 	/*
 	 * Some non-touch devices may reply to the touch query. But their
 	 * second byte is empty, which indicates touch is not supported.
 	 */
 	if (!w8001->response[1])
-		return -ENXIO;
+		return false;
 
-	__set_bit(EV_KEY, dev->evbit);
-	__set_bit(EV_ABS, dev->evbit);
-	__set_bit(BTN_TOUCH, dev->keybit);
-	__set_bit(INPUT_PROP_DIRECT, dev->propbit);
-
-	parse_touchquery(w8001->response, &touch);
-	w8001->max_touch_x = touch.x;
-	w8001->max_touch_y = touch.y;
+	parse_touchquery(w8001->response, touch);
+	w8001->max_touch_x = touch->x;
+	w8001->max_touch_y = touch->y;
 
 	if (w8001->max_pen_x && w8001->max_pen_y) {
 		/* if pen is supported scale to pen maximum */
-		touch.x = w8001->max_pen_x;
-		touch.y = w8001->max_pen_y;
-		touch.panel_res = W8001_PEN_RESOLUTION;
+		touch->x = w8001->max_pen_x;
+		touch->y = w8001->max_pen_y;
+		touch->panel_res = W8001_PEN_RESOLUTION;
 	}
 
-	input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0);
-	input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0);
-	input_abs_set_res(dev, ABS_X, touch.panel_res);
-	input_abs_set_res(dev, ABS_Y, touch.panel_res);
-
-	switch (touch.sensor_id) {
+	switch (touch->sensor_id) {
 	case 0:
 	case 2:
 		w8001->pktlen = W8001_PKTLEN_TOUCH93;
@@ -523,24 +482,6 @@ static int w8001_setup_touch(struct w8001 *w8001, char *basename,
 
 	case 5:
 		w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
-
-		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
-		error = input_mt_init_slots(dev, 2, 0);
-		if (error) {
-			dev_err(&w8001->serio->dev,
-				"failed to initialize MT slots: %d\n", error);
-			return error;
-		}
-
-		input_set_abs_params(dev, ABS_MT_POSITION_X,
-					0, touch.x, 0, 0);
-		input_set_abs_params(dev, ABS_MT_POSITION_Y,
-					0, touch.y, 0, 0);
-		input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
-					0, MT_TOOL_MAX, 0, 0);
-		input_abs_set_res(dev, ABS_MT_POSITION_X, touch.panel_res);
-		input_abs_set_res(dev, ABS_MT_POSITION_Y, touch.panel_res);
-
 		w8001_append_suffix(basename, " 2FG", basename_sz);
 		if (w8001->max_pen_x && w8001->max_pen_y)
 			w8001->id = 0xE3;
@@ -550,13 +491,19 @@ static int w8001_setup_touch(struct w8001 *w8001, char *basename,
 	}
 
 	w8001_append_suffix(basename, " Touchscreen", basename_sz);
-
-	return 0;
+	return true;
 }
 
-static void w8001_set_devdata(struct input_dev *dev, struct w8001 *w8001,
-			      struct serio *serio)
+static struct input_dev *w8001_allocate_device(struct w8001 *w8001,
+					       const char *name)
 {
+	struct input_dev *dev;
+
+	dev = input_allocate_device();
+	if (!dev)
+		return NULL;
+
+	dev->name = name;
 	dev->phys = w8001->phys;
 	dev->id.bustype = BUS_RS232;
 	dev->id.product = w8001->id;
@@ -565,28 +512,139 @@ static void w8001_set_devdata(struct input_dev *dev, struct w8001 *w8001,
 	dev->open = w8001_open;
 	dev->close = w8001_close;
 
-	dev->dev.parent = &serio->dev;
+	dev->dev.parent = &w8001->serio->dev;
+
+	__set_bit(INPUT_PROP_DIRECT, dev->propbit);
+	input_set_capability(dev, EV_KEY, BTN_TOUCH);
 
 	input_set_drvdata(dev, w8001);
+
+	return dev;
+}
+
+static int w8001_setup_pen(struct w8001 *w8001, const char *basename,
+			   const struct w8001_coord *coord)
+{
+	struct input_dev *dev;
+	int error;
+
+	snprintf(w8001->pen_name, sizeof(w8001->pen_name), "%s Pen", basename);
+
+	dev = w8001_allocate_device(w8001, w8001->pen_name);
+	if (!dev)
+		return -ENOMEM;
+
+	__set_bit(BTN_TOOL_PEN, dev->keybit);
+	__set_bit(BTN_TOOL_RUBBER, dev->keybit);
+	__set_bit(BTN_STYLUS, dev->keybit);
+	__set_bit(BTN_STYLUS2, dev->keybit);
+
+	input_set_abs_params(dev, ABS_X, 0, coord->x, 0, 0);
+	input_set_abs_params(dev, ABS_Y, 0, coord->y, 0, 0);
+	input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION);
+	input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION);
+	input_set_abs_params(dev, ABS_PRESSURE, 0, coord->pen_pressure, 0, 0);
+	if (coord->tilt_x && coord->tilt_y) {
+		input_set_abs_params(dev, ABS_TILT_X, 0, coord->tilt_x, 0, 0);
+		input_set_abs_params(dev, ABS_TILT_Y, 0, coord->tilt_y, 0, 0);
+	}
+
+	scoped_guard(serio_pause_rx, w8001->serio)
+		w8001->pen_dev = dev;
+
+	error = input_register_device(dev);
+	if (error)
+		goto err_unpublish_dev;
+
+	return 0;
+
+err_unpublish_dev:
+	scoped_guard(serio_pause_rx, w8001->serio)
+		w8001->pen_dev = NULL;
+	input_free_device(dev);
+	return error;
+}
+
+static int w8001_setup_touch(struct w8001 *w8001, const char *basename,
+			     const struct w8001_touch_query *touch)
+{
+	struct input_dev *dev;
+	int error;
+
+	snprintf(w8001->touch_name, sizeof(w8001->touch_name), "%s Finger", basename);
+
+	dev = w8001_allocate_device(w8001, w8001->touch_name);
+	if (!dev)
+		return -ENOMEM;
+
+	input_set_abs_params(dev, ABS_X, 0, touch->x, 0, 0);
+	input_set_abs_params(dev, ABS_Y, 0, touch->y, 0, 0);
+	input_abs_set_res(dev, ABS_X, touch->panel_res);
+	input_abs_set_res(dev, ABS_Y, touch->panel_res);
+
+	if (touch->sensor_id == 5) {
+		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
+		error = input_mt_init_slots(dev, 2, 0);
+		if (error) {
+			dev_err(&w8001->serio->dev,
+				"failed to initialize MT slots: %d\n", error);
+			goto err_free_dev;
+		}
+
+		input_set_abs_params(dev, ABS_MT_POSITION_X, 0, touch->x, 0, 0);
+		input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, touch->y, 0, 0);
+		input_set_abs_params(dev, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
+		input_abs_set_res(dev, ABS_MT_POSITION_X, touch->panel_res);
+		input_abs_set_res(dev, ABS_MT_POSITION_Y, touch->panel_res);
+	}
+
+	scoped_guard(serio_pause_rx, w8001->serio)
+		w8001->touch_dev = dev;
+
+	error = input_register_device(dev);
+	if (error)
+		goto err_unpublish_dev;
+
+	return 0;
+
+err_unpublish_dev:
+	scoped_guard(serio_pause_rx, w8001->serio)
+		w8001->touch_dev = NULL;
+err_free_dev:
+	input_free_device(dev);
+	return error;
 }
 
 /*
  * w8001_disconnect() is the opposite of w8001_connect()
  */
 
+static void w8001_unregister_devices(struct w8001 *w8001)
+{
+	struct input_dev *pen_dev = NULL;
+	struct input_dev *touch_dev = NULL;
+
+	scoped_guard(serio_pause_rx, w8001->serio) {
+		swap(pen_dev, w8001->pen_dev);
+		swap(touch_dev, w8001->touch_dev);
+	}
+
+	if (pen_dev)
+		input_unregister_device(pen_dev);
+	if (touch_dev)
+		input_unregister_device(touch_dev);
+}
+
 static void w8001_disconnect(struct serio *serio)
 {
 	struct w8001 *w8001 = serio_get_drvdata(serio);
 
+	w8001_unregister_devices(w8001);
+
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 
-	if (w8001->pen_dev)
-		input_unregister_device(w8001->pen_dev);
-	if (w8001->touch_dev)
-		input_unregister_device(w8001->touch_dev);
 	kfree(w8001);
-
-	serio_set_drvdata(serio, NULL);
 }
 
 /*
@@ -598,22 +656,17 @@ static void w8001_disconnect(struct serio *serio)
 static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct w8001 *w8001;
-	struct input_dev *input_dev_pen;
-	struct input_dev *input_dev_touch;
+	struct w8001_coord coord;
+	struct w8001_touch_query touch;
 	char basename[64] = "Wacom Serial";
-	int err, err_pen, err_touch;
+	bool has_pen, has_touch;
+	int err;
 
 	w8001 = kzalloc_obj(*w8001);
-	input_dev_pen = input_allocate_device();
-	input_dev_touch = input_allocate_device();
-	if (!w8001 || !input_dev_pen || !input_dev_touch) {
-		err = -ENOMEM;
-		goto fail1;
-	}
+	if (!w8001)
+		return -ENOMEM;
 
 	w8001->serio = serio;
-	w8001->pen_dev = input_dev_pen;
-	w8001->touch_dev = input_dev_touch;
 	mutex_init(&w8001->mutex);
 	init_completion(&w8001->cmd_done);
 	snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
@@ -621,66 +674,44 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 	serio_set_drvdata(serio, w8001);
 	err = serio_open(serio, drv);
 	if (err)
-		goto fail2;
+		goto err_free_w8001;
 
-	err = w8001_detect(w8001);
+	err = w8001_command(w8001, W8001_CMD_STOP, false);
 	if (err)
-		goto fail3;
+		goto err_close_serio;
+
+	msleep(250);	/* wait 250ms before querying the device */
 
-	/* For backwards-compatibility we compose the basename based on
+	/*
+	 * For backwards-compatibility we compose the basename based on
 	 * capabilities and then just append the tool type
 	 */
-	err_pen = w8001_setup_pen(w8001, basename, sizeof(basename));
-	err_touch = w8001_setup_touch(w8001, basename, sizeof(basename));
-	if (err_pen && err_touch) {
+	has_pen = w8001_detect_pen(w8001, basename, sizeof(basename), &coord);
+	has_touch = w8001_detect_touch(w8001, basename, sizeof(basename), &touch);
+	if (!has_pen && !has_touch) {
 		err = -ENXIO;
-		goto fail3;
+		goto err_close_serio;
 	}
 
-	if (!err_pen) {
-		snprintf(w8001->pen_name, sizeof(w8001->pen_name),
-			 "%s Pen", basename);
-		input_dev_pen->name = w8001->pen_name;
-
-		w8001_set_devdata(input_dev_pen, w8001, serio);
-
-		err = input_register_device(w8001->pen_dev);
+	if (has_pen) {
+		err = w8001_setup_pen(w8001, basename, &coord);
 		if (err)
-			goto fail3;
-	} else {
-		input_free_device(input_dev_pen);
-		input_dev_pen = NULL;
-		w8001->pen_dev = NULL;
+			goto err_close_serio;
 	}
 
-	if (!err_touch) {
-		snprintf(w8001->touch_name, sizeof(w8001->touch_name),
-			 "%s Finger", basename);
-		input_dev_touch->name = w8001->touch_name;
-
-		w8001_set_devdata(input_dev_touch, w8001, serio);
-
-		err = input_register_device(w8001->touch_dev);
+	if (has_touch) {
+		err = w8001_setup_touch(w8001, basename, &touch);
 		if (err)
-			goto fail4;
-	} else {
-		input_free_device(input_dev_touch);
-		input_dev_touch = NULL;
-		w8001->touch_dev = NULL;
+			goto err_close_serio;
 	}
 
 	return 0;
 
-fail4:
-	if (w8001->pen_dev)
-		input_unregister_device(w8001->pen_dev);
-fail3:
+err_close_serio:
+	w8001_unregister_devices(w8001);
 	serio_close(serio);
-fail2:
+err_free_w8001:
 	serio_set_drvdata(serio, NULL);
-fail1:
-	input_free_device(input_dev_pen);
-	input_free_device(input_dev_touch);
 	kfree(w8001);
 	return err;
 }
-- 
2.56.0.385.gd3acb90ef8-goog


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/3] Input: wacom_w8001 - assign distinct phys paths to pen and touch devices
  2026-10-09 19:07 [PATCH 1/3] Input: wacom_w8001 - fix teardown order and device lifetime Dmitry Torokhov
@ 2026-10-09 19:07 ` Dmitry Torokhov
  2026-10-09 19:07 ` [PATCH 3/3] Input: wacom_w8001 - use ACQUIRE() for interruptible mutex in w8001_open() Dmitry Torokhov
  1 sibling, 0 replies; 3+ messages in thread
From: Dmitry Torokhov @ 2026-10-09 19:07 UTC (permalink / raw)
  To: linux-input; +Cc: Ping Cheng, Jason Gerecke, Peter Hutterer, linux-kernel

Previously, both pen and touch input devices used the same phys path
"%s/input0", which made it impossible for userspace or udev rules to
distinguish the devices by physical topology.

Assign distinct phys paths by introducing separate buffers pen_phys
("%s/input0") and touch_phys ("%s/input1") in struct w8001. Pass the
corresponding phys path to w8001_allocate_device() during pen and touch
setup, and drop the shared phys buffer from struct w8001.

Fixes: e0361b70175f ("Input: wacom_w8001 - split the touch and pen devices into two devices")
Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/touchscreen/wacom_w8001.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 1c48e2775214..e967f2413706 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -91,7 +91,8 @@ struct w8001 {
 	unsigned char response_type;
 	unsigned char response[W8001_MAX_LENGTH];
 	unsigned char data[W8001_MAX_LENGTH];
-	char phys[W8001_MAX_PHYS];
+	char pen_phys[W8001_MAX_PHYS];
+	char touch_phys[W8001_MAX_PHYS];
 	int type;
 	unsigned int pktlen;
 	u16 max_touch_x;
@@ -495,7 +496,8 @@ static bool w8001_detect_touch(struct w8001 *w8001,
 }
 
 static struct input_dev *w8001_allocate_device(struct w8001 *w8001,
-					       const char *name)
+					       const char *name,
+					       const char *phys)
 {
 	struct input_dev *dev;
 
@@ -504,7 +506,7 @@ static struct input_dev *w8001_allocate_device(struct w8001 *w8001,
 		return NULL;
 
 	dev->name = name;
-	dev->phys = w8001->phys;
+	dev->phys = phys;
 	dev->id.bustype = BUS_RS232;
 	dev->id.product = w8001->id;
 	dev->id.vendor = 0x056a;
@@ -529,8 +531,10 @@ static int w8001_setup_pen(struct w8001 *w8001, const char *basename,
 	int error;
 
 	snprintf(w8001->pen_name, sizeof(w8001->pen_name), "%s Pen", basename);
+	snprintf(w8001->pen_phys, sizeof(w8001->pen_phys), "%s/input0",
+		 w8001->serio->phys);
 
-	dev = w8001_allocate_device(w8001, w8001->pen_name);
+	dev = w8001_allocate_device(w8001, w8001->pen_name, w8001->pen_phys);
 	if (!dev)
 		return -ENOMEM;
 
@@ -572,8 +576,10 @@ static int w8001_setup_touch(struct w8001 *w8001, const char *basename,
 	int error;
 
 	snprintf(w8001->touch_name, sizeof(w8001->touch_name), "%s Finger", basename);
+	snprintf(w8001->touch_phys, sizeof(w8001->touch_phys), "%s/input1",
+		 w8001->serio->phys);
 
-	dev = w8001_allocate_device(w8001, w8001->touch_name);
+	dev = w8001_allocate_device(w8001, w8001->touch_name, w8001->touch_phys);
 	if (!dev)
 		return -ENOMEM;
 
@@ -669,7 +675,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 	w8001->serio = serio;
 	mutex_init(&w8001->mutex);
 	init_completion(&w8001->cmd_done);
-	snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
 
 	serio_set_drvdata(serio, w8001);
 	err = serio_open(serio, drv);
-- 
2.56.0.385.gd3acb90ef8-goog


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 3/3] Input: wacom_w8001 - use ACQUIRE() for interruptible mutex in w8001_open()
  2026-10-09 19:07 [PATCH 1/3] Input: wacom_w8001 - fix teardown order and device lifetime Dmitry Torokhov
  2026-10-09 19:07 ` [PATCH 2/3] Input: wacom_w8001 - assign distinct phys paths to pen and touch devices Dmitry Torokhov
@ 2026-10-09 19:07 ` Dmitry Torokhov
  1 sibling, 0 replies; 3+ messages in thread
From: Dmitry Torokhov @ 2026-10-09 19:07 UTC (permalink / raw)
  To: linux-input; +Cc: Ping Cheng, Jason Gerecke, Peter Hutterer, linux-kernel

Switch from scoped_guard(mutex_intr, ...) with an error fallback of
-EINTR to ACQUIRE(mutex_intr, lock) and ACQUIRE_ERR(mutex_intr, &lock).
This flattens the function logic and propagates the exact return value
from mutex_lock_interruptible().

Assisted-by: LLM
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/touchscreen/wacom_w8001.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index e967f2413706..b34fcac44f63 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -387,18 +387,20 @@ static int w8001_open(struct input_dev *dev)
 	struct w8001 *w8001 = input_get_drvdata(dev);
 	int err;
 
-	scoped_guard(mutex_intr, &w8001->mutex) {
-		if (w8001->open_count == 0) {
-			err = w8001_command(w8001, W8001_CMD_START, false);
-			if (err)
-				return err;
-		}
+	ACQUIRE(mutex_intr, lock)(&w8001->mutex);
+	err = ACQUIRE_ERR(mutex_intr, &lock);
+	if (err)
+		return err;
 
-		w8001->open_count++;
-		return 0;
+	if (w8001->open_count == 0) {
+		err = w8001_command(w8001, W8001_CMD_START, false);
+		if (err)
+			return err;
 	}
 
-	return -EINTR;
+	w8001->open_count++;
+
+	return 0;
 }
 
 static void w8001_close(struct input_dev *dev)
-- 
2.56.0.385.gd3acb90ef8-goog


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-09 19:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-09 19:07 [PATCH 1/3] Input: wacom_w8001 - fix teardown order and device lifetime Dmitry Torokhov
2026-10-09 19:07 ` [PATCH 2/3] Input: wacom_w8001 - assign distinct phys paths to pen and touch devices Dmitry Torokhov
2026-10-09 19:07 ` [PATCH 3/3] Input: wacom_w8001 - use ACQUIRE() for interruptible mutex in w8001_open() Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®