diff mbox

[v1] Input: synaptics-rmi4 - convert irq distribution to irq_domain

Message ID 1516829193-27590-1-git-send-email-nick@shmanahar.org (mailing list archive)
State New, archived
Headers show

Commit Message

Nick Dyer Jan. 24, 2018, 9:26 p.m. UTC
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>
---
 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(-)

Comments

Dmitry Torokhov Jan. 24, 2018, 9:37 p.m. UTC | #1
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.

> +					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.
Christopher Heiny Jan. 24, 2018, 9:37 p.m. UTC | #2
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;

--
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
Nick Dyer Jan. 24, 2018, 10:23 p.m. UTC | #3
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
--
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
diff mbox

Patch

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_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;