Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v1] Input: synaptics-rmi4 - convert irq distribution to irq_domain
From: Christopher Heiny @ 2018-01-24 21:37 UTC (permalink / raw)
  To: Nick Dyer, Dmitry Torokhov
  Cc: Benjamin Tissoires, Andrew Duggan, linux-input, Chris Healy,
	Lucas Stach
In-Reply-To: <1516829193-27590-1-git-send-email-nick@shmanahar.org>

On Wed, 2018-01-24 at 21:26 +0000, Nick Dyer wrote:
> 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 <nick@shmanahar.org>

Acked-by: Christopher Heiny <cheiny@synaptics.com>

Thanks for the fix - it replaces a bit of paleozoic cruft that I'd
forgotten all about.  I'm not able to bench test this, but don't see
any gotchas on a read-through.

					Cheers,
						Chris

> ---
>  drivers/input/rmi4/Kconfig      |  1 +
>  drivers/input/rmi4/rmi_bus.c    | 13 ++++++++-
>  drivers/input/rmi4/rmi_bus.h    |  3 +-
>  drivers/input/rmi4/rmi_driver.c | 65 ++++++++++++++++++++-----------
> ----------
>  drivers/input/rmi4/rmi_f01.c    | 10 +++----
>  drivers/input/rmi4/rmi_f03.c    |  9 +++---
>  drivers/input/rmi4/rmi_f11.c    | 25 +++++++---------
>  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, 81 insertions(+), 75 deletions(-)
> 
> diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
> index 7172b88..fad2eae 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 ae1bffe..ae288d6 100644
> --- a/drivers/input/rmi4/rmi_bus.c
> +++ b/drivers/input/rmi4/rmi_bus.c
> @@ -178,7 +178,18 @@ static int rmi_function_probe(struct device
> *dev)
>  
>  	if (handler->probe) {
>  		error = handler->probe(fn);
> -		return error;
> +		if (error)
> +			return error;
> +	}
> +
> +	if (fn->irq_base && handler->attention) {
> +		error = devm_request_threaded_irq(&fn->dev, fn-
> >irq_base, NULL,
> +					handler->attention,
> IRQF_ONESHOT,
> +					dev_name(&fn->dev), fn);
> +		if (error) {
> +			dev_err(dev, "Failed registering IRQ %d\n",
> error);
> +			return error;
> +		}
>  	}
>  
>  	return 0;
> diff --git a/drivers/input/rmi4/rmi_bus.h
> b/drivers/input/rmi4/rmi_bus.h
> index b7625a9..745a030 100644
> --- a/drivers/input/rmi4/rmi_bus.h
> +++ b/drivers/input/rmi4/rmi_bus.h
> @@ -35,6 +35,7 @@ struct rmi_function {
>  	struct device dev;
>  	struct list_head node;
>  
> +	unsigned int irq_base;
>  	unsigned int num_of_irqs;
>  	unsigned int irq_pos;
>  	unsigned long irq_mask[];
> @@ -76,7 +77,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 141ea22..b7ef1f5a 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);
> @@ -847,6 +823,10 @@ int rmi_initial_reset(struct rmi_device
> *rmi_dev, void *ctx,
>  	return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
>  }
>  
> +static struct irq_chip rmi_irq_chip = {
> +	.name = "rmi4",
> +};
> +
>  static int rmi_create_function(struct rmi_device *rmi_dev,
>  			       void *ctx, const struct pdt_entry
> *pdt)
>  {
> @@ -878,9 +858,18 @@ static int rmi_create_function(struct rmi_device
> *rmi_dev,
>  	fn->irq_pos = *current_irq_count;
>  	*current_irq_count += fn->num_of_irqs;
>  
> -	for (i = 0; i < fn->num_of_irqs; i++)
> +	for (i = 0; i < fn->num_of_irqs; i++) {
>  		set_bit(fn->irq_pos + i, fn->irq_mask);
>  
> +		fn->irq_base = irq_create_mapping(data->irqdomain,
> +						  fn->irq_pos + i);
> +
> +
> +		irq_set_chip_data(fn->irq_base, data);
> +		irq_set_chip_and_handler(fn->irq_base,
> &rmi_irq_chip,
> +					 handle_simple_irq);
> +	}
> +
>  	error = rmi_register_function(fn);
>  	if (error)
>  		goto err_put_fn;
> @@ -1000,9 +989,12 @@ 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);
> +
>  	rmi_f34_remove_sysfs(rmi_dev);
>  	rmi_free_function_list(rmi_dev);
>  
> @@ -1034,7 +1026,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 device_node *rmi_of_node = rmi_dev->xport->dev-
> >of_node;
> +	int irq_count = 0;
>  	size_t size;
>  	int retval;
>  
> @@ -1045,7 +1038,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 +1049,14 @@ 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_add_linear(rmi_of_node,
> irq_count,
> +					        &irq_domain_simple_o
> ps, 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 +1079,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 8a07ae1..4edaa14 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 ad71a5e..b9f07c9 100644
> --- a/drivers/input/rmi4/rmi_f03.c
> +++ b/drivers/input/rmi4/rmi_f03.c
> @@ -199,8 +199,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);
> @@ -217,7 +218,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);
> @@ -233,7 +234,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);
>  		}
>  	}
>  
> @@ -259,7 +260,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 bc5e37f..e587c87 100644
> --- a/drivers/input/rmi4/rmi_f11.c
> +++ b/drivers/input/rmi4/rmi_f11.c
> @@ -571,8 +571,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)
> +				   int num_irq_regs, int size)
>  {
>  	const u8 *f_state = f11->data.f_state;
>  	u8 finger_state;
> @@ -581,12 +580,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
> @@ -606,7 +600,7 @@ static void rmi_f11_finger_handler(struct
> f11_data *f11,
>  		}
>  	}
>  
> -	if (rel_bits) {
> +	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
> @@ -616,7 +610,7 @@ static void rmi_f11_finger_handler(struct
> f11_data *f11,
>  			rmi_f11_rel_pos_report(f11, i);
>  	}
>  
> -	if (abs_bits) {
> +	if (sensor->report_abs) {
>  		/*
>  		 * the absolute part is made in 2 parts to allow the
> kernel
>  		 * tracking to take place.
> @@ -1275,8 +1269,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 +1297,13 @@ 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,
> +			       drvdata->num_of_irq_regs,
> 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 8b0db08..e226def 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 82e0f0d..5e3ed5a 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 4cfe970..7268cf9 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 5343f2c..98a935e 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 64125443..5ef5c7c 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;


^ permalink raw reply

* Re: [PATCH v1] Revert "Input: synaptics_rmi4 - use devm_device_add_group() for attributes in F01"
From: Dmitry Torokhov @ 2018-01-24 21:47 UTC (permalink / raw)
  To: Nick Dyer
  Cc: Benjamin Tissoires, Andrew Duggan, Christopher Heiny, linux-input,
	Chris Healy, Lucas Stach
In-Reply-To: <1516829163-27534-1-git-send-email-nick@shmanahar.org>

On Wed, Jan 24, 2018 at 09:26:03PM +0000, Nick Dyer wrote:
> Since the sysfs attribute hangs off the RMI bus, which doesn't go away during
> firmware flash, it needs to be explictly removed, otherwise we would try and
> register the same attribute twice.
> 
> This reverts commit 36a44af5c176d619552d99697433261141dd1296.
> 
> Signed-off-by: Nick Dyer <nick@shmanahar.org>

Applied, thank you.

> ---
>  drivers/input/rmi4/rmi_f01.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c
> index ae966e3..8a07ae1 100644
> --- a/drivers/input/rmi4/rmi_f01.c
> +++ b/drivers/input/rmi4/rmi_f01.c
> @@ -570,14 +570,19 @@ static int rmi_f01_probe(struct rmi_function *fn)
>  
>  	dev_set_drvdata(&fn->dev, f01);
>  
> -	error = devm_device_add_group(&fn->rmi_dev->dev, &rmi_f01_attr_group);
> +	error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
>  	if (error)
> -		dev_warn(&fn->dev,
> -			 "Failed to create attribute group: %d\n", error);
> +		dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error);
>  
>  	return 0;
>  }
>  
> +static void rmi_f01_remove(struct rmi_function *fn)
> +{
> +	/* Note that the bus device is used, not the F01 device */
> +	sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group);
> +}
> +
>  static int rmi_f01_config(struct rmi_function *fn)
>  {
>  	struct f01_data *f01 = dev_get_drvdata(&fn->dev);
> @@ -717,6 +722,7 @@ struct rmi_function_handler rmi_f01_handler = {
>  	},
>  	.func		= 0x01,
>  	.probe		= rmi_f01_probe,
> +	.remove		= rmi_f01_remove,
>  	.config		= rmi_f01_config,
>  	.attention	= rmi_f01_attention,
>  	.suspend	= rmi_f01_suspend,
> -- 
> 2.7.4
> 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v1] Input: synaptics-rmi4 - convert irq distribution to irq_domain
From: Nick Dyer @ 2018-01-24 22:23 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Benjamin Tissoires, Andrew Duggan, Christopher Heiny, linux-input,
	Chris Healy, Lucas Stach
In-Reply-To: <20180124213750.3sfmie4upq3ugx7w@dtor-ws>

On Wed, Jan 24, 2018 at 01:37:50PM -0800, Dmitry Torokhov wrote:
> On Wed, Jan 24, 2018 at 09:26:33PM +0000, Nick Dyer wrote:
> > 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)
> 
> Awesome! Thank you!
> 
> > 
> > Signed-off-by: Nick Dyer <nick@shmanahar.org>
> > ---
> >  drivers/input/rmi4/Kconfig      |  1 +
> >  drivers/input/rmi4/rmi_bus.c    | 13 ++++++++-
> >  drivers/input/rmi4/rmi_bus.h    |  3 +-
> >  drivers/input/rmi4/rmi_driver.c | 65 ++++++++++++++++++++---------------------
> >  drivers/input/rmi4/rmi_f01.c    | 10 +++----
> >  drivers/input/rmi4/rmi_f03.c    |  9 +++---
> >  drivers/input/rmi4/rmi_f11.c    | 25 +++++++---------
> >  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, 81 insertions(+), 75 deletions(-)
> > 
> > diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
> > index 7172b88..fad2eae 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 ae1bffe..ae288d6 100644
> > --- a/drivers/input/rmi4/rmi_bus.c
> > +++ b/drivers/input/rmi4/rmi_bus.c
> > @@ -178,7 +178,18 @@ static int rmi_function_probe(struct device *dev)
> >  
> >  	if (handler->probe) {
> >  		error = handler->probe(fn);
> > -		return error;
> > +		if (error)
> > +			return error;
> > +	}
> > +
> > +	if (fn->irq_base && handler->attention) {
> > +		error = devm_request_threaded_irq(&fn->dev, fn->irq_base, NULL,
> 
> Does this mean we have a thread for each function? The "parent" IRQ is
> already threaded, I wonder if we could piggy-back on it... Or irqchip
> code will not allow us to sleep in nested interrupt unless it is on a
> separate thread?
> 
> Sorry, just dumping random thoughts, I have not looked at tghe IRQ ocre
> code closely.

Looking at the way regmap does it, I need to add a call to
irq_set_nested_thread() where the function irq is being set up, then it
appears to skip creating a separate thread. I'll repost a new version
when I've had a chance to test it more thoroughly.

> > +					handler->attention, IRQF_ONESHOT,
> > +					dev_name(&fn->dev), fn);
> > +		if (error) {
> > +			dev_err(dev, "Failed registering IRQ %d\n", error);
> > +			return error;
> > +		}
> >  	}
> >  
> >  	return 0;
> > diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
> > index b7625a9..745a030 100644
> > --- a/drivers/input/rmi4/rmi_bus.h
> > +++ b/drivers/input/rmi4/rmi_bus.h
> > @@ -35,6 +35,7 @@ struct rmi_function {
> >  	struct device dev;
> >  	struct list_head node;
> >  
> > +	unsigned int irq_base;
> >  	unsigned int num_of_irqs;
> >  	unsigned int irq_pos;
> >  	unsigned long irq_mask[];
> > @@ -76,7 +77,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 141ea22..b7ef1f5a 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);
> > @@ -847,6 +823,10 @@ int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
> >  	return pdt->page_start == 0 ? RMI_SCAN_CONTINUE : -ENODEV;
> >  }
> >  
> > +static struct irq_chip rmi_irq_chip = {
> > +	.name = "rmi4",
> > +};
> > +
> >  static int rmi_create_function(struct rmi_device *rmi_dev,
> >  			       void *ctx, const struct pdt_entry *pdt)
> >  {
> > @@ -878,9 +858,18 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
> >  	fn->irq_pos = *current_irq_count;
> >  	*current_irq_count += fn->num_of_irqs;
> >  
> > -	for (i = 0; i < fn->num_of_irqs; i++)
> > +	for (i = 0; i < fn->num_of_irqs; i++) {
> >  		set_bit(fn->irq_pos + i, fn->irq_mask);
> >  
> > +		fn->irq_base = irq_create_mapping(data->irqdomain,
> > +						  fn->irq_pos + i);
> > +
> > +
> > +		irq_set_chip_data(fn->irq_base, data);
> > +		irq_set_chip_and_handler(fn->irq_base, &rmi_irq_chip,
> > +					 handle_simple_irq);
> > +	}
> > +
> >  	error = rmi_register_function(fn);
> >  	if (error)
> >  		goto err_put_fn;
> > @@ -1000,9 +989,12 @@ 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);
> > +
> >  	rmi_f34_remove_sysfs(rmi_dev);
> >  	rmi_free_function_list(rmi_dev);
> >  
> > @@ -1034,7 +1026,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 device_node *rmi_of_node = rmi_dev->xport->dev->of_node;
> > +	int irq_count = 0;
> >  	size_t size;
> >  	int retval;
> >  
> > @@ -1045,7 +1038,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 +1049,14 @@ 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_add_linear(rmi_of_node, 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 +1079,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 8a07ae1..4edaa14 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 ad71a5e..b9f07c9 100644
> > --- a/drivers/input/rmi4/rmi_f03.c
> > +++ b/drivers/input/rmi4/rmi_f03.c
> > @@ -199,8 +199,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);
> > @@ -217,7 +218,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);
> > @@ -233,7 +234,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);
> >  		}
> >  	}
> >  
> > @@ -259,7 +260,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 bc5e37f..e587c87 100644
> > --- a/drivers/input/rmi4/rmi_f11.c
> > +++ b/drivers/input/rmi4/rmi_f11.c
> > @@ -571,8 +571,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)
> > +				   int num_irq_regs, int size)
> >  {
> >  	const u8 *f_state = f11->data.f_state;
> >  	u8 finger_state;
> > @@ -581,12 +580,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
> > @@ -606,7 +600,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
> >  		}
> >  	}
> >  
> > -	if (rel_bits) {
> > +	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
> > @@ -616,7 +610,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11,
> >  			rmi_f11_rel_pos_report(f11, i);
> >  	}
> >  
> > -	if (abs_bits) {
> > +	if (sensor->report_abs) {
> >  		/*
> >  		 * the absolute part is made in 2 parts to allow the kernel
> >  		 * tracking to take place.
> > @@ -1275,8 +1269,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 +1297,13 @@ 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,
> > +			       drvdata->num_of_irq_regs, 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 8b0db08..e226def 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 82e0f0d..5e3ed5a 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 4cfe970..7268cf9 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 5343f2c..98a935e 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 64125443..5ef5c7c 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.7.4
> > 
> 
> Thanks.
> 
> -- 
> Dmitry

^ permalink raw reply

* Re: [PATCH 1/2] Input: wm831x-on: Delete an error message for a failed memory allocation in wm831x_on_probe()
From: Charles Keepax @ 2018-01-25  9:49 UTC (permalink / raw)
  To: SF Markus Elfring
  Cc: linux-input, patches, Dmitry Torokhov, LKML, kernel-janitors
In-Reply-To: <d393999d-0c39-c9ea-3a0c-eb534e61b665@users.sourceforge.net>

On Wed, Jan 24, 2018 at 10:21:39PM +0100, SF Markus Elfring wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Wed, 24 Jan 2018 21:55:49 +0100
> 
> Omit an extra message for a memory allocation failure in this function.
> 
> This issue was detected by using the Coccinelle software.
> 
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
> ---

Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>

Thanks,
Charles

^ permalink raw reply

* Re: [PATCH 2/2] Input: wm831x-on: Improve a size determination in wm831x_on_probe()
From: Charles Keepax @ 2018-01-25  9:49 UTC (permalink / raw)
  To: SF Markus Elfring
  Cc: linux-input, patches, Dmitry Torokhov, LKML, kernel-janitors
In-Reply-To: <43f052c7-c98d-7ca2-08ca-e5428b5ad575@users.sourceforge.net>

On Wed, Jan 24, 2018 at 10:22:35PM +0100, SF Markus Elfring wrote:
> From: Markus Elfring <elfring@users.sourceforge.net>
> Date: Wed, 24 Jan 2018 21:58:42 +0100
> 
> Replace the specification of a data structure by a pointer dereference
> as the parameter for the operator "sizeof" to make the corresponding size
> determination a bit safer according to the Linux coding style convention.
> 
> This issue was detected by using the Coccinelle software.
> 
> Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
> ---

Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>

Thanks,
Charles

^ permalink raw reply

* Re: [PATCH 0/4] MMS114 touchscreen patches
From: Simon Shields @ 2018-01-25 13:01 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: Andi Shyti, Rob Herring, linux-input, linux-kernel
In-Reply-To: <20180124193804.155654-1-dmitry.torokhov@gmail.com>

Hi Dmitry,

Thanks for the extra fixes!

On Wed, Jan 24, 2018 at 11:38:00AM -0800, Dmitry Torokhov wrote:
> Hi,
> 
> This is a combination of couple of my patches + Simons patches dropping
> support for platform data and adding support for mms152, slightly reworked.
> 
> Andi, because patches changed a bit I did not add your reviewed-by or
> tested-by, please take another look.
> 
> Thanks!
> 
> Dmitry Torokhov (2):
>   Input: mms114 - do not clobber interrupt trigger
>   Input: mms114 - mark as direct input device
> 
> Simon Shields (2):
>   Input: mms114 - drop platform data and use generic APIs
>   Input: mms114 - add support for mms152
> 
>  .../bindings/input/touchscreen/mms114.txt          |  35 ++--
>  drivers/input/touchscreen/mms114.c                 | 229 ++++++++++++---------
>  include/linux/platform_data/mms114.h               |  24 ---
>  3 files changed, 151 insertions(+), 137 deletions(-)
>  delete mode 100644 include/linux/platform_data/mms114.h
> 
> -- 
> Dmitry
> 

All looks good to me. Tested on MMS114 and MMS152.

Reviewed-by: Simon Shields <simon@lineageos.org>
Tested-by: Simon Shields <simon@lineageos.org>

Cheers,
Simon

^ permalink raw reply

* [PATCH] Input: twl6040-vibra: Delete an error message for a failed memory allocation in twl6040_vibra_probe()
From: SF Markus Elfring @ 2018-01-25 15:08 UTC (permalink / raw)
  To: linux-input, Dmitry Torokhov; +Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 16:01:32 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/twl6040-vibra.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 5690eb7ff954..1bdca0eeed3f 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -259,7 +259,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info) {
 		of_node_put(twl6040_core_node);
-		dev_err(&pdev->dev, "couldn't allocate memory\n");
 		return -ENOMEM;
 	}
 
-- 
2.16.1


^ permalink raw reply related

* [PATCH 0/2] Input: sirfsoc-onkey: Adjustments for sirfsoc_pwrc_probe()
From: SF Markus Elfring @ 2018-01-25 15:45 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, Barry Song, Dmitry Torokhov
  Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 16:42:24 +0100

Two update suggestions were taken into account
from static source code analysis.

Markus Elfring (2):
  Delete an error message for a failed memory allocation
  Improve a size determination

 drivers/input/misc/sirfsoc-onkey.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

-- 
2.16.1

^ permalink raw reply

* [PATCH 1/2] Input: sirfsoc-onkey: Delete an error message for a failed memory allocation in sirfsoc_pwrc_probe()
From: SF Markus Elfring @ 2018-01-25 15:46 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, Barry Song, Dmitry Torokhov
  Cc: kernel-janitors, LKML
In-Reply-To: <b66f4105-57f2-adc2-ecde-cd4dacac408c@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 16:32:09 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/sirfsoc-onkey.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index 4fd038d476a3..9d8b4e2d7063 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -113,10 +113,8 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 
 	pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(struct sirfsoc_pwrc_drvdata),
 			       GFP_KERNEL);
-	if (!pwrcdrv) {
-		dev_info(&pdev->dev, "Not enough memory for the device data\n");
+	if (!pwrcdrv)
 		return -ENOMEM;
-	}
 
 	/*
 	 * We can't use of_iomap because pwrc is not mapped in memory,
-- 
2.16.1

^ permalink raw reply related

* [PATCH 2/2] Input: sirfsoc-onkey: Improve a size determination in sirfsoc_pwrc_probe()
From: SF Markus Elfring @ 2018-01-25 15:48 UTC (permalink / raw)
  To: linux-input, linux-arm-kernel, Barry Song, Dmitry Torokhov
  Cc: kernel-janitors, LKML
In-Reply-To: <b66f4105-57f2-adc2-ecde-cd4dacac408c@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 16:35:13 +0100

Replace the specification of a data structure by a pointer dereference
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/sirfsoc-onkey.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index 9d8b4e2d7063..cdad20811d35 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -111,8 +111,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 	int irq;
 	int error;
 
-	pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(struct sirfsoc_pwrc_drvdata),
-			       GFP_KERNEL);
+	pwrcdrv = devm_kzalloc(&pdev->dev, sizeof(*pwrcdrv), GFP_KERNEL);
 	if (!pwrcdrv)
 		return -ENOMEM;
 
-- 
2.16.1

^ permalink raw reply related

* Re: [PATCH v2 3/5] Input: add KEY_ROTATE_LOCK_TOGGLE
From: Jason Gerecke @ 2018-01-25 16:23 UTC (permalink / raw)
  To: Brüns, Stefan, Alex Hung, Dmitry Torokhov
  Cc: Bastien Nocera, platform-driver-x86@vger.kernel.org,
	linux-input@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CANRwn3SzMUvNoBjp2X1jtN9XaQ98RxCCZ86Hu4sPQygTORqjKg@mail.gmail.com>

Any movement on this? Are we just waiting on an ACK/NAK from Dmitry?

Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one  /
(That is to say, eight) to the two,     /
But you can’t take seven from three,    /
So you look at the sixty-fours....


On Tue, Dec 5, 2017 at 10:50 AM, Jason Gerecke <killertofu@gmail.com> wrote:
> Looks like this might also be needed for the MobileStudio Pro...
>
> https://bugzilla.kernel.org/show_bug.cgi?id=197991
>
> Jason
> ---
> Now instead of four in the eights place /
> you’ve got three, ‘Cause you added one  /
> (That is to say, eight) to the two,     /
> But you can’t take seven from three,    /
> So you look at the sixty-fours....
>
>
>
> On Thu, Nov 30, 2017 at 9:51 AM, Brüns, Stefan
> <Stefan.Bruens@rwth-aachen.de> wrote:
>> On Freitag, 10. November 2017 00:34:53 CET Bastien Nocera wrote:
>>> On Thu, 2017-11-09 at 23:44 +0100, Stefan Brüns wrote:
>>> > The key has the same use as the SW_ROTATE_LOCK, but is used on
>>> > devices
>>> > where the state is not tracked by the hardware but has to be handled
>>> > in software.
>>>
>>> I'll let the input and hid subsystem maintainers have the final say
>>> here, though I think that sending out Win+O would be easier, as this is
>>> already something that desktops need to support for those devices that
>>> send the actual Win+O key combination when those buttons are pressed
>>> there.
>>>
>>> If we're going with the separate keycode, could you also file bugs
>>> against xkbd-common and xkeyboard-config to get the key added to the
>>> list of XF86 keysyms and to the default evdev keymap? Otherwise Wayland
>>> and X11 based desktops won't be able to use it.
>>
>> Filed for xkeyboard-config:
>> https://bugs.freedesktop.org/show_bug.cgi?id=103998
>>
>> and xkb-common:
>> https://github.com/xkbcommon/libxkbcommon/issues/55
>>
>> Regards,
>>
>> Stefan
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-input" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] Input: kxtj9: Delete an error message for a failed memory allocation in kxtj9_probe()
From: SF Markus Elfring @ 2018-01-25 17:18 UTC (permalink / raw)
  To: linux-input, Dmitry Torokhov; +Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 18:13:57 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/kxtj9.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index efaffcc57e36..ddd5ca6812cb 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -526,11 +526,8 @@ static int kxtj9_probe(struct i2c_client *client,
 	}
 
 	tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL);
-	if (!tj9) {
-		dev_err(&client->dev,
-			"failed to allocate memory for module data\n");
+	if (!tj9)
 		return -ENOMEM;
-	}
 
 	tj9->client = client;
 	tj9->pdata = *pdata;
-- 
2.16.1


^ permalink raw reply related

* [PATCH 0/3] Input: ims-pcu: Adjustments for three function implementations
From: SF Markus Elfring @ 2018-01-25 18:51 UTC (permalink / raw)
  To: linux-input, Arvind Yadav, Dmitry Torokhov, Joe Perches,
	Johan Hovold, Zhen Lei
  Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 19:46:56 +0100

Three update suggestions were taken into account
from static source code analysis.

Markus Elfring (3):
  Delete an error message for a failed memory allocation
    in ims_pcu_buffers_alloc()
  Improve a size determination in two functions
  Delete an unnecessary variable assignment in ims_pcu_setup_gamepad()

 drivers/input/misc/ims-pcu.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

-- 
2.16.1


^ permalink raw reply

* [PATCH 1/3] Input: ims-pcu: Delete an error message for a failed memory allocation in ims_pcu_buffers_alloc()
From: SF Markus Elfring @ 2018-01-25 18:52 UTC (permalink / raw)
  To: linux-input, Arvind Yadav, Dmitry Torokhov, Joe Perches,
	Johan Hovold, Zhen Lei
  Cc: LKML, kernel-janitors
In-Reply-To: <ff77a871-d30a-e873-ab73-2d80198bfbe7@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 19:06:07 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/ims-pcu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 3d51175c4d72..4aca2a02ff6d 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -1556,7 +1556,6 @@ static int ims_pcu_buffers_alloc(struct ims_pcu *pcu)
 	 */
 	pcu->urb_out_buf = kmalloc(pcu->max_out_size, GFP_KERNEL);
 	if (!pcu->urb_out_buf) {
-		dev_err(pcu->dev, "Failed to allocate memory for write buffer\n");
 		error = -ENOMEM;
 		goto err_free_in_urb;
 	}
-- 
2.16.1

^ permalink raw reply related

* [PATCH 2/3] Input: ims-pcu: Improve a size determination in two functions
From: SF Markus Elfring @ 2018-01-25 18:53 UTC (permalink / raw)
  To: linux-input, Arvind Yadav, Dmitry Torokhov, Joe Perches,
	Johan Hovold, Zhen Lei
  Cc: LKML, kernel-janitors
In-Reply-To: <ff77a871-d30a-e873-ab73-2d80198bfbe7@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 19:20:38 +0100

Replace the specification of data structures by pointer dereferences
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/ims-pcu.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 4aca2a02ff6d..d7778b273151 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -288,12 +288,10 @@ static void ims_pcu_gamepad_report(struct ims_pcu *pcu, u32 data)
 
 static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
 {
-	struct ims_pcu_gamepad *gamepad;
-	struct input_dev *input;
 	int error;
+	struct ims_pcu_gamepad *gamepad = kzalloc(sizeof(*gamepad), GFP_KERNEL);
+	struct input_dev *input = input_allocate_device();
 
-	gamepad = kzalloc(sizeof(struct ims_pcu_gamepad), GFP_KERNEL);
-	input = input_allocate_device();
 	if (!gamepad || !input) {
 		dev_err(pcu->dev,
 			"Not enough memory for gamepad device\n");
@@ -2003,10 +2001,9 @@ static int ims_pcu_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
-	struct ims_pcu *pcu;
 	int error;
+	struct ims_pcu *pcu = kzalloc(sizeof(*pcu), GFP_KERNEL);
 
-	pcu = kzalloc(sizeof(struct ims_pcu), GFP_KERNEL);
 	if (!pcu)
 		return -ENOMEM;
 
-- 
2.16.1


^ permalink raw reply related

* [PATCH 3/3] Input: ims-pcu: Delete an unnecessary variable assignment in ims_pcu_setup_gamepad()
From: SF Markus Elfring @ 2018-01-25 18:54 UTC (permalink / raw)
  To: linux-input, Arvind Yadav, Dmitry Torokhov, Joe Perches,
	Johan Hovold, Zhen Lei
  Cc: LKML, kernel-janitors
In-Reply-To: <ff77a871-d30a-e873-ab73-2d80198bfbe7@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 19:37:34 +0100

An error code was assigned to a local variable in an if branch.
This value was not read again before it was used by a return statement
as a constant value at the end of this function.
Thus remove such an unneeded assignment.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/ims-pcu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index d7778b273151..aa1bb284c714 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -295,7 +295,6 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
 	if (!gamepad || !input) {
 		dev_err(pcu->dev,
 			"Not enough memory for gamepad device\n");
-		error = -ENOMEM;
 		goto err_free_mem;
 	}
 
-- 
2.16.1


^ permalink raw reply related

* [PATCH v3 3/3] Input: goodix - use generic touchscreen_properties
From: Marcin Niestroj @ 2018-01-25 19:08 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Bastien Nocera, Antonio Ospite, linux-input, Marcin Niestroj
In-Reply-To: <20180125190829.8968-1-m.niestroj@grinn-global.com>

Use touchscreen_properties structure instead of implementing all
properties by our own. It allows us to reuse generic code for parsing
device-tree properties (which was implemented manually in the driver
for now). Additionally, it allows us to report events using generic
touchscreen_report_pos(), which automatically handles inverted and
swapped axes.

Developed and tested on custom DT-based device with gt1151 touch
panel.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
---
Changes v2 -> v3 (suggested by Bastien):
 - fix commit description

Changes v1 -> v2:
 - rebased on patches 1 and 2 in series
 - added description of test board in changelog (suggested by Bastien)

 drivers/input/touchscreen/goodix.c | 93 ++++++++++++++------------------------
 1 file changed, 33 insertions(+), 60 deletions(-)

diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index dc832890f6d3..f82101cd9c04 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -22,6 +22,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
@@ -43,11 +44,7 @@ struct goodix_ts_data {
 	struct i2c_client *client;
 	struct input_dev *input_dev;
 	const struct goodix_chip_data *chip;
-	int abs_x_max;
-	int abs_y_max;
-	bool swapped_x_y;
-	bool inverted_x;
-	bool inverted_y;
+	struct touchscreen_properties prop;
 	unsigned int max_touch_num;
 	unsigned int int_trigger_type;
 	struct gpio_desc *gpiod_int;
@@ -295,24 +292,10 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
 	int input_y = get_unaligned_le16(&coor_data[3]);
 	int input_w = get_unaligned_le16(&coor_data[5]);
 
-	/* Inversions have to happen before axis swapping */
-	if (!ts->swapped_x_y) {
-		if (ts->inverted_x)
-			input_x = ts->abs_x_max - input_x;
-		if (ts->inverted_y)
-			input_y = ts->abs_y_max - input_y;
-	} else {
-		if (ts->inverted_x)
-			input_x = ts->abs_y_max - input_x;
-		if (ts->inverted_y)
-			input_y = ts->abs_x_max - input_y;
-		swap(input_x, input_y);
-	}
-
 	input_mt_slot(ts->input_dev, id);
 	input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
-	input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
-	input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
+	touchscreen_report_pos(ts->input_dev, &ts->prop, input_x, input_y,
+			true);
 	input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
 	input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
 }
@@ -585,6 +568,7 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts)
 static void goodix_read_config(struct goodix_ts_data *ts)
 {
 	u8 config[GOODIX_CONFIG_MAX_LENGTH];
+	int x_max, y_max;
 	int error;
 
 	error = goodix_i2c_read(ts->client, ts->chip->config_addr,
@@ -593,37 +577,34 @@ static void goodix_read_config(struct goodix_ts_data *ts)
 		dev_warn(&ts->client->dev,
 			 "Error reading config (%d), using defaults\n",
 			 error);
-		ts->abs_x_max = GOODIX_MAX_WIDTH - 1;
-		ts->abs_y_max = GOODIX_MAX_HEIGHT - 1;
-		if (ts->swapped_x_y)
-			swap(ts->abs_x_max, ts->abs_y_max);
+		x_max = GOODIX_MAX_WIDTH;
+		y_max = GOODIX_MAX_HEIGHT;
 		ts->int_trigger_type = GOODIX_INT_TRIGGER;
 		ts->max_touch_num = GOODIX_MAX_CONTACTS;
-		return;
+		goto input_set_params;
 	}
 
-	ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]) - 1;
-	ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]) - 1;
-	if (ts->swapped_x_y)
-		swap(ts->abs_x_max, ts->abs_y_max);
+	x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
+	y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
 	ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
 	ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
