]> Git Repo - linux.git/commitdiff
Merge tag 'input-for-v6.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Sun, 3 Nov 2024 18:35:29 +0000 (08:35 -1000)
committerLinus Torvalds <[email protected]>
Sun, 3 Nov 2024 18:35:29 +0000 (08:35 -1000)
Pull input fixes from Dmitry Torokhov:

 - a fix for regression in input core introduced in 6.11 preventing
   re-registering input handlers

 - a fix for adp5588-keys driver tyring to disable interrupt 0 at
   suspend when devices is used without interrupt

 - a fix for edt-ft5x06 to stop leaking regmap structure when probing
   fails and to make sure it is not released too early on removal.

* tag 'input-for-v6.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: fix regression when re-registering input handlers
  Input: adp5588-keys - do not try to disable interrupt 0
  Input: edt-ft5x06 - fix regmap leak when probe fails

1  2 
drivers/input/input.c
drivers/input/touchscreen/edt-ft5x06.c

diff --combined drivers/input/input.c
index 47fac29cf7c3b3d2a1da40c7f5672c73aa3c84d5,3d2cc13e1f32c89d293380b17f0adef2856d2a45..c51858f1cdc556939c2ee1bd21669c71c169d84e
@@@ -119,12 -119,12 +119,12 @@@ static void input_pass_values(struct in
  
        handle = rcu_dereference(dev->grab);
        if (handle) {
-               count = handle->handler->events(handle, vals, count);
+               count = handle->handle_events(handle, vals, count);
        } else {
                list_for_each_entry_rcu(handle, &dev->h_list, d_node)
                        if (handle->open) {
-                               count = handle->handler->events(handle, vals,
-                                                               count);
+                               count = handle->handle_events(handle, vals,
+                                                             count);
                                if (!count)
                                        break;
                        }
@@@ -1079,31 -1079,33 +1079,31 @@@ static inline void input_wakeup_procfs_
        wake_up(&input_devices_poll_wait);
  }
  
 +struct input_seq_state {
 +      unsigned short pos;
 +      bool mutex_acquired;
 +      int input_devices_state;
 +};
 +
  static __poll_t input_proc_devices_poll(struct file *file, poll_table *wait)
  {
 +      struct seq_file *seq = file->private_data;
 +      struct input_seq_state *state = seq->private;
 +
        poll_wait(file, &input_devices_poll_wait, wait);
 -      if (file->f_version != input_devices_state) {
 -              file->f_version = input_devices_state;
 +      if (state->input_devices_state != input_devices_state) {
 +              state->input_devices_state = input_devices_state;
                return EPOLLIN | EPOLLRDNORM;
        }
  
        return 0;
  }
  
 -union input_seq_state {
 -      struct {
 -              unsigned short pos;
 -              bool mutex_acquired;
 -      };
 -      void *p;
 -};
 -
  static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
  {
 -      union input_seq_state *state = (union input_seq_state *)&seq->private;
 +      struct input_seq_state *state = seq->private;
        int error;
  
 -      /* We need to fit into seq->private pointer */
 -      BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
 -
        error = mutex_lock_interruptible(&input_mutex);
        if (error) {
                state->mutex_acquired = false;
@@@ -1122,7 -1124,7 +1122,7 @@@ static void *input_devices_seq_next(str
  
  static void input_seq_stop(struct seq_file *seq, void *v)
  {
 -      union input_seq_state *state = (union input_seq_state *)&seq->private;
 +      struct input_seq_state *state = seq->private;
  
        if (state->mutex_acquired)
                mutex_unlock(&input_mutex);
@@@ -1208,8 -1210,7 +1208,8 @@@ static const struct seq_operations inpu
  
  static int input_proc_devices_open(struct inode *inode, struct file *file)
  {
 -      return seq_open(file, &input_devices_seq_ops);
 +      return seq_open_private(file, &input_devices_seq_ops,
 +                              sizeof(struct input_seq_state));
  }
  
  static const struct proc_ops input_devices_proc_ops = {
        .proc_poll      = input_proc_devices_poll,
        .proc_read      = seq_read,
        .proc_lseek     = seq_lseek,
 -      .proc_release   = seq_release,
 +      .proc_release   = seq_release_private,
  };
  
  static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
  {
 -      union input_seq_state *state = (union input_seq_state *)&seq->private;
 +      struct input_seq_state *state = seq->private;
        int error;
  
 -      /* We need to fit into seq->private pointer */
 -      BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
 -
        error = mutex_lock_interruptible(&input_mutex);
        if (error) {
                state->mutex_acquired = false;
  
  static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
 -      union input_seq_state *state = (union input_seq_state *)&seq->private;
 +      struct input_seq_state *state = seq->private;
  
        state->pos = *pos + 1;
        return seq_list_next(v, &input_handler_list, pos);
  static int input_handlers_seq_show(struct seq_file *seq, void *v)
  {
        struct input_handler *handler = container_of(v, struct input_handler, node);
 -      union input_seq_state *state = (union input_seq_state *)&seq->private;
 +      struct input_seq_state *state = seq->private;
  
        seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
        if (handler->filter)
@@@ -1269,15 -1273,14 +1269,15 @@@ static const struct seq_operations inpu
  
  static int input_proc_handlers_open(struct inode *inode, struct file *file)
  {
 -      return seq_open(file, &input_handlers_seq_ops);
 +      return seq_open_private(file, &input_handlers_seq_ops,
 +                              sizeof(struct input_seq_state));
  }
  
  static const struct proc_ops input_handlers_proc_ops = {
        .proc_open      = input_proc_handlers_open,
        .proc_read      = seq_read,
        .proc_lseek     = seq_lseek,
 -      .proc_release   = seq_release,
 +      .proc_release   = seq_release_private,
  };
  
  static int __init input_proc_init(void)
@@@ -2534,57 -2537,6 +2534,6 @@@ static int input_handler_check_methods(
        return 0;
  }
  
- /*
-  * An implementation of input_handler's events() method that simply
-  * invokes handler->event() method for each event one by one.
-  */
- static unsigned int input_handler_events_default(struct input_handle *handle,
-                                                struct input_value *vals,
-                                                unsigned int count)
- {
-       struct input_handler *handler = handle->handler;
-       struct input_value *v;
-       for (v = vals; v != vals + count; v++)
-               handler->event(handle, v->type, v->code, v->value);
-       return count;
- }
- /*
-  * An implementation of input_handler's events() method that invokes
-  * handler->filter() method for each event one by one and removes events
-  * that were filtered out from the "vals" array.
-  */
- static unsigned int input_handler_events_filter(struct input_handle *handle,
-                                               struct input_value *vals,
-                                               unsigned int count)
- {
-       struct input_handler *handler = handle->handler;
-       struct input_value *end = vals;
-       struct input_value *v;
-       for (v = vals; v != vals + count; v++) {
-               if (handler->filter(handle, v->type, v->code, v->value))
-                       continue;
-               if (end != v)
-                       *end = *v;
-               end++;
-       }
-       return end - vals;
- }
- /*
-  * An implementation of input_handler's events() method that does nothing.
-  */
- static unsigned int input_handler_events_null(struct input_handle *handle,
-                                             struct input_value *vals,
-                                             unsigned int count)
- {
-       return count;
- }
  /**
   * input_register_handler - register a new input handler
   * @handler: handler to be registered
@@@ -2604,13 -2556,6 +2553,6 @@@ int input_register_handler(struct input
  
        INIT_LIST_HEAD(&handler->h_list);
  
-       if (handler->filter)
-               handler->events = input_handler_events_filter;
-       else if (handler->event)
-               handler->events = input_handler_events_default;
-       else if (!handler->events)
-               handler->events = input_handler_events_null;
        error = mutex_lock_interruptible(&input_mutex);
        if (error)
                return error;
@@@ -2684,6 -2629,75 +2626,75 @@@ int input_handler_for_each_handle(struc
  }
  EXPORT_SYMBOL(input_handler_for_each_handle);
  
+ /*
+  * An implementation of input_handle's handle_events() method that simply
+  * invokes handler->event() method for each event one by one.
+  */
+ static unsigned int input_handle_events_default(struct input_handle *handle,
+                                               struct input_value *vals,
+                                               unsigned int count)
+ {
+       struct input_handler *handler = handle->handler;
+       struct input_value *v;
+       for (v = vals; v != vals + count; v++)
+               handler->event(handle, v->type, v->code, v->value);
+       return count;
+ }
+ /*
+  * An implementation of input_handle's handle_events() method that invokes
+  * handler->filter() method for each event one by one and removes events
+  * that were filtered out from the "vals" array.
+  */
+ static unsigned int input_handle_events_filter(struct input_handle *handle,
+                                              struct input_value *vals,
+                                              unsigned int count)
+ {
+       struct input_handler *handler = handle->handler;
+       struct input_value *end = vals;
+       struct input_value *v;
+       for (v = vals; v != vals + count; v++) {
+               if (handler->filter(handle, v->type, v->code, v->value))
+                       continue;
+               if (end != v)
+                       *end = *v;
+               end++;
+       }
+       return end - vals;
+ }
+ /*
+  * An implementation of input_handle's handle_events() method that does nothing.
+  */
+ static unsigned int input_handle_events_null(struct input_handle *handle,
+                                            struct input_value *vals,
+                                            unsigned int count)
+ {
+       return count;
+ }
+ /*
+  * Sets up appropriate handle->event_handler based on the input_handler
+  * associated with the handle.
+  */
+ static void input_handle_setup_event_handler(struct input_handle *handle)
+ {
+       struct input_handler *handler = handle->handler;
+       if (handler->filter)
+               handle->handle_events = input_handle_events_filter;
+       else if (handler->event)
+               handle->handle_events = input_handle_events_default;
+       else if (handler->events)
+               handle->handle_events = handler->events;
+       else
+               handle->handle_events = input_handle_events_null;
+ }
  /**
   * input_register_handle - register a new input handle
   * @handle: handle to register
@@@ -2701,6 -2715,7 +2712,7 @@@ int input_register_handle(struct input_
        struct input_dev *dev = handle->dev;
        int error;
  
+       input_handle_setup_event_handler(handle);
        /*
         * We take dev->mutex here to prevent race with
         * input_release_device().
index fda49b2fe088522b8df8ec9353d928522171a38f,126b0ed85aa50c2cc21fae2a9d9bec2665e5284c..85c6d8ce003f3a2b131c33ecaae47c23dc7b3313
@@@ -32,7 -32,7 +32,7 @@@
  #include <linux/slab.h>
  #include <linux/uaccess.h>
  
 -#include <asm/unaligned.h>
 +#include <linux/unaligned.h>
  
  #define WORK_REGISTER_THRESHOLD               0x00
  #define WORK_REGISTER_REPORT_RATE     0x08
@@@ -1121,6 -1121,14 +1121,14 @@@ static void edt_ft5x06_ts_set_regs(stru
        }
  }
  
+ static void edt_ft5x06_exit_regmap(void *arg)
+ {
+       struct edt_ft5x06_ts_data *data = arg;
+       if (!IS_ERR_OR_NULL(data->regmap))
+               regmap_exit(data->regmap);
+ }
  static void edt_ft5x06_disable_regulators(void *arg)
  {
        struct edt_ft5x06_ts_data *data = arg;
@@@ -1154,6 -1162,16 +1162,16 @@@ static int edt_ft5x06_ts_probe(struct i
                return PTR_ERR(tsdata->regmap);
        }
  
+       /*
+        * We are not using devm_regmap_init_i2c() and instead install a
+        * custom action because we may replace regmap with M06-specific one
+        * and we need to make sure that it will not be released too early.
+        */
+       error = devm_add_action_or_reset(&client->dev, edt_ft5x06_exit_regmap,
+                                        tsdata);
+       if (error)
+               return error;
        chip_data = device_get_match_data(&client->dev);
        if (!chip_data)
                chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
@@@ -1347,7 -1365,6 +1365,6 @@@ static void edt_ft5x06_ts_remove(struc
        struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
  
        edt_ft5x06_ts_teardown_debugfs(tsdata);
-       regmap_exit(tsdata->regmap);
  }
  
  static int edt_ft5x06_ts_suspend(struct device *dev)
This page took 0.103915 seconds and 4 git commands to generate.