[PATCH 0/3] [SRU][B/OEM-B][PATCH 0/1] Fix touchpad not working

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/3] [SRU][B/OEM-B][PATCH 0/1] Fix touchpad not working

Aaron Ma
BugLink: https://bugs.launchpad.net/bugs/1854798

[Impact]
Synaptics s3203 touchpad not working after update to kernel
4.15.0-72-generic

[Fix]
After applied commit "Input: synaptics-rmi4 - avoid processing unknown
IRQs",
no irq response from touchpad.
This commit is depended on commit:
"Input: synaptics-rmi4 - convert irq distribution to irq_domain"

[Test]
Verified on hardware, tests results are good.

[Regression Potential]
Low.
Fix bug that introduced by stable release update.

2nd and 3rd patches are fixes for the 1st patch.
These commits are already included by eoan kernel, so bionic 4.15 only.

Andrew Duggan (1):
  Input: synaptics-rmi4 - disable the relative position IRQ in the F12
    driver

Nick Dyer (1):
  Input: synaptics-rmi4 - convert irq distribution to irq_domain

Wei Yongjun (1):
  Input: synaptics-rmi4 - fix the error return code in
    rmi_probe_interrupts()

 drivers/input/rmi4/Kconfig      |  1 +
 drivers/input/rmi4/rmi_bus.c    | 50 ++++++++++++++++++++++++++++++-
 drivers/input/rmi4/rmi_bus.h    | 10 ++++++-
 drivers/input/rmi4/rmi_driver.c | 52 +++++++++++++--------------------
 drivers/input/rmi4/rmi_f01.c    | 10 +++----
 drivers/input/rmi4/rmi_f03.c    |  9 +++---
 drivers/input/rmi4/rmi_f11.c    | 42 ++++++++++----------------
 drivers/input/rmi4/rmi_f12.c    | 36 +++++++++++++++++++----
 drivers/input/rmi4/rmi_f30.c    |  9 +++---
 drivers/input/rmi4/rmi_f34.c    |  5 ++--
 drivers/input/rmi4/rmi_f54.c    |  6 ----
 include/linux/rmi.h             |  2 ++
 12 files changed, 145 insertions(+), 87 deletions(-)

--
2.24.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/3] Input: synaptics-rmi4 - convert irq distribution to irq_domain

Aaron Ma
From: Nick Dyer <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1854798

Convert the RMI driver to use the standard mechanism for
distributing IRQs to the various functions.

Tested on:
* S7300 (F11, F34, F54)
* S7817 (F12, F34, F54)

Signed-off-by: Nick Dyer <[hidden email]>
Acked-by: Christopher Heiny <[hidden email]>
Signed-off-by: Dmitry Torokhov <[hidden email]>
(cherry picked from commit 24d28e4f1271cb2f91613dada8f2acccd00eff56)
Signed-off-by: Aaron Ma <[hidden email]>
---
 drivers/input/rmi4/Kconfig      |  1 +
 drivers/input/rmi4/rmi_bus.c    | 50 ++++++++++++++++++++++++++++++-
 drivers/input/rmi4/rmi_bus.h    | 10 ++++++-
 drivers/input/rmi4/rmi_driver.c | 52 +++++++++++++--------------------
 drivers/input/rmi4/rmi_f01.c    | 10 +++----
 drivers/input/rmi4/rmi_f03.c    |  9 +++---
 drivers/input/rmi4/rmi_f11.c    | 42 ++++++++++----------------
 drivers/input/rmi4/rmi_f12.c    |  8 ++---
 drivers/input/rmi4/rmi_f30.c    |  9 +++---
 drivers/input/rmi4/rmi_f34.c    |  5 ++--
 drivers/input/rmi4/rmi_f54.c    |  6 ----
 include/linux/rmi.h             |  2 ++
 12 files changed, 119 insertions(+), 85 deletions(-)

diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
index 7172b88cd064..fad2eae4a118 100644
--- a/drivers/input/rmi4/Kconfig
+++ b/drivers/input/rmi4/Kconfig
@@ -3,6 +3,7 @@
 #
 config RMI4_CORE
  tristate "Synaptics RMI4 bus support"
+ select IRQ_DOMAIN
  help
   Say Y here if you want to support the Synaptics RMI4 bus.  This is
   required for all RMI4 device support.
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index ae1bffe45c75..976f7308d3de 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -9,6 +9,8 @@
 
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/list.h>
 #include <linux/pm.h>
 #include <linux/rmi.h>
@@ -167,6 +169,39 @@ static inline void rmi_function_of_probe(struct rmi_function *fn)
 {}
 #endif
 
+static struct irq_chip rmi_irq_chip = {
+ .name = "rmi4",
+};
+
+static int rmi_create_function_irq(struct rmi_function *fn,
+   struct rmi_function_handler *handler)
+{
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
+ int i, error;
+
+ for (i = 0; i < fn->num_of_irqs; i++) {
+ set_bit(fn->irq_pos + i, fn->irq_mask);
+
+ fn->irq[i] = irq_create_mapping(drvdata->irqdomain,
+ fn->irq_pos + i);
+
+ irq_set_chip_data(fn->irq[i], fn);
+ irq_set_chip_and_handler(fn->irq[i], &rmi_irq_chip,
+ handle_simple_irq);
+ irq_set_nested_thread(fn->irq[i], 1);
+
+ error = devm_request_threaded_irq(&fn->dev, fn->irq[i], NULL,
+ handler->attention, IRQF_ONESHOT,
+ dev_name(&fn->dev), fn);
+ if (error) {
+ dev_err(&fn->dev, "Error %d registering IRQ\n", error);
+ return error;
+ }
+ }
+
+ return 0;
+}
+
 static int rmi_function_probe(struct device *dev)
 {
  struct rmi_function *fn = to_rmi_function(dev);
@@ -178,7 +213,14 @@ static int rmi_function_probe(struct device *dev)
 
  if (handler->probe) {
  error = handler->probe(fn);
- return error;
+ if (error)
+ return error;
+ }
+
+ if (fn->num_of_irqs && handler->attention) {
+ error = rmi_create_function_irq(fn, handler);
+ if (error)
+ return error;
  }
 
  return 0;
@@ -230,12 +272,18 @@ int rmi_register_function(struct rmi_function *fn)
 
 void rmi_unregister_function(struct rmi_function *fn)
 {
+ int i;
+
  rmi_dbg(RMI_DEBUG_CORE, &fn->dev, "Unregistering F%02X.\n",
  fn->fd.function_number);
 
  device_del(&fn->dev);
  of_node_put(fn->dev.of_node);
  put_device(&fn->dev);
+
+ for (i = 0; i < fn->num_of_irqs; i++)
+ irq_dispose_mapping(fn->irq[i]);
+
 }
 
 /**
diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
index b7625a9ac66a..96383eab41ba 100644
--- a/drivers/input/rmi4/rmi_bus.h
+++ b/drivers/input/rmi4/rmi_bus.h
@@ -14,6 +14,12 @@
 
 struct rmi_device;
 
+/*
+ * The interrupt source count in the function descriptor can represent up to
+ * 6 interrupt sources in the normal manner.
+ */
+#define RMI_FN_MAX_IRQS 6
+
 /**
  * struct rmi_function - represents the implementation of an RMI4
  * function for a particular device (basically, a driver for that RMI4 function)
@@ -26,6 +32,7 @@ struct rmi_device;
  * @irq_pos: The position in the irq bitfield this function holds
  * @irq_mask: For convenience, can be used to mask IRQ bits off during ATTN
  * interrupt handling.
+ * @irqs: assigned virq numbers (up to num_of_irqs)
  *
  * @node: entry in device's list of functions
  */
@@ -36,6 +43,7 @@ struct rmi_function {
  struct list_head node;
 
  unsigned int num_of_irqs;
+ int irq[RMI_FN_MAX_IRQS];
  unsigned int irq_pos;
  unsigned long irq_mask[];
 };
@@ -76,7 +84,7 @@ struct rmi_function_handler {
  void (*remove)(struct rmi_function *fn);
  int (*config)(struct rmi_function *fn);
  int (*reset)(struct rmi_function *fn);
- int (*attention)(struct rmi_function *fn, unsigned long *irq_bits);
+ irqreturn_t (*attention)(int irq, void *ctx);
  int (*suspend)(struct rmi_function *fn);
  int (*resume)(struct rmi_function *fn);
 };
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index bae46816a3b3..211832946e68 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -21,6 +21,7 @@
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/irqdomain.h>
 #include <uapi/linux/input.h>
 #include <linux/rmi.h>
 #include "rmi_bus.h"
@@ -127,28 +128,11 @@ static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
  return 0;
 }
 
