Commit 295ba650 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents a33ab3f9 071b24b5
Loading
Loading
Loading
Loading
+73 −61
Original line number Diff line number Diff line
@@ -119,11 +119,11 @@ static void input_pass_values(struct input_dev *dev,

	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 = handle->handle_events(handle, vals,
							      count);
				if (!count)
					break;
@@ -2534,57 +2534,6 @@ static int input_handler_check_methods(const struct input_handler *handler)
	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 +2553,6 @@ int input_register_handler(struct input_handler *handler)

	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 +2626,75 @@ int input_handler_for_each_handle(struct input_handler *handler, void *data,
}
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 +2712,7 @@ int input_register_handle(struct input_handle *handle)
	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().
+4 −2
Original line number Diff line number Diff line
@@ -822,6 +822,7 @@ static int adp5588_suspend(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);

	if (client->irq)
		disable_irq(client->irq);

	return 0;
@@ -831,6 +832,7 @@ static int adp5588_resume(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);

	if (client->irq)
		enable_irq(client->irq);

	return 0;
+18 −1
Original line number Diff line number Diff line
@@ -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)
{
	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);
	}

	/*
	 * 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 @@ static void edt_ft5x06_ts_remove(struct i2c_client *client)
	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)
+9 −1
Original line number Diff line number Diff line
@@ -339,12 +339,16 @@ struct input_handler {
 * @name: name given to the handle by handler that created it
 * @dev: input device the handle is attached to
 * @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
 * @h_node: used to put the handle on handler's list of handles from which
 *	it gets events
 */
struct input_handle {

	void *private;

	int open;
@@ -353,6 +357,10 @@ struct input_handle {
	struct input_dev *dev;
	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	h_node;
};