mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-03 19:55:31 +00:00
Input updates for v6.12-rc5
- 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. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQST2eWILY88ieB2DOtAj56VGEWXnAUCZycQwgAKCRBAj56VGEWX nFgtAQDxuWplL+cwA5f3g+/Rq38faHBY5ebmsC9G/QnBZs4hTQD/dL04tU9NwvNq GYw4MYRNaDIeY8vyq21Y+dQe0uL0rAM= =xAeU -----END PGP SIGNATURE----- Merge tag 'input-for-v6.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input 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
This commit is contained in:
commit
295ba6501d
@ -119,12 +119,12 @@ static void input_pass_values(struct input_dev *dev,
|
|||||||
|
|
||||||
handle = rcu_dereference(dev->grab);
|
handle = rcu_dereference(dev->grab);
|
||||||
if (handle) {
|
if (handle) {
|
||||||
count = handle->handler->events(handle, vals, count);
|
count = handle->handle_events(handle, vals, count);
|
||||||
} else {
|
} else {
|
||||||
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
|
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
|
||||||
if (handle->open) {
|
if (handle->open) {
|
||||||
count = handle->handler->events(handle, vals,
|
count = handle->handle_events(handle, vals,
|
||||||
count);
|
count);
|
||||||
if (!count)
|
if (!count)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2534,57 +2534,6 @@ static int input_handler_check_methods(const struct input_handler *handler)
|
|||||||
return 0;
|
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
|
* input_register_handler - register a new input handler
|
||||||
* @handler: handler to be registered
|
* @handler: handler to be registered
|
||||||
@ -2604,13 +2553,6 @@ int input_register_handler(struct input_handler *handler)
|
|||||||
|
|
||||||
INIT_LIST_HEAD(&handler->h_list);
|
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);
|
error = mutex_lock_interruptible(&input_mutex);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
@ -2684,6 +2626,75 @@ int input_handler_for_each_handle(struct input_handler *handler, void *data,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(input_handler_for_each_handle);
|
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
|
* input_register_handle - register a new input handle
|
||||||
* @handle: handle to register
|
* @handle: handle to register
|
||||||
@ -2701,6 +2712,7 @@ int input_register_handle(struct input_handle *handle)
|
|||||||
struct input_dev *dev = handle->dev;
|
struct input_dev *dev = handle->dev;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
input_handle_setup_event_handler(handle);
|
||||||
/*
|
/*
|
||||||
* We take dev->mutex here to prevent race with
|
* We take dev->mutex here to prevent race with
|
||||||
* input_release_device().
|
* input_release_device().
|
||||||
|
@ -822,7 +822,8 @@ static int adp5588_suspend(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
|
||||||
disable_irq(client->irq);
|
if (client->irq)
|
||||||
|
disable_irq(client->irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -831,7 +832,8 @@ static int adp5588_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
|
||||||
enable_irq(client->irq);
|
if (client->irq)
|
||||||
|
enable_irq(client->irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1121,6 +1121,14 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
static void edt_ft5x06_disable_regulators(void *arg)
|
||||||
{
|
{
|
||||||
struct edt_ft5x06_ts_data *data = arg;
|
struct edt_ft5x06_ts_data *data = arg;
|
||||||
@ -1154,6 +1162,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
|
|||||||
return PTR_ERR(tsdata->regmap);
|
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);
|
chip_data = device_get_match_data(&client->dev);
|
||||||
if (!chip_data)
|
if (!chip_data)
|
||||||
chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
|
chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
|
||||||
@ -1347,7 +1365,6 @@ static void edt_ft5x06_ts_remove(struct i2c_client *client)
|
|||||||
struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
|
struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
|
||||||
|
|
||||||
edt_ft5x06_ts_teardown_debugfs(tsdata);
|
edt_ft5x06_ts_teardown_debugfs(tsdata);
|
||||||
regmap_exit(tsdata->regmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int edt_ft5x06_ts_suspend(struct device *dev)
|
static int edt_ft5x06_ts_suspend(struct device *dev)
|
||||||
|
@ -339,12 +339,16 @@ struct input_handler {
|
|||||||
* @name: name given to the handle by handler that created it
|
* @name: name given to the handle by handler that created it
|
||||||
* @dev: input device the handle is attached to
|
* @dev: input device the handle is attached to
|
||||||
* @handler: handler that works with the device through this handle
|
* @handler: handler that works with the device through this handle
|
||||||
|
* @handle_events: event sequence handler. It is set up by the input core
|
||||||
|
* according to event handling method specified in the @handler. See
|
||||||
|
* input_handle_setup_event_handler().
|
||||||
|
* This method is being called by the input core with interrupts disabled
|
||||||
|
* and dev->event_lock spinlock held and so it may not sleep.
|
||||||
* @d_node: used to put the handle on device's list of attached handles
|
* @d_node: used to put the handle on device's list of attached handles
|
||||||
* @h_node: used to put the handle on handler's list of handles from which
|
* @h_node: used to put the handle on handler's list of handles from which
|
||||||
* it gets events
|
* it gets events
|
||||||
*/
|
*/
|
||||||
struct input_handle {
|
struct input_handle {
|
||||||
|
|
||||||
void *private;
|
void *private;
|
||||||
|
|
||||||
int open;
|
int open;
|
||||||
@ -353,6 +357,10 @@ struct input_handle {
|
|||||||
struct input_dev *dev;
|
struct input_dev *dev;
|
||||||
struct input_handler *handler;
|
struct input_handler *handler;
|
||||||
|
|
||||||
|
unsigned int (*handle_events)(struct input_handle *handle,
|
||||||
|
struct input_value *vals,
|
||||||
|
unsigned int count);
|
||||||
|
|
||||||
struct list_head d_node;
|
struct list_head d_node;
|
||||||
struct list_head h_node;
|
struct list_head h_node;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user