From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
To: Vicki Pfau <vi@endrift.com>
Cc: Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
linux-input@vger.kernel.org
Subject: Re: [PATCH 1/3] hid-steam: Move hidraw input (un)registering to work
Date: Wed, 26 Feb 2025 16:24:53 -0800 [thread overview]
Message-ID: <Z7-w1fO4H0oOt8MP@google.com> (raw)
In-Reply-To: <20250205035529.1022143-1-vi@endrift.com>
Hi Vicki,
On Tue, Feb 04, 2025 at 07:55:27PM -0800, Vicki Pfau wrote:
> Due to an interplay between locking in the input and hid transport subsystems,
> attempting to register or deregister the relevant input devices during the
> hidraw open/close events can lead to a lock ordering issue. Though this
> shouldn't cause a deadlock, this commit moves the input device manipulation to
> deferred work to sidestep the issue.
>
> Signed-off-by: Vicki Pfau <vi@endrift.com>
> ---
> drivers/hid/hid-steam.c | 38 +++++++++++++++++++++++++++++++-------
> 1 file changed, 31 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
> index af38fc8eb34f..395dbe642f00 100644
> --- a/drivers/hid/hid-steam.c
> +++ b/drivers/hid/hid-steam.c
> @@ -313,6 +313,7 @@ struct steam_device {
> u16 rumble_left;
> u16 rumble_right;
> unsigned int sensor_timestamp_us;
> + struct work_struct unregister_work;
> };
>
> static int steam_recv_report(struct steam_device *steam,
> @@ -1072,6 +1073,31 @@ static void steam_mode_switch_cb(struct work_struct *work)
> }
> }
>
> +static void steam_work_unregister_cb(struct work_struct *work)
> +{
> + struct steam_device *steam = container_of(work, struct steam_device,
> + unregister_work);
> + unsigned long flags;
> + bool connected;
> + bool opened;
> +
> + spin_lock_irqsave(&steam->lock, flags);
> + opened = steam->client_opened;
> + connected = steam->connected;
> + spin_unlock_irqrestore(&steam->lock, flags);
> +
> + if (connected) {
> + if (opened) {
> + steam_sensors_unregister(steam);
> + steam_input_unregister(steam);
> + } else {
> + steam_set_lizard_mode(steam, lizard_mode);
> + steam_input_register(steam);
> + steam_sensors_register(steam);
> + }
> + }
> +}
> +
> static bool steam_is_valve_interface(struct hid_device *hdev)
> {
> struct hid_report_enum *rep_enum;
> @@ -1117,8 +1143,7 @@ static int steam_client_ll_open(struct hid_device *hdev)
> steam->client_opened++;
> spin_unlock_irqrestore(&steam->lock, flags);
>
> - steam_sensors_unregister(steam);
> - steam_input_unregister(steam);
> + schedule_work(&steam->unregister_work);
>
> return 0;
> }
> @@ -1135,11 +1160,7 @@ static void steam_client_ll_close(struct hid_device *hdev)
> connected = steam->connected && !steam->client_opened;
> spin_unlock_irqrestore(&steam->lock, flags);
>
> - if (connected) {
> - steam_set_lizard_mode(steam, lizard_mode);
> - steam_input_register(steam);
> - steam_sensors_register(steam);
> - }
> + schedule_work(&steam->unregister_work);
> }
>
> static int steam_client_ll_raw_request(struct hid_device *hdev,
> @@ -1231,6 +1252,7 @@ static int steam_probe(struct hid_device *hdev,
> INIT_LIST_HEAD(&steam->list);
> INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb);
> steam->sensor_timestamp_us = 0;
> + INIT_WORK(&steam->unregister_work, steam_work_unregister_cb);
>
> /*
> * With the real steam controller interface, do not connect hidraw.
> @@ -1291,6 +1313,7 @@ static int steam_probe(struct hid_device *hdev,
> cancel_work_sync(&steam->work_connect);
> cancel_delayed_work_sync(&steam->mode_switch);
> cancel_work_sync(&steam->rumble_work);
> + cancel_work_sync(&steam->unregister_work);
>
> return ret;
> }
> @@ -1307,6 +1330,7 @@ static void steam_remove(struct hid_device *hdev)
> cancel_delayed_work_sync(&steam->mode_switch);
> cancel_work_sync(&steam->work_connect);
> cancel_work_sync(&steam->rumble_work);
> + cancel_work_sync(&steam->unregister_work);
So what happens if you actually cancel the work here? Will you be
leaking input device?
And bigger question - do you actually need to unregister devices? Or it
is just a matter of not delivering data through them when device is in
the different mode?
Thanks.
--
Dmitry
prev parent reply other threads:[~2025-02-27 0:24 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-05 3:55 [PATCH 1/3] hid-steam: Move hidraw input (un)registering to work Vicki Pfau
2025-02-05 3:55 ` [PATCH 2/3] hid-steam: Mutex cleanup Vicki Pfau
2025-02-07 13:29 ` Jiri Kosina
2025-02-05 3:55 ` [PATCH 3/3] hid-steam: Don't use cancel_delayed_work_sync in IRQ context Vicki Pfau
2025-02-07 13:29 ` Jiri Kosina
2025-02-05 9:07 ` [PATCH 1/3] hid-steam: Move hidraw input (un)registering to work Jiri Kosina
2025-02-06 1:59 ` Vicki Pfau
2025-02-07 13:28 ` Jiri Kosina
2025-02-27 0:24 ` Dmitry Torokhov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z7-w1fO4H0oOt8MP@google.com \
--to=dmitry.torokhov@gmail.com \
--cc=benjamin.tissoires@redhat.com \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=vi@endrift.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.