-	if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
+	if (!x_max || !y_max || !ts->max_touch_num) {
 		dev_err(&ts->client->dev,
 			"Invalid config, using defaults\n");
-		ts->abs_x_max = GOODIX_MAX_WIDTH - 1;
-		ts->abs_y_max = GOODIX_MAX_HEIGHT - 1;
-		if (ts->swapped_x_y)
-			swap(ts->abs_x_max, ts->abs_y_max);
+		x_max = GOODIX_MAX_WIDTH;
+		y_max = GOODIX_MAX_HEIGHT;
 		ts->max_touch_num = GOODIX_MAX_CONTACTS;
 	}
 
-	if (dmi_check_system(rotated_screen)) {
-		ts->inverted_x = true;
-		ts->inverted_y = true;
-		dev_dbg(&ts->client->dev,
-			 "Applying '180 degrees rotated screen' quirk\n");
-	}
+input_set_params:
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
+			0, x_max - 1, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
+			0, y_max - 1, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+	input_mt_init_slots(ts->input_dev, ts->max_touch_num,
+			INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
 }
 
 /**
@@ -698,16 +679,6 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts)
 		return -ENOMEM;
 	}
 
-	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
-			     0, ts->abs_x_max, 0, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
-			     0, ts->abs_y_max, 0, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
-
-	input_mt_init_slots(ts->input_dev, ts->max_touch_num,
-			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
-
 	ts->input_dev->name = "Goodix Capacitive TouchScreen";
 	ts->input_dev->phys = "input/ts";
 	ts->input_dev->id.bustype = BUS_I2C;
@@ -742,19 +713,21 @@ static int goodix_configure_dev(struct goodix_ts_data *ts)
 {
 	int error;
 
-	ts->swapped_x_y = device_property_read_bool(&ts->client->dev,
-						    "touchscreen-swapped-x-y");
-	ts->inverted_x = device_property_read_bool(&ts->client->dev,
-						   "touchscreen-inverted-x");
-	ts->inverted_y = device_property_read_bool(&ts->client->dev,
-						   "touchscreen-inverted-y");
-
-	goodix_read_config(ts);
-
 	error = goodix_request_input_dev(ts);
 	if (error)
 		return error;
 
+	goodix_read_config(ts);
+
+	touchscreen_parse_properties(ts->input_dev, true, &ts->prop);
+
+	if (dmi_check_system(rotated_screen)) {
+		ts->prop.invert_x = true;
+		ts->prop.invert_y = true;
+		dev_dbg(&ts->client->dev,
+			"Applying '180 degrees rotated screen' quirk\n");
+	}
+
 	ts->irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
 	error = goodix_request_irq(ts);
 	if (error) {
-- 
2.16.1


^ permalink raw reply related

* [PATCH v3 0/3] Input: goodix - fixes and conversion to touchscreen_properties
From: Marcin Niestroj @ 2018-01-25 19:08 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Bastien Nocera, Antonio Ospite, linux-input, Marcin Niestroj

Hi,

In this patch series I have only improved / fixed commit descriptions.

In comments of v2 patch series [1] there was a question if we should
left these 3 patches separate or meld them together. However there was
no decision made, so I've kept them separate for now. That way patches
1 and 2 can be easily backported to stable releases.

Patches were rebased and tested on v4.15-rc9.

[1] https://www.spinics.net/lists/linux-input/msg53976.html

Marcin Niestroj (3):
  Input: goodix - fix reported range
  Input: goodix - fix simultaneous axes inversion and swap
  Input: goodix - use generic touchscreen_properties

 drivers/input/touchscreen/goodix.c | 87 +++++++++++++++-----------------------
 1 file changed, 33 insertions(+), 54 deletions(-)

-- 
2.16.1


^ permalink raw reply

* [PATCH 0/2] Input-da9063_onkey: Adjustments for da9063_onkey_probe()
From: SF Markus Elfring @ 2018-01-25 19:34 UTC (permalink / raw)
  To: linux-input, support.opensource, Dmitry Torokhov, Steve Twiss
  Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 20:30:40 +0100

Two update suggestions were taken into account
from static source code analysis.

Markus Elfring (2):
  Delete an error message for a failed memory allocation
  Improve a size determination

 drivers/input/misc/da9063_onkey.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

-- 
2.16.1


^ permalink raw reply

* [PATCH 1/2] Input: da9063_onkey: Delete an error message for a failed memory allocation in da9063_onkey_probe()
From: SF Markus Elfring @ 2018-01-25 19:35 UTC (permalink / raw)
  To: linux-input, support.opensource, Dmitry Torokhov, Steve Twiss
  Cc: LKML, kernel-janitors
In-Reply-To: <9b0e8f6a-6386-d307-34fc-7936c52bd0c6@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 20:22:57 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/da9063_onkey.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index 3e9c353d82ef..acf592975bef 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -215,10 +215,8 @@ static int da9063_onkey_probe(struct platform_device *pdev)
 
 	onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
 			     GFP_KERNEL);
-	if (!onkey) {
-		dev_err(&pdev->dev, "Failed to allocate memory.\n");
+	if (!onkey)
 		return -ENOMEM;
-	}
 
 	onkey->config = match->data;
 	onkey->dev = &pdev->dev;
-- 
2.16.1

^ permalink raw reply related

* [PATCH v3 2/3] Input: goodix - fix simultaneous axes inversion and swap
From: Marcin Niestroj @ 2018-01-25 19:08 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Bastien Nocera, Antonio Ospite, linux-input, Marcin Niestroj
In-Reply-To: <20180125190829.8968-1-m.niestroj@grinn-global.com>

goodix_ts_data structure contains abs_x_max and abs_y_max members,
which contain already swapped maximum ranges. That causes reporting
touch events with invalid position (out of range values).

Problem occurs for example when ts->inverted_x and ts->swapped_x_y are
true, but ts->inverted_y is false. Assuming we have 720x1280 touch
panel, ts->abs_x_max == 1279 and ts->abs_y_max == 719 (because we
inverted that in goodix_read_config()). Now let's assume that we
received event from (0:0) position (in touch panel original
coordinates). In function goodix_ts_report_touch() we calculate
input_x as 1279, but after swapping input_y takes that value (which is
more that maximum 719 value reported during initialization).

Take into account that abs_x_max and abs_y_max are already swapped
in goodix_ts_report_touch(), so position for inverted axes will be
calculated correctly.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Fixes: ad48cf5e9597 ("Input: goodix - add axis swapping and axis inversion support")
---
Changes v2 -> v3 (suggested by Bastien):
 - add explanation about when the problem occurs

Changes v1 -> v2 (suggested by Bastien):
 - patch splitted off from patch 3

 drivers/input/touchscreen/goodix.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 7896097ca69b..dc832890f6d3 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -296,12 +296,18 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
 	int input_w = get_unaligned_le16(&coor_data[5]);
 
 	/* Inversions have to happen before axis swapping */
