parent
654e094593
commit
dae65c5bdf
|
@ -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
|
|
@ -0,0 +1,24 @@
|
||||||
|
[PATCH] SCSI: Don't attempt to send extended INQUIRY command if skip_vpd_pages is set
|
||||||
|
|
||||||
|
If a device has the skip_vpd_pages flag set we should simply fail the
|
||||||
|
scsi_get_vpd_page() call.
|
||||||
|
|
||||||
|
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
||||||
|
Acked-by: Alan Stern <stern@rowland.harvard.edu>
|
||||||
|
Tested-by: Stuart Foster <smf.linux@ntlworld.com>
|
||||||
|
Cc: stable@vger.kernel.org
|
||||||
|
|
||||||
|
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
|
||||||
|
index 3b1ea34..eaa808e 100644
|
||||||
|
--- a/drivers/scsi/scsi.c
|
||||||
|
+++ b/drivers/scsi/scsi.c
|
||||||
|
@@ -1031,6 +1031,9 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
|
||||||
|
{
|
||||||
|
int i, result;
|
||||||
|
|
||||||
|
+ if (sdev->skip_vpd_pages)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
/* Ask for all the pages supported by this device */
|
||||||
|
result = scsi_vpd_inquiry(sdev, buf, 0, buf_len);
|
||||||
|
if (result)
|
18
PKGBUILD
18
PKGBUILD
|
@ -5,7 +5,7 @@ pkgbase=linux # Build stock -ARCH kernel
|
||||||
#pkgbase=linux-custom # Build kernel with a different name
|
#pkgbase=linux-custom # Build kernel with a different name
|
||||||
_srcname=linux-3.10
|
_srcname=linux-3.10
|
||||||
pkgver=3.10.6
|
pkgver=3.10.6
|
||||||
pkgrel=1
|
pkgrel=2
|
||||||
arch=('i686' 'x86_64')
|
arch=('i686' 'x86_64')
|
||||||
url="http://www.kernel.org/"
|
url="http://www.kernel.org/"
|
||||||
license=('GPL2')
|
license=('GPL2')
|
||||||
|
@ -18,14 +18,18 @@ source=("http://www.kernel.org/pub/linux/kernel/v3.x/${_srcname}.tar.xz"
|
||||||
# standard config files for mkinitcpio ramdisk
|
# standard config files for mkinitcpio ramdisk
|
||||||
'linux.preset'
|
'linux.preset'
|
||||||
'change-default-console-loglevel.patch'
|
'change-default-console-loglevel.patch'
|
||||||
'criu-no-expert.patch')
|
'criu-no-expert.patch'
|
||||||
|
'3.10.6-logitech-dj.patch'
|
||||||
|
'3.10.6-reset-superseed-xhci-hcd.patch')
|
||||||
md5sums=('4f25cd5bec5f8d5a7d935b3f2ccb8481'
|
md5sums=('4f25cd5bec5f8d5a7d935b3f2ccb8481'
|
||||||
'b41c06c1154592045cc2a9d88363de14'
|
'b41c06c1154592045cc2a9d88363de14'
|
||||||
'09aad29932fe0d1aa765b314800db9a8'
|
'09aad29932fe0d1aa765b314800db9a8'
|
||||||
'5ffd739d5b3e7c68bf07472aaceca400'
|
'5ffd739d5b3e7c68bf07472aaceca400'
|
||||||
'eb14dcfd80c00852ef81ded6e826826a'
|
'eb14dcfd80c00852ef81ded6e826826a'
|
||||||
'f3def2cefdcbb954c21d8505d23cc83c'
|
'f3def2cefdcbb954c21d8505d23cc83c'
|
||||||
'd50c1ac47394e9aec637002ef3392bd1')
|
'd50c1ac47394e9aec637002ef3392bd1'
|
||||||
|
'3ff40ca684cfe719723e627e2cef7cea'
|
||||||
|
'31f4d721494c4d5493ed90d9c504c5c9')
|
||||||
|
|
||||||
_kernelname=${pkgbase#linux}
|
_kernelname=${pkgbase#linux}
|
||||||
|
|
||||||
|
@ -53,6 +57,12 @@ prepare() {
|
||||||
# patch from fedora
|
# patch from fedora
|
||||||
patch -Np1 -i "${srcdir}/criu-no-expert.patch"
|
patch -Np1 -i "${srcdir}/criu-no-expert.patch"
|
||||||
|
|
||||||
|
# fix FS#35991 - [linux] 3.10.x renders Logitech Unified Receivers useless
|
||||||
|
patch -Np1 -i "${srcdir}/3.10.6-logitech-dj.patch"
|
||||||
|
|
||||||
|
# fix FS#36296 - [linux] 3.10.3 reset SuperSpeed USB using xhci_hcd
|
||||||
|
patch -Np1 -i "${srcdir}/3.10.6-reset-superseed-xhci-hcd.patch"
|
||||||
|
|
||||||
if [ "${CARCH}" = "x86_64" ]; then
|
if [ "${CARCH}" = "x86_64" ]; then
|
||||||
cat "${srcdir}/config.x86_64" > ./.config
|
cat "${srcdir}/config.x86_64" > ./.config
|
||||||
else
|
else
|
||||||
|
@ -332,4 +342,4 @@ for _p in ${pkgname[@]}; do
|
||||||
}"
|
}"
|
||||||
done
|
done
|
||||||
|
|
||||||
# vim:set ts=8 sts=2 sw=2 et:
|
# vim:set ts=8 sts=2 sw=2 et:
|
Loading…
Reference in New Issue