summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@redhat.com>2013-07-30 06:42:45 -0400
committerJosh Boyer <jwboyer@redhat.com>2013-07-30 06:44:31 -0400
commitd4864f88dfd6280b4af9c7dc09d499ddec174d8d (patch)
tree17f195be62b23ecf2bf54404326038a5473109dc
parent963bc0bed3c9050b634b22c496fd15f11cbf2d8b (diff)
downloadkernel-d4864f88dfd6280b4af9c7dc09d499ddec174d8d.tar.gz
kernel-d4864f88dfd6280b4af9c7dc09d499ddec174d8d.tar.xz
kernel-d4864f88dfd6280b4af9c7dc09d499ddec174d8d.zip
Revert some changes to make Logitech devices function properly (rhbz 989138)
-rw-r--r--HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch172
-rw-r--r--HID-hid-logitech-dj-querying_devices-was-never-set.patch30
-rw-r--r--kernel.spec11
3 files changed, 213 insertions, 0 deletions
diff --git a/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch b/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch
new file mode 100644
index 000000000..1c112ccde
--- /dev/null
+++ b/HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch
@@ -0,0 +1,172 @@
+From c63e0e370028d7e4033bd40165f18499872b5183 Mon Sep 17 00:00:00 2001
+From: Nestor Lopez Casado <nlopezcasad@logitech.com>
+Date: Thu, 18 Jul 2013 13:21:30 +0000
+Subject: HID: Revert "Revert "HID: Fix logitech-dj: missing Unifying device issue""
+
+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>
+---
+diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
+index 5207591a..cd33084 100644
+--- 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_driver;
+ 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_device(struct dj_receiver_dev *djrcv_dev,
+ 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_device(struct dj_receiver_dev *djrcv_dev,
+ 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 work_struct *work)
+ 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 work_struct *work)
+ 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_report(struct dj_receiver_dev *djrcv_dev,
+ 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(struct dj_receiver_dev *djrcv_dev,
+ 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_devices(struct dj_receiver_dev *djrcv_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_devices(struct dj_receiver_dev *djrcv_dev)
+ return retval;
+ }
+
++
+ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
+ unsigned timeout)
+ {
+diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h
+index fd28a5e..4a40003 100644
+--- 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 {
+--
+cgit v0.9.2
diff --git a/HID-hid-logitech-dj-querying_devices-was-never-set.patch b/HID-hid-logitech-dj-querying_devices-was-never-set.patch
new file mode 100644
index 000000000..0c79b6a5b
--- /dev/null
+++ b/HID-hid-logitech-dj-querying_devices-was-never-set.patch
@@ -0,0 +1,30 @@
+From 407a2c2a4d85100c8c67953e4bac2f4a6c942335 Mon Sep 17 00:00:00 2001
+From: Nestor Lopez Casado <nlopezcasad@logitech.com>
+Date: Thu, 18 Jul 2013 13:21:31 +0000
+Subject: HID: hid-logitech-dj: querying_devices was never set
+
+Set querying_devices flag to true when we start the enumeration
+process.
+
+This was missing from the original patch. It never produced
+undesirable effects as it is highly improbable to have a second
+enumeration triggered while a first one was still in progress.
+
+Signed-off-by: Nestor Lopez Casado <nlopezcasad@logitech.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+---
+diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
+index cd33084..7a57648 100644
+--- a/drivers/hid/hid-logitech-dj.c
++++ b/drivers/hid/hid-logitech-dj.c
+@@ -488,6 +488,8 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
+ if (djrcv_dev->querying_devices)
+ return 0;
+
++ djrcv_dev->querying_devices = true;
++
+ dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
+ if (!dj_report)
+ return -ENOMEM;
+--
+cgit v0.9.2
diff --git a/kernel.spec b/kernel.spec
index f1cfbbc0d..53135b6b5 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -751,6 +751,10 @@ Patch25064: iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch
#rhbz 979581
Patch25069: iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch
+#rhbz 989138
+Patch25072: HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch
+Patch25073: HID-hid-logitech-dj-querying_devices-was-never-set.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -1454,6 +1458,10 @@ ApplyPatch iwlwifi-dvm-dont-send-BT_CONFIG-on-devices-wo-Bluetooth.patch
#rhbz 979581
ApplyPatch iwlwifi-dvm-fix-calling-ieee80211_chswitch_done-with-NULL.patch
+#rhbz 989138
+ApplyPatch HID-Revert-Revert-HID-Fix-logitech-dj-missing-Unifying-device-issue.patch
+ApplyPatch HID-hid-logitech-dj-querying_devices-was-never-set.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2250,6 +2258,9 @@ fi
# ||----w |
# || ||
%changelog
+* Tue Jul 30 2013 Josh Boyer <jwboyer@redhat.com>
+- Revert some changes to make Logitech devices function properly (rhbz 989138)
+
* Mon Jul 29 2013 Kyle McMartin <kyle@redhat.com> - 3.11.0-0.rc3.git0.1
- arm-sound-soc-samsung-dma-avoid-another-64bit-division.patch: ditto