summaryrefslogtreecommitdiff
path: root/drivers/hid/bpf/hid_bpf_dispatch.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <bentiss@kernel.org>2024-06-26 16:46:30 +0300
committerBenjamin Tissoires <bentiss@kernel.org>2024-06-27 12:00:48 +0300
commitfa03f398a8ac46f46927e0b509b302ebe0ed7e8a (patch)
tree0a6577f9023e66ff6e8c01317775f865958fc781 /drivers/hid/bpf/hid_bpf_dispatch.c
parent3ac83fcd6e67c86d25040e6818972f2c36b51d23 (diff)
downloadlinux-fa03f398a8ac46f46927e0b509b302ebe0ed7e8a.tar.xz
HID: bpf: make hid_bpf_input_report() sleep until the device is ready
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 Link: https://patch.msgid.link/20240626-hid_hw_req_bpf-v2-9-cfd60fb6c79f@kernel.org Acked-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Diffstat (limited to 'drivers/hid/bpf/hid_bpf_dispatch.c')
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 68a9a2fcbc06..5174dc6d9d18 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -496,24 +496,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();