-	if (ts->inverted_x)
-		input_x = ts->abs_x_max - input_x;
-	if (ts->inverted_y)
-		input_y = ts->abs_y_max - input_y;
-	if (ts->swapped_x_y)
+	if (!ts->swapped_x_y) {
+		if (ts->inverted_x)
+			input_x = ts->abs_x_max - input_x;
+		if (ts->inverted_y)
+			input_y = ts->abs_y_max - input_y;
+	} else {
+		if (ts->inverted_x)
+			input_x = ts->abs_y_max - input_x;
+		if (ts->inverted_y)
+			input_y = ts->abs_x_max - input_y;
 		swap(input_x, input_y);
+	}
 
 	input_mt_slot(ts->input_dev, id);
 	input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
-- 
2.16.1


^ permalink raw reply related

* [PATCH v3 1/3] Input: goodix - fix reported range
From: Marcin Niestroj @ 2018-01-25 19:08 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Bastien Nocera, Antonio Ospite, linux-input, Marcin Niestroj
In-Reply-To: <20180125190829.8968-1-m.niestroj@grinn-global.com>

Touchscreen coordinates are 0-indexed, so report touchscreen range
as (0:size-1).

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
Fixes: ca96ea86eed4 ("Input: add driver for the Goodix touchpanel")
---
Changes v2 -> v3: fix commit description (suggested by Bastien)

