Linux Input/HID development
 help / color / mirror / Atom feed
* [dtor-input:ib/6.9-disable-irq-guard] BUILD SUCCESS c76494768761aef7630e7e0db820ba7b375964da
From: kernel test robot @ 2024-06-08  0:18 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git ib/6.9-disable-irq-guard
branch HEAD: c76494768761aef7630e7e0db820ba7b375964da  linux/interrupt.h: allow "guard" notation to disable and reenable IRQ

elapsed time: 1513m

configs tested: 61
configs skipped: 3

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig   gcc  
alpha                            allyesconfig   gcc  
alpha                               defconfig   gcc  
arc                               allnoconfig   gcc  
arc                                 defconfig   gcc  
arc                   randconfig-001-20240608   gcc  
arc                   randconfig-002-20240608   gcc  
arm                               allnoconfig   clang
arm                                 defconfig   clang
arm                   randconfig-001-20240608   gcc  
arm                   randconfig-002-20240608   clang
arm64                             allnoconfig   gcc  
arm64                               defconfig   gcc  
csky                              allnoconfig   gcc  
csky                                defconfig   gcc  
hexagon                          allmodconfig   clang
hexagon                           allnoconfig   clang
hexagon                          allyesconfig   clang
hexagon                             defconfig   clang
i386                             allmodconfig   gcc  
i386                              allnoconfig   gcc  
i386                             allyesconfig   gcc  
i386                                defconfig   clang
loongarch                         allnoconfig   gcc  
loongarch                           defconfig   gcc  
m68k                              allnoconfig   gcc  
m68k                                defconfig   gcc  
microblaze                        allnoconfig   gcc  
microblaze                          defconfig   gcc  
mips                              allnoconfig   gcc  
nios2                             allnoconfig   gcc  
nios2                               defconfig   gcc  
openrisc                          allnoconfig   gcc  
openrisc                            defconfig   gcc  
parisc                            allnoconfig   gcc  
parisc                              defconfig   gcc  
parisc64                            defconfig   gcc  
powerpc                           allnoconfig   gcc  
riscv                             allnoconfig   gcc  
riscv                               defconfig   clang
s390                              allnoconfig   clang
s390                                defconfig   clang
sh                               allmodconfig   gcc  
sh                                allnoconfig   gcc  
sh                               allyesconfig   gcc  
sh                                  defconfig   gcc  
sparc                             allnoconfig   gcc  
sparc                               defconfig   gcc  
sparc64                             defconfig   gcc  
um                               allmodconfig   clang
um                                allnoconfig   clang
um                               allyesconfig   gcc  
um                                  defconfig   clang
um                             i386_defconfig   gcc  
um                           x86_64_defconfig   clang
x86_64                            allnoconfig   clang
x86_64                           allyesconfig   clang
x86_64                              defconfig   gcc  
x86_64                                  kexec   clang
x86_64                          rhel-8.3-rust   clang
xtensa                            allnoconfig   gcc  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH V2 5/5] Add support for Awinic sar sensor.
From: kernel test robot @ 2024-06-08  2:22 UTC (permalink / raw)
  To: wangshuaijie, dmitry.torokhov, robh, krzk+dt, conor+dt, jeff,
	linux-input, devicetree, linux-kernel
  Cc: oe-kbuild-all, wangshuaijie, liweilei, kangjiajun
In-Reply-To: <20240605091143.163789-6-wangshuaijie@awinic.com>

Hi,

kernel test robot noticed the following build errors:

[auto build test ERROR on 32f88d65f01bf6f45476d7edbe675e44fb9e1d58]

url:    https://github.com/intel-lab-lkp/linux/commits/wangshuaijie-awinic-com/dt-bindings-input-Add-YAML-to-Awinic-sar-sensor/20240605-172023
base:   32f88d65f01bf6f45476d7edbe675e44fb9e1d58
patch link:    https://lore.kernel.org/r/20240605091143.163789-6-wangshuaijie%40awinic.com
patch subject: [PATCH V2 5/5] Add support for Awinic sar sensor.
config: arm-randconfig-r061-20240608 (https://download.01.org/0day-ci/archive/20240608/202406081000.gRWyFGXO-lkp@intel.com/config)
compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project d7d2d4f53fc79b4b58e8d8d08151b577c3699d4a)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240608/202406081000.gRWyFGXO-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202406081000.gRWyFGXO-lkp@intel.com/

All errors (new ones prefixed by >>):

>> ld.lld: error: undefined symbol: power_supply_reg_notifier
   >>> referenced by aw_sar.c
   >>>               drivers/input/misc/aw_sar/aw_sar.o:(aw_sar_i2c_probe) in archive vmlinux.a
--
>> ld.lld: error: undefined symbol: power_supply_unreg_notifier
   >>> referenced by aw_sar.c
   >>>               drivers/input/misc/aw_sar/aw_sar.o:(aw_sar_i2c_probe) in archive vmlinux.a
   >>> referenced by aw_sar.c
   >>>               drivers/input/misc/aw_sar/aw_sar.o:(aw_sar_i2c_probe) in archive vmlinux.a
   >>> referenced by aw_sar.c
   >>>               drivers/input/misc/aw_sar/aw_sar.o:(aw_sar_i2c_probe) in archive vmlinux.a
   >>> referenced 2 more times
--
>> ld.lld: error: undefined symbol: power_supply_get_property
   >>> referenced by aw_sar.c
   >>>               drivers/input/misc/aw_sar/aw_sar.o:(aw_sar_ps_notify_callback) in archive vmlinux.a

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH HID v2 03/16] HID: bpf: implement HID-BPF through bpf_struct_ops
From: Benjamin Tissoires @ 2024-06-08  8:00 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov,
	open list:KERNEL SELFTEST FRAMEWORK, LKML, bpf,
	open list:HID CORE LAYER, open list:DOCUMENTATION
In-Reply-To: <CAADnVQJo71xGQKLTW6Z1xsTLjtikN8bfemPUF4zj2c2Uvi5JMw@mail.gmail.com>

On Jun 07 2024, Alexei Starovoitov wrote:
> On Fri, Jun 7, 2024 at 8:28 AM Benjamin Tissoires <bentiss@kernel.org> wrote:
> > +struct hid_bpf_ops {
> > +       /* hid_id needs to stay first so we can easily change it
> > +        * from userspace.
> > +        */
> > +       int                     hid_id;
> > +       u32                     flags;
> > +
> > +       /* private: internal use only */
> > +       struct list_head        list;
> > +
> > +       /* public: rest is public */
> 
> Didn't notice it before, but the above comments are misleading.
> The whole struct is private to the kernel and bpf prog, while
> registering, can only touch a handful.
> I'd drop "internal use" and "is public". It's not an uapi.

Good point. The only purpose of this was to expose or not the fields in
the doc, so I'll make it clear that this is the reason of
"private/public".

> 
> > +
> > +/* fast path fields are put first to fill one cache line */
> 
> Also misleading. The whole struct fits one cache line.

true :)

> 
> > +
> > +       /**
> > +        * @hid_device_event: called whenever an event is coming in from the device
> > +        *
> > +        * It has the following arguments:
> > +        *
> > +        * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx
> > +        *
> > +        * Return: %0 on success and keep processing; a positive
> > +        * value to change the incoming size buffer; a negative
> > +        * error code to interrupt the processing of this event
> > +        *
> > +        * Context: Interrupt context.
> > +        */
> > +       int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type);
> > +
> > +/* control/slow paths put last */
> > +
> > +       /**
> > +        * @hid_rdesc_fixup: called when the probe function parses the report descriptor
> > +        * of the HID device
> > +        *
> > +        * It has the following arguments:
> > +        *
> > +        * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx
> > +        *
> > +        * Return: %0 on success and keep processing; a positive
> > +        * value to change the incoming size buffer; a negative
> > +        * error code to interrupt the processing of this device
> > +        */
> > +       int (*hid_rdesc_fixup)(struct hid_bpf_ctx *ctx);
> > +
> > +       /* private: internal use only */
> > +       struct hid_device *hdev;
> > +} ____cacheline_aligned_in_smp;
> 
> Such alignment is an overkill.
> I don't think you can measure the difference.

ack

> 
> > +
> >  struct hid_bpf_prog_list {
> >         u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV];
> >         u8 prog_cnt;
> > @@ -129,6 +188,10 @@ struct hid_bpf {
> >         bool destroyed;                 /* prevents the assignment of any progs */
> >
> >         spinlock_t progs_lock;          /* protects RCU update of progs */
> > +
> > +       struct hid_bpf_ops *rdesc_ops;
> > +       struct list_head prog_list;
> > +       struct mutex prog_list_lock;    /* protects RCU update of prog_list */
> 
> mutex protects rcu update... sounds very odd.
> Just say that mutex protects prog_list update, because "RCU update"
> has a different meaning. RCU logic itself is what protects Update part of rcU.

Ack

> 
> The rest looks good.

Thanks for looking into it!

Cheers,
Benjamin

^ permalink raw reply

* Re: [RFC] HID: ishtp-hid-client: replace fake-flex arrays with flex-array members
From: srinivas pandruvada @ 2024-06-08  8:42 UTC (permalink / raw)
  To: Erick Archer, Jiri Kosina, Benjamin Tissoires, Justin Stitt,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-input, linux-kernel, linux-hardening
In-Reply-To: <AS8PR02MB723760CB93942370E92F00638BF72@AS8PR02MB7237.eurprd02.prod.outlook.com>

On Sun, 2024-05-26 at 15:32 +0200, Erick Archer wrote:
> One-element arrays as fake flex arrays are deprecated [1] and we are
> moving towards adopting C99 flexible-array members, instead. This
> case
> also has more complexity because it is a flexible array of flexible
> arrays and this patch needs to be ready to enable the new compiler
> flag
> -Wflex-array-member-not-at-end (coming in GCC-14) globally.
> 
> So, define a new struct type for the single reports:
> 
> struct report {
> 	uint16_t size;
> 	struct hostif_msg_hdr msg;
> } __packed;
> 
> but without the payload (flex array) in it. And add this payload to
> the
> "hostif_msg" structure. This way, in the "report_list" structure we
> can
> declare a flex array of single reports which now do not contain
> another
> flex array.
> 
> struct report_list {
> 	[...]
>         struct report reports[];
> } __packed;
> 
> Also, use "container_of()" whenever we need to retrieve a pointer to
> the flexible structure, through which we can access the flexible
> array
> if needed.
> 
> Moreover, refactor the code accordingly to use the new structures and
> take advantage of this avoiding some pointer arithmetic and using the
> "struct_size" helper when possible.
> 
> This way, the code is more readable and safer.

Applied and tested, atleast didn't break anything.

But the explanation above didn't give me enough clue. You have added a
payload[] in the  struct hostif_msg {} then using that as a message
pointer following the header. I think this description needs to be
better.

Thanks,
Srinivas

> 
> Link:
> https://www.kernel.org/doc/html/next/process/deprecated.html#zero-length-and-one-element-arrays
>  [1]
> Closes: https://github.com/KSPP/linux/issues/333
> Signed-off-by: Erick Archer <erick.archer@outlook.com>
> ---
> Hi,
> 
> The idea behind this patch is extracted from the ones sent by Gustavo
> A. R. Silva [1] but without the use of "struct_group_tagged()" helper
> to separate the flexible array from the rest of the members in the
> flexible structures.
> 
> Regarding adding the "__counted_by" attribute to the flexible arrays,
> I can say that I have not dared. The reasons are:
> 
> 1.- In both arrays there are a no direct assignment to the counter
>     member. Only exists a cast from a raw stream of bytes to a
> pointer
>     of a structure and this way the counter member has the value.
> 
> 2.- The outer flexible array (in the struct report_list) has elements
>     of different size. I believe that every report can have a
> different
>     size, so I think the "__counted_by" will not work as expected.
> 
> Comments are welcome ;)
> 
> Regards,
> Erick
> 
> [1] Here are some patches that use the same idea:
> Link:
> https://lore.kernel.org/linux-hardening/cover.1709658886.git.gustavoars@kernel.org/
> Link: https://lore.kernel.org/linux-hardening/ZgYWlkxdrrieDYIu@neat/
> Link: https://lore.kernel.org/linux-hardening/ZgG8bbEzhmX5nGRE@neat/
> ---
>  drivers/hid/intel-ish-hid/ishtp-hid-client.c | 27 ++++++++++--------
> --
>  drivers/hid/intel-ish-hid/ishtp-hid.h        | 11 +++++---
>  2 files changed, 20 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c
> b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
> index fbd4f8ea1951..c0c8f4d7b0e3 100644
> --- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c
> +++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
> @@ -70,10 +70,10 @@ static void process_recv(struct ishtp_cl
> *hid_ishtp_cl, void *recv_buf,
>  	unsigned char *payload;
>  	struct device_info *dev_info;
>  	int i, j;
> -	size_t	payload_len, total_len, cur_pos, raw_len;
> +	size_t	payload_len, total_len, cur_pos, raw_len, msg_len;
>  	int report_type;
>  	struct report_list *reports_list;
> -	char *reports;
> +	struct report *report;
>  	size_t report_len;
>  	struct ishtp_cl_data *client_data =
> ishtp_get_client_data(hid_ishtp_cl);
>  	int curr_hid_dev = client_data->cur_hid_dev;
> @@ -99,7 +99,7 @@ static void process_recv(struct ishtp_cl
> *hid_ishtp_cl, void *recv_buf,
>  		payload_len = recv_msg->hdr.size;
>  
>  		/* Sanity checks */
> -		if (cur_pos + payload_len + sizeof(struct
> hostif_msg) >
> +		if (cur_pos + struct_size(recv_msg, payload,
> payload_len) >
>  				total_len) {
>  			++client_data->bad_recv_cnt;
>  			report_bad_packet(hid_ishtp_cl, recv_msg,
> cur_pos,
> @@ -280,14 +280,13 @@ static void process_recv(struct ishtp_cl
> *hid_ishtp_cl, void *recv_buf,
>  		case HOSTIF_PUBLISH_INPUT_REPORT_LIST:
>  			report_type = HID_INPUT_REPORT;
>  			reports_list = (struct report_list
> *)payload;
> -			reports = (char *)reports_list->reports;
> +			report = reports_list->reports;
>  
>  			for (j = 0; j < reports_list-
> >num_of_reports; j++) {
> -				recv_msg = (struct hostif_msg
> *)(reports +
> -					sizeof(uint16_t));
> -				report_len = *(uint16_t *)reports;
> -				payload = reports + sizeof(uint16_t)
> +
> -					sizeof(struct
> hostif_msg_hdr);
> +				recv_msg = container_of(&report-
> >msg,
> +							struct
> hostif_msg, hdr);
> +				report_len = report->size;
> +				payload = recv_msg->payload;
>  				payload_len = report_len -
>  					sizeof(struct
> hostif_msg_hdr);
>  
> @@ -304,7 +303,7 @@ static void process_recv(struct ishtp_cl
> *hid_ishtp_cl, void *recv_buf,
>  						0);
>  					}
>  
> -				reports += sizeof(uint16_t) +
> report_len;
> +				report += sizeof(*report) +
> payload_len;
>  			}
>  			break;
>  		default:
> @@ -316,12 +315,12 @@ static void process_recv(struct ishtp_cl
> *hid_ishtp_cl, void *recv_buf,
>  
>  		}
>  
> -		if (!cur_pos && cur_pos + payload_len +
> -				sizeof(struct hostif_msg) <
> total_len)
> +		msg_len = struct_size(recv_msg, payload,
> payload_len);
> +		if (!cur_pos && cur_pos + msg_len < total_len)
>  			++client_data->multi_packet_cnt;
>  
> -		cur_pos += payload_len + sizeof(struct hostif_msg);
> -		payload += payload_len + sizeof(struct hostif_msg);
> +		cur_pos += msg_len;
> +		payload += msg_len;
>  
>  	} while (cur_pos < total_len);
>  }
> diff --git a/drivers/hid/intel-ish-hid/ishtp-hid.h
> b/drivers/hid/intel-ish-hid/ishtp-hid.h
> index 35dddc5015b3..2bc19e8ba13e 100644
> --- a/drivers/hid/intel-ish-hid/ishtp-hid.h
> +++ b/drivers/hid/intel-ish-hid/ishtp-hid.h
> @@ -31,6 +31,7 @@ struct hostif_msg_hdr {
>  
>  struct hostif_msg {
>  	struct hostif_msg_hdr	hdr;
> +	uint8_t payload[];
>  } __packed;
>  
>  struct hostif_msg_to_sensor {
> @@ -52,15 +53,17 @@ struct ishtp_version {
>  	uint16_t build;
>  } __packed;
>  
> +struct report {
> +	uint16_t size;
> +	struct hostif_msg_hdr msg;
> +} __packed;
> +
>  /* struct for ISHTP aggregated input data */
>  struct report_list {
>  	uint16_t total_size;
>  	uint8_t	num_of_reports;
>  	uint8_t	flags;
> -	struct {
> -		uint16_t	size_of_report;
> -		uint8_t report[1];
> -	} __packed reports[1];
> +	struct report reports[];
>  } __packed;
>  
>  /* HOSTIF commands */


^ permalink raw reply

* [PATCH HID v3 00/16] HID: convert HID-BPF into using bpf_struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires, Peter Hutterer

The purpose of this series is to rethink how HID-BPF is invoked.
Currently it implies a jmp table, a prog fd bpf_map, a preloaded tracing
bpf program and a lot of manual work for handling the bpf program
lifetime and addition/removal.

OTOH, bpf_struct_ops take care of most of the bpf handling leaving us
with a simple list of ops pointers, and we can directly call the
struct_ops program from the kernel as a regular function.

The net gain right now is in term of code simplicity and lines of code
removal (though is an API breakage), but udev-hid-bpf is able to handle
such breakages.

In the near future, we will be able to extend the HID-BPF struct_ops
with entrypoints for hid_hw_raw_request() and hid_hw_output_report(),
allowing for covering all of the initial use cases:
- firewalling a HID device
- fixing all of the HID device interactions (not just device events as
  it is right now).

The matching user-space loader (udev-hid-bpf) MR is at
https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/86

I'll put it out of draft once this is merged.

Cheers,
Benjamin

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
Changes in v3:
- took Alexei's review into account
- Link to v2: https://lore.kernel.org/r/20240607-hid_bpf_struct_ops-v2-0-3f95f4d02292@kernel.org

Changes in v2:
- drop HID_BPF_FLAGS enum and use BPF_F_BEFORE instead
- fix .init_members to not open code member->offset
- allow struct hid_device to be writeable from HID-BPF for its name,
  uniq and phys
- Link to v1: https://lore.kernel.org/r/20240528-hid_bpf_struct_ops-v1-0-8c6663df27d8@kernel.org

---
Benjamin Tissoires (16):
      HID: rename struct hid_bpf_ops into hid_ops
      HID: bpf: add hid_get/put_device() helpers
      HID: bpf: implement HID-BPF through bpf_struct_ops
      selftests/hid: convert the hid_bpf selftests with struct_ops
      HID: samples: convert the 2 HID-BPF samples into struct_ops
      HID: bpf: add defines for HID-BPF SEC in in-tree bpf fixes
      HID: bpf: convert in-tree fixes into struct_ops
      HID: bpf: remove tracing HID-BPF capability
      selftests/hid: add subprog call test
      Documentation: HID: amend HID-BPF for struct_ops
      Documentation: HID: add a small blurb on udev-hid-bpf
      HID: bpf: Artist24: remove unused variable
      HID: bpf: error on warnings when compiling bpf objects
      bpf: allow bpf helpers to be used into HID-BPF struct_ops
      HID: bpf: rework hid_bpf_ops_btf_struct_access
      HID: bpf: make part of struct hid_device writable

 Documentation/hid/hid-bpf.rst                      | 173 ++++---
 drivers/hid/bpf/Makefile                           |   2 +-
 drivers/hid/bpf/entrypoints/Makefile               |  93 ----
 drivers/hid/bpf/entrypoints/README                 |   4 -
 drivers/hid/bpf/entrypoints/entrypoints.bpf.c      |  25 -
 drivers/hid/bpf/entrypoints/entrypoints.lskel.h    | 248 ---------
 drivers/hid/bpf/hid_bpf_dispatch.c                 | 266 +++-------
 drivers/hid/bpf/hid_bpf_dispatch.h                 |  12 +-
 drivers/hid/bpf/hid_bpf_jmp_table.c                | 565 ---------------------
 drivers/hid/bpf/hid_bpf_struct_ops.c               | 298 +++++++++++
 drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c  |   9 +-
 drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c    |   6 +-
 drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c   |   9 +-
 .../hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c  |   6 +-
 drivers/hid/bpf/progs/Makefile                     |   2 +-
 .../hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c    |   6 +-
 drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c          |   6 +-
 drivers/hid/bpf/progs/XPPen__Artist24.bpf.c        |  10 +-
 drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c |  24 +-
 drivers/hid/bpf/progs/hid_bpf.h                    |   5 +
 drivers/hid/hid-core.c                             |   6 +-
 include/linux/hid_bpf.h                            | 119 +++--
 samples/hid/Makefile                               |   5 +-
 samples/hid/hid_bpf_attach.bpf.c                   |  18 -
 samples/hid/hid_bpf_attach.h                       |  14 -
 samples/hid/hid_mouse.bpf.c                        |  26 +-
 samples/hid/hid_mouse.c                            |  39 +-
 samples/hid/hid_surface_dial.bpf.c                 |  10 +-
 samples/hid/hid_surface_dial.c                     |  53 +-
 tools/testing/selftests/hid/hid_bpf.c              | 100 +++-
 tools/testing/selftests/hid/progs/hid.c            | 100 +++-
 .../testing/selftests/hid/progs/hid_bpf_helpers.h  |  19 +-
 32 files changed, 800 insertions(+), 1478 deletions(-)
---
base-commit: 70ec81c2e2b4005465ad0d042e90b36087c36104
change-id: 20240513-hid_bpf_struct_ops-e3212a224555

Best regards,
-- 
Benjamin Tissoires <bentiss@kernel.org>


^ permalink raw reply

* [PATCH HID v3 01/16] HID: rename struct hid_bpf_ops into hid_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

Those operations are the ones from HID, not HID-BPF, and I'd like to
reuse hid_bpf_ops as the user facing struct_ops API.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 drivers/hid/bpf/hid_bpf_dispatch.c | 22 +++++++++++-----------
 drivers/hid/hid-core.c             |  6 +++---
 include/linux/hid_bpf.h            |  4 ++--
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 10289f44d0cc..55c9f82fdef0 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -21,8 +21,8 @@
 #include "hid_bpf_dispatch.h"
 #include "entrypoints/entrypoints.lskel.h"
 
-struct hid_bpf_ops *hid_bpf_ops;
-EXPORT_SYMBOL(hid_bpf_ops);
+struct hid_ops *hid_ops;
+EXPORT_SYMBOL(hid_ops);
 
 /**
  * hid_bpf_device_event - Called whenever an event is coming in from the device
@@ -284,13 +284,13 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
 	struct device *dev;
 	int err, fd;
 
-	if (!hid_bpf_ops)
+	if (!hid_ops)
 		return -EINVAL;
 
 	if ((flags & ~HID_BPF_FLAG_MASK))
 		return -EINVAL;
 
-	dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
+	dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
 	if (!dev)
 		return -EINVAL;
 
@@ -335,10 +335,10 @@ hid_bpf_allocate_context(unsigned int hid_id)
 	struct hid_bpf_ctx_kern *ctx_kern = NULL;
 	struct device *dev;
 
-	if (!hid_bpf_ops)
+	if (!hid_ops)
 		return NULL;
 
-	dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
+	dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
 	if (!dev)
 		return NULL;
 
@@ -386,7 +386,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
 	u32 report_len;
 
 	/* check arguments */
-	if (!ctx || !hid_bpf_ops || !buf)
+	if (!ctx || !hid_ops || !buf)
 		return -EINVAL;
 
 	switch (rtype) {
@@ -404,7 +404,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
 	hdev = (struct hid_device *)ctx->hid; /* discard const */
 
 	report_enum = hdev->report_enum + rtype;
-	report = hid_bpf_ops->hid_get_report(report_enum, buf);
+	report = hid_ops->hid_get_report(report_enum, buf);
 	if (!report)
 		return -EINVAL;
 
@@ -459,7 +459,7 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
 	if (!dma_data)
 		return -ENOMEM;
 
-	ret = hid_bpf_ops->hid_hw_raw_request(hdev,
+	ret = hid_ops->hid_hw_raw_request(hdev,
 					      dma_data[0],
 					      dma_data,
 					      size,
@@ -501,7 +501,7 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
 	if (!dma_data)
 		return -ENOMEM;
 
-	ret = hid_bpf_ops->hid_hw_output_report(hdev,
+	ret = hid_ops->hid_hw_output_report(hdev,
 						dma_data,
 						size);
 
@@ -534,7 +534,7 @@ hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf
 
 	hdev = (struct hid_device *)ctx->hid; /* discard const */
 
-	return hid_bpf_ops->hid_input_report(hdev, type, buf, size, 0);
+	return hid_ops->hid_input_report(hdev, type, buf, size, 0);
 }
 __bpf_kfunc_end_defs();
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index b1fa0378e8f4..14bbac432de5 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2971,7 +2971,7 @@ int hid_check_keys_pressed(struct hid_device *hid)
 EXPORT_SYMBOL_GPL(hid_check_keys_pressed);
 
 #ifdef CONFIG_HID_BPF
-static struct hid_bpf_ops hid_ops = {
+static struct hid_ops __hid_ops = {
 	.hid_get_report = hid_get_report,
 	.hid_hw_raw_request = hid_hw_raw_request,
 	.hid_hw_output_report = hid_hw_output_report,
@@ -2992,7 +2992,7 @@ static int __init hid_init(void)
 	}
 
 #ifdef CONFIG_HID_BPF
-	hid_bpf_ops = &hid_ops;
+	hid_ops = &__hid_ops;
 #endif
 
 	ret = hidraw_init();
@@ -3011,7 +3011,7 @@ static int __init hid_init(void)
 static void __exit hid_exit(void)
 {
 #ifdef CONFIG_HID_BPF
-	hid_bpf_ops = NULL;
+	hid_ops = NULL;
 #endif
 	hid_debug_exit();
 	hidraw_exit();
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index eec2592dec12..a66103618e6e 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -97,7 +97,7 @@ enum hid_bpf_prog_type {
 
 struct hid_report_enum;
 
-struct hid_bpf_ops {
+struct hid_ops {
 	struct hid_report *(*hid_get_report)(struct hid_report_enum *report_enum, const u8 *data);
 	int (*hid_hw_raw_request)(struct hid_device *hdev,
 				  unsigned char reportnum, __u8 *buf,
@@ -110,7 +110,7 @@ struct hid_bpf_ops {
 	const struct bus_type *bus_type;
 };
 
-extern struct hid_bpf_ops *hid_bpf_ops;
+extern struct hid_ops *hid_ops;
 
 struct hid_bpf_prog_list {
 	u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV];

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 02/16] HID: bpf: add hid_get/put_device() helpers
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

no code change, but this way we reduce code duplication and we
can export it later.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 drivers/hid/bpf/hid_bpf_dispatch.c | 47 ++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 20 deletions(-)

diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 55c9f82fdef0..c8bb79ce2354 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -150,6 +150,25 @@ static int device_match_id(struct device *dev, const void *id)
 	return hdev->id == *(int *)id;
 }
 
+static struct hid_device *hid_get_device(unsigned int hid_id)
+{
+	struct device *dev;
+
+	if (!hid_ops)
+		return ERR_PTR(-EINVAL);
+
+	dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	return to_hid_device(dev);
+}
+
+static void hid_put_device(struct hid_device *hid)
+{
+	put_device(&hid->dev);
+}
+
 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
 {
 	u8 *alloc_data;
@@ -281,20 +300,14 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
 {
 	struct hid_device *hdev;
 	struct bpf_prog *prog;
-	struct device *dev;
 	int err, fd;
 
-	if (!hid_ops)
-		return -EINVAL;
-
 	if ((flags & ~HID_BPF_FLAG_MASK))
 		return -EINVAL;
 
-	dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
-	if (!dev)
-		return -EINVAL;
-
-	hdev = to_hid_device(dev);
+	hdev = hid_get_device(hid_id);
+	if (IS_ERR(hdev))
+		return PTR_ERR(hdev);
 
 	/*
 	 * take a ref on the prog itself, it will be released
@@ -317,7 +330,7 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
  out_prog_put:
 	bpf_prog_put(prog);
  out_dev_put:
-	put_device(dev);
+	hid_put_device(hdev);
 	return err;
 }
 
@@ -333,20 +346,14 @@ hid_bpf_allocate_context(unsigned int hid_id)
 {
 	struct hid_device *hdev;
 	struct hid_bpf_ctx_kern *ctx_kern = NULL;
-	struct device *dev;
-
-	if (!hid_ops)
-		return NULL;
 
-	dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
-	if (!dev)
+	hdev = hid_get_device(hid_id);
+	if (IS_ERR(hdev))
 		return NULL;
 
-	hdev = to_hid_device(dev);
-
 	ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
 	if (!ctx_kern) {
-		put_device(dev);
+		hid_put_device(hdev);
 		return NULL;
 	}
 
@@ -373,7 +380,7 @@ hid_bpf_release_context(struct hid_bpf_ctx *ctx)
 	kfree(ctx_kern);
 
 	/* get_device() is called by bus_find_device() */
-	put_device(&hid->dev);
+	hid_put_device(hid);
 }
 
 static int

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 03/16] HID: bpf: implement HID-BPF through bpf_struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

We do this implementation in several steps to not have the CI failing:
- first (this patch), we add struct_ops while keeping the existing infra
  available
- then we change the selftests, the examples and the existing in-tree
  HID-BPF programs
- then we remove the existing trace points making old HID-BPF obsolete

There are a few advantages of struct_ops over tracing:
- compatibility with sleepable programs (for hid_hw_raw_request() in
  a later patch)
- a lot simpler in the kernel: it's a simple rcu protected list
- we can add more parameters to the function called without much trouble
- the "attach" is now generic through BPF-core: the caller just needs to
  set hid_id and flags before calling __load().
- all the BPF tough part is not handled in BPF-core through generic
  processing
- hid_bpf_ctx is now only writable where it needs be

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

changes in v3:
- change private/public misleading comments
- remove cache line comments/attribute
- change mutex prog_list_lock comment

changes in v2:
- drop custom enum hid_bpf_attach_flags (use BPF_F_BEFORE instead)
- fix member offset in .ops_init_member()
---
 drivers/hid/bpf/Makefile             |   2 +-
 drivers/hid/bpf/hid_bpf_dispatch.c   |  52 +++++++-
 drivers/hid/bpf/hid_bpf_dispatch.h   |   4 +
 drivers/hid/bpf/hid_bpf_jmp_table.c  |   3 +
 drivers/hid/bpf/hid_bpf_struct_ops.c | 247 +++++++++++++++++++++++++++++++++++
 include/linux/hid_bpf.h              |  61 ++++++++-
 6 files changed, 360 insertions(+), 9 deletions(-)

diff --git a/drivers/hid/bpf/Makefile b/drivers/hid/bpf/Makefile
index cf55120cf7d6..1cb3f31e9335 100644
--- a/drivers/hid/bpf/Makefile
+++ b/drivers/hid/bpf/Makefile
@@ -8,4 +8,4 @@ LIBBPF_INCLUDE = $(srctree)/tools/lib
 obj-$(CONFIG_HID_BPF) += hid_bpf.o
 CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE)
 CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE)
-hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o
+hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o hid_bpf_struct_ops.o
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index c8bb79ce2354..7216c3c7713d 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -58,6 +58,7 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
 		},
 		.data = hdev->bpf.device_data,
 	};
+	struct hid_bpf_ops *e;
 	int ret;
 
 	if (type >= HID_REPORT_TYPES)
@@ -70,9 +71,25 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
 	memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
 	memcpy(ctx_kern.data, data, *size);
 
+	rcu_read_lock();
+	list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
+		if (e->hid_device_event) {
+			ret = e->hid_device_event(&ctx_kern.ctx, type);
+			if (ret < 0) {
+				rcu_read_unlock();
+				return ERR_PTR(ret);
+			}
+
+			if (ret)
+				ctx_kern.ctx.retval = ret;
+		}
+	}
+	rcu_read_unlock();
+
 	ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern);
 	if (ret < 0)
 		return ERR_PTR(ret);
+	ret = ctx_kern.ctx.retval;
 
 	if (ret) {
 		if (ret > ctx_kern.ctx.allocated_size)
@@ -122,7 +139,10 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s
 
 	memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
 
-	ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern);
+	if (hdev->bpf.rdesc_ops)
+		ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
+	else
+		ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern);
 	if (ret < 0)
 		goto ignore_bpf;
 
@@ -150,7 +170,7 @@ static int device_match_id(struct device *dev, const void *id)
 	return hdev->id == *(int *)id;
 }
 
-static struct hid_device *hid_get_device(unsigned int hid_id)
+struct hid_device *hid_get_device(unsigned int hid_id)
 {
 	struct device *dev;
 
@@ -164,7 +184,7 @@ static struct hid_device *hid_get_device(unsigned int hid_id)
 	return to_hid_device(dev);
 }
 
-static void hid_put_device(struct hid_device *hid)
+void hid_put_device(struct hid_device *hid)
 {
 	put_device(&hid->dev);
 }
@@ -205,7 +225,7 @@ static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size
 	return 0;
 }
 
-static int hid_bpf_allocate_event_data(struct hid_device *hdev)
+int hid_bpf_allocate_event_data(struct hid_device *hdev)
 {
 	/* hdev->bpf.device_data is already allocated, abort */
 	if (hdev->bpf.device_data)
@@ -592,14 +612,22 @@ static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
 
 int hid_bpf_connect_device(struct hid_device *hdev)
 {
-	struct hid_bpf_prog_list *prog_list;
+	bool need_to_allocate = false;
+	struct hid_bpf_ops *e;
 
 	rcu_read_lock();
-	prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]);
+	list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
+		if (e->hid_device_event) {
+			need_to_allocate = true;
+			break;
+		}
+	}
+	if (rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]))
+		need_to_allocate = true;
 	rcu_read_unlock();
 
 	/* only allocate BPF data if there are programs attached */
-	if (!prog_list)
+	if (!need_to_allocate)
 		return 0;
 
 	return hid_bpf_allocate_event_data(hdev);
@@ -623,12 +651,15 @@ void hid_bpf_destroy_device(struct hid_device *hdev)
 	hdev->bpf.destroyed = true;
 
 	__hid_bpf_destroy_device(hdev);
+	__hid_bpf_ops_destroy_device(hdev);
 }
 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
 
 void hid_bpf_device_init(struct hid_device *hdev)
 {
 	spin_lock_init(&hdev->bpf.progs_lock);
+	INIT_LIST_HEAD(&hdev->bpf.prog_list);
+	mutex_init(&hdev->bpf.prog_list_lock);
 }
 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
 
@@ -662,6 +693,13 @@ static int __init hid_bpf_init(void)
 		return 0;
 	}
 
+	/* register struct_ops kfuncs after we are sure we can load our preloaded bpf program */
+	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
+	if (err) {
+		pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
+		return 0;
+	}
+
 	/* register syscalls after we are sure we can load our preloaded bpf program */
 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
 	if (err) {
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.h b/drivers/hid/bpf/hid_bpf_dispatch.h
index fbe0639d09f2..e52c43d81650 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.h
+++ b/drivers/hid/bpf/hid_bpf_dispatch.h
@@ -10,12 +10,16 @@ struct hid_bpf_ctx_kern {
 	u8 *data;
 };
 
+struct hid_device *hid_get_device(unsigned int hid_id);
+void hid_put_device(struct hid_device *hid);
+int hid_bpf_allocate_event_data(struct hid_device *hdev);
 int hid_bpf_preload_skel(void);
 void hid_bpf_free_links_and_skel(void);
 int hid_bpf_get_prog_attach_type(struct bpf_prog *prog);
 int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd,
 			  struct bpf_prog *prog, __u32 flags);
 void __hid_bpf_destroy_device(struct hid_device *hdev);
+void __hid_bpf_ops_destroy_device(struct hid_device *hdev);
 int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
 		     struct hid_bpf_ctx_kern *ctx_kern);
 int hid_bpf_reconnect(struct hid_device *hdev);
diff --git a/drivers/hid/bpf/hid_bpf_jmp_table.c b/drivers/hid/bpf/hid_bpf_jmp_table.c
index aa8e1c79cdf5..8a54ba447718 100644
--- a/drivers/hid/bpf/hid_bpf_jmp_table.c
+++ b/drivers/hid/bpf/hid_bpf_jmp_table.c
@@ -81,6 +81,9 @@ static int hid_bpf_program_count(struct hid_device *hdev,
 	if (type >= HID_BPF_PROG_TYPE_MAX)
 		return -EINVAL;
 
+	if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && hdev->bpf.rdesc_ops)
+		n += 1;
+
 	FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
 		struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
 
diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
new file mode 100644
index 000000000000..9192c66cde20
--- /dev/null
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ *  HID-BPF support for Linux
+ *
+ *  Copyright (c) 2024 Benjamin Tissoires
+ */
+
+#include <linux/bitops.h>
+#include <linux/bpf_verifier.h>
+#include <linux/bpf.h>
+#include <linux/btf.h>
+#include <linux/btf_ids.h>
+#include <linux/filter.h>
+#include <linux/hid.h>
+#include <linux/hid_bpf.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include "hid_bpf_dispatch.h"
+
+static struct btf *hid_bpf_ops_btf;
+
+static int hid_bpf_ops_init(struct btf *btf)
+{
+	hid_bpf_ops_btf = btf;
+	return 0;
+}
+
+static bool hid_bpf_ops_is_valid_access(int off, int size,
+					  enum bpf_access_type type,
+					  const struct bpf_prog *prog,
+					  struct bpf_insn_access_aux *info)
+{
+	return bpf_tracing_btf_ctx_access(off, size, type, prog, info);
+}
+
+static int hid_bpf_ops_check_member(const struct btf_type *t,
+				      const struct btf_member *member,
+				      const struct bpf_prog *prog)
+{
+	u32 moff = __btf_member_bit_offset(t, member) / 8;
+
+	switch (moff) {
+	case offsetof(struct hid_bpf_ops, hid_rdesc_fixup):
+		break;
+	default:
+		if (prog->sleepable)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
+					   const struct bpf_reg_state *reg,
+					   int off, int size)
+{
+	const struct btf_type *state;
+	const struct btf_type *t;
+	s32 type_id;
+
+	type_id = btf_find_by_name_kind(reg->btf, "hid_bpf_ctx",
+					BTF_KIND_STRUCT);
+	if (type_id < 0)
+		return -EINVAL;
+
+	t = btf_type_by_id(reg->btf, reg->btf_id);
+	state = btf_type_by_id(reg->btf, type_id);
+	if (t != state) {
+		bpf_log(log, "only access to hid_bpf_ctx is supported\n");
+		return -EACCES;
+	}
+
+	/* out-of-bound access in hid_bpf_ctx */
+	if (off + size > sizeof(struct hid_bpf_ctx)) {
+		bpf_log(log, "write access at off %d with size %d\n", off, size);
+		return -EACCES;
+	}
+
+	if (off < offsetof(struct hid_bpf_ctx, retval)) {
+		bpf_log(log,
+			"write access at off %d with size %d on read-only part of hid_bpf_ctx\n",
+			off, size);
+		return -EACCES;
+	}
+
+	return NOT_INIT;
+}
+
+static const struct bpf_verifier_ops hid_bpf_verifier_ops = {
+	.is_valid_access = hid_bpf_ops_is_valid_access,
+	.btf_struct_access = hid_bpf_ops_btf_struct_access,
+};
+
+static int hid_bpf_ops_init_member(const struct btf_type *t,
+				 const struct btf_member *member,
+				 void *kdata, const void *udata)
+{
+	u32 moff = __btf_member_bit_offset(t, member) / 8;
+	u32 flags;
+
+	switch (moff) {
+	case offsetof(struct hid_bpf_ops, hid_id):
+		/* For hid_id and flags fields, this function has to copy it
+		 * and return 1 to indicate that the data has been handled by
+		 * the struct_ops type, or the verifier will reject the map if
+		 * the value of those fields is not zero.
+		 */
+		((struct hid_bpf_ops *)kdata)->hid_id = ((struct hid_bpf_ops *)udata)->hid_id;
+		return 1;
+	case offsetof(struct hid_bpf_ops, flags):
+		flags = ((struct hid_bpf_ops *)udata)->flags;
+		if (flags & ~BPF_F_BEFORE)
+			return -EINVAL;
+		((struct hid_bpf_ops *)kdata)->flags = flags;
+		return 1;
+	}
+	return 0;
+}
+
+static int hid_bpf_reg(void *kdata)
+{
+	struct hid_bpf_ops *ops = kdata;
+	struct hid_device *hdev;
+	int count, err = 0;
+
+	hdev = hid_get_device(ops->hid_id);
+	if (IS_ERR(hdev))
+		return PTR_ERR(hdev);
+
+	ops->hdev = hdev;
+
+	mutex_lock(&hdev->bpf.prog_list_lock);
+
+	count = list_count_nodes(&hdev->bpf.prog_list);
+	if (count >= HID_BPF_MAX_PROGS_PER_DEV) {
+		err = -E2BIG;
+		goto out_unlock;
+	}
+
+	if (ops->hid_rdesc_fixup) {
+		if (hdev->bpf.rdesc_ops) {
+			err = -EINVAL;
+			goto out_unlock;
+		}
+
+		hdev->bpf.rdesc_ops = ops;
+	}
+
+	if (ops->hid_device_event) {
+		err = hid_bpf_allocate_event_data(hdev);
+		if (err)
+			goto out_unlock;
+	}
+
+	if (ops->flags & BPF_F_BEFORE)
+		list_add_rcu(&ops->list, &hdev->bpf.prog_list);
+	else
+		list_add_tail_rcu(&ops->list, &hdev->bpf.prog_list);
+
+out_unlock:
+	mutex_unlock(&hdev->bpf.prog_list_lock);
+
+	if (err) {
+		if (hdev->bpf.rdesc_ops == ops)
+			hdev->bpf.rdesc_ops = NULL;
+		hid_put_device(hdev);
+	} else if (ops->hid_rdesc_fixup) {
+		hid_bpf_reconnect(hdev);
+	}
+
+	return err;
+}
+
+static void hid_bpf_unreg(void *kdata)
+{
+	struct hid_bpf_ops *ops = kdata;
+	struct hid_device *hdev;
+	bool reconnect = false;
+
+	hdev = ops->hdev;
+
+	/* check if __hid_bpf_ops_destroy_device() has been called */
+	if (!hdev)
+		return;
+
+	mutex_lock(&hdev->bpf.prog_list_lock);
+
+	list_del_rcu(&ops->list);
+
+	reconnect = hdev->bpf.rdesc_ops == ops;
+	if (reconnect)
+		hdev->bpf.rdesc_ops = NULL;
+
+	mutex_unlock(&hdev->bpf.prog_list_lock);
+
+	if (reconnect)
+		hid_bpf_reconnect(hdev);
+
+	hid_put_device(hdev);
+}
+
+static int __hid_bpf_device_event(struct hid_bpf_ctx *ctx, enum hid_report_type type)
+{
+	return 0;
+}
+
+static int __hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx)
+{
+	return 0;
+}
+
+static struct hid_bpf_ops __bpf_hid_bpf_ops = {
+	.hid_device_event = __hid_bpf_device_event,
+	.hid_rdesc_fixup = __hid_bpf_rdesc_fixup,
+};
+
+static struct bpf_struct_ops bpf_hid_bpf_ops = {
+	.verifier_ops = &hid_bpf_verifier_ops,
+	.init = hid_bpf_ops_init,
+	.check_member = hid_bpf_ops_check_member,
+	.init_member = hid_bpf_ops_init_member,
+	.reg = hid_bpf_reg,
+	.unreg = hid_bpf_unreg,
+	.name = "hid_bpf_ops",
+	.cfi_stubs = &__bpf_hid_bpf_ops,
+	.owner = THIS_MODULE,
+};
+
+void __hid_bpf_ops_destroy_device(struct hid_device *hdev)
+{
+	struct hid_bpf_ops *e;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
+		hid_put_device(hdev);
+		e->hdev = NULL;
+	}
+	rcu_read_unlock();
+}
+
+static int __init hid_bpf_struct_ops_init(void)
+{
+	return register_bpf_struct_ops(&bpf_hid_bpf_ops, hid_bpf_ops);
+}
+late_initcall(hid_bpf_struct_ops_init);
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index a66103618e6e..c4f4ce10b7dd 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -65,11 +65,12 @@ struct hid_bpf_ctx {
  * @HID_BPF_FLAG_INSERT_HEAD: insert the given program before any other program
  *                            currently attached to the device. This doesn't
  *                            guarantee that this program will always be first
- * @HID_BPF_FLAG_MAX: sentinel value, not to be used by the callers
  */
 enum hid_bpf_attach_flags {
 	HID_BPF_FLAG_NONE = 0,
 	HID_BPF_FLAG_INSERT_HEAD = _BITUL(0),
+
+	/* private: internal use only */
 	HID_BPF_FLAG_MAX,
 };
 
@@ -112,6 +113,60 @@ struct hid_ops {
 
 extern struct hid_ops *hid_ops;
 
+/**
+ * struct hid_bpf_ops - A BPF struct_ops of callbacks allowing to attach HID-BPF
+ *			programs to a HID device
+ * @hid_id: the HID uniq ID to attach to. This is writeable before ``load()``, and
+ *	    cannot be changed after
+ * @flags: flags used while attaching the struct_ops to the device. Currently only
+ *	   available value is %0 or ``BPF_F_BEFORE``.
+ *	   Writeable only before ``load()``
+ */
+struct hid_bpf_ops {
+	/* hid_id needs to stay first so we can easily change it
+	 * from userspace.
+	 */
+	int			hid_id;
+	u32			flags;
+
+	/* private: do not show up in the docs */
+	struct list_head	list;
+
+	/* public: rest should show up in the docs */
+
+	/**
+	 * @hid_device_event: called whenever an event is coming in from the device
+	 *
+	 * It has the following arguments:
+	 *
+	 * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx
+	 *
+	 * Return: %0 on success and keep processing; a positive
+	 * value to change the incoming size buffer; a negative
+	 * error code to interrupt the processing of this event
+	 *
+	 * Context: Interrupt context.
+	 */
+	int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type);
+
+	/**
+	 * @hid_rdesc_fixup: called when the probe function parses the report descriptor
+	 * of the HID device
+	 *
+	 * It has the following arguments:
+	 *
+	 * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx
+	 *
+	 * Return: %0 on success and keep processing; a positive
+	 * value to change the incoming size buffer; a negative
+	 * error code to interrupt the processing of this device
+	 */
+	int (*hid_rdesc_fixup)(struct hid_bpf_ctx *ctx);
+
+	/* private: do not show up in the docs */
+	struct hid_device *hdev;
+};
+
 struct hid_bpf_prog_list {
 	u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV];
 	u8 prog_cnt;
@@ -129,6 +184,10 @@ struct hid_bpf {
 	bool destroyed;			/* prevents the assignment of any progs */
 
 	spinlock_t progs_lock;		/* protects RCU update of progs */
+
+	struct hid_bpf_ops *rdesc_ops;
+	struct list_head prog_list;
+	struct mutex prog_list_lock;	/* protects prog_list update */
 };
 
 /* specific HID-BPF link when a program is attached to a device */

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 04/16] selftests/hid: convert the hid_bpf selftests with struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

We drop the need for the attach() bpf syscall, but we need to set up
the hid_id field before calling __load().

The .bpf.c part is mechanical: we create one struct_ops per HID-BPF
program, as all the tests are for one program at a time.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

changes in v2:
- use BPF_F_BEFORE
---
 tools/testing/selftests/hid/hid_bpf.c              | 59 +++++++++--------
 tools/testing/selftests/hid/progs/hid.c            | 76 +++++++++++++++-------
 .../testing/selftests/hid/progs/hid_bpf_helpers.h  | 19 ++----
 3 files changed, 89 insertions(+), 65 deletions(-)

diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c
index f825623e3edc..967dfe6b58cb 100644
--- a/tools/testing/selftests/hid/hid_bpf.c
+++ b/tools/testing/selftests/hid/hid_bpf.c
@@ -460,7 +460,7 @@ FIXTURE(hid_bpf) {
 	int hid_id;
 	pthread_t tid;
 	struct hid *skel;
-	int hid_links[3]; /* max number of programs loaded in a single test */
+	struct bpf_link *hid_links[3]; /* max number of programs loaded in a single test */
 };
 static void detach_bpf(FIXTURE_DATA(hid_bpf) * self)
 {
@@ -472,7 +472,7 @@ static void detach_bpf(FIXTURE_DATA(hid_bpf) * self)
 
 	for (i = 0; i < ARRAY_SIZE(self->hid_links); i++) {
 		if (self->hid_links[i])
-			close(self->hid_links[i]);
+			bpf_link__destroy(self->hid_links[i]);
 	}
 
 	hid__destroy(self->skel);
@@ -527,14 +527,7 @@ static void load_programs(const struct test_program programs[],
 			  FIXTURE_DATA(hid_bpf) * self,
 			  const FIXTURE_VARIANT(hid_bpf) * variant)
 {
-	int attach_fd, err = -EINVAL;
-	struct attach_prog_args args = {
-		.retval = -1,
-	};
-	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
-			    .ctx_in = &args,
-			    .ctx_size_in = sizeof(args),
-	);
+	int err = -EINVAL;
 
 	ASSERT_LE(progs_count, ARRAY_SIZE(self->hid_links))
 		TH_LOG("too many programs are to be loaded");
@@ -545,35 +538,41 @@ static void load_programs(const struct test_program programs[],
 
 	for (int i = 0; i < progs_count; i++) {
 		struct bpf_program *prog;
+		struct bpf_map *map;
+		int *ops_hid_id;
 
 		prog = bpf_object__find_program_by_name(*self->skel->skeleton->obj,
 							programs[i].name);
 		ASSERT_OK_PTR(prog) TH_LOG("can not find program by name '%s'", programs[i].name);
 
 		bpf_program__set_autoload(prog, true);
+
+		map = bpf_object__find_map_by_name(*self->skel->skeleton->obj,
+							  programs[i].name + 4);
+		ASSERT_OK_PTR(map) TH_LOG("can not find struct_ops by name '%s'",
+					  programs[i].name + 4);
+
+		/* hid_id is the first field of struct hid_bpf_ops */
+		ops_hid_id = bpf_map__initial_value(map, NULL);
+		ASSERT_OK_PTR(ops_hid_id) TH_LOG("unable to retrieve struct_ops data");
+
+		*ops_hid_id = self->hid_id;
 	}
 
 	err = hid__load(self->skel);
 	ASSERT_OK(err) TH_LOG("hid_skel_load failed: %d", err);
 
-	attach_fd = bpf_program__fd(self->skel->progs.attach_prog);
-	ASSERT_GE(attach_fd, 0) TH_LOG("locate attach_prog: %d", attach_fd);
-
 	for (int i = 0; i < progs_count; i++) {
-		struct bpf_program *prog;
+		struct bpf_map *map;
 
-		prog = bpf_object__find_program_by_name(*self->skel->skeleton->obj,
-							programs[i].name);
-		ASSERT_OK_PTR(prog) TH_LOG("can not find program by name '%s'", programs[i].name);
-
-		args.prog_fd = bpf_program__fd(prog);
-		args.hid = self->hid_id;
-		args.insert_head = programs[i].insert_head;
-		err = bpf_prog_test_run_opts(attach_fd, &tattr);
-		ASSERT_GE(args.retval, 0)
-			TH_LOG("attach_hid(%s): %d", programs[i].name, args.retval);
+		map = bpf_object__find_map_by_name(*self->skel->skeleton->obj,
+							  programs[i].name + 4);
+		ASSERT_OK_PTR(map) TH_LOG("can not find struct_ops by name '%s'",
+					  programs[i].name + 4);
 
-		self->hid_links[i] = args.retval;
+		self->hid_links[i] = bpf_map__attach_struct_ops(map);
+		ASSERT_OK_PTR(self->hid_links[i]) TH_LOG("failed to attach struct ops '%s'",
+							 programs[i].name + 4);
 	}
 
 	self->hidraw_fd = open_hidraw(self->dev_id);
@@ -648,13 +647,17 @@ TEST_F(hid_bpf, test_attach_detach)
 		{ .name = "hid_first_event" },
 		{ .name = "hid_second_event" },
 	};
+	struct bpf_link *link;
 	__u8 buf[10] = {0};
-	int err, link;
+	int err, link_fd;
 
 	LOAD_PROGRAMS(progs);
 
 	link = self->hid_links[0];
-	ASSERT_GT(link, 0) TH_LOG("HID-BPF link not created");
+	ASSERT_OK_PTR(link) TH_LOG("HID-BPF link not created");
+
+	link_fd = bpf_link__fd(link);
+	ASSERT_GE(link_fd, 0) TH_LOG("HID-BPF link FD not valid");
 
 	/* inject one event */
 	buf[0] = 1;
@@ -673,7 +676,7 @@ TEST_F(hid_bpf, test_attach_detach)
 
 	/* pin the first program and immediately unpin it */
 #define PIN_PATH "/sys/fs/bpf/hid_first_event"
-	err = bpf_obj_pin(link, PIN_PATH);
+	err = bpf_obj_pin(link_fd, PIN_PATH);
 	ASSERT_OK(err) TH_LOG("error while calling bpf_obj_pin");
 	remove(PIN_PATH);
 #undef PIN_PATH
diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c
index f67d35def142..614f1aa32649 100644
--- a/tools/testing/selftests/hid/progs/hid.c
+++ b/tools/testing/selftests/hid/progs/hid.c
@@ -14,8 +14,8 @@ struct attach_prog_args {
 __u64 callback_check = 52;
 __u64 callback2_check = 52;
 
-SEC("?fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx)
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {
 	__u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
 
@@ -29,8 +29,14 @@ int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx)
 	return hid_ctx->size;
 }
 
-SEC("?fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx)
+SEC(".struct_ops.link")
+struct hid_bpf_ops first_event = {
+	.hid_device_event = (void *)hid_first_event,
+	.hid_id = 2,
+};
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {
 	__u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
 
@@ -42,8 +48,13 @@ int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx)
 	return hid_ctx->size;
 }
 
-SEC("?fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx)
+SEC(".struct_ops.link")
+struct hid_bpf_ops second_event = {
+	.hid_device_event = (void *)hid_second_event,
+};
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {
 	__u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
 
@@ -55,15 +66,10 @@ int BPF_PROG(hid_change_report_id, struct hid_bpf_ctx *hid_ctx)
 	return 9;
 }
 
-SEC("syscall")
-int attach_prog(struct attach_prog_args *ctx)
-{
-	ctx->retval = hid_bpf_attach_prog(ctx->hid,
-					  ctx->prog_fd,
-					  ctx->insert_head ? HID_BPF_FLAG_INSERT_HEAD :
-							     HID_BPF_FLAG_NONE);
-	return 0;
-}
+SEC(".struct_ops.link")
+struct hid_bpf_ops change_report_id = {
+	.hid_device_event = (void *)hid_change_report_id,
+};
 
 struct hid_hw_request_syscall_args {
 	/* data needs to come at offset 0 so we can use it in calls */
@@ -181,7 +187,12 @@ static const __u8 rdesc[] = {
 	0xc0,			/* END_COLLECTION */
 };
 
-SEC("?fmod_ret/hid_bpf_rdesc_fixup")
+/*
+ * the following program is marked as sleepable (struct_ops.s).
+ * This is not strictly mandatory but is a nice test for
+ * sleepable struct_ops
+ */
+SEC("?struct_ops.s/hid_rdesc_fixup")
 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hid_ctx)
 {
 	__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4096 /* size */);
@@ -200,8 +211,13 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hid_ctx)
 	return sizeof(rdesc) + 73;
 }
 
-SEC("?fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx)
+SEC(".struct_ops.link")
+struct hid_bpf_ops rdesc_fixup = {
+	.hid_rdesc_fixup = (void *)hid_rdesc_fixup,
+};
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {
 	__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
 
@@ -217,8 +233,14 @@ int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx)
 	return 0;
 }
 
-SEC("?fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx)
+SEC(".struct_ops.link")
+struct hid_bpf_ops test_insert1 = {
+	.hid_device_event = (void *)hid_test_insert1,
+	.flags = BPF_F_BEFORE,
+};
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {
 	__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
 
@@ -234,8 +256,13 @@ int BPF_PROG(hid_test_insert2, struct hid_bpf_ctx *hid_ctx)
 	return 0;
 }
 
-SEC("?fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx)
+SEC(".struct_ops.link")
+struct hid_bpf_ops test_insert2 = {
+	.hid_device_event = (void *)hid_test_insert2,
+};
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {
 	__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 4 /* size */);
 
@@ -250,3 +277,8 @@ int BPF_PROG(hid_test_insert3, struct hid_bpf_ctx *hid_ctx)
 
 	return 0;
 }
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops test_insert3 = {
+	.hid_device_event = (void *)hid_test_insert3,
+};
diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
index 9cd56821d0f1..e02e24e3eab3 100644
--- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
+++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
@@ -20,9 +20,6 @@
 #define HID_REQ_SET_REPORT       HID_REQ_SET_REPORT___not_used
 #define HID_REQ_SET_IDLE         HID_REQ_SET_IDLE___not_used
 #define HID_REQ_SET_PROTOCOL     HID_REQ_SET_PROTOCOL___not_used
-#define HID_BPF_FLAG_NONE        HID_BPF_FLAG_NONE___not_used
-#define HID_BPF_FLAG_INSERT_HEAD HID_BPF_FLAG_INSERT_HEAD___not_used
-#define HID_BPF_FLAG_MAX         HID_BPF_FLAG_MAX___not_used
 
 #include "vmlinux.h"
 
@@ -40,9 +37,6 @@
 #undef HID_REQ_SET_REPORT
 #undef HID_REQ_SET_IDLE
 #undef HID_REQ_SET_PROTOCOL
-#undef HID_BPF_FLAG_NONE
-#undef HID_BPF_FLAG_INSERT_HEAD
-#undef HID_BPF_FLAG_MAX
 
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_tracing.h>
@@ -57,10 +51,8 @@ enum hid_report_type {
 };
 
 struct hid_bpf_ctx {
-	__u32 index;
-	const struct hid_device *hid;
+	struct hid_device *hid;
 	__u32 allocated_size;
-	enum hid_report_type report_type;
 	union {
 		__s32 retval;
 		__s32 size;
@@ -76,17 +68,14 @@ enum hid_class_request {
 	HID_REQ_SET_PROTOCOL		= 0x0B,
 };
 
-enum hid_bpf_attach_flags {
-	HID_BPF_FLAG_NONE = 0,
-	HID_BPF_FLAG_INSERT_HEAD = _BITUL(0),
-	HID_BPF_FLAG_MAX,
-};
+#ifndef BPF_F_BEFORE
+#define BPF_F_BEFORE (1U << 3)
+#endif
 
 /* following are kfuncs exported by HID for HID-BPF */
 extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,
 			      unsigned int offset,
 			      const size_t __sz) __ksym;
-extern int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, u32 flags) __ksym;
 extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __ksym;
 extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __ksym;
 extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx,

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 05/16] HID: samples: convert the 2 HID-BPF samples into struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

This is mostly mechanical: attach_prog is dropped, and
the SEC are converted into struct_ops.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2 but the commit message.
---
 samples/hid/Makefile               |  5 ++--
 samples/hid/hid_bpf_attach.bpf.c   | 18 -------------
 samples/hid/hid_bpf_attach.h       | 14 ----------
 samples/hid/hid_mouse.bpf.c        | 26 +++++++++++++++----
 samples/hid/hid_mouse.c            | 39 ++++++++--------------------
 samples/hid/hid_surface_dial.bpf.c | 10 +++++--
 samples/hid/hid_surface_dial.c     | 53 +++++++++++---------------------------
 7 files changed, 57 insertions(+), 108 deletions(-)

diff --git a/samples/hid/Makefile b/samples/hid/Makefile
index c128ccd49974..8ea59e9631a3 100644
--- a/samples/hid/Makefile
+++ b/samples/hid/Makefile
@@ -16,7 +16,6 @@ LIBBPF_DESTDIR = $(LIBBPF_OUTPUT)
 LIBBPF_INCLUDE = $(LIBBPF_DESTDIR)/include
 LIBBPF = $(LIBBPF_OUTPUT)/libbpf.a
 
-EXTRA_HEADERS := hid_bpf_attach.h
 EXTRA_BPF_HEADERS := hid_bpf_helpers.h
 
 hid_mouse-objs := hid_mouse.o
@@ -207,8 +206,8 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(EXTRA_BPF_HEADERS_SRC) $(obj)/vmlinux.h
 LINKED_SKELS := hid_mouse.skel.h hid_surface_dial.skel.h
 clean-files += $(LINKED_SKELS)
 
-hid_mouse.skel.h-deps := hid_mouse.bpf.o hid_bpf_attach.bpf.o
-hid_surface_dial.skel.h-deps := hid_surface_dial.bpf.o hid_bpf_attach.bpf.o
+hid_mouse.skel.h-deps := hid_mouse.bpf.o
+hid_surface_dial.skel.h-deps := hid_surface_dial.bpf.o
 
 LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps)))
 
diff --git a/samples/hid/hid_bpf_attach.bpf.c b/samples/hid/hid_bpf_attach.bpf.c
deleted file mode 100644
index d4dce4ea7c6e..000000000000
--- a/samples/hid/hid_bpf_attach.bpf.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2022 Benjamin Tissoires
- */
-
-#include "vmlinux.h"
-#include <bpf/bpf_helpers.h>
-#include <bpf/bpf_tracing.h>
-#include "hid_bpf_attach.h"
-#include "hid_bpf_helpers.h"
-
-SEC("syscall")
-int attach_prog(struct attach_prog_args *ctx)
-{
-	ctx->retval = hid_bpf_attach_prog(ctx->hid,
-					  ctx->prog_fd,
-					  0);
-	return 0;
-}
diff --git a/samples/hid/hid_bpf_attach.h b/samples/hid/hid_bpf_attach.h
deleted file mode 100644
index 35bb28b49264..000000000000
--- a/samples/hid/hid_bpf_attach.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2022 Benjamin Tissoires
- */
-
-#ifndef __HID_BPF_ATTACH_H
-#define __HID_BPF_ATTACH_H
-
-struct attach_prog_args {
-	int prog_fd;
-	unsigned int hid;
-	int retval;
-};
-
-#endif /* __HID_BPF_ATTACH_H */
diff --git a/samples/hid/hid_mouse.bpf.c b/samples/hid/hid_mouse.bpf.c
index 7c8b453ccb16..bd901fa855c9 100644
--- a/samples/hid/hid_mouse.bpf.c
+++ b/samples/hid/hid_mouse.bpf.c
@@ -5,8 +5,7 @@
 #include <bpf/bpf_tracing.h>
 #include "hid_bpf_helpers.h"
 
-SEC("fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx)
+static int hid_y_event(struct hid_bpf_ctx *hctx)
 {
 	s16 y;
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
@@ -51,8 +50,7 @@ int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
-SEC("fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx)
+static int hid_x_event(struct hid_bpf_ctx *hctx)
 {
 	s16 x;
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
@@ -69,7 +67,19 @@ int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC("struct_ops/device_event")
+int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type)
+{
+	int ret = hid_y_event(hctx);
+
+	if (ret)
+		return ret;
+
+	return hid_x_event(hctx);
+}
+
+
+SEC("struct_ops/rdesc_fixup")
 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -109,4 +119,10 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+SEC(".struct_ops.link")
+struct hid_bpf_ops mouse_invert = {
+	.rdesc_fixup = (void *)hid_rdesc_fixup,
+	.device_event = (void *)hid_event,
+};
+
 char _license[] SEC("license") = "GPL";
diff --git a/samples/hid/hid_mouse.c b/samples/hid/hid_mouse.c
index 018f1185f203..4b80d4e4c154 100644
--- a/samples/hid/hid_mouse.c
+++ b/samples/hid/hid_mouse.c
@@ -29,7 +29,6 @@
 #include <bpf/libbpf.h>
 
 #include "hid_mouse.skel.h"
-#include "hid_bpf_attach.h"
 
 static bool running = true;
 
@@ -76,18 +75,11 @@ static int get_hid_id(const char *path)
 int main(int argc, char **argv)
 {
 	struct hid_mouse *skel;
-	struct bpf_program *prog;
+	struct bpf_link *link;
 	int err;
 	const char *optstr = "";
 	const char *sysfs_path;
-	int opt, hid_id, attach_fd;
-	struct attach_prog_args args = {
-		.retval = -1,
-	};
-	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
-			    .ctx_in = &args,
-			    .ctx_size_in = sizeof(args),
-	);
+	int opt, hid_id;
 
 	while ((opt = getopt(argc, argv, optstr)) != -1) {
 		switch (opt) {
@@ -108,7 +100,7 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	skel = hid_mouse__open_and_load();
+	skel = hid_mouse__open();
 	if (!skel) {
 		fprintf(stderr, "%s  %s:%d", __func__, __FILE__, __LINE__);
 		return -1;
@@ -120,27 +112,18 @@ int main(int argc, char **argv)
 		fprintf(stderr, "can not open HID device: %m\n");
 		return 1;
 	}
-	args.hid = hid_id;
+	skel->struct_ops.mouse_invert->hid_id = hid_id;
 
-	attach_fd = bpf_program__fd(skel->progs.attach_prog);
-	if (attach_fd < 0) {
-		fprintf(stderr, "can't locate attach prog: %m\n");
+	err = hid_mouse__load(skel);
+	if (err < 0) {
+		fprintf(stderr, "can not load HID-BPF program: %m\n");
 		return 1;
 	}
 
-	bpf_object__for_each_program(prog, *skel->skeleton->obj) {
-		/* ignore syscalls */
-		if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING)
-			continue;
-
-		args.retval = -1;
-		args.prog_fd = bpf_program__fd(prog);
-		err = bpf_prog_test_run_opts(attach_fd, &tattr);
-		if (err) {
-			fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n",
-				hid_id, err);
-			return 1;
-		}
+	link = bpf_map__attach_struct_ops(skel->maps.mouse_invert);
+	if (!link) {
+		fprintf(stderr, "can not attach HID-BPF program: %m\n");
+		return 1;
 	}
 
 	signal(SIGINT, int_exit);
diff --git a/samples/hid/hid_surface_dial.bpf.c b/samples/hid/hid_surface_dial.bpf.c
index 1f80478c0918..d8d0fb07391f 100644
--- a/samples/hid/hid_surface_dial.bpf.c
+++ b/samples/hid/hid_surface_dial.bpf.c
@@ -10,7 +10,7 @@
 #define HID_UP_BUTTON		0x0009
 #define HID_GD_WHEEL		0x0038
 
-SEC("fmod_ret/hid_bpf_device_event")
+SEC("struct_ops/device_event")
 int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
@@ -101,7 +101,7 @@ int set_haptic(struct haptic_syscall_args *args)
 }
 
 /* Convert REL_DIAL into REL_WHEEL */
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC("struct_ops/rdesc_fixup")
 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -130,5 +130,11 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+SEC(".struct_ops.link")
+struct hid_bpf_ops surface_dial = {
+	.rdesc_fixup = (void *)hid_rdesc_fixup,
+	.device_event = (void *)hid_event,
+};
+
 char _license[] SEC("license") = "GPL";
 u32 _version SEC("version") = 1;
diff --git a/samples/hid/hid_surface_dial.c b/samples/hid/hid_surface_dial.c
index 4bc97373a708..9dd363845a85 100644
--- a/samples/hid/hid_surface_dial.c
+++ b/samples/hid/hid_surface_dial.c
@@ -31,7 +31,6 @@
 #include <bpf/libbpf.h>
 
 #include "hid_surface_dial.skel.h"
-#include "hid_bpf_attach.h"
 
 static bool running = true;
 
@@ -86,34 +85,6 @@ static int get_hid_id(const char *path)
 	return (int)strtol(str_id, NULL, 16);
 }
 
-static int attach_prog(struct hid_surface_dial *skel, struct bpf_program *prog, int hid_id)
-{
-	struct attach_prog_args args = {
-		.hid = hid_id,
-		.retval = -1,
-	};
-	int attach_fd, err;
-	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
-			    .ctx_in = &args,
-			    .ctx_size_in = sizeof(args),
-	);
-
-	attach_fd = bpf_program__fd(skel->progs.attach_prog);
-	if (attach_fd < 0) {
-		fprintf(stderr, "can't locate attach prog: %m\n");
-		return 1;
-	}
-
-	args.prog_fd = bpf_program__fd(prog);
-	err = bpf_prog_test_run_opts(attach_fd, &tattr);
-	if (err) {
-		fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n",
-			hid_id, err);
-		return 1;
-	}
-	return 0;
-}
-
 static int set_haptic(struct hid_surface_dial *skel, int hid_id)
 {
 	struct haptic_syscall_args args = {
@@ -144,10 +115,10 @@ static int set_haptic(struct hid_surface_dial *skel, int hid_id)
 int main(int argc, char **argv)
 {
 	struct hid_surface_dial *skel;
-	struct bpf_program *prog;
 	const char *optstr = "r:";
+	struct bpf_link *link;
 	const char *sysfs_path;
-	int opt, hid_id, resolution = 72;
+	int err, opt, hid_id, resolution = 72;
 
 	while ((opt = getopt(argc, argv, optstr)) != -1) {
 		switch (opt) {
@@ -189,7 +160,7 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
-	skel = hid_surface_dial__open_and_load();
+	skel = hid_surface_dial__open();
 	if (!skel) {
 		fprintf(stderr, "%s  %s:%d", __func__, __FILE__, __LINE__);
 		return -1;
@@ -201,15 +172,21 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
+	skel->struct_ops.surface_dial->hid_id = hid_id;
+
+	err = hid_surface_dial__load(skel);
+	if (err < 0) {
+		fprintf(stderr, "can not load HID-BPF program: %m\n");
+		return 1;
+	}
+
 	skel->data->resolution = resolution;
 	skel->data->physical = (int)(resolution / 72);
 
-	bpf_object__for_each_program(prog, *skel->skeleton->obj) {
-		/* ignore syscalls */
-		if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING)
-			continue;
-
-		attach_prog(skel, prog, hid_id);
+	link = bpf_map__attach_struct_ops(skel->maps.surface_dial);
+	if (!link) {
+		fprintf(stderr, "can not attach HID-BPF program: %m\n");
+		return 1;
 	}
 
 	signal(SIGINT, int_exit);

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 06/16] HID: bpf: add defines for HID-BPF SEC in in-tree bpf fixes
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

We are going to switch over struct_ops, so instead of having to manually
replace all fields one by one, let's have a common place to change it.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c     | 4 ++--
 drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c       | 2 +-
 drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c      | 4 ++--
 drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c | 2 +-
 drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c   | 2 +-
 drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c             | 2 +-
 drivers/hid/bpf/progs/XPPen__Artist24.bpf.c           | 4 ++--
 drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c    | 6 +++---
 drivers/hid/bpf/progs/hid_bpf.h                       | 3 +++
 9 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
index dc26a7677d36..2c2c1637ade8 100644
--- a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
+++ b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
@@ -133,7 +133,7 @@ HID_BPF_CONFIG(
  *   integer. We thus divide it by 30 to match what other joysticks are
  *   doing
  */
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
@@ -152,7 +152,7 @@ int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)
  * divide it by 30.
  * Byte 34 is always null, so it is ignored.
  */
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
 int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 64 /* size */);
diff --git a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
index 3d14bbb6f276..17fc55f6f02c 100644
--- a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
+++ b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
@@ -30,7 +30,7 @@ HID_BPF_CONFIG(
  * pointer.
  */
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
diff --git a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
index ff759f2276f9..24b8a5aa05f3 100644
--- a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
+++ b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
@@ -191,7 +191,7 @@ static const __u8 fixed_rdesc[] = {
 	0xc0,                          // End Collection                      327
 };
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
@@ -215,7 +215,7 @@ int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
  * - if there was this out-of-proximity event, we are entering
  *   eraser mode, and we will until the next out-of-proximity.
  */
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
 int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
diff --git a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
index 225cbefdbf0e..bee37872ee8c 100644
--- a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
+++ b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
@@ -21,7 +21,7 @@ HID_BPF_CONFIG(
  * We just fix the report descriptor to enable those missing 7 buttons.
  */
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
 {
 	const u8 offsets[] = {84, 112, 140};
diff --git a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c b/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
index c04abecab8ee..f9ad33f4a373 100644
--- a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
+++ b/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
@@ -93,7 +93,7 @@ _Static_assert(sizeof(rdesc_assign_selection) == sizeof(fixed_rdesc_assign_selec
 _Static_assert(sizeof(rdesc_assign_selection) + OFFSET_ASSIGN_SELECTION < ORIGINAL_RDESC_SIZE,
 	       "Rdesc at given offset is too big");
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
diff --git a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
index dc05aa48faa7..39d77c5e9172 100644
--- a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
+++ b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
@@ -101,7 +101,7 @@ static inline __u8 *get_u8(__u8 *data, unsigned int offset)
 	return (__u8 *)get_bits(data, offset);
 }
 
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
 int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, PEN_REPORT_LEN /* size */);
diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index e1be6a12bb75..c938808bd589 100644
--- a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
@@ -91,7 +91,7 @@ static const __u8 fixed_rdesc[] = {
 
 #define U16(index) (data[index] | (data[index + 1] << 8))
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc_xppen_artist24, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -152,7 +152,7 @@ static __u8 prev_state = 0;
  *     E: TipSwitch                     InRange
  *
  */
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
 int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
diff --git a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
index 65ef10036126..77ef8b95d52e 100644
--- a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
@@ -82,7 +82,7 @@ static const __u8 fixed_rdesc[] = {
 	0xc0,                          // End Collection                      112
 };
 
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
 int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -105,7 +105,7 @@ int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
 	return sizeof(fixed_rdesc);
 }
 
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
 int BPF_PROG(xppen_16_fix_eraser, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
@@ -207,7 +207,7 @@ static void compensate_coordinates_by_tilt(__u8 *data, const __u8 idx,
 	data[idx+1] = coords >> 8;
 }
 
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
 int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
diff --git a/drivers/hid/bpf/progs/hid_bpf.h b/drivers/hid/bpf/progs/hid_bpf.h
index 7ee371cac2e1..1970faf84310 100644
--- a/drivers/hid/bpf/progs/hid_bpf.h
+++ b/drivers/hid/bpf/progs/hid_bpf.h
@@ -5,6 +5,9 @@
 #ifndef ____HID_BPF__H
 #define ____HID_BPF__H
 
+#define HID_BPF_DEVICE_EVENT "fmod_ret/hid_bpf_device_event"
+#define HID_BPF_RDESC_FIXUP  "fmod_ret/hid_bpf_rdesc_fixup"
+
 struct hid_bpf_probe_args {
 	unsigned int hid;
 	unsigned int rdesc_size;

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 07/16] HID: bpf: convert in-tree fixes into struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

Very mechanical:
- Change HID_BPF_DEVICE_EVENT and HID_BPF_RDESC_FIXUP #defines
- add a matching SEC(".struct_ops.link")
- in ArtistPro16Gen2 make the 2 functions static and have a new one
  calling them

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c  |  5 +++++
 drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c    |  4 ++++
 drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c   |  5 +++++
 .../hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c  |  4 ++++
 .../hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c    |  4 ++++
 drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c          |  4 ++++
 drivers/hid/bpf/progs/XPPen__Artist24.bpf.c        |  5 +++++
 drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c | 22 ++++++++++++++++++----
 drivers/hid/bpf/progs/hid_bpf.h                    |  6 ++++--
 9 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
index 2c2c1637ade8..caec91391d32 100644
--- a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
+++ b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
@@ -168,6 +168,11 @@ int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(raptor_mach_2) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc_raptor_mach_2,
+	.hid_device_event = (void *)raptor_mach_2_fix_hat_switch,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
index 17fc55f6f02c..c2413fa80543 100644
--- a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
+++ b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
@@ -45,6 +45,10 @@ int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(hp_elite_presenter) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
index 24b8a5aa05f3..a4a4f324aedd 100644
--- a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
+++ b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
@@ -255,6 +255,11 @@ int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(huion_Kamvas_pro_19) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc_huion_kamvas_pro_19,
+	.hid_device_event = (void *)kamvas_pro_19_fix_3rd_button,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
index bee37872ee8c..82f1950445dd 100644
--- a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
+++ b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
@@ -45,6 +45,10 @@ int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(iogear_kaliber_momentum) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c b/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
index f9ad33f4a373..70b16edfb59a 100644
--- a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
+++ b/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
@@ -114,6 +114,10 @@ int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(xbox_elite_2) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
index 39d77c5e9172..2da680bc4e11 100644
--- a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
+++ b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
@@ -139,6 +139,10 @@ int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(wacom_artpen) = {
+	.hid_device_event = (void *)artpen_pressure_interpolate,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index c938808bd589..bc0b85c38445 100644
--- a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
@@ -209,6 +209,11 @@ int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+HID_BPF_OPS(xppen_artist_24) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc_xppen_artist24,
+	.hid_device_event = (void *)xppen_24_fix_eraser,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
index 77ef8b95d52e..a669525691aa 100644
--- a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
@@ -105,8 +105,7 @@ int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
 	return sizeof(fixed_rdesc);
 }
 
-SEC(HID_BPF_DEVICE_EVENT)
-int BPF_PROG(xppen_16_fix_eraser, struct hid_bpf_ctx *hctx)
+static int xppen_16_fix_eraser(struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
 
@@ -207,8 +206,7 @@ static void compensate_coordinates_by_tilt(__u8 *data, const __u8 idx,
 	data[idx+1] = coords >> 8;
 }
 
-SEC(HID_BPF_DEVICE_EVENT)
-int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx)
+static int xppen_16_fix_angle_offset(struct hid_bpf_ctx *hctx)
 {
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
 
@@ -254,6 +252,22 @@ int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx)
 	return 0;
 }
 
+SEC(HID_BPF_DEVICE_EVENT)
+int BPF_PROG(xppen_artist_pro_16_device_event, struct hid_bpf_ctx *hctx)
+{
+	int ret = xppen_16_fix_angle_offset(hctx);
+
+	if (ret)
+		return ret;
+
+	return xppen_16_fix_eraser(hctx);
+}
+
+HID_BPF_OPS(xppen_artist_pro_16) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc_xppen_artistpro16gen2,
+	.hid_device_event = (void *)xppen_artist_pro_16_device_event,
+};
+
 SEC("syscall")
 int probe(struct hid_bpf_probe_args *ctx)
 {
diff --git a/drivers/hid/bpf/progs/hid_bpf.h b/drivers/hid/bpf/progs/hid_bpf.h
index 1970faf84310..8c1cd9e25bc3 100644
--- a/drivers/hid/bpf/progs/hid_bpf.h
+++ b/drivers/hid/bpf/progs/hid_bpf.h
@@ -5,8 +5,10 @@
 #ifndef ____HID_BPF__H
 #define ____HID_BPF__H
 
-#define HID_BPF_DEVICE_EVENT "fmod_ret/hid_bpf_device_event"
-#define HID_BPF_RDESC_FIXUP  "fmod_ret/hid_bpf_rdesc_fixup"
+#define HID_BPF_DEVICE_EVENT "struct_ops/hid_device_event"
+#define HID_BPF_RDESC_FIXUP  "struct_ops/hid_rdesc_fixup"
+#define HID_BPF_OPS(name) SEC(".struct_ops.link") \
+	struct hid_bpf_ops name
 
 struct hid_bpf_probe_args {
 	unsigned int hid;

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 08/16] HID: bpf: remove tracing HID-BPF capability
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

We can now rely on struct_ops as we cleared the users in-tree.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

changes in v2:
- remove now unused enum hid_bpf_attach_flags
---
 drivers/hid/bpf/Makefile                        |   2 +-
 drivers/hid/bpf/entrypoints/Makefile            |  93 ----
 drivers/hid/bpf/entrypoints/README              |   4 -
 drivers/hid/bpf/entrypoints/entrypoints.bpf.c   |  25 --
 drivers/hid/bpf/entrypoints/entrypoints.lskel.h | 248 -----------
 drivers/hid/bpf/hid_bpf_dispatch.c              | 193 +-------
 drivers/hid/bpf/hid_bpf_dispatch.h              |   8 -
 drivers/hid/bpf/hid_bpf_jmp_table.c             | 568 ------------------------
 include/linux/hid_bpf.h                         |  54 +--
 9 files changed, 8 insertions(+), 1187 deletions(-)

diff --git a/drivers/hid/bpf/Makefile b/drivers/hid/bpf/Makefile
index 1cb3f31e9335..d1f2b81788ca 100644
--- a/drivers/hid/bpf/Makefile
+++ b/drivers/hid/bpf/Makefile
@@ -8,4 +8,4 @@ LIBBPF_INCLUDE = $(srctree)/tools/lib
 obj-$(CONFIG_HID_BPF) += hid_bpf.o
 CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE)
 CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE)
-hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o hid_bpf_struct_ops.o
+hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_struct_ops.o
diff --git a/drivers/hid/bpf/entrypoints/Makefile b/drivers/hid/bpf/entrypoints/Makefile
deleted file mode 100644
index 43b99b5575cf..000000000000
--- a/drivers/hid/bpf/entrypoints/Makefile
+++ /dev/null
@@ -1,93 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-OUTPUT := .output
-abs_out := $(abspath $(OUTPUT))
-
-CLANG ?= clang
-LLC ?= llc
-LLVM_STRIP ?= llvm-strip
-
-TOOLS_PATH := $(abspath ../../../../tools)
-BPFTOOL_SRC := $(TOOLS_PATH)/bpf/bpftool
-BPFTOOL_OUTPUT := $(abs_out)/bpftool
-DEFAULT_BPFTOOL := $(BPFTOOL_OUTPUT)/bootstrap/bpftool
-BPFTOOL ?= $(DEFAULT_BPFTOOL)
-
-LIBBPF_SRC := $(TOOLS_PATH)/lib/bpf
-LIBBPF_OUTPUT := $(abs_out)/libbpf
-LIBBPF_DESTDIR := $(LIBBPF_OUTPUT)
-LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)/include
-BPFOBJ := $(LIBBPF_OUTPUT)/libbpf.a
-
-INCLUDES := -I$(OUTPUT) -I$(LIBBPF_INCLUDE) -I$(TOOLS_PATH)/include/uapi
-CFLAGS := -g -Wall
-
-VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux)				\
-		     $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux)	\
-		     ../../../../vmlinux				\
-		     /sys/kernel/btf/vmlinux				\
-		     /boot/vmlinux-$(shell uname -r)
-VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
-ifeq ($(VMLINUX_BTF),)
-$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)")
-endif
-
-ifeq ($(V),1)
-Q =
-msg =
-else
-Q = @
-msg = @printf '  %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))";
-MAKEFLAGS += --no-print-directory
-submake_extras := feature_display=0
-endif
-
-.DELETE_ON_ERROR:
-
-.PHONY: all clean
-
-all: entrypoints.lskel.h
-
-clean:
-	$(call msg,CLEAN)
-	$(Q)rm -rf $(OUTPUT) entrypoints
-
-entrypoints.lskel.h: $(OUTPUT)/entrypoints.bpf.o | $(BPFTOOL)
-	$(call msg,GEN-SKEL,$@)
-	$(Q)$(BPFTOOL) gen skeleton -L $< > $@
-
-
-$(OUTPUT)/entrypoints.bpf.o: entrypoints.bpf.c $(OUTPUT)/vmlinux.h $(BPFOBJ) | $(OUTPUT)
-	$(call msg,BPF,$@)
-	$(Q)$(CLANG) -g -O2 --target=bpf $(INCLUDES)			      \
-		 -c $(filter %.c,$^) -o $@ &&				      \
-	$(LLVM_STRIP) -g $@
-
-$(OUTPUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR)
-ifeq ($(VMLINUX_H),)
-	$(call msg,GEN,,$@)
-	$(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
-else
-	$(call msg,CP,,$@)
-	$(Q)cp "$(VMLINUX_H)" $@
-endif
-
-$(OUTPUT) $(LIBBPF_OUTPUT) $(BPFTOOL_OUTPUT):
-	$(call msg,MKDIR,$@)
-	$(Q)mkdir -p $@
-
-$(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT)
-	$(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC)			       \
-		    OUTPUT=$(abspath $(dir $@))/ prefix=		       \
-		    DESTDIR=$(LIBBPF_DESTDIR) $(abspath $@) install_headers
-
-ifeq ($(CROSS_COMPILE),)
-$(DEFAULT_BPFTOOL): $(BPFOBJ) | $(BPFTOOL_OUTPUT)
-	$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC)			       \
-		    OUTPUT=$(BPFTOOL_OUTPUT)/				       \
-		    LIBBPF_BOOTSTRAP_OUTPUT=$(LIBBPF_OUTPUT)/		       \
-		    LIBBPF_BOOTSTRAP_DESTDIR=$(LIBBPF_DESTDIR)/ bootstrap
-else
-$(DEFAULT_BPFTOOL): | $(BPFTOOL_OUTPUT)
-	$(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_SRC)			       \
-		    OUTPUT=$(BPFTOOL_OUTPUT)/ bootstrap
-endif
diff --git a/drivers/hid/bpf/entrypoints/README b/drivers/hid/bpf/entrypoints/README
deleted file mode 100644
index 147e0d41509f..000000000000
--- a/drivers/hid/bpf/entrypoints/README
+++ /dev/null
@@ -1,4 +0,0 @@
-WARNING:
-If you change "entrypoints.bpf.c" do "make -j" in this directory to rebuild "entrypoints.skel.h".
-Make sure to have clang 10 installed.
-See Documentation/bpf/bpf_devel_QA.rst
diff --git a/drivers/hid/bpf/entrypoints/entrypoints.bpf.c b/drivers/hid/bpf/entrypoints/entrypoints.bpf.c
deleted file mode 100644
index c22921125a1a..000000000000
--- a/drivers/hid/bpf/entrypoints/entrypoints.bpf.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2022 Benjamin Tissoires */
-
-#include ".output/vmlinux.h"
-#include <bpf/bpf_helpers.h>
-#include <bpf/bpf_tracing.h>
-
-#define HID_BPF_MAX_PROGS 1024
-
-struct {
-	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
-	__uint(max_entries, HID_BPF_MAX_PROGS);
-	__uint(key_size, sizeof(__u32));
-	__uint(value_size, sizeof(__u32));
-} hid_jmp_table SEC(".maps");
-
-SEC("fmod_ret/__hid_bpf_tail_call")
-int BPF_PROG(hid_tail_call, struct hid_bpf_ctx *hctx)
-{
-	bpf_tail_call(ctx, &hid_jmp_table, hctx->index);
-
-	return 0;
-}
-
-char LICENSE[] SEC("license") = "GPL";
diff --git a/drivers/hid/bpf/entrypoints/entrypoints.lskel.h b/drivers/hid/bpf/entrypoints/entrypoints.lskel.h
deleted file mode 100644
index 35618051598c..000000000000
--- a/drivers/hid/bpf/entrypoints/entrypoints.lskel.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
-/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */
-#ifndef __ENTRYPOINTS_BPF_SKEL_H__
-#define __ENTRYPOINTS_BPF_SKEL_H__
-
-#include <bpf/skel_internal.h>
-
-struct entrypoints_bpf {
-	struct bpf_loader_ctx ctx;
-	struct {
-		struct bpf_map_desc hid_jmp_table;
-	} maps;
-	struct {
-		struct bpf_prog_desc hid_tail_call;
-	} progs;
-	struct {
-		int hid_tail_call_fd;
-	} links;
-};
-
-static inline int
-entrypoints_bpf__hid_tail_call__attach(struct entrypoints_bpf *skel)
-{
-	int prog_fd = skel->progs.hid_tail_call.prog_fd;
-	int fd = skel_raw_tracepoint_open(NULL, prog_fd);
-
-	if (fd > 0)
-		skel->links.hid_tail_call_fd = fd;
-	return fd;
-}
-
-static inline int
-entrypoints_bpf__attach(struct entrypoints_bpf *skel)
-{
-	int ret = 0;
-
-	ret = ret < 0 ? ret : entrypoints_bpf__hid_tail_call__attach(skel);
-	return ret < 0 ? ret : 0;
-}
-
-static inline void
-entrypoints_bpf__detach(struct entrypoints_bpf *skel)
-{
-	skel_closenz(skel->links.hid_tail_call_fd);
-}
-static void
-entrypoints_bpf__destroy(struct entrypoints_bpf *skel)
-{
-	if (!skel)
-		return;
-	entrypoints_bpf__detach(skel);
-	skel_closenz(skel->progs.hid_tail_call.prog_fd);
-	skel_closenz(skel->maps.hid_jmp_table.map_fd);
-	skel_free(skel);
-}
-static inline struct entrypoints_bpf *
-entrypoints_bpf__open(void)
-{
-	struct entrypoints_bpf *skel;
-
-	skel = skel_alloc(sizeof(*skel));
-	if (!skel)
-		goto cleanup;
-	skel->ctx.sz = (void *)&skel->links - (void *)skel;
-	return skel;
-cleanup:
-	entrypoints_bpf__destroy(skel);
-	return NULL;
-}
-
-static inline int
-entrypoints_bpf__load(struct entrypoints_bpf *skel)
-{
-	struct bpf_load_and_run_opts opts = {};
-	int err;
-
-	opts.ctx = (struct bpf_loader_ctx *)skel;
-	opts.data_sz = 2856;
-	opts.data = (void *)"\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x01\0\
-\x18\0\0\0\0\0\0\0\x60\x02\0\0\x60\x02\0\0\x12\x02\0\0\0\0\0\0\0\0\0\x02\x03\0\
-\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\
-\0\0\x04\0\0\0\x03\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\
-\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\0\x04\0\0\0\0\0\0\
-\0\0\0\x02\x08\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\
-\0\0\0\x04\0\0\x04\x20\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\
-\x40\0\0\0\x2a\0\0\0\x07\0\0\0\x80\0\0\0\x33\0\0\0\x07\0\0\0\xc0\0\0\0\x3e\0\0\
-\0\0\0\0\x0e\x09\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x0c\0\0\0\x4c\0\0\0\0\0\0\
-\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x5f\0\0\0\x0b\0\0\0\x63\
-\0\0\0\x01\0\0\x0c\x0d\0\0\0\x09\x01\0\0\x05\0\0\x04\x20\0\0\0\x15\x01\0\0\x10\
-\0\0\0\0\0\0\0\x1b\x01\0\0\x12\0\0\0\x40\0\0\0\x1f\x01\0\0\x10\0\0\0\x80\0\0\0\
-\x2e\x01\0\0\x14\0\0\0\xa0\0\0\0\0\0\0\0\x15\0\0\0\xc0\0\0\0\x3a\x01\0\0\0\0\0\
-\x08\x11\0\0\0\x40\x01\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\x02\x13\
-\0\0\0\0\0\0\0\0\0\0\x0a\x1c\0\0\0\x4d\x01\0\0\x04\0\0\x06\x04\0\0\0\x5d\x01\0\
-\0\0\0\0\0\x6e\x01\0\0\x01\0\0\0\x80\x01\0\0\x02\0\0\0\x93\x01\0\0\x03\0\0\0\0\
-\0\0\0\x02\0\0\x05\x04\0\0\0\xa4\x01\0\0\x16\0\0\0\0\0\0\0\xab\x01\0\0\x16\0\0\
-\0\0\0\0\0\xb0\x01\0\0\0\0\0\x08\x02\0\0\0\xec\x01\0\0\0\0\0\x01\x01\0\0\0\x08\
-\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x17\0\0\0\x04\0\0\0\x04\0\0\0\xf1\x01\0\0\0\
-\0\0\x0e\x18\0\0\0\x01\0\0\0\xf9\x01\0\0\x01\0\0\x0f\x20\0\0\0\x0a\0\0\0\0\0\0\
-\0\x20\0\0\0\xff\x01\0\0\x01\0\0\x0f\x04\0\0\0\x19\0\0\0\0\0\0\0\x04\0\0\0\x07\
-\x02\0\0\0\0\0\x07\0\0\0\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\
-\x49\x5a\x45\x5f\x54\x59\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\x6d\x61\x78\x5f\
-\x65\x6e\x74\x72\x69\x65\x73\0\x6b\x65\x79\x5f\x73\x69\x7a\x65\0\x76\x61\x6c\
-\x75\x65\x5f\x73\x69\x7a\x65\0\x68\x69\x64\x5f\x6a\x6d\x70\x5f\x74\x61\x62\x6c\
-\x65\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e\x67\
-\0\x63\x74\x78\0\x68\x69\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\x66\x6d\
-\x6f\x64\x5f\x72\x65\x74\x2f\x5f\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\
-\x69\x6c\x5f\x63\x61\x6c\x6c\0\x2f\x68\x6f\x6d\x65\x2f\x62\x74\x69\x73\x73\x6f\
-\x69\x72\x2f\x53\x72\x63\x2f\x68\x69\x64\x2f\x64\x72\x69\x76\x65\x72\x73\x2f\
-\x68\x69\x64\x2f\x62\x70\x66\x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\
-\x2f\x65\x6e\x74\x72\x79\x70\x6f\x69\x6e\x74\x73\x2e\x62\x70\x66\x2e\x63\0\x69\
-\x6e\x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x68\x69\x64\x5f\x74\x61\x69\
-\x6c\x5f\x63\x61\x6c\x6c\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x68\x69\x64\x5f\
-\x62\x70\x66\x5f\x63\x74\x78\x20\x2a\x68\x63\x74\x78\x29\0\x68\x69\x64\x5f\x62\
-\x70\x66\x5f\x63\x74\x78\0\x69\x6e\x64\x65\x78\0\x68\x69\x64\0\x61\x6c\x6c\x6f\
-\x63\x61\x74\x65\x64\x5f\x73\x69\x7a\x65\0\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\
-\x70\x65\0\x5f\x5f\x75\x33\x32\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x69\x6e\
-\x74\0\x68\x69\x64\x5f\x72\x65\x70\x6f\x72\x74\x5f\x74\x79\x70\x65\0\x48\x49\
-\x44\x5f\x49\x4e\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x4f\
-\x55\x54\x50\x55\x54\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x46\x45\x41\
-\x54\x55\x52\x45\x5f\x52\x45\x50\x4f\x52\x54\0\x48\x49\x44\x5f\x52\x45\x50\x4f\
-\x52\x54\x5f\x54\x59\x50\x45\x53\0\x72\x65\x74\x76\x61\x6c\0\x73\x69\x7a\x65\0\
-\x5f\x5f\x73\x33\x32\0\x30\x3a\x30\0\x09\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\
-\x63\x61\x6c\x6c\x28\x63\x74\x78\x2c\x20\x26\x68\x69\x64\x5f\x6a\x6d\x70\x5f\
-\x74\x61\x62\x6c\x65\x2c\x20\x68\x63\x74\x78\x2d\x3e\x69\x6e\x64\x65\x78\x29\
-\x3b\0\x63\x68\x61\x72\0\x4c\x49\x43\x45\x4e\x53\x45\0\x2e\x6d\x61\x70\x73\0\
-\x6c\x69\x63\x65\x6e\x73\x65\0\x68\x69\x64\x5f\x64\x65\x76\x69\x63\x65\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x8a\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\
-\0\0\0\x04\0\0\0\x04\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\x64\x5f\
-\x6a\x6d\x70\x5f\x74\x61\x62\x6c\x65\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\x47\x50\x4c\0\0\0\0\0\x79\x12\0\0\0\0\0\0\x61\x23\0\0\0\0\
-\0\0\x18\x52\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x85\0\0\0\x0c\0\0\0\xb7\0\0\0\0\0\0\0\
-\x95\0\0\0\0\0\0\0\0\0\0\0\x0e\0\0\0\0\0\0\0\x8e\0\0\0\xd3\0\0\0\x05\x48\0\0\
-\x01\0\0\0\x8e\0\0\0\xba\x01\0\0\x02\x50\0\0\x05\0\0\0\x8e\0\0\0\xd3\0\0\0\x05\
-\x48\0\0\x08\0\0\0\x0f\0\0\0\xb6\x01\0\0\0\0\0\0\x1a\0\0\0\x07\0\0\0\0\0\0\0\0\
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x69\
-\x64\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\0\0\0\0\0\0\x1a\0\0\0\0\0\0\0\
-\x08\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\x01\0\
-\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x5f\
-\x5f\x68\x69\x64\x5f\x62\x70\x66\x5f\x74\x61\x69\x6c\x5f\x63\x61\x6c\x6c\0\0\0\
-\0\0";
-	opts.insns_sz = 1192;
-	opts.insns = (void *)"\
-\xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x02\0\
-\0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x11\0\0\0\0\0\x61\
-\xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c\xff\
-\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0\xd5\
-\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\
-\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\
-\xbf\x70\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\
-\0\0\0\0\0\xa8\x09\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\
-\0\0\0\0\0\0\0\xa4\x09\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\
-\0\0\0\0\0\0\0\0\0\x98\x09\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\
-\0\x05\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x09\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\
-\0\0\x12\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x90\x09\0\0\xb7\x03\0\0\x1c\0\0\0\
-\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xd7\xff\0\0\0\0\x63\x7a\x78\
-\xff\0\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\
-\0\0\xbc\x09\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\
-\0\0\0\xb0\x09\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\
-\0\xc5\x07\xca\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\0\0\0\0\
-\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf8\x09\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\
-\x0a\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x0a\0\0\x18\x61\0\0\
-\0\0\0\0\0\0\0\0\x88\x0a\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\
-\x38\x0a\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd0\x0a\0\0\x7b\x01\0\0\0\0\0\0\x18\
-\x60\0\0\0\0\0\0\0\0\0\0\x40\x0a\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xe0\x0a\0\0\
-\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x0a\0\0\x18\x61\0\0\0\0\0\
-\0\0\0\0\0\0\x0b\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
-\x18\x61\0\0\0\0\0\0\0\0\0\0\xf8\x0a\0\0\x7b\x01\0\0\0\0\0\0\x61\x60\x08\0\0\0\
-\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x98\x0a\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\
-\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x9c\x0a\0\0\x63\x01\0\0\0\0\0\0\x79\x60\
-\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xa0\x0a\0\0\x7b\x01\0\0\0\0\0\0\x61\
-\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc8\x0a\0\0\x63\x01\0\0\0\0\0\
-\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x0b\0\0\xb7\x02\0\0\x14\0\0\0\xb7\x03\0\0\
-\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\
-\x91\xff\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x80\x0a\0\0\x63\x70\x6c\0\0\0\0\0\
-\x77\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0\xb7\x01\0\0\x05\0\0\0\x18\x62\0\0\
-\0\0\0\0\0\0\0\0\x80\x0a\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\
-\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf0\x0a\0\0\x61\x01\0\0\0\0\0\0\xd5\
-\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xc5\x07\x7f\xff\0\0\
-\0\0\x63\x7a\x80\xff\0\0\0\0\x61\xa1\x78\xff\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\
-\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa0\x80\xff\0\0\0\0\x63\x06\x28\0\0\0\
-\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\0\
-\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0";
-	err = bpf_load_and_run(&opts);
-	if (err < 0)
-		return err;
-	return 0;
-}
-
-static inline struct entrypoints_bpf *
-entrypoints_bpf__open_and_load(void)
-{
-	struct entrypoints_bpf *skel;
-
-	skel = entrypoints_bpf__open();
-	if (!skel)
-		return NULL;
-	if (entrypoints_bpf__load(skel)) {
-		entrypoints_bpf__destroy(skel);
-		return NULL;
-	}
-	return skel;
-}
-
-__attribute__((unused)) static void
-entrypoints_bpf__assert(struct entrypoints_bpf *s __attribute__((unused)))
-{
-#ifdef __cplusplus
-#define _Static_assert static_assert
-#endif
-#ifdef __cplusplus
-#undef _Static_assert
-#endif
-}
-
-#endif /* __ENTRYPOINTS_BPF_SKEL_H__ */
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 7216c3c7713d..06cc628e7bb4 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -3,7 +3,7 @@
 /*
  *  HID-BPF support for Linux
  *
- *  Copyright (c) 2022 Benjamin Tissoires
+ *  Copyright (c) 2022-2024 Benjamin Tissoires
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -17,34 +17,11 @@
 #include <linux/kfifo.h>
 #include <linux/minmax.h>
 #include <linux/module.h>
-#include <linux/workqueue.h>
 #include "hid_bpf_dispatch.h"
-#include "entrypoints/entrypoints.lskel.h"
 
 struct hid_ops *hid_ops;
 EXPORT_SYMBOL(hid_ops);
 
-/**
- * hid_bpf_device_event - Called whenever an event is coming in from the device
- *
- * @ctx: The HID-BPF context
- *
- * @return %0 on success and keep processing; a positive value to change the
- * incoming size buffer; a negative error code to interrupt the processing
- * of this event
- *
- * Declare an %fmod_ret tracing bpf program to this function and attach this
- * program through hid_bpf_attach_prog() to have this helper called for
- * any incoming event from the device itself.
- *
- * The function is called while on IRQ context, so we can not sleep.
- */
-/* never used by the kernel but declared so we can load and attach a tracepoint */
-__weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx)
-{
-	return 0;
-}
-
 u8 *
 dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
 			      u32 *size, int interrupt)
