From: Greg Kroah-Hartman Date: Sat, 11 Jan 2014 00:13:26 +0000 (-0800) Subject: 3.10-stable patches X-Git-Tag: v3.4.77~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8d24079ca34b64f67e80e3d101c22e05355b0ca5;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch --- 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 index 00000000000..43d942503a8 --- /dev/null +++ b/queue-3.10/hid-revert-revert-hid-fix-logitech-dj-missing-unifying-device-issue.patch @@ -0,0 +1,176 @@ +From c63e0e370028d7e4033bd40165f18499872b5183 Mon Sep 17 00:00:00 2001 +From: Nestor Lopez Casado +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 + +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 +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + 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 { diff --git a/queue-3.10/series b/queue-3.10/series index eafa7ba1c5f..1fa5f8beab2 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -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