Skip to content

Commit

Permalink
Input: synaptics-rmi4 - allow to add attention data
Browse files Browse the repository at this point in the history
The HID implementation of RMI4 provides the data during
the interrupt (in the input report). We need to provide
a way for this transport driver to provide the attention
data while calling an IRQ.

We use a fifo in rmi_core to not lose any incoming event.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
  • Loading branch information
Benjamin Tissoires authored and Dmitry Torokhov committed Dec 3, 2016
1 parent e621132 commit b908d3c
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
49 changes: 47 additions & 2 deletions drivers/input/rmi4/rmi_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,53 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
return 0;
}

void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
void *data, size_t size)
{
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct rmi4_attn_data attn_data;
void *fifo_data;

if (!drvdata->enabled)
return;

fifo_data = kmemdup(data, size, GFP_ATOMIC);
if (!fifo_data)
return;

attn_data.irq_status = irq_status;
attn_data.size = size;
attn_data.data = fifo_data;

kfifo_put(&drvdata->attn_fifo, attn_data);
}
EXPORT_SYMBOL_GPL(rmi_set_attn_data);

static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
{
struct rmi_device *rmi_dev = dev_id;
int ret;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct rmi4_attn_data attn_data = {0};
int ret, count;

count = kfifo_get(&drvdata->attn_fifo, &attn_data);
if (count) {
*(drvdata->irq_status) = attn_data.irq_status;
rmi_dev->xport->attn_data = attn_data.data;
rmi_dev->xport->attn_size = attn_data.size;
}

ret = rmi_process_interrupt_requests(rmi_dev);
if (ret)
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
"Failed to process interrupt request: %d\n", ret);

if (count)
kfree(attn_data.data);

if (!kfifo_is_empty(&drvdata->attn_fifo))
return rmi_irq_fn(irq, dev_id);

return IRQ_HANDLED;
}

Expand Down Expand Up @@ -880,8 +917,9 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
{
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi4_attn_data attn_data = {0};
int irq = pdata->irq;
int retval;
int retval, count;

mutex_lock(&data->enabled_mutex);

Expand All @@ -898,6 +936,13 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
retval);
}

/* make sure the fifo is clean */
while (!kfifo_is_empty(&data->attn_fifo)) {
count = kfifo_get(&data->attn_fifo, &attn_data);
if (count)
kfree(attn_data.data);
}

out:
mutex_unlock(&data->enabled_mutex);
}
Expand Down
11 changes: 11 additions & 0 deletions include/linux/rmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/kfifo.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/types.h>
Expand Down Expand Up @@ -331,6 +332,12 @@ struct rmi_device {

};

struct rmi4_attn_data {
unsigned long irq_status;
size_t size;
void *data;
};

struct rmi_driver_data {
struct list_head function_list;

Expand All @@ -357,11 +364,15 @@ struct rmi_driver_data {

bool enabled;
struct mutex enabled_mutex;
DECLARE_KFIFO(attn_fifo, struct rmi4_attn_data, 16);
};

int rmi_register_transport_device(struct rmi_transport_dev *xport);
void rmi_unregister_transport_device(struct rmi_transport_dev *xport);

void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
void *data, size_t size);

int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake);
int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake);
#endif

0 comments on commit b908d3c

Please sign in to comment.