@@ -52,7 +29,6 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
 	struct hid_bpf_ctx_kern ctx_kern = {
 		.ctx = {
 			.hid = hdev,
-			.report_type = type,
 			.allocated_size = hdev->bpf.allocated_data,
 			.size = *size,
 		},
@@ -86,11 +62,6 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
 	}
 	rcu_read_unlock();
 
-	ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern);
-	if (ret < 0)
-		return ERR_PTR(ret);
-	ret = ctx_kern.ctx.retval;
-
 	if (ret) {
 		if (ret > ctx_kern.ctx.allocated_size)
 			return ERR_PTR(-EINVAL);
@@ -102,26 +73,6 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
 }
 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
 
-/**
- * hid_bpf_rdesc_fixup - Called when the probe function parses the report
- * descriptor of the HID device
- *
- * @ctx: The HID-BPF context
- *
- * @return 0 on success and keep processing; a positive value to change the
- * incoming size buffer; a negative error code to interrupt the processing
- * of this event
- *
- * Declare an %fmod_ret tracing bpf program to this function and attach this
- * program through hid_bpf_attach_prog() to have this helper called before any
- * parsing of the report descriptor by HID.
- */
-/* never used by the kernel but declared so we can load and attach a tracepoint */
-__weak noinline int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx)
-{
-	return 0;
-}
-
 u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size)
 {
 	int ret;
@@ -133,16 +84,16 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s
 		},
 	};
 
+	if (!hdev->bpf.rdesc_ops)
+		goto ignore_bpf;
+
 	ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
 	if (!ctx_kern.data)
 		goto ignore_bpf;
 
 	memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
 
-	if (hdev->bpf.rdesc_ops)
-		ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
-	else
-		ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern);
+	ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
 	if (ret < 0)
 		goto ignore_bpf;
 
@@ -242,39 +193,6 @@ int hid_bpf_reconnect(struct hid_device *hdev)
 	return 0;
 }
 
-static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog,
-				  __u32 flags)
-{
-	int fd, err, prog_type;
-
-	prog_type = hid_bpf_get_prog_attach_type(prog);
-	if (prog_type < 0)
-		return prog_type;
-
-	if (prog_type >= HID_BPF_PROG_TYPE_MAX)
-		return -EINVAL;
-
-	if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
-		err = hid_bpf_allocate_event_data(hdev);
-		if (err)
-			return err;
-	}
-
-	fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags);
-	if (fd < 0)
-		return fd;
-
-	if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
-		err = hid_bpf_reconnect(hdev);
-		if (err) {
-			close_fd(fd);
-			return err;
-		}
-	}
-
-	return fd;
-}
-
 /* Disables missing prototype warnings */
 __bpf_kfunc_start_defs();
 
@@ -303,57 +221,6 @@ hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr
 	return ctx_kern->data + offset;
 }
 
-/**
- * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
- *
- * @hid_id: the system unique identifier of the HID device
- * @prog_fd: an fd in the user process representing the program to attach
- * @flags: any logical OR combination of &enum hid_bpf_attach_flags
- *
- * @returns an fd of a bpf_link object on success (> %0), an error code otherwise.
- * Closing this fd will detach the program from the HID device (unless the bpf_link
- * is pinned to the BPF file system).
- */
-/* called from syscall */
-__bpf_kfunc int
-hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
-{
-	struct hid_device *hdev;
-	struct bpf_prog *prog;
-	int err, fd;
-
-	if ((flags & ~HID_BPF_FLAG_MASK))
-		return -EINVAL;
-
-	hdev = hid_get_device(hid_id);
-	if (IS_ERR(hdev))
-		return PTR_ERR(hdev);
-
-	/*
-	 * take a ref on the prog itself, it will be released
-	 * on errors or when it'll be detached
-	 */
-	prog = bpf_prog_get(prog_fd);
-	if (IS_ERR(prog)) {
-		err = PTR_ERR(prog);
-		goto out_dev_put;
-	}
-
-	fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags);
-	if (fd < 0) {
-		err = fd;
-		goto out_prog_put;
-	}
-
-	return fd;
-
- out_prog_put:
-	bpf_prog_put(prog);
- out_dev_put:
-	hid_put_device(hdev);
-	return err;
-}
-
 /**
  * hid_bpf_allocate_context - Allocate a context to the given HID device
  *
@@ -583,21 +450,8 @@ static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
 	.set   = &hid_bpf_kfunc_ids,
 };
 
-/* our HID-BPF entrypoints */
-BTF_SET8_START(hid_bpf_fmodret_ids)
-BTF_ID_FLAGS(func, hid_bpf_device_event)
-BTF_ID_FLAGS(func, hid_bpf_rdesc_fixup)
-BTF_ID_FLAGS(func, __hid_bpf_tail_call)
-BTF_SET8_END(hid_bpf_fmodret_ids)
-
-static const struct btf_kfunc_id_set hid_bpf_fmodret_set = {
-	.owner = THIS_MODULE,
-	.set   = &hid_bpf_fmodret_ids,
-};
-
 /* for syscall HID-BPF */
 BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
-BTF_ID_FLAGS(func, hid_bpf_attach_prog)
 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
 BTF_ID_FLAGS(func, hid_bpf_hw_request)
@@ -622,8 +476,6 @@ int hid_bpf_connect_device(struct hid_device *hdev)
 			break;
 		}
 	}
-	if (rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]))
-		need_to_allocate = true;
 	rcu_read_unlock();
 
 	/* only allocate BPF data if there are programs attached */
@@ -650,14 +502,12 @@ void hid_bpf_destroy_device(struct hid_device *hdev)
 	/* mark the device as destroyed in bpf so we don't reattach it */
 	hdev->bpf.destroyed = true;
 
-	__hid_bpf_destroy_device(hdev);
 	__hid_bpf_ops_destroy_device(hdev);
 }
 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
 
 void hid_bpf_device_init(struct hid_device *hdev)
 {
-	spin_lock_init(&hdev->bpf.progs_lock);
 	INIT_LIST_HEAD(&hdev->bpf.prog_list);
 	mutex_init(&hdev->bpf.prog_list_lock);
 }
@@ -670,37 +520,15 @@ static int __init hid_bpf_init(void)
 	/* Note: if we exit with an error any time here, we would entirely break HID, which
 	 * is probably not something we want. So we log an error and return success.
 	 *
-	 * This is not a big deal: the syscall allowing to attach a BPF program to a HID device
-	 * will not be available, so nobody will be able to use the functionality.
+	 * This is not a big deal: nobody will be able to use the functionality.
 	 */
 
-	err = register_btf_fmodret_id_set(&hid_bpf_fmodret_set);
-	if (err) {
-		pr_warn("error while registering fmodret entrypoints: %d", err);
-		return 0;
-	}
-
-	err = hid_bpf_preload_skel();
-	if (err) {
-		pr_warn("error while preloading HID BPF dispatcher: %d", err);
-		return 0;
-	}
-
-	/* register tracing kfuncs after we are sure we can load our preloaded bpf program */
-	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set);
-	if (err) {
-		pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
-		return 0;
-	}
-
-	/* register struct_ops kfuncs after we are sure we can load our preloaded bpf program */
 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
 	if (err) {
 		pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
 		return 0;
 	}
 
-	/* register syscalls after we are sure we can load our preloaded bpf program */
 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
 	if (err) {
 		pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
@@ -710,15 +538,6 @@ static int __init hid_bpf_init(void)
 	return 0;
 }
 
-static void __exit hid_bpf_exit(void)
-{
-	/* HID depends on us, so if we hit that code, we are guaranteed that hid
-	 * has been removed and thus we do not need to clear the HID devices
-	 */
-	hid_bpf_free_links_and_skel();
-}
-
 late_initcall(hid_bpf_init);
-module_exit(hid_bpf_exit);
 MODULE_AUTHOR("Benjamin Tissoires");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.h b/drivers/hid/bpf/hid_bpf_dispatch.h
index e52c43d81650..835e6f69f479 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.h
+++ b/drivers/hid/bpf/hid_bpf_dispatch.h
@@ -13,15 +13,7 @@ struct hid_bpf_ctx_kern {
 struct hid_device *hid_get_device(unsigned int hid_id);
 void hid_put_device(struct hid_device *hid);
 int hid_bpf_allocate_event_data(struct hid_device *hdev);
-int hid_bpf_preload_skel(void);
-void hid_bpf_free_links_and_skel(void);
-int hid_bpf_get_prog_attach_type(struct bpf_prog *prog);
-int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd,
-			  struct bpf_prog *prog, __u32 flags);
-void __hid_bpf_destroy_device(struct hid_device *hdev);
 void __hid_bpf_ops_destroy_device(struct hid_device *hdev);
-int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
-		     struct hid_bpf_ctx_kern *ctx_kern);
 int hid_bpf_reconnect(struct hid_device *hdev);
 
 struct bpf_prog;
diff --git a/drivers/hid/bpf/hid_bpf_jmp_table.c b/drivers/hid/bpf/hid_bpf_jmp_table.c
deleted file mode 100644
index 8a54ba447718..000000000000
--- a/drivers/hid/bpf/hid_bpf_jmp_table.c
+++ /dev/null
@@ -1,568 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-/*
- *  HID-BPF support for Linux
- *
- *  Copyright (c) 2022 Benjamin Tissoires
- */
-
-#include <linux/bitops.h>
-#include <linux/btf.h>
-#include <linux/btf_ids.h>
-#include <linux/circ_buf.h>
-#include <linux/filter.h>
-#include <linux/hid.h>
-#include <linux/hid_bpf.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/workqueue.h>
-#include "hid_bpf_dispatch.h"
-#include "entrypoints/entrypoints.lskel.h"
-
-#define HID_BPF_MAX_PROGS 1024 /* keep this in sync with preloaded bpf,
-				* needs to be a power of 2 as we use it as
-				* a circular buffer
-				*/
-
-#define NEXT(idx) (((idx) + 1) & (HID_BPF_MAX_PROGS - 1))
-#define PREV(idx) (((idx) - 1) & (HID_BPF_MAX_PROGS - 1))
-
-/*
- * represents one attached program stored in the hid jump table
- */
-struct hid_bpf_prog_entry {
-	struct bpf_prog *prog;
-	struct hid_device *hdev;
-	enum hid_bpf_prog_type type;
-	u16 idx;
-};
-
-struct hid_bpf_jmp_table {
-	struct bpf_map *map;
-	struct hid_bpf_prog_entry entries[HID_BPF_MAX_PROGS]; /* compacted list, circular buffer */
-	int tail, head;
-	struct bpf_prog *progs[HID_BPF_MAX_PROGS]; /* idx -> progs mapping */
-	unsigned long enabled[BITS_TO_LONGS(HID_BPF_MAX_PROGS)];
-};
-
-#define FOR_ENTRIES(__i, __start, __end) \
-	for (__i = __start; CIRC_CNT(__end, __i, HID_BPF_MAX_PROGS); __i = NEXT(__i))
-
-static struct hid_bpf_jmp_table jmp_table;
-
-static DEFINE_MUTEX(hid_bpf_attach_lock);		/* held when attaching/detaching programs */
-
-static void hid_bpf_release_progs(struct work_struct *work);
-
-static DECLARE_WORK(release_work, hid_bpf_release_progs);
-
-BTF_ID_LIST(hid_bpf_btf_ids)
-BTF_ID(func, hid_bpf_device_event)			/* HID_BPF_PROG_TYPE_DEVICE_EVENT */
-BTF_ID(func, hid_bpf_rdesc_fixup)			/* HID_BPF_PROG_TYPE_RDESC_FIXUP */
-
-static int hid_bpf_max_programs(enum hid_bpf_prog_type type)
-{
-	switch (type) {
-	case HID_BPF_PROG_TYPE_DEVICE_EVENT:
-		return HID_BPF_MAX_PROGS_PER_DEV;
-	case HID_BPF_PROG_TYPE_RDESC_FIXUP:
-		return 1;
-	default:
-		return -EINVAL;
-	}
-}
-
-static int hid_bpf_program_count(struct hid_device *hdev,
-				 struct bpf_prog *prog,
-				 enum hid_bpf_prog_type type)
-{
-	int i, n = 0;
-
-	if (type >= HID_BPF_PROG_TYPE_MAX)
-		return -EINVAL;
-
-	if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && hdev->bpf.rdesc_ops)
-		n += 1;
-
-	FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
-		struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
-		if (type != HID_BPF_PROG_TYPE_UNDEF && entry->type != type)
-			continue;
-
-		if (hdev && entry->hdev != hdev)
-			continue;
-
-		if (prog && entry->prog != prog)
-			continue;
-
-		n++;
-	}
-
-	return n;
-}
-
-__weak noinline int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx)
-{
-	return 0;
-}
-
-int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
-		     struct hid_bpf_ctx_kern *ctx_kern)
-{
-	struct hid_bpf_prog_list *prog_list;
-	int i, idx, err = 0;
-
-	rcu_read_lock();
-	prog_list = rcu_dereference(hdev->bpf.progs[type]);
-
-	if (!prog_list)
-		goto out_unlock;
-
-	for (i = 0; i < prog_list->prog_cnt; i++) {
-		idx = prog_list->prog_idx[i];
-
-		if (!test_bit(idx, jmp_table.enabled))
-			continue;
-
-		ctx_kern->ctx.index = idx;
-		err = __hid_bpf_tail_call(&ctx_kern->ctx);
-		if (err < 0)
-			break;
-		if (err)
-			ctx_kern->ctx.retval = err;
-	}
-
- out_unlock:
-	rcu_read_unlock();
-
-	return err;
-}
-
-/*
- * assign the list of programs attached to a given hid device.
- */
-static void __hid_bpf_set_hdev_progs(struct hid_device *hdev, struct hid_bpf_prog_list *new_list,
-				     enum hid_bpf_prog_type type)
-{
-	struct hid_bpf_prog_list *old_list;
-
-	spin_lock(&hdev->bpf.progs_lock);
-	old_list = rcu_dereference_protected(hdev->bpf.progs[type],
-					     lockdep_is_held(&hdev->bpf.progs_lock));
-	rcu_assign_pointer(hdev->bpf.progs[type], new_list);
-	spin_unlock(&hdev->bpf.progs_lock);
-	synchronize_rcu();
-
-	kfree(old_list);
-}
-
-/*
- * allocate and populate the list of programs attached to a given hid device.
- *
- * Must be called under lock.
- */
-static int hid_bpf_populate_hdev(struct hid_device *hdev, enum hid_bpf_prog_type type)
-{
-	struct hid_bpf_prog_list *new_list;
-	int i;
-
-	if (type >= HID_BPF_PROG_TYPE_MAX || !hdev)
-		return -EINVAL;
-
-	if (hdev->bpf.destroyed)
-		return 0;
-
-	new_list = kzalloc(sizeof(*new_list), GFP_KERNEL);
-	if (!new_list)
-		return -ENOMEM;
-
-	FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
-		struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
-		if (entry->type == type && entry->hdev == hdev &&
-		    test_bit(entry->idx, jmp_table.enabled))
-			new_list->prog_idx[new_list->prog_cnt++] = entry->idx;
-	}
-
-	__hid_bpf_set_hdev_progs(hdev, new_list, type);
-
-	return 0;
-}
-
-static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx)
-{
-	skel_map_delete_elem(map_fd, &idx);
-	jmp_table.progs[idx] = NULL;
-}
-
-static void hid_bpf_release_progs(struct work_struct *work)
-{
-	int i, j, n, map_fd = -1;
-	bool hdev_destroyed;
-
-	if (!jmp_table.map)
-		return;
-
-	/* retrieve a fd of our prog_array map in BPF */
-	map_fd = skel_map_get_fd_by_id(jmp_table.map->id);
-	if (map_fd < 0)
-		return;
-
-	mutex_lock(&hid_bpf_attach_lock); /* protects against attaching new programs */
-
-	/* detach unused progs from HID devices */
-	FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
-		struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-		enum hid_bpf_prog_type type;
-		struct hid_device *hdev;
-
-		if (test_bit(entry->idx, jmp_table.enabled))
-			continue;
-
-		/* we have an attached prog */
-		if (entry->hdev) {
-			hdev = entry->hdev;
-			type = entry->type;
-			/*
-			 * hdev is still valid, even if we are called after hid_destroy_device():
-			 * when hid_bpf_attach() gets called, it takes a ref on the dev through
-			 * bus_find_device()
-			 */
-			hdev_destroyed = hdev->bpf.destroyed;
-
-			hid_bpf_populate_hdev(hdev, type);
-
-			/* mark all other disabled progs from hdev of the given type as detached */
-			FOR_ENTRIES(j, i, jmp_table.head) {
-				struct hid_bpf_prog_entry *next;
-
-				next = &jmp_table.entries[j];
-
-				if (test_bit(next->idx, jmp_table.enabled))
-					continue;
-
-				if (next->hdev == hdev && next->type == type) {
-					/*
-					 * clear the hdev reference and decrement the device ref
-					 * that was taken during bus_find_device() while calling
-					 * hid_bpf_attach()
-					 */
-					next->hdev = NULL;
-					put_device(&hdev->dev);
-				}
-			}
-
-			/* if type was rdesc fixup and the device is not gone, reconnect device */
-			if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && !hdev_destroyed)
-				hid_bpf_reconnect(hdev);
-		}
-	}
-
-	/* remove all unused progs from the jump table */
-	FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
-		struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
-		if (test_bit(entry->idx, jmp_table.enabled))
-			continue;
-
-		if (entry->prog)
-			__hid_bpf_do_release_prog(map_fd, entry->idx);
-	}
-
-	/* compact the entry list */
-	n = jmp_table.tail;
-	FOR_ENTRIES(i, jmp_table.tail, jmp_table.head) {
-		struct hid_bpf_prog_entry *entry = &jmp_table.entries[i];
-
-		if (!test_bit(entry->idx, jmp_table.enabled))
-			continue;
-
-		jmp_table.entries[n] = jmp_table.entries[i];
-		n = NEXT(n);
-	}
-
-	jmp_table.head = n;
-
-	mutex_unlock(&hid_bpf_attach_lock);
-
-	if (map_fd >= 0)
-		close_fd(map_fd);
-}
-
-static void hid_bpf_release_prog_at(int idx)
-{
-	int map_fd = -1;
-
-	/* retrieve a fd of our prog_array map in BPF */
-	map_fd = skel_map_get_fd_by_id(jmp_table.map->id);
-	if (map_fd < 0)
-		return;
-
-	__hid_bpf_do_release_prog(map_fd, idx);
-
-	close(map_fd);
-}
-
-/*
- * Insert the given BPF program represented by its fd in the jmp table.
- * Returns the index in the jump table or a negative error.
- */
-static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog)
-{
-	int i, index = -1, map_fd = -1, err = -EINVAL;
-
-	/* retrieve a fd of our prog_array map in BPF */
-	map_fd = skel_map_get_fd_by_id(jmp_table.map->id);
-
-	if (map_fd < 0) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	/* find the first available index in the jmp_table */
-	for (i = 0; i < HID_BPF_MAX_PROGS; i++) {
-		if (!jmp_table.progs[i] && index < 0) {
-			/* mark the index as used */
-			jmp_table.progs[i] = prog;
-			index = i;
-			__set_bit(i, jmp_table.enabled);
-		}
-	}
-	if (index < 0) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	/* insert the program in the jump table */
-	err = skel_map_update_elem(map_fd, &index, &prog_fd, 0);
-	if (err)
-		goto out;
-
-	/* return the index */
-	err = index;
-
- out:
-	if (err < 0)
-		__hid_bpf_do_release_prog(map_fd, index);
-	if (map_fd >= 0)
-		close_fd(map_fd);
-	return err;
-}
-
-int hid_bpf_get_prog_attach_type(struct bpf_prog *prog)
-{
-	int prog_type = HID_BPF_PROG_TYPE_UNDEF;
-	int i;
-
-	for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) {
-		if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) {
-			prog_type = i;
-			break;
-		}
-	}
-
-	return prog_type;
-}
-
-static void hid_bpf_link_release(struct bpf_link *link)
-{
-	struct hid_bpf_link *hid_link =
-		container_of(link, struct hid_bpf_link, link);
-
-	__clear_bit(hid_link->hid_table_index, jmp_table.enabled);
-	schedule_work(&release_work);
-}
-
-static void hid_bpf_link_dealloc(struct bpf_link *link)
-{
-	struct hid_bpf_link *hid_link =
-		container_of(link, struct hid_bpf_link, link);
-
-	kfree(hid_link);
-}
-
-static void hid_bpf_link_show_fdinfo(const struct bpf_link *link,
-					 struct seq_file *seq)
-{
-	seq_printf(seq,
-		   "attach_type:\tHID-BPF\n");
-}
-
-static const struct bpf_link_ops hid_bpf_link_lops = {
-	.release = hid_bpf_link_release,
-	.dealloc = hid_bpf_link_dealloc,
-	.show_fdinfo = hid_bpf_link_show_fdinfo,
-};
-
-/* called from syscall */
-noinline int
-__hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
-		      int prog_fd, struct bpf_prog *prog, __u32 flags)
-{
-	struct bpf_link_primer link_primer;
-	struct hid_bpf_link *link;
-	struct hid_bpf_prog_entry *prog_entry;
-	int cnt, err = -EINVAL, prog_table_idx = -1;
-
-	mutex_lock(&hid_bpf_attach_lock);
-
-	link = kzalloc(sizeof(*link), GFP_USER);
-	if (!link) {
-		err = -ENOMEM;
-		goto err_unlock;
-	}
-
-	bpf_link_init(&link->link, BPF_LINK_TYPE_UNSPEC,
-		      &hid_bpf_link_lops, prog);
-
-	/* do not attach too many programs to a given HID device */
-	cnt = hid_bpf_program_count(hdev, NULL, prog_type);
-	if (cnt < 0) {
-		err = cnt;
-		goto err_unlock;
-	}
-
-	if (cnt >= hid_bpf_max_programs(prog_type)) {
-		err = -E2BIG;
-		goto err_unlock;
-	}
-
-	prog_table_idx = hid_bpf_insert_prog(prog_fd, prog);
-	/* if the jmp table is full, abort */
-	if (prog_table_idx < 0) {
-		err = prog_table_idx;
-		goto err_unlock;
-	}
-
-	if (flags & HID_BPF_FLAG_INSERT_HEAD) {
-		/* take the previous prog_entry slot */
-		jmp_table.tail = PREV(jmp_table.tail);
-		prog_entry = &jmp_table.entries[jmp_table.tail];
-	} else {
-		/* take the next prog_entry slot */
-		prog_entry = &jmp_table.entries[jmp_table.head];
-		jmp_table.head = NEXT(jmp_table.head);
-	}
-
-	/* we steal the ref here */
-	prog_entry->prog = prog;
-	prog_entry->idx = prog_table_idx;
-	prog_entry->hdev = hdev;
-	prog_entry->type = prog_type;
-
-	/* finally store the index in the device list */
-	err = hid_bpf_populate_hdev(hdev, prog_type);
-	if (err) {
-		hid_bpf_release_prog_at(prog_table_idx);
-		goto err_unlock;
-	}
-
-	link->hid_table_index = prog_table_idx;
-
-	err = bpf_link_prime(&link->link, &link_primer);
-	if (err)
-		goto err_unlock;
-
-	mutex_unlock(&hid_bpf_attach_lock);
-
-	return bpf_link_settle(&link_primer);
-
- err_unlock:
-	mutex_unlock(&hid_bpf_attach_lock);
-
-	kfree(link);
-
-	return err;
-}
-
-void __hid_bpf_destroy_device(struct hid_device *hdev)
-{
-	int type, i;
-	struct hid_bpf_prog_list *prog_list;
-
-	rcu_read_lock();
-
-	for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++) {
-		prog_list = rcu_dereference(hdev->bpf.progs[type]);
-
-		if (!prog_list)
-			continue;
-
-		for (i = 0; i < prog_list->prog_cnt; i++)
-			__clear_bit(prog_list->prog_idx[i], jmp_table.enabled);
-	}
-
-	rcu_read_unlock();
-
-	for (type = 0; type < HID_BPF_PROG_TYPE_MAX; type++)
-		__hid_bpf_set_hdev_progs(hdev, NULL, type);
-
-	/* schedule release of all detached progs */
-	schedule_work(&release_work);
-}
-
-#define HID_BPF_PROGS_COUNT 1
-
-static struct bpf_link *links[HID_BPF_PROGS_COUNT];
-static struct entrypoints_bpf *skel;
-
-void hid_bpf_free_links_and_skel(void)
-{
-	int i;
-
-	/* the following is enough to release all programs attached to hid */
-	if (jmp_table.map)
-		bpf_map_put_with_uref(jmp_table.map);
-
-	for (i = 0; i < ARRAY_SIZE(links); i++) {
-		if (!IS_ERR_OR_NULL(links[i]))
-			bpf_link_put(links[i]);
-	}
-	entrypoints_bpf__destroy(skel);
-}
-
-#define ATTACH_AND_STORE_LINK(__name) do {					\
-	err = entrypoints_bpf__##__name##__attach(skel);			\
-	if (err)								\
-		goto out;							\
-										\
-	links[idx] = bpf_link_get_from_fd(skel->links.__name##_fd);		\
-	if (IS_ERR(links[idx])) {						\
-		err = PTR_ERR(links[idx]);					\
-		goto out;							\
-	}									\
-										\
-	/* Avoid taking over stdin/stdout/stderr of init process. Zeroing out	\
-	 * makes skel_closenz() a no-op later in iterators_bpf__destroy().	\
-	 */									\
-	close_fd(skel->links.__name##_fd);					\
-	skel->links.__name##_fd = 0;						\
-	idx++;									\
-} while (0)
-
-int hid_bpf_preload_skel(void)
-{
-	int err, idx = 0;
-
-	skel = entrypoints_bpf__open();
-	if (!skel)
-		return -ENOMEM;
-
-	err = entrypoints_bpf__load(skel);
-	if (err)
-		goto out;
-
-	jmp_table.map = bpf_map_get_with_uref(skel->maps.hid_jmp_table.map_fd);
-	if (IS_ERR(jmp_table.map)) {
-		err = PTR_ERR(jmp_table.map);
-		goto out;
-	}
-
-	ATTACH_AND_STORE_LINK(hid_tail_call);
-
-	return 0;
-out:
-	hid_bpf_free_links_and_skel();
-	return err;
-}
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index c4f4ce10b7dd..447b94aa99ab 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -4,7 +4,7 @@
 #define __HID_BPF_H
 
 #include <linux/bpf.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <uapi/linux/hid.h>
 
 struct hid_device;
@@ -24,11 +24,7 @@ struct hid_device;
  *
  * All of these fields are currently read-only.
  *
- * @index: program index in the jump table. No special meaning (a smaller index
- *         doesn't mean the program will be executed before another program with
- *         a bigger index).
  * @hid: the ``struct hid_device`` representing the device itself
- * @report_type: used for ``hid_bpf_device_event()``
  * @allocated_size: Allocated size of data.
  *
  *                  This is how much memory is available and can be requested
@@ -47,54 +43,21 @@ struct hid_device;
  * @retval: Return value of the previous program.
  */
 struct hid_bpf_ctx {
-	__u32 index;
 	const struct hid_device *hid;
 	__u32 allocated_size;
-	enum hid_report_type report_type;
 	union {
 		__s32 retval;
 		__s32 size;
 	};
 };
 
-/**
- * enum hid_bpf_attach_flags - flags used when attaching a HIF-BPF program
- *
- * @HID_BPF_FLAG_NONE: no specific flag is used, the kernel choses where to
- *                     insert the program
- * @HID_BPF_FLAG_INSERT_HEAD: insert the given program before any other program
- *                            currently attached to the device. This doesn't
- *                            guarantee that this program will always be first
- */
-enum hid_bpf_attach_flags {
-	HID_BPF_FLAG_NONE = 0,
-	HID_BPF_FLAG_INSERT_HEAD = _BITUL(0),
-
-	/* private: internal use only */
-	HID_BPF_FLAG_MAX,
-};
-
-/* Following functions are tracepoints that BPF programs can attach to */
-int hid_bpf_device_event(struct hid_bpf_ctx *ctx);
-int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx);
-
 /*
  * Below is HID internal
  */
 
-/* internal function to call eBPF programs, not to be used by anybody */
-int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx);
-
 #define HID_BPF_MAX_PROGS_PER_DEV 64
 #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1)
 
-/* types of HID programs to attach to */
-enum hid_bpf_prog_type {
-	HID_BPF_PROG_TYPE_UNDEF = -1,
-	HID_BPF_PROG_TYPE_DEVICE_EVENT,			/* an event is emitted from the device */
-	HID_BPF_PROG_TYPE_RDESC_FIXUP,
-	HID_BPF_PROG_TYPE_MAX,
-};
 
 struct hid_report_enum;
 
@@ -167,11 +130,6 @@ struct hid_bpf_ops {
 	struct hid_device *hdev;
 };
 
-struct hid_bpf_prog_list {
-	u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV];
-	u8 prog_cnt;
-};
-
 /* stored in each device */
 struct hid_bpf {
 	u8 *device_data;		/* allocated when a bpf program of type
@@ -179,23 +137,13 @@ struct hid_bpf {
 					 * to this HID device
 					 */
 	u32 allocated_data;
-
-	struct hid_bpf_prog_list __rcu *progs[HID_BPF_PROG_TYPE_MAX];	/* attached BPF progs */
 	bool destroyed;			/* prevents the assignment of any progs */
 
-	spinlock_t progs_lock;		/* protects RCU update of progs */
-
 	struct hid_bpf_ops *rdesc_ops;
 	struct list_head prog_list;
 	struct mutex prog_list_lock;	/* protects prog_list update */
 };
 
-/* specific HID-BPF link when a program is attached to a device */
-struct hid_bpf_link {
-	struct bpf_link link;
-	int hid_table_index;
-};
-
 #ifdef CONFIG_HID_BPF
 u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
 				  u32 *size, int interrupt);

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 09/16] selftests/hid: add subprog call test
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

I got a weird verifier error with a subprog once, so let's have a test
for it.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 tools/testing/selftests/hid/hid_bpf.c   | 41 +++++++++++++++++++++++++++++++++
 tools/testing/selftests/hid/progs/hid.c | 24 +++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c
index 967dfe6b58cb..45e173db35bd 100644
--- a/tools/testing/selftests/hid/hid_bpf.c
+++ b/tools/testing/selftests/hid/hid_bpf.c
@@ -638,6 +638,47 @@ TEST_F(hid_bpf, raw_event)
 	ASSERT_EQ(buf[2], 52);
 }
 
+/*
+ * Attach hid_first_event to the given uhid device,
+ * retrieve and open the matching hidraw node,
+ * inject one event in the uhid device,
+ * check that the program sees it and can change the data
+ */
+TEST_F(hid_bpf, subprog_raw_event)
+{
+	const struct test_program progs[] = {
+		{ .name = "hid_subprog_first_event" },
+	};
+	__u8 buf[10] = {0};
+	int err;
+
+	LOAD_PROGRAMS(progs);
+
+	/* inject one event */
+	buf[0] = 1;
+	buf[1] = 42;
+	uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+
+	/* read the data from hidraw */
+	memset(buf, 0, sizeof(buf));
+	err = read(self->hidraw_fd, buf, sizeof(buf));
+	ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
+	ASSERT_EQ(buf[0], 1);
+	ASSERT_EQ(buf[2], 47);
+
+	/* inject another event */
+	memset(buf, 0, sizeof(buf));
+	buf[0] = 1;
+	buf[1] = 47;
+	uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+
+	/* read the data from hidraw */
+	memset(buf, 0, sizeof(buf));
+	err = read(self->hidraw_fd, buf, sizeof(buf));
+	ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
+	ASSERT_EQ(buf[2], 52);
+}
+
 /*
  * Ensures that we can attach/detach programs
  */
diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c
index 614f1aa32649..2e7e5a736dc6 100644
--- a/tools/testing/selftests/hid/progs/hid.c
+++ b/tools/testing/selftests/hid/progs/hid.c
@@ -35,6 +35,30 @@ struct hid_bpf_ops first_event = {
 	.hid_id = 2,
 };
 
+int __hid_subprog_first_event(struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
+{
+	__u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
+
+	if (!rw_data)
+		return 0; /* EPERM check */
+
+	rw_data[2] = rw_data[1] + 5;
+
+	return hid_ctx->size;
+}
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_subprog_first_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
+{
+	return __hid_subprog_first_event(hid_ctx, type);
+}
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops subprog_first_event = {
+	.hid_device_event = (void *)hid_subprog_first_event,
+	.hid_id = 2,
+};
+
 SEC("?struct_ops/hid_device_event")
 int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 10/16] Documentation: HID: amend HID-BPF for struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

Now that we are using struct_ops, the docs need to be changed.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

changes in v2
- use BPF_F_BEFORE
---
 Documentation/hid/hid-bpf.rst | 156 +++++++++++++++++++-----------------------
 include/linux/hid_bpf.h       |   8 +--
 2 files changed, 76 insertions(+), 88 deletions(-)

diff --git a/Documentation/hid/hid-bpf.rst b/Documentation/hid/hid-bpf.rst
index 0765b3298ecf..456e15097d87 100644
--- a/Documentation/hid/hid-bpf.rst
+++ b/Documentation/hid/hid-bpf.rst
@@ -132,16 +132,17 @@ input events.
 Available types of programs
 ===========================
 
-HID-BPF is built "on top" of BPF, meaning that we use tracing method to
+HID-BPF is built "on top" of BPF, meaning that we use bpf struct_ops method to
 declare our programs.
 
 HID-BPF has the following attachment types available:
 
-1. event processing/filtering with ``SEC("fmod_ret/hid_bpf_device_event")`` in libbpf
+1. event processing/filtering with ``SEC("struct_ops/hid_device_event")`` in libbpf
 2. actions coming from userspace with ``SEC("syscall")`` in libbpf
-3. change of the report descriptor with ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` in libbpf
+3. change of the report descriptor with ``SEC("struct_ops/hid_rdesc_fixup")`` or
+   ``SEC("struct_ops.s/hid_rdesc_fixup")`` in libbpf
 
-A ``hid_bpf_device_event`` is calling a BPF program when an event is received from
+A ``hid_device_event`` is calling a BPF program when an event is received from
 the device. Thus we are in IRQ context and can act on the data or notify userspace.
 And given that we are in IRQ context, we can not talk back to the device.
 
@@ -149,37 +150,42 @@ A ``syscall`` means that userspace called the syscall ``BPF_PROG_RUN`` facility.
 This time, we can do any operations allowed by HID-BPF, and talking to the device is
 allowed.
 
-Last, ``hid_bpf_rdesc_fixup`` is different from the others as there can be only one
+Last, ``hid_rdesc_fixup`` is different from the others as there can be only one
 BPF program of this type. This is called on ``probe`` from the driver and allows to
-change the report descriptor from the BPF program. Once a ``hid_bpf_rdesc_fixup``
+change the report descriptor from the BPF program. Once a ``hid_rdesc_fixup``
 program has been loaded, it is not possible to overwrite it unless the program which
 inserted it allows us by pinning the program and closing all of its fds pointing to it.
 
+Note that ``hid_rdesc_fixup`` can be declared as sleepable (``SEC("struct_ops.s/hid_rdesc_fixup")``).
+
+
 Developer API:
 ==============
 
-User API data structures available in programs:
------------------------------------------------
+Available ``struct_ops`` for HID-BPF:
+-------------------------------------
 
 .. kernel-doc:: include/linux/hid_bpf.h
+   :identifiers: hid_bpf_ops
 
-Available tracing functions to attach a HID-BPF program:
---------------------------------------------------------
 
-.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
-   :functions: hid_bpf_device_event hid_bpf_rdesc_fixup
+User API data structures available in programs:
+-----------------------------------------------
+
+.. kernel-doc:: include/linux/hid_bpf.h
+   :identifiers: hid_bpf_ctx
 
-Available API that can be used in all HID-BPF programs:
--------------------------------------------------------
+Available API that can be used in all HID-BPF struct_ops programs:
+------------------------------------------------------------------
 
 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
-   :functions: hid_bpf_get_data
+   :identifiers: hid_bpf_get_data
 
-Available API that can be used in syscall HID-BPF programs:
------------------------------------------------------------
+Available API that can be used in syscall HID-BPF programs or in sleepable HID-BPF struct_ops programs:
+-------------------------------------------------------------------------------------------------------
 
 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
-   :functions: hid_bpf_attach_prog hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_allocate_context hid_bpf_release_context
+   :identifiers: hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_allocate_context hid_bpf_release_context
 
 General overview of a HID-BPF program
 =====================================
@@ -222,20 +228,21 @@ This allows the following:
 Effect of a HID-BPF program
 ---------------------------
 
-For all HID-BPF attachment types except for :c:func:`hid_bpf_rdesc_fixup`, several eBPF
-programs can be attached to the same device.
+For all HID-BPF attachment types except for :c:func:`hid_rdesc_fixup`, several eBPF
+programs can be attached to the same device. If a HID-BPF struct_ops has a
+:c:func:`hid_rdesc_fixup` while another is already attached to the device, the
+kernel will return `-EINVAL` when attaching the struct_ops.
 
-Unless ``HID_BPF_FLAG_INSERT_HEAD`` is added to the flags while attaching the
-program, the new program is appended at the end of the list.
-``HID_BPF_FLAG_INSERT_HEAD`` will insert the new program at the beginning of the
-list which is useful for e.g. tracing where we need to get the unprocessed events
-from the device.
+Unless ``BPF_F_BEFORE`` is added to the flags while attaching the program, the new
+program is appended at the end of the list.
+``BPF_F_BEFORE`` will insert the new program at the beginning of the list which is
+useful for e.g. tracing where we need to get the unprocessed events from the device.
 
-Note that if there are multiple programs using the ``HID_BPF_FLAG_INSERT_HEAD`` flag,
+Note that if there are multiple programs using the ``BPF_F_BEFORE`` flag,
 only the most recently loaded one is actually the first in the list.
 
-``SEC("fmod_ret/hid_bpf_device_event")``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``SEC("struct_ops/hid_device_event")``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Whenever a matching event is raised, the eBPF programs are called one after the other
 and are working on the same data buffer.
@@ -258,17 +265,17 @@ with, userspace needs to refer to the device by its unique system id (the last 4
 in the sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``).
 
 To retrieve a context associated with the device, the program must call
-:c:func:`hid_bpf_allocate_context` and must release it with :c:func:`hid_bpf_release_context`
+hid_bpf_allocate_context() and must release it with hid_bpf_release_context()
 before returning.
 Once the context is retrieved, one can also request a pointer to kernel memory with
-:c:func:`hid_bpf_get_data`. This memory is big enough to support all input/output/feature
+hid_bpf_get_data(). This memory is big enough to support all input/output/feature
 reports of the given device.
 
-``SEC("fmod_ret/hid_bpf_rdesc_fixup")``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``SEC("struct_ops/hid_rdesc_fixup")``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The ``hid_bpf_rdesc_fixup`` program works in a similar manner to
-``.report_fixup`` of ``struct hid_driver``.
+The ``hid_rdesc_fixup`` program works in a similar manner to ``.report_fixup``
+of ``struct hid_driver``.
 
 When the device is probed, the kernel sets the data buffer of the context with the
 content of the report descriptor. The memory associated with that buffer is
@@ -277,33 +284,31 @@ content of the report descriptor. The memory associated with that buffer is
 The eBPF program can modify the data buffer at-will and the kernel uses the
 modified content and size as the report descriptor.
 
-Whenever a ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is attached (if no
-program was attached before), the kernel immediately disconnects the HID device
-and does a reprobe.
+Whenever a struct_ops containing a ``SEC("struct_ops/hid_rdesc_fixup")`` program
+is attached (if no program was attached before), the kernel immediately disconnects
+the HID device and does a reprobe.
 
-In the same way, when the ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is
-detached, the kernel issues a disconnect on the device.
+In the same way, when this struct_ops is detached, the kernel issues a disconnect
+on the device.
 
 There is no ``detach`` facility in HID-BPF. Detaching a program happens when
-all the user space file descriptors pointing at a program are closed.
+all the user space file descriptors pointing at a HID-BPF struct_ops link are closed.
 Thus, if we need to replace a report descriptor fixup, some cooperation is
 required from the owner of the original report descriptor fixup.
-The previous owner will likely pin the program in the bpffs, and we can then
+The previous owner will likely pin the struct_ops link in the bpffs, and we can then
 replace it through normal bpf operations.
 
 Attaching a bpf program to a device
 ===================================
 
-``libbpf`` does not export any helper to attach a HID-BPF program.
-Users need to use a dedicated ``syscall`` program which will call
-``hid_bpf_attach_prog(hid_id, program_fd, flags)``.
+We now use standard struct_ops attachment through ``bpf_map__attach_struct_ops()``.
+But given that we need to attach a struct_ops to a dedicated HID device, the caller
+must set ``hid_id`` in the struct_ops map before loading the program in the kernel.
 
 ``hid_id`` is the unique system ID of the HID device (the last 4 numbers in the
 sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``)
 
-``progam_fd`` is the opened file descriptor of the program to attach.
-
-``flags`` is of type ``enum hid_bpf_attach_flags``.
+One can also set ``flags``, which is of type ``enum hid_bpf_attach_flags``.
 
 We can not rely on hidraw to bind a BPF program to a HID device. hidraw is an
 artefact of the processing of the HID device, and is not stable. Some drivers
@@ -358,32 +363,15 @@ For that, we can create a basic skeleton for our BPF program::
   extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,
 			      unsigned int offset,
 			      const size_t __sz) __ksym;
-  extern int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, u32 flags) __ksym;
 
   struct {
 	__uint(type, BPF_MAP_TYPE_RINGBUF);
 	__uint(max_entries, 4096 * 64);
   } ringbuf SEC(".maps");
 
-  struct attach_prog_args {
-	int prog_fd;
-	unsigned int hid;
-	unsigned int flags;
-	int retval;
-  };
-
-  SEC("syscall")
-  int attach_prog(struct attach_prog_args *ctx)
-  {
-	ctx->retval = hid_bpf_attach_prog(ctx->hid,
-					  ctx->prog_fd,
-					  ctx->flags);
-	return 0;
-  }
-
   __u8 current_value = 0;
 
-  SEC("?fmod_ret/hid_bpf_device_event")
+  SEC("struct_ops/hid_device_event")
   int BPF_PROG(filter_switch, struct hid_bpf_ctx *hid_ctx)
   {
 	__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 192 /* size */);
@@ -407,37 +395,37 @@ For that, we can create a basic skeleton for our BPF program::
 	return 0;
   }
 
-To attach ``filter_switch``, userspace needs to call the ``attach_prog`` syscall
-program first::
+  SEC(".struct_ops.link")
+  struct hid_bpf_ops haptic_tablet = {
+  	.hid_device_event = (void *)filter_switch,
+  };
+
+
+To attach ``haptic_tablet``, userspace needs to set ``hid_id`` first::
 
   static int attach_filter(struct hid *hid_skel, int hid_id)
   {
-	int err, prog_fd;
-	int ret = -1;
-	struct attach_prog_args args = {
-		.hid = hid_id,
-	};
-	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
-		.ctx_in = &args,
-		.ctx_size_in = sizeof(args),
-	);
+  	int err, link_fd;
 
-	args.prog_fd = bpf_program__fd(hid_skel->progs.filter_switch);
+  	hid_skel->struct_ops.haptic_tablet->hid_id = hid_id;
+  	err = hid__load(skel);
+  	if (err)
+  		return err;
 
-	prog_fd = bpf_program__fd(hid_skel->progs.attach_prog);
-
-	err = bpf_prog_test_run_opts(prog_fd, &tattrs);
-	if (err)
-		return err;
+  	link_fd = bpf_map__attach_struct_ops(hid_skel->maps.haptic_tablet);
+  	if (!link_fd) {
+  		fprintf(stderr, "can not attach HID-BPF program: %m\n");
+  		return -1;
+  	}
 
-	return args.retval; /* the fd of the created bpf_link */
+  	return link_fd; /* the fd of the created bpf_link */
   }
 
 Our userspace program can now listen to notifications on the ring buffer, and
 is awaken only when the value changes.
 
 When the userspace program doesn't need to listen to events anymore, it can just
-close the returned fd from :c:func:`attach_filter`, which will tell the kernel to
+close the returned bpf link from :c:func:`attach_filter`, which will tell the kernel to
 detach the program from the HID device.
 
 Of course, in other use cases, the userspace program can also pin the fd to the
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index 447b94aa99ab..1b4cc1b2c31d 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -20,11 +20,9 @@ struct hid_device;
  * struct hid_bpf_ctx - User accessible data for all HID programs
  *
  * ``data`` is not directly accessible from the context. We need to issue
- * a call to ``hid_bpf_get_data()`` in order to get a pointer to that field.
+ * a call to hid_bpf_get_data() in order to get a pointer to that field.
  *
- * All of these fields are currently read-only.
- *
- * @hid: the ``struct hid_device`` representing the device itself
+ * @hid: the &struct hid_device representing the device itself
  * @allocated_size: Allocated size of data.
  *
  *                  This is how much memory is available and can be requested
@@ -41,6 +39,8 @@ struct hid_device;
  *        ``size`` must always be less or equal than ``allocated_size`` (it is enforced
  *        once all BPF programs have been run).
  * @retval: Return value of the previous program.
+ *
+ * ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write.
  */
 struct hid_bpf_ctx {
 	const struct hid_device *hid;

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 11/16] Documentation: HID: add a small blurb on udev-hid-bpf
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

This is the current decision we took: we don't provide automatic loading
of HID-BPF by the kernel directly, but rely on an external tool for it.

This tool is currently udev-hid-bpf, so let's make people aware of it.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 Documentation/hid/hid-bpf.rst | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/Documentation/hid/hid-bpf.rst b/Documentation/hid/hid-bpf.rst
index 456e15097d87..8ae8f49801cb 100644
--- a/Documentation/hid/hid-bpf.rst
+++ b/Documentation/hid/hid-bpf.rst
@@ -129,6 +129,23 @@ When a BPF program needs to emit input events, it needs to talk with the HID
 protocol, and rely on the HID kernel processing to translate the HID data into
 input events.
 
+In-tree HID-BPF programs and ``udev-hid-bpf``
+=============================================
+
+Official device fixes are shipped in the kernel tree as source in the
+``drivers/hid/bpf/progs`` directory. This allows to add selftests to them in
+``tools/testing/selftests/hid``.
+
+However, the compilation of these objects is not part of a regular kernel compilation
+given that they need an external tool to be loaded. This tool is currently
+`udev-hid-bpf <https://libevdev.pages.freedesktop.org/udev-hid-bpf/index.html>`_.
+
+For convenience, that external repository duplicates the files from here in
+``drivers/hid/bpf/progs`` into its own ``src/bpf/stable`` directory. This allows
+distributions to not have to pull the entire kernel source tree to ship and package
+those HID-BPF fixes. ``udev-hid-bpf`` also has capabilities of handling multiple
+objects files depending on the kernel the user is running.
+
 Available types of programs
 ===========================
 

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 12/16] HID: bpf: Artist24: remove unused variable
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires, Peter Hutterer
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

