summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <johannes.goede@oss.qualcomm.com>2025-11-08 22:03:19 +0100
committerJiri Kosina <jkosina@suse.com>2025-11-26 16:16:34 +0100
commit36dcfa468525336fc33cfa88f2a5514fc9cc0666 (patch)
treeddb40554d11ed4136562d6a1862a19089f489c0c
parentca389a55d8b2d86a817433bf82e0602b68c4d541 (diff)
HID: logitech-dj: Fix probe failure when used with KVM
Since commit 6f20d3261265 ("HID: logitech-dj: Fix error handling in logi_dj_recv_switch_to_dj_mode()") logi_dj_recv_switch_to_dj_mode() will return an error when the hid_hw_raw_request() call to enable [dis]connect events fails. This can happen when used with a KVM like the Aten CS1784a and the PC does not have the KVM focus when probe() runs, which causes probe() to fail after which the receiver will simply not work. The logi_dj_recv_query_paired_devices() call done at the end of probe() already ignores any errors for the KVM without focus case. When focus is restored and an input report is received this will trigger logi_dj_recv_queue_unknown_work() which retries the query_paired_devices() call from a workqueue. To fix the probe() failure let it ignore logi_dj_recv_switch_to_dj_mode() errors too, track if a successful logi_dj_recv_switch_to_dj_mode() was done and retry if necessary from logi_dj_recv_queue_unknown_work(). Queurying paired devices while not in dj-mode is not useful and this will be redone after the unknown work has retried setting dj-mode, so skip queurying paired devices when not in dj-mode yet. The new bool to track successful setting of the dj-mode will also cause setting dj-mode to be retried from the unknown work, if setting dj-mode failed after a reset_resume. Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
-rw-r--r--drivers/hid/hid-logitech-dj.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 3b5412541c92..fd1ea6f62068 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -148,6 +148,7 @@ struct dj_receiver_dev {
struct kfifo notif_fifo;
unsigned long last_query; /* in jiffies */
bool ready;
+ bool dj_mode;
enum recvr_type type;
unsigned int unnumbered_application;
spinlock_t lock;
@@ -557,6 +558,8 @@ static const u8 hid_reportid_size_map[NUMBER_OF_HID_REPORTS] = {
static const struct hid_ll_driver logi_dj_ll_driver;
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
+static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
+ unsigned int timeout);
static void delayedwork_callback(struct work_struct *work);
static LIST_HEAD(dj_hdev_list);
@@ -841,6 +844,9 @@ static void delayedwork_callback(struct work_struct *work)
logi_dj_recv_destroy_djhid_device(djrcv_dev, &workitem);
break;
case WORKITEM_TYPE_UNKNOWN:
+ if (!djrcv_dev->dj_mode)
+ logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
+
logi_dj_recv_query_paired_devices(djrcv_dev);
break;
case WORKITEM_TYPE_EMPTY:
@@ -1234,6 +1240,9 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
djrcv_dev->last_query = jiffies;
+ if (!djrcv_dev->dj_mode)
+ return 0;
+
if (djrcv_dev->type != recvr_type_dj) {
retval = logi_dj_recv_query_hidpp_devices(djrcv_dev);
goto out;
@@ -1317,6 +1326,7 @@ out:
if (retval < 0)
hid_err(hdev, "%s error:%d\n", __func__, retval);
+ djrcv_dev->dj_mode = retval >= 0;
return retval;
}
@@ -1837,9 +1847,11 @@ static int logi_dj_probe(struct hid_device *hdev,
}
if (has_hidpp) {
- retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
- if (retval < 0)
- goto switch_to_dj_mode_fail;
+ /*
+ * This can fail with a KVM. Ignore errors to let the probe
+ * succeed, logi_dj_recv_queue_unknown_work will retry later.
+ */
+ logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
}
/* This is enabling the polling urb on the IN endpoint */
@@ -1857,17 +1869,13 @@ static int logi_dj_probe(struct hid_device *hdev,
spin_lock_irqsave(&djrcv_dev->lock, flags);
djrcv_dev->ready = true;
spin_unlock_irqrestore(&djrcv_dev->lock, flags);
- /*
- * This can fail with a KVM. Ignore errors to let the probe
- * succeed, logi_dj_recv_queue_unknown_work will retry later.
- */
+ /* This too can fail with a KVM, ignore errors. */
logi_dj_recv_query_paired_devices(djrcv_dev);
}
return 0;
llopen_failed:
-switch_to_dj_mode_fail:
hid_hw_stop(hdev);
hid_hw_start_fail: