summaryrefslogtreecommitdiffstats
path: root/drivers/hid/wacom_wac.c
diff options
context:
space:
mode:
authorBenjamin Tissoires2016-07-13 18:06:01 +0200
committerJiri Kosina2016-08-05 13:39:16 +0200
commite6f2813a6d3fd924a399f8b19bcd8b11487155bc (patch)
tree38e49d6df64ecdfc907a2d2baf605788f51cdbd7 /drivers/hid/wacom_wac.c
parentHID: wacom: leds: dynamically allocate LED groups (diff)
downloadkernel-qcow2-linux-e6f2813a6d3fd924a399f8b19bcd8b11487155bc.tar.gz
kernel-qcow2-linux-e6f2813a6d3fd924a399f8b19bcd8b11487155bc.tar.xz
kernel-qcow2-linux-e6f2813a6d3fd924a399f8b19bcd8b11487155bc.zip
HID: wacom: EKR: add a worker to add/remove resources on addition/removal
wacom_remote_status_irq() sends information of addition/removal of EKR. We want to allocate one input node per remote, so better having this in a separate worker, not handled in the IRQ directly. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Acked-by: Ping Cheng <pingc@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/wacom_wac.c')
-rw-r--r--drivers/hid/wacom_wac.c53
1 files changed, 21 insertions, 32 deletions
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 932d3eec933b..d54992967391 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -823,52 +823,40 @@ static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len)
return 1;
}
-static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
+static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len)
{
struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
unsigned char *data = wacom_wac->data;
- int i;
+ struct wacom_remote_data remote_data;
+ unsigned long flags;
+ int i, ret;
if (data[0] != WACOM_REPORT_DEVICE_LIST)
- return 0;
+ return;
+
+ memset(&remote_data, 0, sizeof(struct wacom_remote_data));
for (i = 0; i < WACOM_MAX_REMOTES; i++) {
int j = i * 6;
int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4];
bool connected = data[j+2];
- if (connected) {
- int k;
-
- if (wacom_wac->serial[i] == serial)
- continue;
-
- if (wacom_wac->serial[i]) {
- wacom_remote_destroy_attr_group(wacom,
- wacom_wac->serial[i]);
- }
-
- /* A remote can pair more than once with an EKR,
- * check to make sure this serial isn't already paired.
- */
- for (k = 0; k < WACOM_MAX_REMOTES; k++) {
- if (wacom_wac->serial[k] == serial)
- break;
- }
+ remote_data.remote[i].serial = serial;
+ remote_data.remote[i].connected = connected;
+ }
- if (k < WACOM_MAX_REMOTES) {
- wacom_wac->serial[i] = serial;
- continue;
- }
- wacom_remote_create_attr_group(wacom, serial, i);
+ spin_lock_irqsave(&wacom->remote_lock, flags);
- } else if (wacom_wac->serial[i]) {
- wacom_remote_destroy_attr_group(wacom,
- wacom_wac->serial[i]);
- }
+ ret = kfifo_in(&wacom->remote_fifo, &remote_data, sizeof(remote_data));
+ if (ret != sizeof(remote_data)) {
+ spin_unlock_irqrestore(&wacom->remote_lock, flags);
+ hid_err(wacom->hdev, "Can't queue Remote status event.\n");
+ return;
}
- return 0;
+ spin_unlock_irqrestore(&wacom->remote_lock, flags);
+
+ wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE);
}
static int wacom_intuos_general(struct wacom_wac *wacom)
@@ -2310,8 +2298,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
break;
case REMOTE:
+ sync = false;
if (wacom_wac->data[0] == WACOM_REPORT_DEVICE_LIST)
- sync = wacom_remote_status_irq(wacom_wac, len);
+ wacom_remote_status_irq(wacom_wac, len);
else
sync = wacom_remote_irq(wacom_wac, len);
break;