-static void process_one_interrupt(struct rmi_driver_data *data,
-  struct rmi_function *fn)
-{
- struct rmi_function_handler *fh;
-
- if (!fn || !fn->dev.driver)
- return;
-
- fh = to_rmi_function_handler(fn->dev.driver);
- if (fh->attention) {
- bitmap_and(data->fn_irq_bits, data->irq_status, fn->irq_mask,
- data->irq_count);
- if (!bitmap_empty(data->fn_irq_bits, data->irq_count))
- fh->attention(fn, data->fn_irq_bits);
- }
-}
-
 static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
 {
  struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
  struct device *dev = &rmi_dev->dev;
- struct rmi_function *entry;
+ int i;
  int error;
 
  if (!data)
@@ -173,16 +157,8 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
  */
  mutex_unlock(&data->irq_mutex);
 
- /*
- * It would be nice to be able to use irq_chip to handle these
- * nested IRQs.  Unfortunately, most of the current customers for
- * this driver are using older kernels (3.0.x) that don't support
- * the features required for that.  Once they've shifted to more
- * recent kernels (say, 3.3 and higher), this should be switched to
- * use irq_chip.
- */
- list_for_each_entry(entry, &data->function_list, node)
- process_one_interrupt(data, entry);
+ for_each_set_bit(i, data->irq_status, data->irq_count)
+ handle_nested_irq(irq_find_mapping(data->irqdomain, i));
 
  if (data->input)
  input_sync(data->input);
@@ -1000,9 +976,13 @@ EXPORT_SYMBOL_GPL(rmi_driver_resume);
 static int rmi_driver_remove(struct device *dev)
 {
  struct rmi_device *rmi_dev = to_rmi_device(dev);
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
  rmi_disable_irq(rmi_dev, false);
 
+ irq_domain_remove(data->irqdomain);
+ data->irqdomain = NULL;
+
  rmi_f34_remove_sysfs(rmi_dev);
  rmi_free_function_list(rmi_dev);
 
@@ -1034,7 +1014,8 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
 {
  struct rmi_device *rmi_dev = data->rmi_dev;
  struct device *dev = &rmi_dev->dev;
- int irq_count;
+ struct fwnode_handle *fwnode = rmi_dev->xport->dev->fwnode;
+ int irq_count = 0;
  size_t size;
  int retval;
 
@@ -1045,7 +1026,6 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
  * being accessed.
  */
  rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
- irq_count = 0;
  data->bootloader_mode = false;
 
  retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
@@ -1057,6 +1037,15 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
  if (data->bootloader_mode)
  dev_warn(dev, "Device in bootloader mode.\n");
 
+ /* Allocate and register a linear revmap irq_domain */
+ data->irqdomain = irq_domain_create_linear(fwnode, irq_count,
+   &irq_domain_simple_ops,
+   data);
+ if (!data->irqdomain) {
+ dev_err(&rmi_dev->dev, "Failed to create IRQ domain\n");
+ return PTR_ERR(data->irqdomain);
+ }
+
  data->irq_count = irq_count;
  data->num_of_irq_regs = (data->irq_count + 7) / 8;
 
@@ -1079,10 +1068,9 @@ int rmi_init_functions(struct rmi_driver_data *data)
 {
  struct rmi_device *rmi_dev = data->rmi_dev;
  struct device *dev = &rmi_dev->dev;
- int irq_count;
+ int irq_count = 0;
  int retval;
 
- irq_count = 0;
  rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
  retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
  if (retval < 0) {
diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
index 8a07ae147df6..4edaa14fe878 100644
--- a/drivers/input/rmi4/rmi_f01.c
+++ b/drivers/input/rmi4/rmi_f01.c
@@ -681,9 +681,9 @@ static int rmi_f01_resume(struct rmi_function *fn)
  return 0;
 }
 
-static int rmi_f01_attention(struct rmi_function *fn,
-     unsigned long *irq_bits)
+static irqreturn_t rmi_f01_attention(int irq, void *ctx)
 {
+ struct rmi_function *fn = ctx;
  struct rmi_device *rmi_dev = fn->rmi_dev;
  int error;
  u8 device_status;
@@ -692,7 +692,7 @@ static int rmi_f01_attention(struct rmi_function *fn,
  if (error) {
  dev_err(&fn->dev,
  "Failed to read device status: %d.\n", error);
- return error;
+ return IRQ_RETVAL(error);
  }
 
  if (RMI_F01_STATUS_BOOTLOADER(device_status))
@@ -704,11 +704,11 @@ static int rmi_f01_attention(struct rmi_function *fn,
  error = rmi_dev->driver->reset_handler(rmi_dev);
  if (error) {
  dev_err(&fn->dev, "Device reset failed: %d\n", error);
- return error;
+ return IRQ_RETVAL(error);
  }
  }
 
- return 0;
+ return IRQ_HANDLED;
 }
 
 struct rmi_function_handler rmi_f01_handler = {
diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c
index 7ccbb370a9a8..58811e1d6945 100644
--- a/drivers/input/rmi4/rmi_f03.c
+++ b/drivers/input/rmi4/rmi_f03.c
@@ -243,8 +243,9 @@ static int rmi_f03_config(struct rmi_function *fn)
  return 0;
 }
 
-static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f03_attention(int irq, void *ctx)
 {
+ struct rmi_function *fn = ctx;
  struct rmi_device *rmi_dev = fn->rmi_dev;
  struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
  struct f03_data *f03 = dev_get_drvdata(&fn->dev);
@@ -261,7 +262,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
  /* First grab the data passed by the transport device */
  if (drvdata->attn_data.size < ob_len) {
  dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
- return 0;
+ return IRQ_HANDLED;
  }
 
  memcpy(obs, drvdata->attn_data.data, ob_len);
@@ -276,7 +277,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
  "%s: Failed to read F03 output buffers: %d\n",
  __func__, error);
  serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
- return error;
+ return IRQ_RETVAL(error);
  }
  }
 
@@ -302,7 +303,7 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
  serio_interrupt(f03->serio, ob_data, serio_flags);
  }
 
- return 0;
+ return IRQ_HANDLED;
 }
 
 static void rmi_f03_remove(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index bb63b8823d62..b07f55c6d0be 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -570,9 +570,7 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger)
 }
 
 static void rmi_f11_finger_handler(struct f11_data *f11,
-   struct rmi_2d_sensor *sensor,
-   unsigned long *irq_bits, int num_irq_regs,
-   int size)
+   struct rmi_2d_sensor *sensor, int size)
 {
  const u8 *f_state = f11->data.f_state;
  u8 finger_state;
@@ -581,12 +579,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
  int rel_fingers;
  int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
 
- int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
-  num_irq_regs * 8);
- int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
-  num_irq_regs * 8);
-
- if (abs_bits) {
+ if (sensor->report_abs) {
  if (abs_size > size)
  abs_fingers = size / RMI_F11_ABS_BYTES;
  else
@@ -604,19 +597,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
  rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i],
  finger_state, i);
  }
- }
 
- if (rel_bits) {
- if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
- rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
- else
- rel_fingers = sensor->nbr_fingers;
-
- for (i = 0; i < rel_fingers; i++)
- rmi_f11_rel_pos_report(f11, i);
- }
-
- if (abs_bits) {
  /*
  * the absolute part is made in 2 parts to allow the kernel
  * tracking to take place.
@@ -638,7 +619,16 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
  }
 
  input_mt_sync_frame(sensor->input);
+ } else if (sensor->report_rel) {
+ if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
+ rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
+ else
+ rel_fingers = sensor->nbr_fingers;
+
+ for (i = 0; i < rel_fingers; i++)
+ rmi_f11_rel_pos_report(f11, i);
  }
+
 }
 
 static int f11_2d_construct_data(struct f11_data *f11)
@@ -1275,8 +1265,9 @@ static int rmi_f11_config(struct rmi_function *fn)
  return 0;
 }
 
-static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f11_attention(int irq, void *ctx)
 {
+ struct rmi_function *fn = ctx;
  struct rmi_device *rmi_dev = fn->rmi_dev;
  struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
  struct f11_data *f11 = dev_get_drvdata(&fn->dev);
@@ -1302,13 +1293,12 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits)
  data_base_addr, f11->sensor.data_pkt,
  f11->sensor.pkt_size);
  if (error < 0)
- return error;
+ return IRQ_RETVAL(error);
  }
 
- rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
- drvdata->num_of_irq_regs, valid_bytes);
+ rmi_f11_finger_handler(f11, &f11->sensor, valid_bytes);
 
- return 0;
+ return IRQ_HANDLED;
 }
 
 static int rmi_f11_resume(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8b0db086d68a..e226def74d82 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -197,10 +197,10 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
  rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
 }
 
-static int rmi_f12_attention(struct rmi_function *fn,
-     unsigned long *irq_nr_regs)
+static irqreturn_t rmi_f12_attention(int irq, void *ctx)
 {
  int retval;
+ struct rmi_function *fn = ctx;
  struct rmi_device *rmi_dev = fn->rmi_dev;
  struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
  struct f12_data *f12 = dev_get_drvdata(&fn->dev);
@@ -222,7 +222,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
  if (retval < 0) {
  dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
  retval);
- return retval;
+ return IRQ_RETVAL(retval);
  }
  }
 
@@ -232,7 +232,7 @@ static int rmi_f12_attention(struct rmi_function *fn,
 
  input_mt_sync_frame(sensor->input);
 
- return 0;
+ return IRQ_HANDLED;
 }
 
 static int rmi_f12_write_control_regs(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
index 82e0f0d43d55..5e3ed5ac0c3e 100644
--- a/drivers/input/rmi4/rmi_f30.c
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -122,8 +122,9 @@ static void rmi_f30_report_button(struct rmi_function *fn,
  }
 }
 
-static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f30_attention(int irq, void *ctx)
 {
+ struct rmi_function *fn = ctx;
  struct f30_data *f30 = dev_get_drvdata(&fn->dev);
  struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
  int error;
@@ -134,7 +135,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
  if (drvdata->attn_data.size < f30->register_count) {
  dev_warn(&fn->dev,
  "F30 interrupted, but data is missing\n");
- return 0;
+ return IRQ_HANDLED;
  }
  memcpy(f30->data_regs, drvdata->attn_data.data,
  f30->register_count);
@@ -147,7 +148,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
  dev_err(&fn->dev,
  "%s: Failed to read F30 data registers: %d\n",
  __func__, error);
- return error;
+ return IRQ_RETVAL(error);
  }
  }
 
@@ -159,7 +160,7 @@ static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
  rmi_f03_commit_buttons(f30->f03);
  }
 
- return 0;
+ return IRQ_HANDLED;
 }
 
 static int rmi_f30_config(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c
index 4cfe9703a8e7..7268cf911845 100644
--- a/drivers/input/rmi4/rmi_f34.c
+++ b/drivers/input/rmi4/rmi_f34.c
@@ -101,8 +101,9 @@ static int rmi_f34_command(struct f34_data *f34, u8 command,
  return 0;
 }
 
-static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
+static irqreturn_t rmi_f34_attention(int irq, void *ctx)
 {
+ struct rmi_function *fn = ctx;
  struct f34_data *f34 = dev_get_drvdata(&fn->dev);
  int ret;
  u8 status;
@@ -127,7 +128,7 @@ static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
  complete(&f34->v7.cmd_done);
  }
 
- return 0;
+ return IRQ_HANDLED;
 }
 
 static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c
index 5343f2c08f15..98a935efec8e 100644
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -610,11 +610,6 @@ static void rmi_f54_work(struct work_struct *work)
  mutex_unlock(&f54->data_mutex);
 }
 
-static int rmi_f54_attention(struct rmi_function *fn, unsigned long *irqbits)
-{
- return 0;
-}
-
 static int rmi_f54_config(struct rmi_function *fn)
 {
  struct rmi_driver *drv = fn->rmi_dev->driver;
@@ -756,6 +751,5 @@ struct rmi_function_handler rmi_f54_handler = {
  .func = 0x54,
  .probe = rmi_f54_probe,
  .config = rmi_f54_config,
- .attention = rmi_f54_attention,
  .remove = rmi_f54_remove,
 };
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index 64125443f8a6..5ef5c7c412a7 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -354,6 +354,8 @@ struct rmi_driver_data {
  struct mutex irq_mutex;
  struct input_dev *input;
 
+ struct irq_domain *irqdomain;
+
  u8 pdt_props;
 
  u8 num_rx_electrodes;
--
2.24.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/3] Input: synaptics-rmi4 - fix the error return code in rmi_probe_interrupts()

Aaron Ma
In reply to this post by Aaron Ma
From: Wei Yongjun <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1854798

The error return code PTR_ERR(data->irqdomain) is always 0 since
data->irqdomain is equal to NULL in this error handling case.

Fixes: 24d28e4f1271 ("Input: synaptics-rmi4 - convert irq distribution to irq_domain")
Signed-off-by: Wei Yongjun <[hidden email]>
Reviewed-by: Lyude Paul <[hidden email]>
Reviewed-by: Nick Desaulniers <[hidden email]>
Signed-off-by: Dmitry Torokhov <[hidden email]>
(cherry picked from commit fd629294759b1e6e5dfc0c9bf892e63553dcc6fa)
Signed-off-by: Aaron Ma <[hidden email]>
---
 drivers/input/rmi4/rmi_driver.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 211832946e68..fb882f6e7abb 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -1043,7 +1043,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
    data);
  if (!data->irqdomain) {
  dev_err(&rmi_dev->dev, "Failed to create IRQ domain\n");
- return PTR_ERR(data->irqdomain);
+ return -ENOMEM;
  }
 
  data->irq_count = irq_count;
--
2.24.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 3/3] Input: synaptics-rmi4 - disable the relative position IRQ in the F12 driver

Aaron Ma
In reply to this post by Aaron Ma
From: Andrew Duggan <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1854798

This patch fixes an issue seen on HID touchpads which report finger
positions using RMI4 Function 12. The issue manifests itself as
spurious button presses as described in:
https://www.spinics.net/lists/linux-input/msg58618.html

Commit 24d28e4f1271 ("Input: synaptics-rmi4 - convert irq distribution
to irq_domain") switched the RMI4 driver to using an irq_domain to handle
RMI4 function interrupts. Functions with more then one interrupt now have
each interrupt mapped to their own IRQ and IRQ handler. The result of
this change is that the F12 IRQ handler was now getting called twice. Once
for the absolute data interrupt and once for the relative data interrupt.
For HID devices, calling rmi_f12_attention() a second time causes the
attn_data data pointer and size to be set incorrectly. When the touchpad
button is pressed, F30 will generate an interrupt and attempt to read the
F30 data from the invalid attn_data data pointer and report incorrect
button events.

This patch disables the F12 relative interrupt which prevents
rmi_f12_attention() from being called twice.

Signed-off-by: Andrew Duggan <[hidden email]>
Reported-by: Simon Wood <[hidden email]>
Cc: [hidden email]
Link: https://lore.kernel.org/r/20191025002527.3189-2-aduggan@...
Signed-off-by: Dmitry Torokhov <[hidden email]>
(cherry picked from commit f6aabe1ff1d9d7bad0879253011216438bdb2530)
Signed-off-by: Aaron Ma <[hidden email]>
---
 drivers/input/rmi4/rmi_f12.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index e226def74d82..63ebefa967f4 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -58,6 +58,9 @@ struct f12_data {
 
  const struct rmi_register_desc_item *data15;
  u16 data15_offset;
+
+ unsigned long *abs_mask;
+ unsigned long *rel_mask;
 };
 
 static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
@@ -296,9 +299,18 @@ static int rmi_f12_write_control_regs(struct rmi_function *fn)
 static int rmi_f12_config(struct rmi_function *fn)
 {
  struct rmi_driver *drv = fn->rmi_dev->driver;
+ struct f12_data *f12 = dev_get_drvdata(&fn->dev);
+ struct rmi_2d_sensor *sensor;
  int ret;
 
- drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
+ sensor = &f12->sensor;
+
+ if (!sensor->report_abs)
+ drv->clear_irq_bits(fn->rmi_dev, f12->abs_mask);
+ else
+ drv->set_irq_bits(fn->rmi_dev, f12->abs_mask);
+
+ drv->clear_irq_bits(fn->rmi_dev, f12->rel_mask);
 
  ret = rmi_f12_write_control_regs(fn);
  if (ret)
@@ -320,9 +332,12 @@ static int rmi_f12_probe(struct rmi_function *fn)
  struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
  struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
  u16 data_offset = 0;
+ int mask_size;
 
  rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
 
+ mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long);
+
  ret = rmi_read(fn->rmi_dev, query_addr, &buf);
  if (ret < 0) {
  dev_err(&fn->dev, "Failed to read general info register: %d\n",
@@ -337,10 +352,19 @@ static int rmi_f12_probe(struct rmi_function *fn)
  return -ENODEV;
  }
 
- f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data), GFP_KERNEL);
+ f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
+ GFP_KERNEL);
  if (!f12)
  return -ENOMEM;
 
+ f12->abs_mask = (unsigned long *)((char *)f12
+ + sizeof(struct f12_data));
+ f12->rel_mask = (unsigned long *)((char *)f12
+ + sizeof(struct f12_data) + mask_size);
+
+ set_bit(fn->irq_pos, f12->abs_mask);
+ set_bit(fn->irq_pos + 1, f12->rel_mask);
+
  f12->has_dribble = !!(buf & BIT(3));
 
  if (fn->dev.of_node) {
--
2.24.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/3] [SRU][B/OEM-B][PATCH 0/1] Fix touchpad not working

Kleber Souza
In reply to this post by Aaron Ma
On 2019-12-04 05:59, Aaron Ma wrote:

> BugLink: https://bugs.launchpad.net/bugs/1854798
>
> [Impact]
> Synaptics s3203 touchpad not working after update to kernel
> 4.15.0-72-generic
>
> [Fix]
> After applied commit "Input: synaptics-rmi4 - avoid processing unknown
> IRQs",
> no irq response from touchpad.
> This commit is depended on commit:
> "Input: synaptics-rmi4 - convert irq distribution to irq_domain"
>
> [Test]
> Verified on hardware, tests results are good.
>
> [Regression Potential]
> Low.
> Fix bug that introduced by stable release update.
>
> 2nd and 3rd patches are fixes for the 1st patch.
> These commits are already included by eoan kernel, so bionic 4.15 only.

As discussed on IRC, these patches might be no needed, as the commit
that introduced the issue ("Input: synaptics-rmi4 - avoid processing unknown
IRQs") was reverted in v4.14.155 and picked up by 4.15.0-73. However,
I will not NAK it for now until we have a plan on how to fix this issue.


Thanks,
Kleber

>
> Andrew Duggan (1):
>   Input: synaptics-rmi4 - disable the relative position IRQ in the F12
>     driver
>
> Nick Dyer (1):
>   Input: synaptics-rmi4 - convert irq distribution to irq_domain
>
> Wei Yongjun (1):
>   Input: synaptics-rmi4 - fix the error return code in
>     rmi_probe_interrupts()
>
>  drivers/input/rmi4/Kconfig      |  1 +
>  drivers/input/rmi4/rmi_bus.c    | 50 ++++++++++++++++++++++++++++++-
>  drivers/input/rmi4/rmi_bus.h    | 10 ++++++-
>  drivers/input/rmi4/rmi_driver.c | 52 +++++++++++++--------------------
>  drivers/input/rmi4/rmi_f01.c    | 10 +++----
>  drivers/input/rmi4/rmi_f03.c    |  9 +++---
>  drivers/input/rmi4/rmi_f11.c    | 42 ++++++++++----------------
>  drivers/input/rmi4/rmi_f12.c    | 36 +++++++++++++++++++----
>  drivers/input/rmi4/rmi_f30.c    |  9 +++---
>  drivers/input/rmi4/rmi_f34.c    |  5 ++--
>  drivers/input/rmi4/rmi_f54.c    |  6 ----
>  include/linux/rmi.h             |  2 ++
>  12 files changed, 145 insertions(+), 87 deletions(-)
>


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

NAK: [PATCH 0/3] [SRU][B/OEM-B][PATCH 0/1] Fix touchpad not working

Kleber Souza
In reply to this post by Aaron Ma
On 2019-12-04 05:59, Aaron Ma wrote:

> BugLink: https://bugs.launchpad.net/bugs/1854798
>
> [Impact]
> Synaptics s3203 touchpad not working after update to kernel
> 4.15.0-72-generic
>
> [Fix]
> After applied commit "Input: synaptics-rmi4 - avoid processing unknown
> IRQs",
> no irq response from touchpad.
> This commit is depended on commit:
> "Input: synaptics-rmi4 - convert irq distribution to irq_domain"
>
> [Test]
> Verified on hardware, tests results are good.
>
> [Regression Potential]
> Low.
> Fix bug that introduced by stable release update.
>
> 2nd and 3rd patches are fixes for the 1st patch.
> These commits are already included by eoan kernel, so bionic 4.15 only.
>
> Andrew Duggan (1):
>   Input: synaptics-rmi4 - disable the relative position IRQ in the F12
>     driver
>
> Nick Dyer (1):
>   Input: synaptics-rmi4 - convert irq distribution to irq_domain
>
> Wei Yongjun (1):
>   Input: synaptics-rmi4 - fix the error return code in
>     rmi_probe_interrupts()
>
>  drivers/input/rmi4/Kconfig      |  1 +
>  drivers/input/rmi4/rmi_bus.c    | 50 ++++++++++++++++++++++++++++++-
>  drivers/input/rmi4/rmi_bus.h    | 10 ++++++-
>  drivers/input/rmi4/rmi_driver.c | 52 +++++++++++++--------------------
>  drivers/input/rmi4/rmi_f01.c    | 10 +++----
>  drivers/input/rmi4/rmi_f03.c    |  9 +++---
>  drivers/input/rmi4/rmi_f11.c    | 42 ++++++++++----------------
>  drivers/input/rmi4/rmi_f12.c    | 36 +++++++++++++++++++----
>  drivers/input/rmi4/rmi_f30.c    |  9 +++---
>  drivers/input/rmi4/rmi_f34.c    |  5 ++--
>  drivers/input/rmi4/rmi_f54.c    |  6 ----
>  include/linux/rmi.h             |  2 ++
>  12 files changed, 145 insertions(+), 87 deletions(-)
>

As discussed offline, these patches are not needed.

Thanks,
Kleber

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team