|
Takashi Iwai |
d2026c |
From 6abe534f0776d2437c8302f58d8eb5abd483e926 Mon Sep 17 00:00:00 2001
|
|
Takashi Iwai |
d2026c |
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
|
Takashi Iwai |
d2026c |
Date: Wed, 17 Jan 2018 15:46:18 -0800
|
|
Takashi Iwai |
d2026c |
Subject: [PATCH] Input: synaptics-rmi4 - unmask F03 interrupts when port is opened
|
|
Takashi Iwai |
d2026c |
Git-commit: 6abe534f0776d2437c8302f58d8eb5abd483e926
|
|
Takashi Iwai |
d2026c |
Patch-mainline: v4.16-rc1
|
|
Takashi Iwai |
d2026c |
References: bsc#1051510
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
Currently we register the pass-through serio port when we probe the F03 RMI
|
|
Takashi Iwai |
d2026c |
function, and then, in sensor configure phase, we unmask interrupts.
|
|
Takashi Iwai |
d2026c |
Unfortunately this is too late, as other drivers are free probe devices
|
|
Takashi Iwai |
d2026c |
attached to the serio port as soon as it is probed. Because interrupts are
|
|
Takashi Iwai |
d2026c |
masked, the IO times out, which may result in not being able to detect
|
|
Takashi Iwai |
d2026c |
trackpoints on the pass-through port.
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
To fix the issue we implement open() and close() methods for the
|
|
Takashi Iwai |
d2026c |
pass-through serio port and unmask interrupts from there. We also move
|
|
Takashi Iwai |
d2026c |
creation of the pass-through port form probe to configure stage, as RMI
|
|
Takashi Iwai |
d2026c |
driver does not enable transport interrupt until all functions are probed
|
|
Takashi Iwai |
d2026c |
(we should change this, but this is a separate topic).
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
We also try to clear the pending data before unmasking interrupts, because
|
|
Takashi Iwai |
d2026c |
some devices like to spam the system with multiple 0xaa 0x00 announcements,
|
|
Takashi Iwai |
d2026c |
which may interfere with us trying to query ID of the device.
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
Fixes: c5e8848fc98e ("Input: synaptics-rmi4 - add support for F03")
|
|
Takashi Iwai |
d2026c |
Cc: stable@vger.kernel.org
|
|
Takashi Iwai |
d2026c |
Reviewed-by: Lyude Paul <lyude@redhat.com>
|
|
Takashi Iwai |
d2026c |
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
|
Takashi Iwai |
d2026c |
Acked-by: Takashi Iwai <tiwai@suse.de>
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
---
|
|
Takashi Iwai |
d2026c |
drivers/input/rmi4/rmi_f03.c | 64 ++++++++++++++++++++++++++++++++++++-------
|
|
Takashi Iwai |
d2026c |
1 file changed, 54 insertions(+), 10 deletions(-)
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
--- a/drivers/input/rmi4/rmi_f03.c
|
|
Takashi Iwai |
d2026c |
+++ b/drivers/input/rmi4/rmi_f03.c
|
|
Takashi Iwai |
d2026c |
@@ -32,6 +32,7 @@ struct f03_data {
|
|
Takashi Iwai |
d2026c |
struct rmi_function *fn;
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
struct serio *serio;
|
|
Takashi Iwai |
d2026c |
+ bool serio_registered;
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
unsigned int overwrite_buttons;
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
@@ -138,6 +139,37 @@ static int rmi_f03_initialize(struct f03
|
|
Takashi Iwai |
d2026c |
return 0;
|
|
Takashi Iwai |
d2026c |
}
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
+static int rmi_f03_pt_open(struct serio *serio)
|
|
Takashi Iwai |
d2026c |
+{
|
|
Takashi Iwai |
d2026c |
+ struct f03_data *f03 = serio->port_data;
|
|
Takashi Iwai |
d2026c |
+ struct rmi_function *fn = f03->fn;
|
|
Takashi Iwai |
d2026c |
+ const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
|
|
Takashi Iwai |
d2026c |
+ const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET;
|
|
Takashi Iwai |
d2026c |
+ u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
|
|
Takashi Iwai |
d2026c |
+ int error;
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
+ /*
|
|
Takashi Iwai |
d2026c |
+ * Consume any pending data. Some devices like to spam with
|
|
Takashi Iwai |
d2026c |
+ * 0xaa 0x00 announcements which may confuse us as we try to
|
|
Takashi Iwai |
d2026c |
+ * probe the device.
|
|
Takashi Iwai |
d2026c |
+ */
|
|
Takashi Iwai |
d2026c |
+ error = rmi_read_block(fn->rmi_dev, data_addr, &obs, ob_len);
|
|
Takashi Iwai |
d2026c |
+ if (!error)
|
|
Takashi Iwai |
d2026c |
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev,
|
|
Takashi Iwai |
d2026c |
+ "%s: Consumed %*ph (%d) from PS2 guest\n",
|
|
Takashi Iwai |
d2026c |
+ __func__, ob_len, obs, ob_len);
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
+ return fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
|
|
Takashi Iwai |
d2026c |
+}
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
+static void rmi_f03_pt_close(struct serio *serio)
|
|
Takashi Iwai |
d2026c |
+{
|
|
Takashi Iwai |
d2026c |
+ struct f03_data *f03 = serio->port_data;
|
|
Takashi Iwai |
d2026c |
+ struct rmi_function *fn = f03->fn;
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
+ fn->rmi_dev->driver->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
|
|
Takashi Iwai |
d2026c |
+}
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
static int rmi_f03_register_pt(struct f03_data *f03)
|
|
Takashi Iwai |
d2026c |
{
|
|
Takashi Iwai |
d2026c |
struct serio *serio;
|
|
Takashi Iwai |
d2026c |
@@ -148,6 +180,8 @@ static int rmi_f03_register_pt(struct f0
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
serio->id.type = SERIO_PS_PSTHRU;
|
|
Takashi Iwai |
d2026c |
serio->write = rmi_f03_pt_write;
|
|
Takashi Iwai |
d2026c |
+ serio->open = rmi_f03_pt_open;
|
|
Takashi Iwai |
d2026c |
+ serio->close = rmi_f03_pt_close;
|
|
Takashi Iwai |
d2026c |
serio->port_data = f03;
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
strlcpy(serio->name, "Synaptics RMI4 PS/2 pass-through",
|
|
Takashi Iwai |
d2026c |
@@ -184,17 +218,27 @@ static int rmi_f03_probe(struct rmi_func
|
|
Takashi Iwai |
d2026c |
f03->device_count);
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
dev_set_drvdata(dev, f03);
|
|
Takashi Iwai |
d2026c |
-
|
|
Takashi Iwai |
d2026c |
- error = rmi_f03_register_pt(f03);
|
|
Takashi Iwai |
d2026c |
- if (error)
|
|
Takashi Iwai |
d2026c |
- return error;
|
|
Takashi Iwai |
d2026c |
-
|
|
Takashi Iwai |
d2026c |
return 0;
|
|
Takashi Iwai |
d2026c |
}
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
static int rmi_f03_config(struct rmi_function *fn)
|
|
Takashi Iwai |
d2026c |
{
|
|
Takashi Iwai |
d2026c |
- fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
|
|
Takashi Iwai |
d2026c |
+ struct f03_data *f03 = dev_get_drvdata(&fn->dev);
|
|
Takashi Iwai |
d2026c |
+ int error;
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
+ if (!f03->serio_registered) {
|
|
Takashi Iwai |
d2026c |
+ error = rmi_f03_register_pt(f03);
|
|
Takashi Iwai |
d2026c |
+ if (error)
|
|
Takashi Iwai |
d2026c |
+ return error;
|
|
Takashi Iwai |
d2026c |
+
|
|
Takashi Iwai |
d2026c |
+ f03->serio_registered = true;
|
|
Takashi Iwai |
d2026c |
+ } else {
|
|
Takashi Iwai |
d2026c |
+ /*
|
|
Takashi Iwai |
d2026c |
+ * We must be re-configuring the sensor, just enable
|
|
Takashi Iwai |
d2026c |
+ * interrupts for this function.
|
|
Takashi Iwai |
d2026c |
+ */
|
|
Takashi Iwai |
d2026c |
+ fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
|
|
Takashi Iwai |
d2026c |
+ }
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
return 0;
|
|
Takashi Iwai |
d2026c |
}
|
|
Takashi Iwai |
d2026c |
@@ -204,7 +248,7 @@ static int rmi_f03_attention(struct rmi_
|
|
Takashi Iwai |
d2026c |
struct rmi_device *rmi_dev = fn->rmi_dev;
|
|
Takashi Iwai |
d2026c |
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
|
|
Takashi Iwai |
d2026c |
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
|
|
Takashi Iwai |
d2026c |
- u16 data_addr = fn->fd.data_base_addr;
|
|
Takashi Iwai |
d2026c |
+ const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET;
|
|
Takashi Iwai |
d2026c |
const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
|
|
Takashi Iwai |
d2026c |
u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
|
|
Takashi Iwai |
d2026c |
u8 ob_status;
|
|
Takashi Iwai |
d2026c |
@@ -226,8 +270,7 @@ static int rmi_f03_attention(struct rmi_
|
|
Takashi Iwai |
d2026c |
drvdata->attn_data.size -= ob_len;
|
|
Takashi Iwai |
d2026c |
} else {
|
|
Takashi Iwai |
d2026c |
/* Grab all of the data registers, and check them for data */
|
|
Takashi Iwai |
d2026c |
- error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
|
|
Takashi Iwai |
d2026c |
- &obs, ob_len);
|
|
Takashi Iwai |
d2026c |
+ error = rmi_read_block(fn->rmi_dev, data_addr, &obs, ob_len);
|
|
Takashi Iwai |
d2026c |
if (error) {
|
|
Takashi Iwai |
d2026c |
dev_err(&fn->dev,
|
|
Takashi Iwai |
d2026c |
"%s: Failed to read F03 output buffers: %d\n",
|
|
Takashi Iwai |
d2026c |
@@ -266,7 +309,8 @@ static void rmi_f03_remove(struct rmi_fu
|
|
Takashi Iwai |
d2026c |
{
|
|
Takashi Iwai |
d2026c |
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
- serio_unregister_port(f03->serio);
|
|
Takashi Iwai |
d2026c |
+ if (f03->serio_registered)
|
|
Takashi Iwai |
d2026c |
+ serio_unregister_port(f03->serio);
|
|
Takashi Iwai |
d2026c |
}
|
|
Takashi Iwai |
d2026c |
|
|
Takashi Iwai |
d2026c |
struct rmi_function_handler rmi_f03_handler = {
|