]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 Jan 2014 00:13:26 +0000 (16:13 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 11 Jan 2014 00:13:26 +0000 (16:13 -0800)
added patches:
hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch

queue-3.10/hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch b/queue-3.10/hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch
new file mode 100644 (file)
index 0000000..43d9425
--- /dev/null
@@ -0,0 +1,176 @@
+From c63e0e370028d7e4033bd40165f18499872b5183 Mon Sep 17 00:00:00 2001
+From: Nestor Lopez Casado <nlopezcasad@logitech.com>
+Date: Thu, 18 Jul 2013 06:21:30 -0700
+Subject: HID: Revert "Revert "HID: Fix logitech-dj: missing Unifying device issue""
+
+From: Nestor Lopez Casado <nlopezcasad@logitech.com>
+
+commit c63e0e370028d7e4033bd40165f18499872b5183 upstream.
+
+This reverts commit 8af6c08830b1ae114d1a8b548b1f8b056e068887.
+
+This patch re-adds the workaround introduced by 596264082f10dd4
+which was reverted by 8af6c08830b1ae114.
+
+The original patch 596264 was needed to overcome a situation where
+the hid-core would drop incoming reports while probe() was being
+executed.
+
+This issue was solved by c849a6143bec520af which added
+hid_device_io_start() and hid_device_io_stop() that enable a specific
+hid driver to opt-in for input reports while its probe() is being
+executed.
+
+Commit a9dd22b730857347 modified hid-logitech-dj so as to use the
+functionality added to hid-core. Having done that, workaround 596264
+was no longer necessary and was reverted by 8af6c08.
+
+We now encounter a different problem that ends up 'again' thwarting
+the Unifying receiver enumeration. The problem is time and usb controller
+dependent. Ocasionally the reports sent to the usb receiver to start
+the paired devices enumeration fail with -EPIPE and the receiver never
+gets to enumerate the paired devices.
+
+With dcd9006b1b053c7b1c the problem was "hidden" as the call to the usb
+driver became asynchronous and none was catching the error from the
+failing URB.
+
+As the root cause for this failing SET_REPORT is not understood yet,
+-possibly a race on the usb controller drivers or a problem with the
+Unifying receiver- reintroducing this workaround solves the problem.
+
+Overall what this workaround does is: If an input report from an
+unknown device is received, then a (re)enumeration is performed.
+
+related bug:
+https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1194649
+
+Signed-off-by: Nestor Lopez Casado <nlopezcasad@logitech.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-logitech-dj.c |   45 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/hid/hid-logitech-dj.h |    1 
+ 2 files changed, 46 insertions(+)
+
+--- a/drivers/hid/hid-logitech-dj.c
++++ b/drivers/hid/hid-logitech-dj.c
+@@ -192,6 +192,7 @@ static struct hid_ll_driver logi_dj_ll_d
+ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
+                                       size_t count,
+                                       unsigned char report_type);
++static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
+ static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
+                                               struct dj_report *dj_report)
+@@ -232,6 +233,7 @@ static void logi_dj_recv_add_djhid_devic
+       if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
+           SPFUNCTION_DEVICE_LIST_EMPTY) {
+               dbg_hid("%s: device list is empty\n", __func__);
++              djrcv_dev->querying_devices = false;
+               return;
+       }
+@@ -242,6 +244,12 @@ static void logi_dj_recv_add_djhid_devic
+               return;
+       }
++      if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
++              /* The device is already known. No need to reallocate it. */
++              dbg_hid("%s: device is already known\n", __func__);
++              return;
++      }
++
+       dj_hiddev = hid_allocate_device();
+       if (IS_ERR(dj_hiddev)) {
+               dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
+@@ -305,6 +313,7 @@ static void delayedwork_callback(struct
+       struct dj_report dj_report;
+       unsigned long flags;
+       int count;
++      int retval;
+       dbg_hid("%s\n", __func__);
+@@ -337,6 +346,25 @@ static void delayedwork_callback(struct
+               logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
+               break;
+       default:
++      /* A normal report (i. e. not belonging to a pair/unpair notification)
++       * arriving here, means that the report arrived but we did not have a
++       * paired dj_device associated to the report's device_index, this
++       * means that the original "device paired" notification corresponding
++       * to this dj_device never arrived to this driver. The reason is that
++       * hid-core discards all packets coming from a device while probe() is
++       * executing. */
++      if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
++              /* ok, we don't know the device, just re-ask the
++               * receiver for the list of connected devices. */
++              retval = logi_dj_recv_query_paired_devices(djrcv_dev);
++              if (!retval) {
++                      /* everything went fine, so just leave */
++                      break;
++              }
++              dev_err(&djrcv_dev->hdev->dev,
++                      "%s:logi_dj_recv_query_paired_devices "
++                      "error:%d\n", __func__, retval);
++              }
+               dbg_hid("%s: unexpected report type\n", __func__);
+       }
+ }
+@@ -367,6 +395,12 @@ static void logi_dj_recv_forward_null_re
+       if (!djdev) {
+               dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+                       " is NULL, index %d\n", dj_report->device_index);
++              kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
++
++              if (schedule_work(&djrcv_dev->work) == 0) {
++                      dbg_hid("%s: did not schedule the work item, was already "
++                      "queued\n", __func__);
++              }
+               return;
+       }
+@@ -397,6 +431,12 @@ static void logi_dj_recv_forward_report(
+       if (dj_device == NULL) {
+               dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
+                       " is NULL, index %d\n", dj_report->device_index);
++              kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
++
++              if (schedule_work(&djrcv_dev->work) == 0) {
++                      dbg_hid("%s: did not schedule the work item, was already "
++                      "queued\n", __func__);
++              }
+               return;
+       }
+@@ -444,6 +484,10 @@ static int logi_dj_recv_query_paired_dev
+       struct dj_report *dj_report;
+       int retval;
++      /* no need to protect djrcv_dev->querying_devices */
++      if (djrcv_dev->querying_devices)
++              return 0;
++
+       dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
+       if (!dj_report)
+               return -ENOMEM;
+@@ -455,6 +499,7 @@ static int logi_dj_recv_query_paired_dev
+       return retval;
+ }
++
+ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
+                                         unsigned timeout)
+ {
+--- a/drivers/hid/hid-logitech-dj.h
++++ b/drivers/hid/hid-logitech-dj.h
+@@ -101,6 +101,7 @@ struct dj_receiver_dev {
+       struct work_struct work;
+       struct kfifo notif_fifo;
+       spinlock_t lock;
++      bool querying_devices;
+ };
+ struct dj_device {
index eafa7ba1c5f72b25f65caf14b1d9f3a4955ed7c2..1fa5f8beab20565ee976413ca1b20e307a6145e7 100644 (file)
@@ -1,3 +1,4 @@
 irqchip-renesas-irqc-fix-irqc_probe-error-handling.patch
 clocksource-em_sti-set-cpu_possible_mask-to-fix-smp-broadcast.patch
 gpio-rcar-r-car-gpio-irq-share-interrupt.patch
+hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch