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@xxxxxxxxxxxxx> > > --- > > 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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html