linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Tissoires <bentiss@kernel.org>
To: Jiri Kosina <jikos@kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	 Shuah Khan <shuah@kernel.org>, Jonathan Corbet <corbet@lwn.net>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
	 bpf@vger.kernel.org, linux-kselftest@vger.kernel.org,
	 linux-doc@vger.kernel.org,
	Benjamin Tissoires <bentiss@kernel.org>
Subject: [PATCH HID 08/12] HID: bpf: make hid_bpf_input_report() sleep until the device is ready
Date: Fri, 21 Jun 2024 10:55:53 +0200	[thread overview]
Message-ID: <20240621-hid_hw_req_bpf-v1-8-d7ab8b885a0b@kernel.org> (raw)
In-Reply-To: <20240621-hid_hw_req_bpf-v1-0-d7ab8b885a0b@kernel.org>

hid_bpf_input_report() is already marked to be used in sleepable context
only. So instead of hammering with timers the device to hopefully get
an available slot where the device is not sending events, we can make
that kfunc wait for the current event to be terminated before it goes in.

This allows to work with the following pseudo code:

in struct_ops/hid_device_event:
  - schedule a bpf_wq, which calls hid_bpf_input_report()
  - once this struct_ops function terminates, hid_bpf_input_report()
    immediately starts before the next event

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/bpf/hid_bpf_dispatch.c | 16 ++++++++++++----
 drivers/hid/hid-core.c             | 16 ++++++++++++----
 include/linux/hid_bpf.h            |  3 ++-
 3 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 709403340fd7..3ab513fba3d2 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -492,24 +492,32 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
  * @buf: a %PTR_TO_MEM buffer
  * @buf__sz: the size of the data to transfer
  *
- * Returns %0 on success, a negative error code otherwise.
+ * Returns %0 on success, a negative error code otherwise. This function will wait for the
+ * device to be available before injecting the event, thus needs to be called in sleepable
+ * context.
  */
 __bpf_kfunc int
 hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
 		     const size_t buf__sz)
 {
-	struct hid_device *hdev;
 	size_t size = buf__sz;
 	int ret;
 
+	ret = down_interruptible(&ctx->hid->driver_input_lock);
+	if (ret)
+		return ret;
+
 	/* check arguments */
 	ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
 	if (ret)
 		return ret;
 
-	hdev = (struct hid_device *)ctx->hid; /* discard const */
+	ret = hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (__u64)ctx,
+					true /* lock_already_taken */);
+
+	up(&ctx->hid->driver_input_lock);
 
-	return hid_ops->hid_input_report(hdev, type, buf, size, 0, (__u64)ctx);
+	return ret;
 }
 __bpf_kfunc_end_defs();
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5a5fa4a32cbc..b45d060f68c2 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2027,7 +2027,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
 
 
 static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
-			      u8 *data, u32 size, int interrupt, u64 source)
+			      u8 *data, u32 size, int interrupt, u64 source,
+			      bool lock_already_taken)
 {
 	struct hid_report_enum *report_enum;
 	struct hid_driver *hdrv;
@@ -2037,8 +2038,13 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
 	if (!hid)
 		return -ENODEV;
 
-	if (down_trylock(&hid->driver_input_lock))
+	ret = down_trylock(&hid->driver_input_lock);
+	if (lock_already_taken && !ret) {
+		up(&hid->driver_input_lock);
+		return -EINVAL;
+	} else if (!lock_already_taken && ret) {
 		return -EBUSY;
+	}
 
 	if (!hid->driver) {
 		ret = -ENODEV;
@@ -2079,7 +2085,8 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
 	ret = hid_report_raw_event(hid, type, data, size, interrupt);
 
 unlock:
-	up(&hid->driver_input_lock);
+	if (!lock_already_taken)
+		up(&hid->driver_input_lock);
 	return ret;
 }
 
@@ -2097,7 +2104,8 @@ static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
 int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
 		     int interrupt)
 {
-	return __hid_input_report(hid, type, data, size, interrupt, 0);
+	return __hid_input_report(hid, type, data, size, interrupt, 0,
+				  false /* lock_already_taken */);
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
 
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index 3872c6fac62b..1e450d38e239 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -71,7 +71,8 @@ struct hid_ops {
 	int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len,
 				    __u64 source, bool from_bpf);
 	int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type,
-				u8 *data, u32 size, int interrupt, u64 source);
+				u8 *data, u32 size, int interrupt, u64 source,
+				bool lock_already_taken);
 	struct module *owner;
 	const struct bus_type *bus_type;
 };

-- 
2.44.0


  parent reply	other threads:[~2024-06-21  8:56 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-21  8:55 [PATCH HID 00/12] HID: bpf_struct_ops, part 2 Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 01/12] HID: bpf: fix dispatch_hid_bpf_device_event uninitialized ret value Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 02/12] HID: add source argument to HID low level functions Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 03/12] HID: bpf: add HID-BPF hooks for hid_hw_raw_requests Benjamin Tissoires
2024-06-21 15:35   ` Alexei Starovoitov
2024-06-21  8:55 ` [PATCH HID 04/12] HID: bpf: prevent infinite recursions with hid_hw_raw_requests hooks Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 05/12] selftests/hid: add tests for hid_hw_raw_request HID-BPF hooks Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 06/12] HID: bpf: add HID-BPF hooks for hid_hw_output_report Benjamin Tissoires
2024-06-21 15:37   ` Alexei Starovoitov
2024-06-21 16:08     ` Benjamin Tissoires
2024-06-21 16:26       ` Alexei Starovoitov
2024-06-24  8:52         ` Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 07/12] selftests/hid: add tests for hid_hw_output_report HID-BPF hooks Benjamin Tissoires
2024-06-21  8:55 ` Benjamin Tissoires [this message]
2024-06-21  8:55 ` [PATCH HID 09/12] selftests/hid: add wq test for hid_bpf_input_report() Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 10/12] HID: bpf: allow hid_device_event hooks to inject input reports on self Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 11/12] selftests/hid: add another test for injecting an event from an event hook Benjamin Tissoires
2024-06-21  8:55 ` [PATCH HID 12/12] selftests/hid: add an infinite loop test for hid_bpf_try_input_report Benjamin Tissoires

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=20240621-hid_hw_req_bpf-v1-8-d7ab8b885a0b@kernel.org \
    --to=bentiss@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=corbet@lwn.net \
    --cc=jikos@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=shuah@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).