diff options
| author | Hans de Goede <johannes.goede@oss.qualcomm.com> | 2025-11-08 22:03:19 +0100 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.com> | 2025-11-26 16:16:34 +0100 |
| commit | 36dcfa468525336fc33cfa88f2a5514fc9cc0666 (patch) | |
| tree | ddb40554d11ed4136562d6a1862a19089f489c0c | |
| parent | ca389a55d8b2d86a817433bf82e0602b68c4d541 (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.c | 24 |
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: |