warning: unused variable ‘tilt’ [-Wunused-variable]

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 drivers/hid/bpf/progs/XPPen__Artist24.bpf.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index bc0b85c38445..d4d062c3a653 100644
--- a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
@@ -158,7 +158,6 @@ int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
 	__u8 current_state, changed_state;
 	bool prev_tip;
-	__u16 tilt;
 
 	if (!data)
 		return 0; /* EPERM check */

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 13/16] HID: bpf: error on warnings when compiling bpf objects
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

There is no real reasons to paper over warnings for such small programs.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

no changes in v2
---
 drivers/hid/bpf/progs/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hid/bpf/progs/Makefile b/drivers/hid/bpf/progs/Makefile
index 63ed7e02adf1..ec1fc642fd63 100644
--- a/drivers/hid/bpf/progs/Makefile
+++ b/drivers/hid/bpf/progs/Makefile
@@ -56,7 +56,7 @@ clean:
 
 %.bpf.o: %.bpf.c vmlinux.h $(BPFOBJ) | $(OUTPUT)
 	$(call msg,BPF,$@)
-	$(Q)$(CLANG) -g -O2 --target=bpf $(INCLUDES)			      \
+	$(Q)$(CLANG) -g -O2 --target=bpf -Wall -Werror $(INCLUDES)	      \
 		 -c $(filter %.c,$^) -o $@ &&				      \
 	$(LLVM_STRIP) -g $@
 

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 14/16] bpf: allow bpf helpers to be used into HID-BPF struct_ops
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

Without this helpers like bpf_printk() or bpf_map_update() are not
available, making anything but change of bytes impossible to do.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

no changes in v3

new in v2
---
 drivers/hid/bpf/hid_bpf_struct_ops.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
index 9192c66cde20..056d05d96962 100644
--- a/drivers/hid/bpf/hid_bpf_struct_ops.c
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -89,6 +89,7 @@ static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
 }
 
 static const struct bpf_verifier_ops hid_bpf_verifier_ops = {
+	.get_func_proto = bpf_base_func_proto,
 	.is_valid_access = hid_bpf_ops_is_valid_access,
 	.btf_struct_access = hid_bpf_ops_btf_struct_access,
 };

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 15/16] HID: bpf: rework hid_bpf_ops_btf_struct_access
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

The idea is to provide a list of stucts and their editable fields.

Currently no functional changes are introduced here, we will add some
more writeable fields in the next patch.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

changes in v3:
- rewrote WRITE_RANGE macro to not deal with offset from the caller side

new in v2
---
 drivers/hid/bpf/hid_bpf_struct_ops.c | 91 +++++++++++++++++++++++++++---------
 1 file changed, 69 insertions(+), 22 deletions(-)

diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
index 056d05d96962..b14eccb121e0 100644
--- a/drivers/hid/bpf/hid_bpf_struct_ops.c
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -16,6 +16,7 @@
 #include <linux/hid_bpf.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/stddef.h>
 #include <linux/workqueue.h>
 #include "hid_bpf_dispatch.h"
 
@@ -52,40 +53,86 @@ static int hid_bpf_ops_check_member(const struct btf_type *t,
 	return 0;
 }
 
+struct hid_bpf_offset_write_range {
+	const char *struct_name;
+	u32 struct_length;
+	u32 start;
+	u32 end;
+};
+
 static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
 					   const struct bpf_reg_state *reg,
 					   int off, int size)
 {
-	const struct btf_type *state;
-	const struct btf_type *t;
-	s32 type_id;
+#define WRITE_RANGE(_name, _field, _is_string)					\
+	{									\
+		.struct_name = #_name,						\
+		.struct_length = sizeof(struct _name),				\
+		.start = offsetof(struct _name, _field),			\
+		.end = offsetofend(struct _name, _field) - !!(_is_string),	\
+	}
 
-	type_id = btf_find_by_name_kind(reg->btf, "hid_bpf_ctx",
-					BTF_KIND_STRUCT);
-	if (type_id < 0)
-		return -EINVAL;
+	const struct hid_bpf_offset_write_range write_ranges[] = {
+		WRITE_RANGE(hid_bpf_ctx, retval, false),
+	};
+#undef WRITE_RANGE
+	const struct btf_type *state = NULL;
+	const struct btf_type *t;
+	const char *cur = NULL;
+	int i;
 
 	t = btf_type_by_id(reg->btf, reg->btf_id);
-	state = btf_type_by_id(reg->btf, type_id);
-	if (t != state) {
-		bpf_log(log, "only access to hid_bpf_ctx is supported\n");
-		return -EACCES;
-	}
 
-	/* out-of-bound access in hid_bpf_ctx */
-	if (off + size > sizeof(struct hid_bpf_ctx)) {
-		bpf_log(log, "write access at off %d with size %d\n", off, size);
-		return -EACCES;
+	for (i = 0; i < ARRAY_SIZE(write_ranges); i++) {
+		const struct hid_bpf_offset_write_range *write_range = &write_ranges[i];
+		s32 type_id;
+
+		/* we already found a writeable struct, but there is a
+		 * new one, let's break the loop.
+		 */
+		if (t == state && write_range->struct_name != cur)
+			break;
+
+		/* new struct to look for */
+		if (write_range->struct_name != cur) {
+			type_id = btf_find_by_name_kind(reg->btf, write_range->struct_name,
+							BTF_KIND_STRUCT);
+			if (type_id < 0)
+				return -EINVAL;
+
+			state = btf_type_by_id(reg->btf, type_id);
+		}
+
+		/* this is not the struct we are looking for */
+		if (t != state) {
+			cur = write_range->struct_name;
+			continue;
+		}
+
+		/* first time we see this struct, check for out of bounds */
+		if (cur != write_range->struct_name &&
+		    off + size > write_range->struct_length) {
+			bpf_log(log, "write access for struct %s at off %d with size %d\n",
+				write_range->struct_name, off, size);
+			return -EACCES;
+		}
+
+		/* now check if we are in our boundaries */
+		if (off >= write_range->start && off + size <= write_range->end)
+			return NOT_INIT;
+
+		cur = write_range->struct_name;
 	}
 
-	if (off < offsetof(struct hid_bpf_ctx, retval)) {
+
+	if (t != state)
+		bpf_log(log, "write access to this struct is not supported\n");
+	else
 		bpf_log(log,
-			"write access at off %d with size %d on read-only part of hid_bpf_ctx\n",
-			off, size);
-		return -EACCES;
-	}
+			"write access at off %d with size %d on read-only part of %s\n",
+			off, size, cur);
 
-	return NOT_INIT;
+	return -EACCES;
 }
 
 static const struct bpf_verifier_ops hid_bpf_verifier_ops = {

-- 
2.44.0


^ permalink raw reply related

* [PATCH HID v3 16/16] HID: bpf: make part of struct hid_device writable
From: Benjamin Tissoires @ 2024-06-08  9:01 UTC (permalink / raw)
  To: Shuah Khan, Jiri Kosina, Jonathan Corbet, Alexei Starovoitov
  Cc: linux-kselftest, linux-kernel, bpf, linux-input, linux-doc,
	Benjamin Tissoires
In-Reply-To: <20240608-hid_bpf_struct_ops-v3-0-6ac6ade58329@kernel.org>

It is useful to change the name, the phys and/or the uniq of a
struct hid_device during .rdesc_fixup().

For example, hid-uclogic.ko changes the uniq to store the firmware version
to differentiate between 2 devices sharing the same PID. In the same
way, changing the device name is useful when the device export 3 nodes,
all with the same name.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

---

changes in v3:
- amend for new WRITE_RANGE API

new in v2
---
 drivers/hid/bpf/hid_bpf_struct_ops.c | 3 +++
 include/linux/hid_bpf.h              | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
index b14eccb121e0..e28cca78e1f5 100644
--- a/drivers/hid/bpf/hid_bpf_struct_ops.c
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -74,6 +74,9 @@ static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
 
 	const struct hid_bpf_offset_write_range write_ranges[] = {
 		WRITE_RANGE(hid_bpf_ctx, retval, false),
+		WRITE_RANGE(hid_device, name, true),
+		WRITE_RANGE(hid_device, uniq, true),
+		WRITE_RANGE(hid_device, phys, true),
 	};
 #undef WRITE_RANGE
 	const struct btf_type *state = NULL;
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index 1b4cc1b2c31d..65d7e0acc8c2 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -43,7 +43,7 @@ struct hid_device;
  * ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write.
  */
 struct hid_bpf_ctx {
-	const struct hid_device *hid;
+	struct hid_device *hid;
 	__u32 allocated_size;
 	union {
 		__s32 retval;

-- 
2.44.0


^ permalink raw reply related

* Re: [RFC] HID: ishtp-hid-client: replace fake-flex arrays with flex-array members
From: Erick Archer @ 2024-06-08  9:56 UTC (permalink / raw)
  To: srinivas pandruvada
  Cc: Erick Archer, Jiri Kosina, Benjamin Tissoires, Justin Stitt,
	Kees Cook, Gustavo A. R. Silva, linux-input, linux-kernel,
	linux-hardening
In-Reply-To: <80976997acb82fe3e6ba54fa2708c8f40fb3eb00.camel@linux.intel.com>

Hi Srinivas,
First of all, thanks for looking at this ;)

On Sat, Jun 08, 2024 at 01:42:54AM -0700, srinivas pandruvada wrote:
> On Sun, 2024-05-26 at 15:32 +0200, Erick Archer wrote:
> > One-element arrays as fake flex arrays are deprecated [1] and we are
> > moving towards adopting C99 flexible-array members, instead. This
> > case
> > also has more complexity because it is a flexible array of flexible
> > arrays and this patch needs to be ready to enable the new compiler
> > flag
> > -Wflex-array-member-not-at-end (coming in GCC-14) globally.
> > 
> > So, define a new struct type for the single reports:
> > 
> > struct report {
> > 	uint16_t size;
> > 	struct hostif_msg_hdr msg;
> > } __packed;
> > 
> > but without the payload (flex array) in it. And add this payload to
> > the
> > "hostif_msg" structure. This way, in the "report_list" structure we
> > can
> > declare a flex array of single reports which now do not contain
> > another
> > flex array.
> > 
> > struct report_list {
> > 	[...]
> >         struct report reports[];
> > } __packed;
> > 
> > Also, use "container_of()" whenever we need to retrieve a pointer to
> > the flexible structure, through which we can access the flexible
> > array
> > if needed.
> > 
> > Moreover, refactor the code accordingly to use the new structures and
> > take advantage of this avoiding some pointer arithmetic and using the
> > "struct_size" helper when possible.
> > 
> > This way, the code is more readable and safer.
> 
> Applied and tested, atleast didn't break anything.
> 
> But the explanation above didn't give me enough clue. You have added a
> payload[] in the  struct hostif_msg {} then using that as a message
> pointer following the header. I think this description needs to be
> better.

Yeah, I will try to improve the commit message. What do you think about
the following parragrafs?

[I have copied part of the message to show where the new info will be]
> > declare a flex array of single reports which now do not contain
> > another flex array.
> > 
> > struct report_list {
> > 	[...]
> >         struct report reports[];
> > } __packed;

Therefore, the "struct hostif_msg" is now made up of a header and a
payload. And the "struct report" uses only the "hostif_msg" header.
The perfect solution would be for the "report" structure to use the
whole "hostif_msg" structure but this is not possible due to nested
flexible arrays. Anyway, the end result is equivalent since this patch
does attemp to change the behaviour of the code.

Now as well, we have more clarity after the cast from the raw bytes to
the new structures.

> > 
> > Also, use "container_of()" whenever we need to retrieve a pointer to
> > the flexible structure, through which we can access the flexible
> > array
> > if needed.

I would like to know if it is enough :)

Regards,
Erick
> 
> Thanks,
> Srinivas

^ permalink raw reply

* [PATCH] Input: touchscreen - use sizeof(*pointer) instead of sizeof(type)
From: Erick Archer @ 2024-06-08 14:34 UTC (permalink / raw)
  To: Dmitry Torokhov, Benjamin Gaignard, Hans Verkuil, Ricardo Ribalda,
	Andrzej Pietrasiewicz, Oliver Graute, Uwe Kleine-König,
	ye xingchen, Jason Gerecke, Kees Cook, Gustavo A. R. Silva,
	Justin Stitt
  Cc: Erick Archer, Support Opensource, linux-input, linux-kernel,
	linux-hardening

It is preferred to use sizeof(*pointer) instead of sizeof(type)
due to the type of the variable can change and one needs not
change the former (unlike the latter).

The refactoring is mostly trivial except for "usbtouchscreen.c"
file. Here, in the "mtouch_alloc" and "nexio_alloc" functions,
it is necessary to use a variable with a predefined type instead
of the "usbtouch->priv" variable (void * type). This way, the
"sizeof" operator can now know the correct size. Moreover, we
need to set the "usbtouch->priv" pointer after the memory
allocation since now the "kmalloc" return value is not assigned
directly.

This patch has no effect on runtime behavior.

Signed-off-by: Erick Archer <erick.archer@outlook.com>
---
 drivers/input/touchscreen/da9052_tsi.c       |  2 +-
 drivers/input/touchscreen/dynapro.c          |  2 +-
 drivers/input/touchscreen/egalax_ts_serial.c |  2 +-
 drivers/input/touchscreen/elo.c              |  2 +-
 drivers/input/touchscreen/fujitsu_ts.c       |  2 +-
 drivers/input/touchscreen/gunze.c            |  2 +-
 drivers/input/touchscreen/hampshire.c        |  2 +-
 drivers/input/touchscreen/inexio.c           |  2 +-
 drivers/input/touchscreen/mtouch.c           |  2 +-
 drivers/input/touchscreen/penmount.c         |  2 +-
 drivers/input/touchscreen/sur40.c            |  2 +-
 drivers/input/touchscreen/touchit213.c       |  2 +-
 drivers/input/touchscreen/touchright.c       |  2 +-
 drivers/input/touchscreen/touchwin.c         |  2 +-
 drivers/input/touchscreen/tsc40.c            |  2 +-
 drivers/input/touchscreen/usbtouchscreen.c   | 15 ++++++++-------
 drivers/input/touchscreen/wacom_w8001.c      |  2 +-
 17 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index d71690ce6463..52e0e834e76f 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -232,7 +232,7 @@ static int da9052_ts_probe(struct platform_device *pdev)
 	if (!da9052)
 		return -EINVAL;
 
-	tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL);
+	tsi = kzalloc(sizeof(*tsi), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!tsi || !input_dev) {
 		error = -ENOMEM;
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c
index dc07fca7c5ed..fe626a226b85 100644
--- a/drivers/input/touchscreen/dynapro.c
+++ b/drivers/input/touchscreen/dynapro.c
@@ -110,7 +110,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL);
+	pdynapro = kzalloc(sizeof(*pdynapro), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!pdynapro || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/egalax_ts_serial.c b/drivers/input/touchscreen/egalax_ts_serial.c
index 375922d3a6d1..07a4aa1c19bb 100644
--- a/drivers/input/touchscreen/egalax_ts_serial.c
+++ b/drivers/input/touchscreen/egalax_ts_serial.c
@@ -99,7 +99,7 @@ static int egalax_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int error;
 
-	egalax = kzalloc(sizeof(struct egalax), GFP_KERNEL);
+	egalax = kzalloc(sizeof(*egalax), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!egalax || !input_dev) {
 		error = -ENOMEM;
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 96173232e53f..eb883db55420 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -307,7 +307,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	elo = kzalloc(sizeof(struct elo), GFP_KERNEL);
+	elo = kzalloc(sizeof(*elo), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!elo || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c
index 3b0b8fccc3f0..1a3e14ea2e08 100644
--- a/drivers/input/touchscreen/fujitsu_ts.c
+++ b/drivers/input/touchscreen/fujitsu_ts.c
@@ -99,7 +99,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL);
+	fujitsu = kzalloc(sizeof(*fujitsu), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!fujitsu || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 5a5f9da73fa1..dbf92fb02f80 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -97,7 +97,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL);
+	gunze = kzalloc(sizeof(*gunze), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!gunze || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c
index 5c4d877564ee..dc0a2482ddd6 100644
--- a/drivers/input/touchscreen/hampshire.c
+++ b/drivers/input/touchscreen/hampshire.c
@@ -109,7 +109,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL);
+	phampshire = kzalloc(sizeof(*phampshire), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!phampshire || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c
index 1d7e4c3966ce..82f7ac62a4f2 100644
--- a/drivers/input/touchscreen/inexio.c
+++ b/drivers/input/touchscreen/inexio.c
@@ -114,7 +114,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL);
+	pinexio = kzalloc(sizeof(*pinexio), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!pinexio || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index 28e449eea318..eefae96a2d40 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -128,7 +128,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL);
+	mtouch = kzalloc(sizeof(*mtouch), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!mtouch || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 12abb3b36128..95adede26703 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -199,7 +199,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
 	int max_x, max_y;
 	int err;
 
-	pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
+	pm = kzalloc(sizeof(*pm), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!pm || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
index 5f2cf8881e72..8365a2ac6fce 100644
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -672,7 +672,7 @@ static int sur40_probe(struct usb_interface *interface,
 		return -ENODEV;
 
 	/* Allocate memory for our device state and initialize it. */
-	sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL);
+	sur40 = kzalloc(sizeof(*sur40), GFP_KERNEL);
 	if (!sur40)
 		return -ENOMEM;
 
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c
index fb49687da405..c2718350815c 100644
--- a/drivers/input/touchscreen/touchit213.c
+++ b/drivers/input/touchscreen/touchit213.c
@@ -139,7 +139,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	touchit213 = kzalloc(sizeof(struct touchit213), GFP_KERNEL);
+	touchit213 = kzalloc(sizeof(*touchit213), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!touchit213 || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c
index 3cd58a13e44f..30ba97bd00a1 100644
--- a/drivers/input/touchscreen/touchright.c
+++ b/drivers/input/touchscreen/touchright.c
@@ -102,7 +102,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	tr = kzalloc(sizeof(struct tr), GFP_KERNEL);
+	tr = kzalloc(sizeof(*tr), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!tr || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index bde3c6ee3c60..fbd72789ea80 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -109,7 +109,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err;
 
-	tw = kzalloc(sizeof(struct tw), GFP_KERNEL);
+	tw = kzalloc(sizeof(*tw), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!tw || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c
index 139577021413..9f485cf57a72 100644
--- a/drivers/input/touchscreen/tsc40.c
+++ b/drivers/input/touchscreen/tsc40.c
@@ -83,7 +83,7 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int error;
 
-	ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL);
+	ptsc = kzalloc(sizeof(*ptsc), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!ptsc || !input_dev) {
 		error = -ENOMEM;
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 60354ebc7242..dd6b12c6dc58 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -505,12 +505,14 @@ static int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch)
 
 static int mtouch_alloc(struct usbtouch_usb *usbtouch)
 {
+	struct mtouch_priv *priv;
 	int ret;
 
-	usbtouch->priv = kmalloc(sizeof(struct mtouch_priv), GFP_KERNEL);
-	if (!usbtouch->priv)
+	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 
+	usbtouch->priv = priv;
 	ret = sysfs_create_group(&usbtouch->interface->dev.kobj,
 				 &mtouch_attr_group);
 	if (ret) {
@@ -924,12 +926,11 @@ static int nexio_alloc(struct usbtouch_usb *usbtouch)
 	struct nexio_priv *priv;
 	int ret = -ENOMEM;
 
-	usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL);
-	if (!usbtouch->priv)
+	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		goto out_buf;
 
-	priv = usbtouch->priv;
-
+	usbtouch->priv = priv;
 	priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt),
 				GFP_KERNEL);
 	if (!priv->ack_buf)
@@ -1661,7 +1662,7 @@ static int usbtouch_probe(struct usb_interface *intf,
 	if (!endpoint)
 		return -ENXIO;
 
-	usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
+	usbtouch = kzalloc(sizeof(*usbtouch), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!usbtouch || !input_dev)
 		goto out_free;
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 4ddb6b3baba5..c8abb9557ee8 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -598,7 +598,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 	char basename[64] = "Wacom Serial";
 	int err, err_pen, err_touch;
 
-	w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL);
+	w8001 = kzalloc(sizeof(*w8001), GFP_KERNEL);
 	input_dev_pen = input_allocate_device();
 	input_dev_touch = input_allocate_device();
 	if (!w8001 || !input_dev_pen || !input_dev_touch) {
-- 
2.25.1


^ permalink raw reply related

* [PATCH] Input: joystick - use sizeof(*pointer) instead of sizeof(type)
From: Erick Archer @ 2024-06-08 15:13 UTC (permalink / raw)
  To: Dmitry Torokhov, Linus Walleij, Uwe Kleine-König, Vicki Pfau,
	Brenton Simpson, Max Nguyen, Carl Ng, Matt Scialabba,
	Christophe JAILLET, Kees Cook, Gustavo A. R. Silva, Justin Stitt
  Cc: Erick Archer, linux-input, linux-kernel, linux-hardening

It is preferred to use sizeof(*pointer) instead of sizeof(type)
due to the type of the variable can change and one needs not
change the former (unlike the latter).

At the same time refactor the code to not use assignment in "if"
conditions.

This patch has no effect on runtime behavior.

Signed-off-by: Erick Archer <erick.archer@outlook.com>
---
 drivers/input/joystick/a3d.c          | 2 +-
 drivers/input/joystick/adi.c          | 2 +-
 drivers/input/joystick/analog.c       | 3 ++-
 drivers/input/joystick/as5011.c       | 2 +-
 drivers/input/joystick/cobra.c        | 2 +-
 drivers/input/joystick/db9.c          | 2 +-
 drivers/input/joystick/gamecon.c      | 2 +-
 drivers/input/joystick/gf2k.c         | 2 +-
 drivers/input/joystick/grip.c         | 3 ++-
 drivers/input/joystick/grip_mp.c      | 3 ++-
 drivers/input/joystick/guillemot.c    | 2 +-
 drivers/input/joystick/interact.c     | 2 +-
 drivers/input/joystick/magellan.c     | 2 +-
 drivers/input/joystick/maplecontrol.c | 2 +-
 drivers/input/joystick/n64joy.c       | 2 +-
 drivers/input/joystick/sidewinder.c   | 2 +-
 drivers/input/joystick/spaceball.c    | 2 +-
 drivers/input/joystick/spaceorb.c     | 2 +-
 drivers/input/joystick/stinger.c      | 2 +-
 drivers/input/joystick/tmdc.c         | 3 ++-
 drivers/input/joystick/turbografx.c   | 2 +-
 drivers/input/joystick/twidjoy.c      | 2 +-
 drivers/input/joystick/warrior.c      | 2 +-
 drivers/input/joystick/xpad.c         | 4 ++--
 drivers/input/joystick/zhenhua.c      | 2 +-
 25 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index fd1827baf27c..15182f16ed19 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -249,7 +249,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
 	int i;
 	int err;
 
-	a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL);
+	a3d = kzalloc(sizeof(*a3d), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!a3d || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
index f1a720be458b..963250de24b7 100644
--- a/drivers/input/joystick/adi.c
+++ b/drivers/input/joystick/adi.c
@@ -456,7 +456,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
 	int i;
 	int err;
 
-	port = kzalloc(sizeof(struct adi_port), GFP_KERNEL);
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
 	if (!port)
 		return -ENOMEM;
 
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 0c9e172a9818..c709b58d770a 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -582,7 +582,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv
 	int i;
 	int err;
 
-	if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL)))
+	port = kzalloc(sizeof(*port), GFP_KERNEL);
+	if (!port)
 		return -ENOMEM;
 
 	err = analog_init_port(gameport, drv, port);
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index 407062bcc84b..49a0dfbbeb49 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -237,7 +237,7 @@ static int as5011_probe(struct i2c_client *client)
 		return -ENODEV;
 	}
 
-	as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL);
+	as5011 = kmalloc(sizeof(*as5011), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!as5011 || !input_dev) {
 		dev_err(&client->dev,
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 7ff78c9388bd..5a0ea3ad5efa 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -141,7 +141,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
 	int i, j;
 	int err;
 
-	cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL);
+	cobra = kzalloc(sizeof(*cobra), GFP_KERNEL);
 	if (!cobra)
 		return -ENOMEM;
 
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 4fba28b1a1e7..682a29c27832 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -587,7 +587,7 @@ static void db9_attach(struct parport *pp)
 		return;
 	}
 
-	db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
+	db9 = kzalloc(sizeof(*db9), GFP_KERNEL);
 	if (!db9)
 		goto err_unreg_pardev;
 
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 41d5dac05448..c38de3094553 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -950,7 +950,7 @@ static void gc_attach(struct parport *pp)
 		return;
 	}
 
-	gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
+	gc = kzalloc(sizeof(*gc), GFP_KERNEL);
 	if (!gc) {
 		pr_err("Not enough memory\n");
 		goto err_unreg_pardev;
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index abefbd1484df..e7ff7bdb1a3a 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -222,7 +222,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
 	unsigned char data[GF2K_LENGTH];
 	int i, err;
 
-	gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL);
+	gf2k = kzalloc(sizeof(*gf2k), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!gf2k || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 0e86b269a90e..f339ce2b7a33 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -284,7 +284,8 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
 	int i, j, t;
 	int err;
 
-	if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL)))
+	grip = kzalloc(sizeof(*grip), GFP_KERNEL);
+	if (!grip)
 		return -ENOMEM;
 
 	grip->gameport = gameport;
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 056a89ac2bdf..5eadb5a3ca37 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -632,7 +632,8 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
 	struct grip_mp *grip;
 	int err;
 
-	if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL)))
+	grip = kzalloc(sizeof(*grip), GFP_KERNEL);
+	if (!grip)
 		return -ENOMEM;
 
 	grip->gameport = gameport;
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 205eb6f8b84d..1c5a76f72239 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -163,7 +163,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver *
 	int i, t;
 	int err;
 
-	guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
+	guillemot = kzalloc(sizeof(*guillemot), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!guillemot || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index 03a9f0829f7e..262f022e5695 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -192,7 +192,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d
 	int i, t;
 	int err;
 
-	interact = kzalloc(sizeof(struct interact), GFP_KERNEL);
+	interact = kzalloc(sizeof(*interact), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!interact || !input_dev) {
 		err = -ENOMEM;
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index 017ef8c6170b..2eaa25c9c68c 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -132,7 +132,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv)
 	int err = -ENOMEM;
 	int i;
 
-	magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL);
+	magellan = kzalloc(sizeof(*magellan), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!magellan || !input_dev)
 		goto fail1;
diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
index 3833ac47b2b8..8b54f9b18e7c 100644
--- a/drivers/input/joystick/maplecontrol.c
+++ b/drivers/input/joystick/maplecontrol.c
@@ -102,7 +102,7 @@ static int probe_maple_controller(struct device *dev)
 	struct input_dev *idev;
 	unsigned long data = be32_to_cpu(mdev->devinfo.function_data[0]);
 
-	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
+	pad = kzalloc(sizeof(*pad), GFP_KERNEL);
 	idev = input_allocate_device();
 	if (!pad || !idev) {
 		error = -ENOMEM;
diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c
index 9dbca366613e..b0986d2195d6 100644
--- a/drivers/input/joystick/n64joy.c
+++ b/drivers/input/joystick/n64joy.c
@@ -246,7 +246,7 @@ static int __init n64joy_probe(struct platform_device *pdev)
 	int err = 0;
 	u32 i, j, found = 0;
 
-	priv = kzalloc(sizeof(struct n64joy_priv), GFP_KERNEL);
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 	mutex_init(&priv->n64joy_mutex);
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 7282301c3ae7..f6e92db4d789 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -577,7 +577,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
 
 	comment[0] = 0;
 
-	sw = kzalloc(sizeof(struct sw), GFP_KERNEL);
+	sw = kzalloc(sizeof(*sw), GFP_KERNEL);
 	buf = kmalloc(SW_LENGTH, GFP_KERNEL);
 	idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
 	if (!sw || !buf || !idbuf) {
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index fa8ec533cd69..49101f1c858b 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -199,7 +199,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
 	if ((id = serio->id.id) > SPACEBALL_MAX_ID)
 		return -ENODEV;
 
-	spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
+	spaceball = kmalloc(sizeof(*spaceball), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!spaceball || !input_dev)
 		goto fail1;
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index dbbc69f17c89..7250d74d62a1 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -147,7 +147,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 	int err = -ENOMEM;
 	int i;
 
-	spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL);
+	spaceorb = kzalloc(sizeof(*spaceorb), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!spaceorb || !input_dev)
 		goto fail1;
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 530de468cb61..1b24ea21aa30 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -118,7 +118,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err = -ENOMEM;
 
-	stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL);
+	stinger = kmalloc(sizeof(*stinger), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!stinger || !input_dev)
 		goto fail1;
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 93562ecc0ca1..514b1026e379 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -348,7 +348,8 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
 	int i;
 	int err;
 
-	if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
+	tmdc = kzalloc(sizeof(*tmdc), GFP_KERNEL);
+	if (!tmdc)
 		return -ENOMEM;
 
 	tmdc->gameport = gameport;
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index dfb9c684651f..eb8455c34e67 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -172,7 +172,7 @@ static void tgfx_attach(struct parport *pp)
 		return;
 	}
 
-	tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
+	tgfx = kzalloc(sizeof(*tgfx), GFP_KERNEL);
 	if (!tgfx) {
 		printk(KERN_ERR "turbografx.c: Not enough memory\n");
 		goto err_unreg_pardev;
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 9b6792ac27f1..ab99d76e5d8d 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -171,7 +171,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
 	int err = -ENOMEM;
 	int i;
 
-	twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL);
+	twidjoy = kzalloc(sizeof(*twidjoy), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!twidjoy || !input_dev)
 		goto fail1;
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index f66bddf145c2..ebeab441e9ec 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -124,7 +124,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err = -ENOMEM;
 
-	warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
+	warrior = kzalloc(sizeof(*warrior), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!warrior || !input_dev)
 		goto fail1;
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 70f0654c58b6..40a4ddee0b14 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -1686,7 +1686,7 @@ static int xpad_led_probe(struct usb_xpad *xpad)
 	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W)
 		return 0;
 
-	xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL);
+	xpad->led = led = kzalloc(sizeof(*led), GFP_KERNEL);
 	if (!led)
 		return -ENOMEM;
 
@@ -2022,7 +2022,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
 			break;
 	}
 
-	xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL);
+	xpad = kzalloc(sizeof(*xpad), GFP_KERNEL);
 	if (!xpad)
 		return -ENOMEM;
 
diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c
index 3f2460e2b095..cc0e2a77ac5e 100644
--- a/drivers/input/joystick/zhenhua.c
+++ b/drivers/input/joystick/zhenhua.c
@@ -131,7 +131,7 @@ static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
 	struct input_dev *input_dev;
 	int err = -ENOMEM;
 
-	zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
+	zhenhua = kzalloc(sizeof(*zhenhua), GFP_KERNEL);
 	input_dev = input_allocate_device();
 	if (!zhenhua || !input_dev)
 		goto fail1;
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH] HID: uclogic: avoid linking common code into multiple modules
From: José Expósito @ 2024-06-08 18:28 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Jiri Kosina, Benjamin Tissoires, Arnd Bergmann, Rahul Rameshbabu,
	Fabio Baltieri, Ivan Gorinov, Johannes Roith, linux-input,
	linux-kernel
In-Reply-To: <20240529094816.1859073-1-arnd@kernel.org>

Hi Arnd,

On Wed, May 29, 2024 at 11:48:05AM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> The hid-uclogic-params.o and hid-uclogic-rdesc.o files are linked
> into both the driver module and the unit test, which triggers a
> W=1 warning:
> 
> scripts/Makefile.build:236: drivers/hid/Makefile: hid-uclogic-rdesc.o is added to multiple modules: hid-uclogic hid-uclogic-test
> scripts/Makefile.build:236: drivers/hid/Makefile: hid-uclogic-params.o is added to multiple modules: hid-uclogic hid-uclogic-test
> 
> Avoids this by moving these two files into a separate module
> that is used by the driver and the unit test.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> I have made patches for all such warnings in the tree, this is one I'm not
> sure about, maybe there is a better fix.
> ---
>  drivers/hid/Makefile             | 12 ++----
>  drivers/hid/hid-uclogic-params.c |  8 ++++
>  drivers/hid/hid-uclogic-rdesc.c  | 72 ++++++++++++++++++++++++++++++++
>  3 files changed, 84 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index ce71b53ea6c5..864dfbae8ace 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -133,10 +133,8 @@ obj-$(CONFIG_HID_TOPSEED)	+= hid-topseed.o
>  obj-$(CONFIG_HID_TOPRE)	+= hid-topre.o
>  obj-$(CONFIG_HID_TWINHAN)	+= hid-twinhan.o
>  obj-$(CONFIG_HID_U2FZERO)	+= hid-u2fzero.o
> -hid-uclogic-objs		:= hid-uclogic-core.o \
> -				   hid-uclogic-rdesc.o \
> -				   hid-uclogic-params.o
> -obj-$(CONFIG_HID_UCLOGIC)	+= hid-uclogic.o
> +hid-uclogic-objs		:= hid-uclogic-core.o
> +obj-$(CONFIG_HID_UCLOGIC)	+= hid-uclogic.o hid-uclogic-rdesc.o hid-uclogic-params.o
>  obj-$(CONFIG_HID_UDRAW_PS3)	+= hid-udraw-ps3.o
>  obj-$(CONFIG_HID_LED)		+= hid-led.o
>  obj-$(CONFIG_HID_XIAOMI)	+= hid-xiaomi.o
> @@ -154,10 +152,8 @@ obj-$(CONFIG_HID_WINWING)	+= hid-winwing.o
>  obj-$(CONFIG_HID_SENSOR_HUB)	+= hid-sensor-hub.o
>  obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR)	+= hid-sensor-custom.o
>  
> -hid-uclogic-test-objs		:= hid-uclogic-rdesc.o \
> -				   hid-uclogic-params.o \
> -				   hid-uclogic-rdesc-test.o
> -obj-$(CONFIG_HID_KUNIT_TEST)	+= hid-uclogic-test.o
> +hid-uclogic-test-objs		:= hid-uclogic-rdesc-test.o
> +obj-$(CONFIG_HID_KUNIT_TEST)	+= hid-uclogic-test.o hid-uclogic-params.o hid-uclogic-params.o
>  
>  obj-$(CONFIG_USB_HID)		+= usbhid/
>  obj-$(CONFIG_USB_MOUSE)		+= usbhid/

I tested your patch with:

	hid-uclogic-objs		:= hid-uclogic-core.o \
					   hid-uclogic-rdesc.o \
					   hid-uclogic-params.o
	obj-$(CONFIG_HID_UCLOGIC)	+= hid-uclogic.o
	[...]
	hid-uclogic-test-objs		:= hid-uclogic-rdesc-test.o
	obj-$(CONFIG_HID_KUNIT_TEST)	+= hid-uclogic.o hid-uclogic-test.o

And I think it is a bit more clear and it looks like it does the trick
removing the warning.

Also, with that change only "EXPORT_SYMBOL_GPL(uclogic_rdesc_template_apply);"
is required. The other EXPORT_SYMBOL_GPL can be removed.

However, I'm not sure about what are the best practices using EXPORT_SYMBOL_GPL
and if it should be used for each function/data in the .h file. Maybe that's
why you added them.

Best wishes,
Jose

> diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c
> index 5bab006ec165..97ae7e4f61e1 100644
> --- a/drivers/hid/hid-uclogic-params.c
> +++ b/drivers/hid/hid-uclogic-params.c
> @@ -133,6 +133,7 @@ void uclogic_params_hid_dbg(const struct hid_device *hdev,
>  	}
>  	hid_dbg(hdev, "}\n");
>  }
> +EXPORT_SYMBOL_GPL(uclogic_params_hid_dbg);
>  
>  /**
>   * uclogic_params_get_str_desc - retrieve a string descriptor from a HID
> @@ -660,6 +661,7 @@ void uclogic_params_cleanup(struct uclogic_params *params)
>  		memset(params, 0, sizeof(*params));
>  	}
>  }
> +EXPORT_SYMBOL_GPL(uclogic_params_cleanup);
>  
>  /**
>   * uclogic_params_get_desc() - Get a replacement report descriptor for a
> @@ -732,6 +734,7 @@ int uclogic_params_get_desc(const struct uclogic_params *params,
>  	kfree(desc);
>  	return rc;
>  }
> +EXPORT_SYMBOL_GPL(uclogic_params_get_desc);
>  
>  /**
>   * uclogic_params_init_invalid() - initialize tablet interface parameters,
> @@ -1859,7 +1862,12 @@ int uclogic_params_init(struct uclogic_params *params,
>  	uclogic_params_cleanup(&p);
>  	return rc;
>  }
> +EXPORT_SYMBOL_GPL(uclogic_params_init);
>  
>  #ifdef CONFIG_HID_KUNIT_TEST
>  #include "hid-uclogic-params-test.c"
>  #endif
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Nikolai Kondrashov");
> +MODULE_DESCRIPTION("HID driver for UC-Logic devices tablet initialization and parameter retrieval");
> diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c
> index b6dfdf6356a6..d4f1ee79e0a1 100644
> --- a/drivers/hid/hid-uclogic-rdesc.c
> +++ b/drivers/hid/hid-uclogic-rdesc.c
> @@ -59,9 +59,11 @@ __u8 uclogic_rdesc_wp4030u_fixed_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp4030u_fixed_arr);
>  
>  const size_t uclogic_rdesc_wp4030u_fixed_size =
>  			sizeof(uclogic_rdesc_wp4030u_fixed_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp4030u_fixed_size);
>  
>  /* Fixed WP5540U report descriptor */
>  __u8 uclogic_rdesc_wp5540u_fixed_arr[] = {
> @@ -136,9 +138,11 @@ __u8 uclogic_rdesc_wp5540u_fixed_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp5540u_fixed_arr);
>  
>  const size_t uclogic_rdesc_wp5540u_fixed_size =
>  			sizeof(uclogic_rdesc_wp5540u_fixed_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp5540u_fixed_size);
>  
>  /* Fixed WP8060U report descriptor */
>  __u8 uclogic_rdesc_wp8060u_fixed_arr[] = {
> @@ -213,9 +217,11 @@ __u8 uclogic_rdesc_wp8060u_fixed_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp8060u_fixed_arr);
>  
>  const size_t uclogic_rdesc_wp8060u_fixed_size =
>  			sizeof(uclogic_rdesc_wp8060u_fixed_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp8060u_fixed_size);
>  
>  /* Fixed WP1062 report descriptor */
>  __u8 uclogic_rdesc_wp1062_fixed_arr[] = {
> @@ -261,9 +267,11 @@ __u8 uclogic_rdesc_wp1062_fixed_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp1062_fixed_arr);
>  
>  const size_t uclogic_rdesc_wp1062_fixed_size =
>  			sizeof(uclogic_rdesc_wp1062_fixed_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_wp1062_fixed_size);
>  
>  /* Fixed PF1209 report descriptor */
>  __u8 uclogic_rdesc_pf1209_fixed_arr[] = {
> @@ -338,9 +346,11 @@ __u8 uclogic_rdesc_pf1209_fixed_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_pf1209_fixed_arr);
>  
>  const size_t uclogic_rdesc_pf1209_fixed_size =
>  			sizeof(uclogic_rdesc_pf1209_fixed_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_pf1209_fixed_size);
>  
>  /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
>  __u8 uclogic_rdesc_twhl850_fixed0_arr[] = {
> @@ -384,9 +394,11 @@ __u8 uclogic_rdesc_twhl850_fixed0_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twhl850_fixed0_arr);
>  
>  const size_t uclogic_rdesc_twhl850_fixed0_size =
>  			sizeof(uclogic_rdesc_twhl850_fixed0_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twhl850_fixed0_size);
>  
>  /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
>  __u8 uclogic_rdesc_twhl850_fixed1_arr[] = {
> @@ -424,9 +436,11 @@ __u8 uclogic_rdesc_twhl850_fixed1_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twhl850_fixed1_arr);
>  
>  const size_t uclogic_rdesc_twhl850_fixed1_size =
>  			sizeof(uclogic_rdesc_twhl850_fixed1_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twhl850_fixed1_size);
>  
>  /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
>  __u8 uclogic_rdesc_twhl850_fixed2_arr[] = {
> @@ -450,9 +464,11 @@ __u8 uclogic_rdesc_twhl850_fixed2_arr[] = {
>  	0x80,               /*      Input,                          */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twhl850_fixed2_arr);
>  
>  const size_t uclogic_rdesc_twhl850_fixed2_size =
>  			sizeof(uclogic_rdesc_twhl850_fixed2_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twhl850_fixed2_size);
>  
>  /* Fixed TWHA60 report descriptor, interface 0 (stylus) */
>  __u8 uclogic_rdesc_twha60_fixed0_arr[] = {
> @@ -499,9 +515,11 @@ __u8 uclogic_rdesc_twha60_fixed0_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twha60_fixed0_arr);
>  
>  const size_t uclogic_rdesc_twha60_fixed0_size =
>  			sizeof(uclogic_rdesc_twha60_fixed0_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twha60_fixed0_size);
>  
>  /* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */
>  __u8 uclogic_rdesc_twha60_fixed1_arr[] = {
> @@ -527,9 +545,11 @@ __u8 uclogic_rdesc_twha60_fixed1_arr[] = {
>  	0x81, 0x01, /*      Input (Constant),       */
>  	0xC0        /*  End Collection              */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twha60_fixed1_arr);
>  
>  const size_t uclogic_rdesc_twha60_fixed1_size =
>  			sizeof(uclogic_rdesc_twha60_fixed1_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_twha60_fixed1_size);
>  
>  /* Fixed report descriptor template for (tweaked) v1 pen reports */
>  const __u8 uclogic_rdesc_v1_pen_template_arr[] = {
> @@ -581,9 +601,11 @@ const __u8 uclogic_rdesc_v1_pen_template_arr[] = {
>  	0xC0,                   /*      End Collection,                     */
>  	0xC0                    /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v1_pen_template_arr);
>  
>  const size_t uclogic_rdesc_v1_pen_template_size =
>  			sizeof(uclogic_rdesc_v1_pen_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v1_pen_template_size);
>  
>  /* Fixed report descriptor template for (tweaked) v2 pen reports */
>  const __u8 uclogic_rdesc_v2_pen_template_arr[] = {
> @@ -647,9 +669,11 @@ const __u8 uclogic_rdesc_v2_pen_template_arr[] = {
>  	0xC0,                   /*      End Collection,                     */
>  	0xC0                    /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_pen_template_arr);
>  
>  const size_t uclogic_rdesc_v2_pen_template_size =
>  			sizeof(uclogic_rdesc_v2_pen_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_pen_template_size);
>  
>  /*
>   * Expand to the contents of a generic frame buttons report descriptor.
> @@ -702,16 +726,22 @@ const size_t uclogic_rdesc_v2_pen_template_size =
>  const __u8 uclogic_rdesc_v1_frame_arr[] = {
>  	UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(UCLOGIC_RDESC_V1_FRAME_ID, 8)
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v1_frame_arr);
> +
>  const size_t uclogic_rdesc_v1_frame_size =
>  			sizeof(uclogic_rdesc_v1_frame_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v1_frame_size);
>  
>  /* Fixed report descriptor for (tweaked) v2 frame button reports */
>  const __u8 uclogic_rdesc_v2_frame_buttons_arr[] = {
>  	UCLOGIC_RDESC_FRAME_BUTTONS_BYTES(UCLOGIC_RDESC_V2_FRAME_BUTTONS_ID,
>  					  12)
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_buttons_arr);
> +
>  const size_t uclogic_rdesc_v2_frame_buttons_size =
>  			sizeof(uclogic_rdesc_v2_frame_buttons_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_buttons_size);
>  
>  /* Fixed report descriptor for (tweaked) v2 frame touch ring reports */
>  const __u8 uclogic_rdesc_v2_frame_touch_ring_arr[] = {
> @@ -758,8 +788,11 @@ const __u8 uclogic_rdesc_v2_frame_touch_ring_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_touch_ring_arr);
> +
>  const size_t uclogic_rdesc_v2_frame_touch_ring_size =
>  			sizeof(uclogic_rdesc_v2_frame_touch_ring_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_touch_ring_size);
>  
>  /* Fixed report descriptor for (tweaked) v2 frame touch strip reports */
>  const __u8 uclogic_rdesc_v2_frame_touch_strip_arr[] = {
> @@ -806,8 +839,11 @@ const __u8 uclogic_rdesc_v2_frame_touch_strip_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_touch_strip_arr);
> +
>  const size_t uclogic_rdesc_v2_frame_touch_strip_size =
>  			sizeof(uclogic_rdesc_v2_frame_touch_strip_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_touch_strip_size);
>  
>  /* Fixed report descriptor for (tweaked) v2 frame dial reports */
>  const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
> @@ -856,14 +892,22 @@ const __u8 uclogic_rdesc_v2_frame_dial_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_dial_arr);
> +
>  const size_t uclogic_rdesc_v2_frame_dial_size =
>  			sizeof(uclogic_rdesc_v2_frame_dial_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_v2_frame_dial_size);
>  
>  const __u8 uclogic_ugee_v2_probe_arr[] = {
>  	0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
>  };
> +EXPORT_SYMBOL_GPL(uclogic_ugee_v2_probe_arr);
> +
>  const size_t uclogic_ugee_v2_probe_size = sizeof(uclogic_ugee_v2_probe_arr);
> +EXPORT_SYMBOL_GPL(uclogic_ugee_v2_probe_size);
> +
>  const int uclogic_ugee_v2_probe_endpoint = 0x03;
> +EXPORT_SYMBOL_GPL(uclogic_ugee_v2_probe_endpoint);
>  
>  /* Fixed report descriptor template for UGEE v2 pen reports */
>  const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[] = {
> @@ -935,8 +979,11 @@ const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[] = {
>  	0xc0,               /*      End Collection,                     */
>  	0xc0,               /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_pen_template_arr);
> +
>  const size_t uclogic_rdesc_ugee_v2_pen_template_size =
>  			sizeof(uclogic_rdesc_ugee_v2_pen_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_pen_template_size);
>  
>  /* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */
>  const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = {
> @@ -964,8 +1011,11 @@ const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = {
>  	0xC0,               /*      End Collection,                     */
>  	0xC0                /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_frame_btn_template_arr);
> +
>  const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size =
>  			sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_frame_btn_template_size);
>  
>  /* Fixed report descriptor template for UGEE v2 frame reports (dial) */
>  const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[] = {
> @@ -1004,8 +1054,11 @@ const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[] = {
>  	0xC0,               /*      End Collection,                     */
>  	0xC0                /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_frame_dial_template_arr);
> +
>  const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size =
>  			sizeof(uclogic_rdesc_ugee_v2_frame_dial_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_frame_dial_template_size);
>  
>  /* Fixed report descriptor template for UGEE v2 frame reports (mouse) */
>  const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = {
> @@ -1038,8 +1091,11 @@ const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = {
>  	0xC0,               /*      End Collection,                     */
>  	0xC0                /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_frame_mouse_template_arr);
> +
>  const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size =
>  			sizeof(uclogic_rdesc_ugee_v2_frame_mouse_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_frame_mouse_template_size);
>  
>  /* Fixed report descriptor template for UGEE v2 battery reports */
>  const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[] = {
> @@ -1072,8 +1128,11 @@ const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[] = {
>  	0x81, 0x01,         /*      Input (Constant),                   */
>  	0xC0                /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_battery_template_arr);
> +
>  const size_t uclogic_rdesc_ugee_v2_battery_template_size =
>  			sizeof(uclogic_rdesc_ugee_v2_battery_template_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_v2_battery_template_size);
>  
>  /* Fixed report descriptor for Ugee EX07 frame */
>  const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
> @@ -1099,8 +1158,11 @@ const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
>  	0xC0,                   /*      End Collection,                     */
>  	0xC0                    /*  End Collection                          */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_ex07_frame_arr);
> +
>  const size_t uclogic_rdesc_ugee_ex07_frame_size =
>  			sizeof(uclogic_rdesc_ugee_ex07_frame_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_ex07_frame_size);
>  
>  /* Fixed report descriptor for Ugee G5 frame controls */
>  const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
> @@ -1153,8 +1215,10 @@ const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
>  	0xC0,               /*      End Collection,                 */
>  	0xC0                /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_g5_frame_arr);
>  const size_t uclogic_rdesc_ugee_g5_frame_size =
>  			sizeof(uclogic_rdesc_ugee_g5_frame_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_ugee_g5_frame_size);
>  
>  /* Fixed report descriptor for XP-Pen Deco 01 frame controls */
>  const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
> @@ -1187,9 +1251,11 @@ const __u8 uclogic_rdesc_xppen_deco01_frame_arr[] = {
>  	0xC0,       /*      End Collection,                 */
>  	0xC0        /*  End Collection                      */
>  };
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_xppen_deco01_frame_arr);
>  
>  const size_t uclogic_rdesc_xppen_deco01_frame_size =
>  			sizeof(uclogic_rdesc_xppen_deco01_frame_arr);
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_xppen_deco01_frame_size);
>  
>  /**
>   * uclogic_rdesc_template_apply() - apply report descriptor parameters to a
> @@ -1242,3 +1308,9 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr,
>  
>  	return rdesc_ptr;
>  }
> +EXPORT_SYMBOL_GPL(uclogic_rdesc_template_apply);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Martin Rusko");
> +MODULE_AUTHOR("Nikolai Kondrashov");
> +MODULE_DESCRIPTION("HID driver for UC-Logic devices original and fixed report descriptors");
> -- 
> 2.39.2
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox