diff options
-rw-r--r-- | drivers/input/rmi4/rmi_driver.c | 49 | ||||
-rw-r--r-- | include/linux/rmi.h | 11 |
2 files changed, 58 insertions, 2 deletions
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index a718e51afb0b..85062e414e73 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c | |||
@@ -191,16 +191,53 @@ static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev) | |||
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
193 | 193 | ||
194 | void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status, | ||
195 | void *data, size_t size) | ||
196 | { | ||
197 | struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); | ||
198 | struct rmi4_attn_data attn_data; | ||
199 | void *fifo_data; | ||
200 | |||
201 | if (!drvdata->enabled) | ||
202 | return; | ||
203 | |||
204 | fifo_data = kmemdup(data, size, GFP_ATOMIC); | ||
205 | if (!fifo_data) | ||
206 | return; | ||
207 | |||
208 | attn_data.irq_status = irq_status; | ||
209 | attn_data.size = size; | ||
210 | attn_data.data = fifo_data; | ||
211 | |||
212 | kfifo_put(&drvdata->attn_fifo, attn_data); | ||
213 | } | ||
214 | EXPORT_SYMBOL_GPL(rmi_set_attn_data); | ||
215 | |||
194 | static irqreturn_t rmi_irq_fn(int irq, void *dev_id) | 216 | static irqreturn_t rmi_irq_fn(int irq, void *dev_id) |
195 | { | 217 | { |
196 | struct rmi_device *rmi_dev = dev_id; | 218 | struct rmi_device *rmi_dev = dev_id; |
197 | int ret; | 219 | struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev); |
220 | struct rmi4_attn_data attn_data = {0}; | ||
221 | int ret, count; | ||
222 | |||
223 | count = kfifo_get(&drvdata->attn_fifo, &attn_data); | ||
224 | if (count) { | ||
225 | *(drvdata->irq_status) = attn_data.irq_status; | ||
226 | rmi_dev->xport->attn_data = attn_data.data; | ||
227 | rmi_dev->xport->attn_size = attn_data.size; | ||
228 | } | ||
198 | 229 | ||
199 | ret = rmi_process_interrupt_requests(rmi_dev); | 230 | ret = rmi_process_interrupt_requests(rmi_dev); |
200 | if (ret) | 231 | if (ret) |
201 | rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, | 232 | rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, |
202 | "Failed to process interrupt request: %d\n", ret); | 233 | "Failed to process interrupt request: %d\n", ret); |
203 | 234 | ||
235 | if (count) | ||
236 | kfree(attn_data.data); | ||
237 | |||
238 | if (!kfifo_is_empty(&drvdata->attn_fifo)) | ||
239 | return rmi_irq_fn(irq, dev_id); | ||
240 | |||
204 | return IRQ_HANDLED; | 241 | return IRQ_HANDLED; |
205 | } | 242 | } |
206 | 243 | ||
@@ -880,8 +917,9 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake) | |||
880 | { | 917 | { |
881 | struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev); | 918 | struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev); |
882 | struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev); | 919 | struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev); |
920 | struct rmi4_attn_data attn_data = {0}; | ||
883 | int irq = pdata->irq; | 921 | int irq = pdata->irq; |
884 | int retval; | 922 | int retval, count; |
885 | 923 | ||
886 | mutex_lock(&data->enabled_mutex); | 924 | mutex_lock(&data->enabled_mutex); |
887 | 925 | ||
@@ -898,6 +936,13 @@ void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake) | |||
898 | retval); | 936 | retval); |
899 | } | 937 | } |
900 | 938 | ||
939 | /* make sure the fifo is clean */ | ||
940 | while (!kfifo_is_empty(&data->attn_fifo)) { | ||
941 | count = kfifo_get(&data->attn_fifo, &attn_data); | ||
942 | if (count) | ||
943 | kfree(attn_data.data); | ||
944 | } | ||
945 | |||
901 | out: | 946 | out: |
902 | mutex_unlock(&data->enabled_mutex); | 947 | mutex_unlock(&data->enabled_mutex); |
903 | } | 948 | } |
diff --git a/include/linux/rmi.h b/include/linux/rmi.h index 7780e40a2573..1d4865621493 100644 --- a/include/linux/rmi.h +++ b/include/linux/rmi.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/input.h> | 15 | #include <linux/input.h> |
16 | #include <linux/kfifo.h> | ||
16 | #include <linux/list.h> | 17 | #include <linux/list.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/types.h> | 19 | #include <linux/types.h> |
@@ -331,6 +332,12 @@ struct rmi_device { | |||
331 | 332 | ||
332 | }; | 333 | }; |
333 | 334 | ||
335 | struct rmi4_attn_data { | ||
336 | unsigned long irq_status; | ||
337 | size_t size; | ||
338 | void *data; | ||
339 | }; | ||
340 | |||
334 | struct rmi_driver_data { | 341 | struct rmi_driver_data { |
335 | struct list_head function_list; | 342 | struct list_head function_list; |
336 | 343 | ||
@@ -357,11 +364,15 @@ struct rmi_driver_data { | |||
357 | 364 | ||
358 | bool enabled; | 365 | bool enabled; |
359 | struct mutex enabled_mutex; | 366 | struct mutex enabled_mutex; |
367 | DECLARE_KFIFO(attn_fifo, struct rmi4_attn_data, 16); | ||
360 | }; | 368 | }; |
361 | 369 | ||
362 | int rmi_register_transport_device(struct rmi_transport_dev *xport); | 370 | int rmi_register_transport_device(struct rmi_transport_dev *xport); |
363 | void rmi_unregister_transport_device(struct rmi_transport_dev *xport); | 371 | void rmi_unregister_transport_device(struct rmi_transport_dev *xport); |
364 | 372 | ||
373 | void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status, | ||
374 | void *data, size_t size); | ||
375 | |||
365 | int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake); | 376 | int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake); |
366 | int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake); | 377 | int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake); |
367 | #endif | 378 | #endif |