Changes v1 -> v2: patch splitted off from patch 3 (suggested by Bastien)

 drivers/input/touchscreen/goodix.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index 69d0b8cbc71f..7896097ca69b 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -587,8 +587,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
 		dev_warn(&ts->client->dev,
 			 "Error reading config (%d), using defaults\n",
 			 error);
-		ts->abs_x_max = GOODIX_MAX_WIDTH;
-		ts->abs_y_max = GOODIX_MAX_HEIGHT;
+		ts->abs_x_max = GOODIX_MAX_WIDTH - 1;
+		ts->abs_y_max = GOODIX_MAX_HEIGHT - 1;
 		if (ts->swapped_x_y)
 			swap(ts->abs_x_max, ts->abs_y_max);
 		ts->int_trigger_type = GOODIX_INT_TRIGGER;
@@ -596,8 +596,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
 		return;
 	}
 
-	ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
-	ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
+	ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]) - 1;
+	ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]) - 1;
 	if (ts->swapped_x_y)
 		swap(ts->abs_x_max, ts->abs_y_max);
 	ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
@@ -605,8 +605,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
 	if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
 		dev_err(&ts->client->dev,
 			"Invalid config, using defaults\n");
-		ts->abs_x_max = GOODIX_MAX_WIDTH;
-		ts->abs_y_max = GOODIX_MAX_HEIGHT;
+		ts->abs_x_max = GOODIX_MAX_WIDTH - 1;
+		ts->abs_y_max = GOODIX_MAX_HEIGHT - 1;
 		if (ts->swapped_x_y)
 			swap(ts->abs_x_max, ts->abs_y_max);
 		ts->max_touch_num = GOODIX_MAX_CONTACTS;
-- 
2.16.1


^ permalink raw reply related

* [PATCH 2/2] Input: da9063_onkey: Improve a size determination in da9063_onkey_probe()
From: SF Markus Elfring @ 2018-01-25 19:36 UTC (permalink / raw)
  To: linux-input, support.opensource, Dmitry Torokhov, Steve Twiss
  Cc: LKML, kernel-janitors
In-Reply-To: <9b0e8f6a-6386-d307-34fc-7936c52bd0c6@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 20:24:47 +0100

Replace the specification of a data structure by a pointer dereference
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/da9063_onkey.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/input/misc/da9063_onkey.c b/drivers/input/misc/da9063_onkey.c
index acf592975bef..310f9c408636 100644
--- a/drivers/input/misc/da9063_onkey.c
+++ b/drivers/input/misc/da9063_onkey.c
@@ -213,8 +213,7 @@ static int da9063_onkey_probe(struct platform_device *pdev)
 	if (!match)
 		return -ENXIO;
 
-	onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
-			     GFP_KERNEL);
+	onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
 	if (!onkey)
 		return -ENOMEM;
 
-- 
2.16.1

^ permalink raw reply related

* [PATCH] Input: da9055_onkey: Delete an error message for a failed memory allocation in da9055_onkey_probe()
From: SF Markus Elfring @ 2018-01-25 19:51 UTC (permalink / raw)
  To: linux-input, support.opensource, Dmitry Torokhov; +Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 20:47:03 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/misc/da9055_onkey.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c
