summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDennis Wassenberg <dennis.wassenberg@secunet.com>2016-12-02 17:45:29 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-12-02 17:51:30 -0800
commite621132f934f5922e8a3968edd236f97cdad60cf (patch)
tree1133048e39447c9d4246dce23768c467a69d7629
parentc5e8848fc98e363ea51b68de01392366312d9efa (diff)
downloadlinux-e621132f934f5922e8a3968edd236f97cdad60cf.tar.bz2
Input: synaptics-rmi4 - f03 - grab data passed by transport device
First check if there are data available passed by the transport device. If data available use these data. If there are no data available try to read the rmi block if dsata are passed this way. This is the way the other rmi function handlers will do this. This patch is needed on HID devices because the firmware reads F03 data registers and adds them to the HID attention report. Reading those registers from the driver after the firmware read them will result in invalid data. Reviewed-by: Andrew Duggan <aduggan@synaptics.com> Signed-off-by: Dennis Wassenberg <dennis.wassenberg@secunet.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/rmi4/rmi_f03.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index 24c7375aa361..7a3ec0ed0c27 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -163,6 +163,7 @@ static int rmi_f03_config(struct rmi_function *fn)
static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
{
+ struct rmi_device *rmi_dev = fn->rmi_dev;
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
u16 data_addr = fn->fd.data_base_addr;
const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
@@ -173,15 +174,31 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
int i;
int error;
- /* Grab all of the data registers, and check them for data */
- error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
- &obs, ob_len);
- if (error) {
- dev_err(&fn->dev,
- "%s: Failed to read F03 output buffers: %d\n",
- __func__, error);
- serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
- return error;
+ if (!rmi_dev || !rmi_dev->xport)
+ return -ENODEV;
+
+ if (rmi_dev->xport->attn_data) {
+ /* First grab the data passed by the transport device */
+ if (rmi_dev->xport->attn_size < ob_len) {
+ dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
+ return 0;
+ }
+
+ memcpy(obs, rmi_dev->xport->attn_data, ob_len);
+
+ rmi_dev->xport->attn_data += ob_len;
+ rmi_dev->xport->attn_size -= ob_len;
+ } else {
+ /* Grab all of the data registers, and check them for data */
+ error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
+ &obs, ob_len);
+ if (error) {
+ dev_err(&fn->dev,
+ "%s: Failed to read F03 output buffers: %d\n",
+ __func__, error);
+ serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
+ return error;
+ }
}
for (i = 0; i < ob_len; i += RMI_F03_OB_SIZE) {