index 3251a9693f45..eabddb226998 100644
--- a/drivers/input/misc/da9055_onkey.c
+++ b/drivers/input/misc/da9055_onkey.c
@@ -87,10 +87,8 @@ static int da9055_onkey_probe(struct platform_device *pdev)
 	}
 
 	onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
-	if (!onkey) {
-		dev_err(&pdev->dev, "Failed to allocate memory\n");
+	if (!onkey)
 		return -ENOMEM;
-	}
 
 	input_dev = input_allocate_device();
 	if (!input_dev) {
-- 
2.16.1


^ permalink raw reply related

* [PATCH] Input: matrix-keymap: Delete an error message for a failed memory allocation in matrix_keypad_build_keymap()
From: SF Markus Elfring @ 2018-01-25 20:12 UTC (permalink / raw)
  To: linux-input, Dmitry Torokhov; +Cc: LKML, kernel-janitors

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 25 Jan 2018 21:07:00 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/input/matrix-keymap.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index 8ccefc15c7a4..298bd56b02bd 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -173,11 +173,8 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
 		keymap = devm_kzalloc(input_dev->dev.parent,
 				      max_keys * sizeof(*keymap),
 				      GFP_KERNEL);
-		if (!keymap) {
-			dev_err(input_dev->dev.parent,
-				"Unable to allocate memory for keymap");
+		if (!keymap)
 			return -ENOMEM;
-		}
 	}
 
 	input_dev->keycode = keymap;
-- 
2.16.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox