All of lore.kernel.org
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: [PATCH bpf-next] bpf/bpftool: add unprivileged_bpf_disabled check against value of 2
  2022-03-22 15:54  6% ` Quentin Monnet
@ 2022-03-22 17:39  0%   ` KP Singh
  0 siblings, 0 replies; 77+ results
From: KP Singh @ 2022-03-22 17:39 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Milan Landaverde, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin KaFai Lau, Song Liu, Yonghong Song,
	John Fastabend, Paul Chaignon, Niklas Söderlund, netdev,
	bpf, linux-kernel

On Tue, Mar 22, 2022 at 4:54 PM Quentin Monnet <quentin@isovalent.com> wrote:
>
> 2022-03-22 10:49 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > In [1], we added a kconfig knob that can set
> > /proc/sys/kernel/unprivileged_bpf_disabled to 2
> >
> > We now check against this value in bpftool feature probe
> >
> > [1] https://lore.kernel.org/bpf/74ec548079189e4e4dffaeb42b8987bb3c852eee.1620765074.git.daniel@iogearbox.net
> >
> > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
>
> Acked-by: Quentin Monnet <quentin@isovalent.com>

Acked-by: KP Singh <kpsingh@kernel.org>

Thanks, this is very useful!

^ permalink raw reply	[relevance 0%]

* Re: [PATCH bpf-next 1/3] bpf/bpftool: add syscall prog type
  2022-04-01 16:04  6%   ` Quentin Monnet
@ 2022-04-01 18:40  0%     ` Andrii Nakryiko
  2022-04-01 21:20  0%       ` Quentin Monnet
  0 siblings, 1 reply; 77+ results
From: Andrii Nakryiko @ 2022-04-01 18:40 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Milan Landaverde, bpf, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin Lau, Song Liu, Yonghong Song,
	john fastabend, KP Singh, Dave Marchevsky, Stanislav Fomichev,
	Networking, open list

On Fri, Apr 1, 2022 at 9:04 AM Quentin Monnet <quentin@isovalent.com> wrote:
>
> 2022-03-31 11:45 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > In addition to displaying the program type in bpftool prog show
> > this enables us to be able to query bpf_prog_type_syscall
> > availability through feature probe as well as see
> > which helpers are available in those programs (such as
> > bpf_sys_bpf and bpf_sys_close)
> >
> > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> > ---
> >  tools/bpf/bpftool/prog.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
> > index bc4e05542c2b..8643b37d4e43 100644
> > --- a/tools/bpf/bpftool/prog.c
> > +++ b/tools/bpf/bpftool/prog.c
> > @@ -68,6 +68,7 @@ const char * const prog_type_name[] = {
> >       [BPF_PROG_TYPE_EXT]                     = "ext",
> >       [BPF_PROG_TYPE_LSM]                     = "lsm",
> >       [BPF_PROG_TYPE_SK_LOOKUP]               = "sk_lookup",
> > +     [BPF_PROG_TYPE_SYSCALL]                 = "syscall",
> >  };
> >
> >  const size_t prog_type_name_size = ARRAY_SIZE(prog_type_name);
>
> Reviewed-by: Quentin Monnet <quentin@isovalent.com>
>
> Thanks! This one should have been caught by CI :/. Instead it complains
> when you add it. This is because BPF_PROG_TYPE_SYSCALL in the UAPI
> header has a comment next to it, and the regex used in
> tools/testing/selftests/bpf/test_bpftool_synctypes.py to extract the
> program types does not account for it. The fix should be:
>
> ------
> diff --git a/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> b/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> index 6bf21e47882a..cd239cbfd80c 100755
> --- a/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> +++ b/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> @@ -180,7 +180,7 @@ class FileExtractor(object):
>          @enum_name: name of the enum to parse
>          """
>          start_marker = re.compile(f'enum {enum_name} {{\n')
> -        pattern = re.compile('^\s*(BPF_\w+),?$')
> +        pattern = re.compile('^\s*(BPF_\w+),?( /\* .* \*/)?$')

small nit: do you need those spaces inside /* and */? why make
unnecessary assumptions about proper formatting? ;)

>          end_marker = re.compile('^};')
>          parser = BlockParser(self.reader)
>          parser.search_block(start_marker)
> ------
>
> I can submit this separately as a patch.
>
> Quentin

^ permalink raw reply	[relevance 0%]

* Re: [PATCH bpf-next 3/3] bpf/bpftool: handle libbpf_probe_prog_type errors
  2022-04-01 16:05  6%   ` Quentin Monnet
@ 2022-04-01 18:42  0%     ` Andrii Nakryiko
  2022-04-01 21:33  0%       ` Quentin Monnet
  0 siblings, 1 reply; 77+ results
From: Andrii Nakryiko @ 2022-04-01 18:42 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Milan Landaverde, bpf, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin Lau, Song Liu, Yonghong Song,
	john fastabend, KP Singh, Dave Marchevsky, Stanislav Fomichev,
	Networking, open list

On Fri, Apr 1, 2022 at 9:05 AM Quentin Monnet <quentin@isovalent.com> wrote:
>
> 2022-03-31 11:45 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > Previously [1], we were using bpf_probe_prog_type which returned a
> > bool, but the new libbpf_probe_bpf_prog_type can return a negative
> > error code on failure. This change decides for bpftool to declare
> > a program type is not available on probe failure.
> >
> > [1] https://lore.kernel.org/bpf/20220202225916.3313522-3-andrii@kernel.org/
> >
> > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> > ---
> >  tools/bpf/bpftool/feature.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
> > index c2f43a5d38e0..b2fbaa7a6b15 100644
> > --- a/tools/bpf/bpftool/feature.c
> > +++ b/tools/bpf/bpftool/feature.c
> > @@ -564,7 +564,7 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
> >
> >               res = probe_prog_type_ifindex(prog_type, ifindex);
> >       } else {
> > -             res = libbpf_probe_bpf_prog_type(prog_type, NULL);
> > +             res = libbpf_probe_bpf_prog_type(prog_type, NULL) > 0;
> >       }
> >
> >  #ifdef USE_LIBCAP
>

A completely unrelated question to you, Quentin. How hard is bpftool's
dependency on libcap? We've recently removed libcap from selftests, I
wonder if it would be possible to do that for bpftool as well to
reduce amount of shared libraries bpftool depends on.

> Reviewed-by: Quentin Monnet <quentin@isovalent.com>
>
> Thanks!

^ permalink raw reply	[relevance 0%]

* Re: [PATCH bpf-next 1/3] bpf/bpftool: add syscall prog type
  2022-04-01 18:40  0%     ` Andrii Nakryiko
@ 2022-04-01 21:20  0%       ` Quentin Monnet
  0 siblings, 0 replies; 77+ results
From: Quentin Monnet @ 2022-04-01 21:20 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Milan Landaverde, bpf, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin Lau, Song Liu, Yonghong Song,
	john fastabend, KP Singh, Dave Marchevsky, Stanislav Fomichev,
	Networking, open list

On Fri, 1 Apr 2022 at 19:40, Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>
> On Fri, Apr 1, 2022 at 9:04 AM Quentin Monnet <quentin@isovalent.com> wrote:
> >
> > 2022-03-31 11:45 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > > In addition to displaying the program type in bpftool prog show
> > > this enables us to be able to query bpf_prog_type_syscall
> > > availability through feature probe as well as see
> > > which helpers are available in those programs (such as
> > > bpf_sys_bpf and bpf_sys_close)
> > >
> > > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> > > ---
> > >  tools/bpf/bpftool/prog.c | 1 +
> > >  1 file changed, 1 insertion(+)
> > >
> > > diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
> > > index bc4e05542c2b..8643b37d4e43 100644
> > > --- a/tools/bpf/bpftool/prog.c
> > > +++ b/tools/bpf/bpftool/prog.c
> > > @@ -68,6 +68,7 @@ const char * const prog_type_name[] = {
> > >       [BPF_PROG_TYPE_EXT]                     = "ext",
> > >       [BPF_PROG_TYPE_LSM]                     = "lsm",
> > >       [BPF_PROG_TYPE_SK_LOOKUP]               = "sk_lookup",
> > > +     [BPF_PROG_TYPE_SYSCALL]                 = "syscall",
> > >  };
> > >
> > >  const size_t prog_type_name_size = ARRAY_SIZE(prog_type_name);
> >
> > Reviewed-by: Quentin Monnet <quentin@isovalent.com>
> >
> > Thanks! This one should have been caught by CI :/. Instead it complains
> > when you add it. This is because BPF_PROG_TYPE_SYSCALL in the UAPI
> > header has a comment next to it, and the regex used in
> > tools/testing/selftests/bpf/test_bpftool_synctypes.py to extract the
> > program types does not account for it. The fix should be:
> >
> > ------
> > diff --git a/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> > b/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> > index 6bf21e47882a..cd239cbfd80c 100755
> > --- a/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> > +++ b/tools/testing/selftests/bpf/test_bpftool_synctypes.py
> > @@ -180,7 +180,7 @@ class FileExtractor(object):
> >          @enum_name: name of the enum to parse
> >          """
> >          start_marker = re.compile(f'enum {enum_name} {{\n')
> > -        pattern = re.compile('^\s*(BPF_\w+),?$')
> > +        pattern = re.compile('^\s*(BPF_\w+),?( /\* .* \*/)?$')
>
> small nit: do you need those spaces inside /* and */? why make
> unnecessary assumptions about proper formatting? ;)

No I don't need the spaces, I'll remove them indeed, thanks. I'll send
the patch next week.

^ permalink raw reply	[relevance 0%]

* Re: [PATCH bpf-next 3/3] bpf/bpftool: handle libbpf_probe_prog_type errors
  2022-04-01 18:42  0%     ` Andrii Nakryiko
@ 2022-04-01 21:33  0%       ` Quentin Monnet
  2022-04-03 23:51  0%         ` Andrii Nakryiko
  0 siblings, 1 reply; 77+ results
From: Quentin Monnet @ 2022-04-01 21:33 UTC (permalink / raw)
  To: Andrii Nakryiko
  Cc: Milan Landaverde, bpf, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin Lau, Song Liu, Yonghong Song,
	john fastabend, KP Singh, Dave Marchevsky, Stanislav Fomichev,
	Networking, open list

On Fri, 1 Apr 2022 at 19:42, Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>
> On Fri, Apr 1, 2022 at 9:05 AM Quentin Monnet <quentin@isovalent.com> wrote:
> >
> > 2022-03-31 11:45 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > > Previously [1], we were using bpf_probe_prog_type which returned a
> > > bool, but the new libbpf_probe_bpf_prog_type can return a negative
> > > error code on failure. This change decides for bpftool to declare
> > > a program type is not available on probe failure.
> > >
> > > [1] https://lore.kernel.org/bpf/20220202225916.3313522-3-andrii@kernel.org/
> > >
> > > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> > > ---
> > >  tools/bpf/bpftool/feature.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
> > > index c2f43a5d38e0..b2fbaa7a6b15 100644
> > > --- a/tools/bpf/bpftool/feature.c
> > > +++ b/tools/bpf/bpftool/feature.c
> > > @@ -564,7 +564,7 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
> > >
> > >               res = probe_prog_type_ifindex(prog_type, ifindex);
> > >       } else {
> > > -             res = libbpf_probe_bpf_prog_type(prog_type, NULL);
> > > +             res = libbpf_probe_bpf_prog_type(prog_type, NULL) > 0;
> > >       }
> > >
> > >  #ifdef USE_LIBCAP
> >
>
> A completely unrelated question to you, Quentin. How hard is bpftool's
> dependency on libcap? We've recently removed libcap from selftests, I
> wonder if it would be possible to do that for bpftool as well to
> reduce amount of shared libraries bpftool depends on.

There's not a super-strong dependency on it. It's used in feature
probing, for two things.

First one is to be accurate when we check that the user has the right
capabilities for probing efficiently the system. A workaround consists
in checking that we run with uid=0 (root), although it's less
accurate.

Second thing is probing as an unprivileged user: if bpftool is run to
probe as root but with the "unprivileged" keyword, libcap is used to
drop the CAP_SYS_ADMIN and run the probes without it. I don't know if
there's an easy alternative to libcap for that. Also I don't know how
many people use this feature, but I remember that this was added
because there was some demand at the time, so presumably there are
users relying on this.

This being said, libcap is optional for compiling bpftool, so you
should be able to have it work just as well if the library is not
available on the system? Basically you'd just lose the ability to
probe as an unprivileged user. Do you need to remove the optional
dependency completely?

Quentin

PS: Not directly related but since we're talking of libcap, we
recently discovered that the lib is apparently changing errno when it
maybe shouldn't and plays badly with batch mode:
https://stackoverflow.com/questions/71608181/bpf-xdp-bpftool-batch-file-returns-error-reading-batch-file-failed-opera

^ permalink raw reply	[relevance 0%]

* Re: [PATCH bpf-next 3/3] bpf/bpftool: handle libbpf_probe_prog_type errors
  2022-04-01 21:33  0%       ` Quentin Monnet
@ 2022-04-03 23:51  0%         ` Andrii Nakryiko
  0 siblings, 0 replies; 77+ results
From: Andrii Nakryiko @ 2022-04-03 23:51 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Milan Landaverde, bpf, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin Lau, Song Liu, Yonghong Song,
	john fastabend, KP Singh, Dave Marchevsky, Stanislav Fomichev,
	Networking, open list

On Fri, Apr 1, 2022 at 2:33 PM Quentin Monnet <quentin@isovalent.com> wrote:
>
> On Fri, 1 Apr 2022 at 19:42, Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
> >
> > On Fri, Apr 1, 2022 at 9:05 AM Quentin Monnet <quentin@isovalent.com> wrote:
> > >
> > > 2022-03-31 11:45 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > > > Previously [1], we were using bpf_probe_prog_type which returned a
> > > > bool, but the new libbpf_probe_bpf_prog_type can return a negative
> > > > error code on failure. This change decides for bpftool to declare
> > > > a program type is not available on probe failure.
> > > >
> > > > [1] https://lore.kernel.org/bpf/20220202225916.3313522-3-andrii@kernel.org/
> > > >
> > > > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> > > > ---
> > > >  tools/bpf/bpftool/feature.c | 2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
> > > > index c2f43a5d38e0..b2fbaa7a6b15 100644
> > > > --- a/tools/bpf/bpftool/feature.c
> > > > +++ b/tools/bpf/bpftool/feature.c
> > > > @@ -564,7 +564,7 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
> > > >
> > > >               res = probe_prog_type_ifindex(prog_type, ifindex);
> > > >       } else {
> > > > -             res = libbpf_probe_bpf_prog_type(prog_type, NULL);
> > > > +             res = libbpf_probe_bpf_prog_type(prog_type, NULL) > 0;
> > > >       }
> > > >
> > > >  #ifdef USE_LIBCAP
> > >
> >
> > A completely unrelated question to you, Quentin. How hard is bpftool's
> > dependency on libcap? We've recently removed libcap from selftests, I
> > wonder if it would be possible to do that for bpftool as well to
> > reduce amount of shared libraries bpftool depends on.
>
> There's not a super-strong dependency on it. It's used in feature
> probing, for two things.
>
> First one is to be accurate when we check that the user has the right
> capabilities for probing efficiently the system. A workaround consists
> in checking that we run with uid=0 (root), although it's less
> accurate.
>
> Second thing is probing as an unprivileged user: if bpftool is run to
> probe as root but with the "unprivileged" keyword, libcap is used to
> drop the CAP_SYS_ADMIN and run the probes without it. I don't know if
> there's an easy alternative to libcap for that. Also I don't know how
> many people use this feature, but I remember that this was added
> because there was some demand at the time, so presumably there are
> users relying on this.
>
> This being said, libcap is optional for compiling bpftool, so you
> should be able to have it work just as well if the library is not
> available on the system? Basically you'd just lose the ability to
> probe as an unprivileged user. Do you need to remove the optional
> dependency completely?

Well, see recent patches from Martin:

82cb2b30773e bpf: selftests: Remove libcap usage from test_progs
b1c2768a82b9 bpf: selftests: Remove libcap usage from test_verifier
663af70aabb7 bpf: selftests: Add helpers to directly use the capget
and capset syscall

We completely got rid of libcap dependency and ended up with more
straightforward code. So I was wondering if this is possible for
bpftool. The less unnecessary library dependencies - the better. The
less feature detection -- the better. That's my only line of thought
here :)

>
> Quentin
>
> PS: Not directly related but since we're talking of libcap, we
> recently discovered that the lib is apparently changing errno when it
> maybe shouldn't and plays badly with batch mode:
> https://stackoverflow.com/questions/71608181/bpf-xdp-bpftool-batch-file-returns-error-reading-batch-file-failed-opera

just another argument in favor of getting rid of extra layers of dependencies

^ permalink raw reply	[relevance 0%]

* Re: [PATCH bpf-next 2/3] bpf/bpftool: add missing link types
  2022-04-01 16:05  6%   ` Quentin Monnet
@ 2022-04-04 21:55  0%     ` Andrii Nakryiko
  0 siblings, 0 replies; 77+ results
From: Andrii Nakryiko @ 2022-04-04 21:55 UTC (permalink / raw)
  To: Quentin Monnet
  Cc: Milan Landaverde, bpf, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin Lau, Song Liu, Yonghong Song,
	john fastabend, KP Singh, Dave Marchevsky, Stanislav Fomichev,
	Networking, open list

On Fri, Apr 1, 2022 at 9:05 AM Quentin Monnet <quentin@isovalent.com> wrote:
>
> 2022-03-31 11:45 UTC-0400 ~ Milan Landaverde <milan@mdaverde.com>
> > Will display the link type names in bpftool link show output
> >
> > Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> > ---
> >  tools/bpf/bpftool/link.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
> > index 97dec81950e5..9392ef390828 100644
> > --- a/tools/bpf/bpftool/link.c
> > +++ b/tools/bpf/bpftool/link.c
> > @@ -20,6 +20,8 @@ static const char * const link_type_name[] = {
> >       [BPF_LINK_TYPE_CGROUP]                  = "cgroup",
> >       [BPF_LINK_TYPE_ITER]                    = "iter",
> >       [BPF_LINK_TYPE_NETNS]                   = "netns",
> > +     [BPF_LINK_TYPE_XDP]                             = "xdp",

fixed indentation here and added KPROBE_MULTI while applying

> > +     [BPF_LINK_TYPE_PERF_EVENT]              = "perf_event",
>
> Since this goes into bpf-next, we should add BPF_LINK_TYPE_KPROBE_MULTI
> as well.
>
> Quentin

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v8 17/31] rust: add `kernel` crate
  2022-08-02  1:50  1% ` [PATCH v8 17/31] rust: add `kernel` crate Miguel Ojeda
@ 2022-08-02 13:34  0%   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 77+ results
From: Greg Kroah-Hartman @ 2022-08-02 13:34 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Linus Torvalds, rust-for-linux, linux-kernel, Jarkko Sakkinen,
	Wedson Almeida Filho, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Michael Ellerman, Sumera Priyadarsini,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Boqun Feng,
	Fox Chen, Dan Robertson, Viktor Garske, Dariusz Sosnowski,
	Léo Lanteri Thauvin, Niklas Mohrin, Gioh Kim, Daniel Xu,
	Milan Landaverde, Morgan Bartlett, Maciej Falkowski,
	Jiapeng Chong, Nándor István Krácser, David Gow,
	John Baublitz, Björn Roy Baron

On Tue, Aug 02, 2022 at 03:50:04AM +0200, Miguel Ojeda wrote:
> From: Wedson Almeida Filho <wedsonaf@google.com>
> 
> The `kernel` crate currently includes all the abstractions that wrap
> kernel features written in C.
> 
> These abstractions call the C side of the kernel via the generated
> bindings with the `bindgen` tool. Modules developed in Rust should
> never call the bindings themselves.
> 
> In the future, as the abstractions grow in number, we may need
> to split this crate into several, possibly following a similar
> subdivision in subsystems as the kernel itself and/or moving
> the code to the actual subsystems.
> 
> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
> Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
> Co-developed-by: Finn Behrens <me@kloenk.de>
> Signed-off-by: Finn Behrens <me@kloenk.de>
> Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
> Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
> Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
> Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
> Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
> Co-developed-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
> Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
> Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> Co-developed-by: Fox Chen <foxhlchen@gmail.com>
> Signed-off-by: Fox Chen <foxhlchen@gmail.com>
> Co-developed-by: Dan Robertson <daniel.robertson@starlab.io>
> Signed-off-by: Dan Robertson <daniel.robertson@starlab.io>
> Co-developed-by: Viktor Garske <viktor@v-gar.de>
> Signed-off-by: Viktor Garske <viktor@v-gar.de>
> Co-developed-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl>
> Signed-off-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl>
> Co-developed-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
> Signed-off-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
> Co-developed-by: Niklas Mohrin <dev@niklasmohrin.de>
> Signed-off-by: Niklas Mohrin <dev@niklasmohrin.de>
> Co-developed-by: Gioh Kim <gurugio@gmail.com>
> Signed-off-by: Gioh Kim <gurugio@gmail.com>
> Co-developed-by: Daniel Xu <dxu@dxuuu.xyz>
> Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
> Co-developed-by: Milan Landaverde <milan@mdaverde.com>
> Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> Co-developed-by: Morgan Bartlett <mjmouse9999@gmail.com>
> Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com>
> Co-developed-by: Maciej Falkowski <m.falkowski@samsung.com>
> Signed-off-by: Maciej Falkowski <m.falkowski@samsung.com>
> Co-developed-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
> Signed-off-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
> Co-developed-by: Nándor István Krácser <bonifaido@gmail.com>
> Signed-off-by: Nándor István Krácser <bonifaido@gmail.com>
> Co-developed-by: David Gow <davidgow@google.com>
> Signed-off-by: David Gow <davidgow@google.com>
> Co-developed-by: John Baublitz <john.m.baublitz@gmail.com>
> Signed-off-by: John Baublitz <john.m.baublitz@gmail.com>
> Co-developed-by: Björn Roy Baron <bjorn3_gh@protonmail.com>
> Signed-off-by: Björn Roy Baron <bjorn3_gh@protonmail.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> Co-developed-by: Miguel Ojeda <ojeda@kernel.org>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
>  rust/kernel/allocator.rs                 |  64 ++
>  rust/kernel/amba.rs                      | 261 +++++++
>  rust/kernel/build_assert.rs              |  83 +++
>  rust/kernel/chrdev.rs                    | 206 ++++++
>  rust/kernel/clk.rs                       |  79 ++
>  rust/kernel/cred.rs                      |  46 ++
>  rust/kernel/delay.rs                     | 104 +++
>  rust/kernel/device.rs                    | 527 ++++++++++++++
>  rust/kernel/driver.rs                    | 442 +++++++++++
>  rust/kernel/error.rs                     | 564 ++++++++++++++
>  rust/kernel/file.rs                      | 887 +++++++++++++++++++++++
>  rust/kernel/fs.rs                        | 846 +++++++++++++++++++++
>  rust/kernel/fs/param.rs                  | 553 ++++++++++++++
>  rust/kernel/gpio.rs                      | 505 +++++++++++++
>  rust/kernel/hwrng.rs                     | 210 ++++++
>  rust/kernel/io_buffer.rs                 | 153 ++++
>  rust/kernel/io_mem.rs                    | 278 +++++++
>  rust/kernel/iov_iter.rs                  |  81 +++
>  rust/kernel/irq.rs                       | 681 +++++++++++++++++
>  rust/kernel/kasync.rs                    |  50 ++
>  rust/kernel/kasync/executor.rs           | 154 ++++
>  rust/kernel/kasync/executor/workqueue.rs | 291 ++++++++
>  rust/kernel/kasync/net.rs                | 322 ++++++++
>  rust/kernel/kunit.rs                     |  91 +++
>  rust/kernel/lib.rs                       | 267 +++++++
>  rust/kernel/linked_list.rs               | 247 +++++++
>  rust/kernel/miscdev.rs                   | 290 ++++++++
>  rust/kernel/mm.rs                        | 149 ++++
>  rust/kernel/module_param.rs              | 499 +++++++++++++
>  rust/kernel/net.rs                       | 392 ++++++++++
>  rust/kernel/net/filter.rs                | 447 ++++++++++++
>  rust/kernel/of.rs                        |  63 ++
>  rust/kernel/pages.rs                     | 144 ++++
>  rust/kernel/platform.rs                  | 223 ++++++
>  rust/kernel/power.rs                     | 118 +++
>  rust/kernel/prelude.rs                   |  36 +
>  rust/kernel/print.rs                     | 406 +++++++++++
>  rust/kernel/random.rs                    |  42 ++
>  rust/kernel/raw_list.rs                  | 361 +++++++++
>  rust/kernel/rbtree.rs                    | 563 ++++++++++++++
>  rust/kernel/revocable.rs                 | 425 +++++++++++
>  rust/kernel/security.rs                  |  38 +
>  rust/kernel/static_assert.rs             |  34 +
>  rust/kernel/std_vendor.rs                | 161 ++++
>  rust/kernel/str.rs                       | 597 +++++++++++++++
>  rust/kernel/sync.rs                      |  48 +-
>  rust/kernel/sysctl.rs                    | 199 +++++
>  rust/kernel/task.rs                      | 239 ++++++
>  rust/kernel/types.rs                     | 705 ++++++++++++++++++
>  rust/kernel/unsafe_list.rs               | 680 +++++++++++++++++
>  rust/kernel/user_ptr.rs                  | 175 +++++
>  rust/kernel/workqueue.rs                 | 512 +++++++++++++
>  52 files changed, 15518 insertions(+), 20 deletions(-)

This is huge for a single commit, and pretty much impossible to review
as-is.

Any chance you can turn this into a series of commits, that starts with
the basics and builds on top of that?  Right now you are mixing many
many different subsystems all at once into one commit, guaranteeing that
no one can review the whole thing properly :(

thanks,

greg k-h

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v10 26/27] samples: add first Rust examples
  2022-09-27 13:14  6% ` [PATCH v10 26/27] samples: add first Rust examples Miguel Ojeda
  2022-09-28 14:23  0%   ` Wei Liu
@ 2022-09-27 15:25  0%   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 77+ results
From: Greg Kroah-Hartman @ 2022-09-27 15:25 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Linus Torvalds, rust-for-linux, linux-kernel, linux-fsdevel,
	patches, Jarkko Sakkinen, Kees Cook, Alex Gaynor, Finn Behrens,
	Wedson Almeida Filho, Milan Landaverde, Boqun Feng, Gary Guo,
	Björn Roy Baron

On Tue, Sep 27, 2022 at 03:14:57PM +0200, Miguel Ojeda wrote:
> The beginning of a set of Rust modules that showcase how Rust
> modules look like and how to use the abstracted kernel features.
> 
> It also includes an example of a Rust host program with
> several modules.
> 
> These samples also double as tests in the CI.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> Co-developed-by: Finn Behrens <me@kloenk.de>
> Signed-off-by: Finn Behrens <me@kloenk.de>
> Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> Co-developed-by: Milan Landaverde <milan@mdaverde.com>
> Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[relevance 0%]

* Re: [PATCH v10 26/27] samples: add first Rust examples
  2022-09-27 13:14  6% ` [PATCH v10 26/27] samples: add first Rust examples Miguel Ojeda
@ 2022-09-28 14:23  0%   ` Wei Liu
  2022-09-27 15:25  0%   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 77+ results
From: Wei Liu @ 2022-09-28 14:23 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Linus Torvalds, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	linux-fsdevel, patches, Jarkko Sakkinen, Kees Cook, Alex Gaynor,
	Finn Behrens, Wedson Almeida Filho, Milan Landaverde, Boqun Feng,
	Gary Guo, Björn Roy Baron, Wei Liu

On Tue, Sep 27, 2022 at 03:14:57PM +0200, Miguel Ojeda wrote:
> The beginning of a set of Rust modules that showcase how Rust
> modules look like and how to use the abstracted kernel features.
> 
> It also includes an example of a Rust host program with
> several modules.
> 
> These samples also double as tests in the CI.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
> Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
> Co-developed-by: Finn Behrens <me@kloenk.de>
> Signed-off-by: Finn Behrens <me@kloenk.de>
> Co-developed-by: Wedson Almeida Filho <wedsonaf@google.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
> Co-developed-by: Milan Landaverde <milan@mdaverde.com>
> Signed-off-by: Milan Landaverde <milan@mdaverde.com>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

Reviewed-by: Wei Liu <wei.liu@kernel.org>

^ permalink raw reply	[relevance 0%]

* Re: [PATCH 6.0 0000/1066] 6.0.16-rc2 review
@ 2022-12-30 19:23  0% Joel Fernandes
  0 siblings, 0 replies; 77+ results
From: Joel Fernandes @ 2022-12-30 19:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
	patches, lkft-triage, pavel, jonathanh, f.fainelli,
	sudipm.mukherjee, srw, rwarsow, Paul E. McKenney


> On Dec 30, 2022, at 4:50 AM, Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> 
> This is the start of the stable review cycle for the 6.0.16 release.
> There are 1066 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
> 
> Responses should be made by Sun, 01 Jan 2023 09:38:41 +0000.
> Anything received after that time might be too late.
> 
> The whole patch series can be found in one patch at:
>    https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.0.16-rc2.gz
> or in the git tree and branch at:
>    git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.0.y
> and the diffstat can be found below.

All rcutorture scenarios pass, 30 minutes test time each.

Tested-by: Joel Fernandes (Google) <joel@joelfernandes.org>

Thanks,

 - Joel

> 
> thanks,
> 
> greg k-h
> 
> -------------
> Pseudo-Shortlog of commits:
> 
> Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>    Linux 6.0.16-rc2
> 
> Steven Price <steven.price@arm.com>
>    pwm: tegra: Fix 32 bit build
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    mfd: qcom_rpm: Use devm_of_platform_populate() to simplify code
> 
> ChenXiaoSong <chenxiaosong2@huawei.com>
>    cifs: fix use-after-free on the link name
> 
> Paulo Alcantara <pc@cjr.nz>
>    cifs: fix memory leaks in session setup
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    cifs: Fix xid leak in cifs_get_file_info_unix()
> 
> Paulo Alcantara <pc@cjr.nz>
>    cifs: fix double-fault crash during ntlmssp
> 
> Yassine Oudjana <y.oudjana@protonmail.com>
>    extcon: usbc-tusb320: Call the Type-C IRQ handler only if a port is registered
> 
> Geert Uytterhoeven <geert+renesas@glider.be>
>    clk: renesas: r8a779f0: Fix SD0H clock name
> 
> Martin Leung <Martin.Leung@amd.com>
>    drm/amd/display: revert Disable DRR actions during state commit
> 
> Lin Ma <linma@zju.edu.cn>
>    media: dvbdev: fix refcnt bug
> 
> Lin Ma <linma@zju.edu.cn>
>    media: dvbdev: fix build warning due to comments
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    net: stmmac: fix errno when create_singlethread_workqueue() fails
> 
> Pavel Begunkov <asml.silence@gmail.com>
>    io_uring: remove iopoll spinlock
> 
> Pavel Begunkov <asml.silence@gmail.com>
>    io_uring: protect cq_timeouts with timeout_lock
> 
> Pavel Begunkov <asml.silence@gmail.com>
>    io_uring/net: fix cleanup after recycle
> 
> Pavel Begunkov <asml.silence@gmail.com>
>    io_uring: improve io_double_lock_ctx fail handling
> 
> Pavel Begunkov <asml.silence@gmail.com>
>    io_uring: add completion locking for iopoll
> 
> Arun Easi <aeasi@marvell.com>
>    scsi: qla2xxx: Fix crash when I/O abort times out
> 
> David Hildenbrand <david@redhat.com>
>    mm/gup: disallow FOLL_FORCE|FOLL_WRITE on hugetlb mappings
> 
> Filipe Manana <fdmanana@suse.com>
>    btrfs: do not BUG_ON() on ENOMEM when dropping extent items for a range
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    ovl: fix use inode directly in rcu-walk mode
> 
> Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
>    fbdev: fbcon: release buffer when fbcon_do_set_font() failed
> 
> Rickard x Andersson <rickaran@axis.com>
>    gcov: add support for checksum field
> 
> Yuan Can <yuancan@huawei.com>
>    floppy: Fix memory leak in do_floppy_init()
> 
> Johan Hovold <johan+linaro@kernel.org>
>    regulator: core: fix deadlock on regulator enable
> 
> Rasmus Villemoes <linux@rasmusvillemoes.dk>
>    iio: addac: ad74413r: fix integer promotion bug in ad74413_get_input_current_offset()
> 
> Rasmus Villemoes <linux@rasmusvillemoes.dk>
>    iio: adc128s052: add proper .data members in adc128_of_match table
> 
> Nuno Sá <nuno.sa@analog.com>
>    iio: adc: ad_sigma_delta: do not use internal iio_dev lock
> 
> Zeng Heng <zengheng4@huawei.com>
>    iio: fix memory leak in iio_device_register_eventset()
> 
> Roberto Sassu <roberto.sassu@huawei.com>
>    reiserfs: Add missing calls to reiserfs_security_free()
> 
> Nathan Chancellor <nathan@kernel.org>
>    security: Restrict CONFIG_ZERO_CALL_USED_REGS to gcc or clang > 15.0.6
> 
> Schspa Shi <schspa@gmail.com>
>    9p: set req refcount to zero to avoid uninitialized usage
> 
> Isaac J. Manjarres <isaacmanjarres@google.com>
>    loop: Fix the max_loop commandline argument treatment when it is set to 0
> 
> Enrik Berkhan <Enrik.Berkhan@inka.de>
>    HID: mcp2221: don't connect hidraw
> 
> Jason Gerecke <killertofu@gmail.com>
>    HID: wacom: Ensure bootloader PID is usable in hidraw mode
> 
> Mathias Nyman <mathias.nyman@linux.intel.com>
>    xhci: Prevent infinite loop in transaction errors recovery for streams
> 
> Ferry Toth <ftoth@exalondelft.nl>
>    usb: dwc3: core: defer probe on ulpi_read_id timeout
> 
> Sven Peter <sven@svenpeter.dev>
>    usb: dwc3: Fix race between dwc3_set_mode and __dwc3_set_mode
> 
> Li Jun <jun.li@nxp.com>
>    clk: imx: imx8mp: add shared clk gate for usb suspend clk
> 
> Li Jun <jun.li@nxp.com>
>    dt-bindings: clocks: imx8mp: Add ID for usb suspend clock
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm8250: fix USB-DP PHY registers
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm6350: fix USB-DP PHY registers
> 
> Chunfeng Yun <chunfeng.yun@mediatek.com>
>    usb: xhci-mtk: fix leakage of shared hcd when fail to set wakeup irq
> 
> Pawel Laszczak <pawell@cadence.com>
>    usb: cdnsp: fix lack of ZLP for ep0
> 
> Bastien Nocera <hadess@hadess.net>
>    HID: logitech-hidpp: Guard FF init code against non-USB devices
> 
> Jiao Zhou <jiaozhou@google.com>
>    ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list
> 
> Edward Pacman <edward@edward-p.xyz>
>    ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB
> 
> wangdicheng <wangdicheng@kylinos.cn>
>    ALSA: usb-audio: add the quirk for KT0206 device
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - add support for IQS7222A v1.13+
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - trim force communication command
> 
> Jeff LaBundy <jeff@labundy.com>
>    dt-bindings: input: iqs7222: Add support for IQS7222A v1.13+
> 
> Jeff LaBundy <jeff@labundy.com>
>    dt-bindings: input: iqs7222: Correct minimum slider size
> 
> Jeff LaBundy <jeff@labundy.com>
>    dt-bindings: input: iqs7222: Reduce 'linux,code' to optional
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - avoid sending empty SYN_REPORT events
> 
> GUO Zihua <guozihua@huawei.com>
>    ima: Simplify ima_lsm_copy_rule
> 
> John Stultz <jstultz@google.com>
>    pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES
> 
> David Howells <dhowells@redhat.com>
>    afs: Fix lost servers_outstanding count
> 
> Michael Petlan <mpetlan@redhat.com>
>    perf test: Fix "all PMU test" to skip parametrized events
> 
> Sergio Paracuellos <sergio.paracuellos@gmail.com>
>    MIPS: ralink: mt7621: avoid to init common ralink reset controller
> 
> Yang Jihong <yangjihong1@huawei.com>
>    perf debug: Set debug_peo_args and redirect_to_stderr variable to correct values in perf_quiet_option()
> 
> Arnd Bergmann <arnd@arndb.de>
>    drm/amd/pm: avoid large variable on kernel stack
> 
> John Stultz <jstultz@google.com>
>    pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion
> 
> Kristina Martsenko <kristina.martsenko@arm.com>
>    lkdtm: cfi: Make PAC test work with GCC 7 and 8
> 
> Kees Cook <keescook@chromium.org>
>    LoadPin: Ignore the "contents" argument of the LSM hooks
> 
> Khaled Almahallawy <khaled.almahallawy@intel.com>
>    drm/i915/display: Don't disable DDI/Transcoder when setting phy test pattern
> 
> Hans de Goede <hdegoede@redhat.com>
>    ASoC: rt5670: Remove unbalanced pm_runtime_put()
> 
> Wang Jingjin <wangjingjin1@huawei.com>
>    ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in rk_spdif_runtime_resume()
> 
> Marek Szyprowski <m.szyprowski@samsung.com>
>    ASoC: wm8994: Fix potential deadlock
> 
> Kai Vehmanen <kai.vehmanen@linux.intel.com>
>    ALSA: hda/hdmi: fix stream-id config keep-alive for rt suspend
> 
> Jaroslav Kysela <perex@perex.cz>
>    ALSA: hda/hdmi: Use only dynamic PCM device allocation
> 
> Kai Vehmanen <kai.vehmanen@linux.intel.com>
>    ALSA: hda/hdmi: set default audio parameters for KAE silent-stream
> 
> Kai Vehmanen <kai.vehmanen@linux.intel.com>
>    ALSA: hda/hdmi: fix i915 silent stream programming flow
> 
> Wang Yufen <wangyufen@huawei.com>
>    ASoC: mediatek: mt8183: fix refcount leak in mt8183_mt6358_ts3a227_max98357_dev_probe()
> 
> Wang Jingjin <wangjingjin1@huawei.com>
>    ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in rockchip_pdm_runtime_resume()
> 
> Wang Yufen <wangyufen@huawei.com>
>    ASoC: audio-graph-card: fix refcount leak of cpu_ep in __graph_for_each_link()
> 
> Wang Yufen <wangyufen@huawei.com>
>    ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in mt8173_rt5650_rt5514_dev_probe()
> 
> Cezary Rojewski <cezary.rojewski@intel.com>
>    ASoC: Intel: Skylake: Fix driver hang during shutdown
> 
> Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
>    ALSA: hda: add snd_hdac_stop_streams() helper
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    ASoC: sof_es8336: fix possible use-after-free in sof_es8336_remove()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    hwmon: (jc42) Fix missing unlock on error in jc42_write()
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    clk: renesas: r8a779f0: Add TMU and parent SASYNC clocks
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    clk: renesas: r8a779f0: Add SDH0 clock
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init()
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    orangefs: Fix kmemleak in orangefs_sysfs_init()
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string()
> 
> Maurizio Lombardi <mlombard@redhat.com>
>    scsi: target: iscsi: Fix a race condition between login_work and the login thread
> 
> Nathan Chancellor <nathan@kernel.org>
>    drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid()
> 
> Nathan Chancellor <nathan@kernel.org>
>    drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid()
> 
> Kumar Meiyappan <Kumar.Meiyappan@microchip.com>
>    scsi: smartpqi: Correct device removal for multi-actuator devices
> 
> Mike McGowen <mike.mcgowen@microchip.com>
>    scsi: smartpqi: Add new controller PCI IDs
> 
> Hawkins Jiawei <yin31149@gmail.com>
>    hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param()
> 
> Nathan Chancellor <nathan@kernel.org>
>    scsi: elx: libefc: Fix second parameter type in state callbacks
> 
> Bjorn Helgaas <bhelgaas@google.com>
>    Revert "PCI: Clear PCI_STATUS when setting up device"
> 
> Kai Ye <yekai13@huawei.com>
>    crypto: hisilicon/qm - increase the memory of local variables
> 
> Bart Van Assche <bvanassche@acm.org>
>    scsi: ufs: Reduce the START STOP UNIT timeout
> 
> Justin Tee <justin.tee@broadcom.com>
>    scsi: lpfc: Fix hard lockup when reading the rx_monitor from debugfs
> 
> Zhiqi Song <songzhiqi1@huawei.com>
>    crypto: hisilicon/hpre - fix resource leak in remove process
> 
> ChiYuan Huang <cy_huang@richtek.com>
>    regulator: core: Fix resolve supply lookup issue
> 
> Sven Peter <sven@svenpeter.dev>
>    Bluetooth: Add quirk to disable MWS Transport Configuration
> 
> Sven Peter <sven@svenpeter.dev>
>    Bluetooth: Add quirk to disable extended scanning
> 
> Marek Vasut <marex@denx.de>
>    Bluetooth: hci_bcm: Add CYW4373A0 support
> 
> ChiYuan Huang <cy_huang@richtek.com>
>    regulator: core: Use different devices for resource allocation and DT lookup
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    clk: st: Fix memory leak in st_of_quadfs_setup()
> 
> Shigeru Yoshida <syoshida@redhat.com>
>    media: si470x: Fix use-after-free in si470x_int_in_callback()
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    mmc: renesas_sdhi: better reset from HS400 mode
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    mmc: renesas_sdhi: add quirk for broken register layout
> 
> Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
>    mmc: f-sdh30: Add quirks for broken timeout clock capability
> 
> Hawkins Jiawei <yin31149@gmail.com>
>    nfs: fix possible null-ptr-deref when parsing param
> 
> James Hilliard <james.hilliard1@gmail.com>
>    selftests/bpf: Fix conflicts with built-in functions in bpf_iter_ksym
> 
> Denis Pauk <pauk.denis@gmail.com>
>    hwmon: (nct6775) add ASUS CROSSHAIR VIII/TUF/ProArt B550M
> 
> Lorenzo Bianconi <lorenzo@kernel.org>
>    wifi: mt76: do not run mt76u_status_worker if the device is not running
> 
> Rui Zhang <zr.zhang@vivo.com>
>    regulator: core: fix use_count leakage when handling boot-on
> 
> Andrii Nakryiko <andrii@kernel.org>
>    libbpf: Avoid enum forward-declarations in public API in C++ mode
> 
> Artem Lukyanov <dukzcry@ya.ru>
>    ASoC: amd: yc: Add Xiaomi Redmi Book Pro 14 2022 into DMI table
> 
> Alvin Lee <Alvin.Lee2@amd.com>
>    drm/amd/display: Fix DTBCLK disable requests and SRC_SEL programming
> 
> Wesley Chalmers <Wesley.Chalmers@amd.com>
>    drm/amd/display: Use the largest vready_offset in pipe group
> 
> Ye Bin <yebin10@huawei.com>
>    blk-mq: fix possible memleak when register 'hctx' failed
> 
> Yunfei Dong <yunfei.dong@mediatek.com>
>    media: mediatek: vcodec: Can't set dst buffer to done when lat decode error
> 
> Mazin Al Haddad <mazinalhaddad05@gmail.com>
>    media: dvb-usb: fix memory leak in dvb_usb_adapter_init()
> 
> Lin Ma <linma@zju.edu.cn>
>    media: dvbdev: adopts refcnt to avoid UAF
> 
> Yan Lei <yan_lei@dahuatech.com>
>    media: dvb-frontends: fix leak of memory fw
> 
> Maxim Korotkov <korotkov.maxim.s@gmail.com>
>    ethtool: avoiding integer overflow in ethtool_phys_id()
> 
> Stanislav Fomichev <sdf@google.com>
>    bpf: Prevent decl_tag from being referenced in func_proto arg
> 
> Yonghong Song <yhs@fb.com>
>    bpf: Fix a BTF_ID_LIST bug with CONFIG_DEBUG_INFO_BTF not set
> 
> Stanislav Fomichev <sdf@google.com>
>    ppp: associate skb with a device at tx
> 
> Felix Fietkau <nbd@nbd.name>
>    net: ethernet: mtk_eth_soc: drop packets to WDMA if the ring is full
> 
> Schspa Shi <schspa@gmail.com>
>    mrp: introduce active flags to prevent UAF when applicant uninit
> 
> Eric Dumazet <edumazet@google.com>
>    ipv6/sit: use DEV_STATS_INC() to avoid data-races
> 
> Eric Dumazet <edumazet@google.com>
>    net: add atomic_long_t to net_device_stats fields
> 
> Sagi Grimberg <sagi@grimberg.me>
>    nvme-auth: don't override ctrl keys before validation
> 
> Aurabindo Pillai <aurabindo.pillai@amd.com>
>    drm/amd/display: fix array index out of bound error in bios parser
> 
> George Shen <george.shen@amd.com>
>    drm/amd/display: Workaround to increase phantom pipe vactive in pipesplit
> 
> Jiang Li <jiang.li@ugreen.com>
>    md/raid1: stop mdx_raid1 thread when raid1 array run failed
> 
> Xiao Ni <xni@redhat.com>
>    md/raid0, raid10: Don't set discard sectors for request queue
> 
> Li Zhong <floridsleeves@gmail.com>
>    drivers/md/md-bitmap: check the return value of md_bitmap_get_counter()
> 
> Nathan Chancellor <nathan@kernel.org>
>    drm/mediatek: Fix return type of mtk_hdmi_bridge_mode_valid()
> 
> Ville Syrjälä <ville.syrjala@linux.intel.com>
>    drm/sti: Use drm_mode_copy()
> 
> Ville Syrjälä <ville.syrjala@linux.intel.com>
>    drm/rockchip: Use drm_mode_copy()
> 
> Ville Syrjälä <ville.syrjala@linux.intel.com>
>    drm/msm: Use drm_mode_copy()
> 
> Wesley Chalmers <Wesley.Chalmers@amd.com>
>    drm/amd/display: Disable DRR actions during state commit
> 
> Nathan Chancellor <nathan@kernel.org>
>    s390/lcs: Fix return type of lcs_start_xmit()
> 
> Nathan Chancellor <nathan@kernel.org>
>    s390/netiucv: Fix return type of netiucv_tx()
> 
> Nathan Chancellor <nathan@kernel.org>
>    s390/ctcm: Fix return type of ctc{mp,}m_tx()
> 
> Nathan Chancellor <nathan@kernel.org>
>    drm/amdgpu: Fix type of second parameter in odn_edit_dpm_table() callback
> 
> Nathan Chancellor <nathan@kernel.org>
>    drm/amdgpu: Fix type of second parameter in trans_msg() callback
> 
> Kees Cook <keescook@chromium.org>
>    igb: Do not free q_vector unless new one was allocated
> 
> José Expósito <jose.exposito89@gmail.com>
>    HID: input: do not query XP-PEN Deco LW battery
> 
> Minsuk Kang <linuxlovemin@yonsei.ac.kr>
>    wifi: brcmfmac: Fix potential shift-out-of-bounds in brcmf_fw_alloc_request()
> 
> Nathan Chancellor <nathan@kernel.org>
>    hamradio: baycom_epp: Fix return type of baycom_send_packet()
> 
> Nathan Chancellor <nathan@kernel.org>
>    net: ethernet: ti: Fix return type of netcp_ndo_start_xmit()
> 
> Stanislav Fomichev <sdf@google.com>
>    bpf: make sure skb->len != 0 when redirecting to a tunneling device
> 
> Nathan Chancellor <nathan@kernel.org>
>    drm/meson: Fix return type of meson_encoder_cvbs_mode_valid()
> 
> Jiri Slaby (SUSE) <jirislaby@kernel.org>
>    qed (gcc13): use u16 for fid to be big enough
> 
> Rahul Bhattacharjee <quic_rbhattac@quicinc.com>
>    wifi: ath11k: Fix qmi_msg_handler data structure initialization
> 
> Kerem Karabay <kekrby@gmail.com>
>    HID: apple: enable APPLE_ISO_TILDE_QUIRK for the keyboards of Macs with the T2 chip
> 
> Kerem Karabay <kekrby@gmail.com>
>    HID: apple: fix key translations where multiple quirks attempt to translate the same key
> 
> David Jeffery <djeffery@redhat.com>
>    blk-mq: avoid double ->queue_rq() because of early timeout
> 
> Yuan Can <yuancan@huawei.com>
>    drm/rockchip: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
> 
> Hamza Mahfooz <hamza.mahfooz@amd.com>
>    Revert "drm/amd/display: Limit max DSC target bpp for specific monitors"
> 
> Hamza Mahfooz <hamza.mahfooz@amd.com>
>    drm/edid: add a quirk for two LG monitors to get them to work on 10bpc
> 
> gehao <gehao@kylinos.cn>
>    drm/amd/display: prevent memory leak
> 
> Youghandhar Chintala <quic_youghand@quicinc.com>
>    wifi: ath10k: Delay the unmapping of the buffer
> 
> Zhang Yuchen <zhangyuchen.lcr@bytedance.com>
>    ipmi: fix memleak when unload ipmi driver
> 
> Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
>    ASoC: Intel: avs: Add quirk for KBL-R RVP platform
> 
> Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com>
>    ASoC: codecs: rt298: Add quirk for KBL-R RVP platform
> 
> Shigeru Yoshida <syoshida@redhat.com>
>    wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out
> 
> Fedor Pchelkin <pchelkin@ispras.ru>
>    wifi: ath9k: verify the expected usb_endpoints are present
> 
> Wright Feng <wright.feng@cypress.com>
>    brcmfmac: return error when getting invalid max_flowrings from dongle
> 
> Ming Qian <ming.qian@nxp.com>
>    media: imx-jpeg: Disable useless interrupt to avoid kernel panic
> 
> Doug Brown <doug@schmorgal.com>
>    drm/etnaviv: add missing quirks for GC300
> 
> ZhangPeng <zhangpeng362@huawei.com>
>    hfs: fix OOB Read in __hfs_brec_find
> 
> Hans de Goede <hdegoede@redhat.com>
>    ACPI: x86: Add skip i2c clients quirk for Medion Lifetab S10346
> 
> Hans de Goede <hdegoede@redhat.com>
>    ACPI: x86: Add skip i2c clients quirk for Lenovo Yoga Tab 3 Pro (YT3-X90F)
> 
> Mateusz Jończyk <mat.jonczyk@o2.pl>
>    x86/apic: Handle no CONFIG_X86_X2APIC on systems with x2APIC enabled by BIOS
> 
> Zheng Yejian <zhengyejian1@huawei.com>
>    acct: fix potential integer overflow in encode_comp_t()
> 
> Ryusuke Konishi <konishi.ryusuke@gmail.com>
>    nilfs2: fix shift-out-of-bounds due to too large exponent of block size
> 
> Ryusuke Konishi <konishi.ryusuke@gmail.com>
>    nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset()
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    ACPICA: Fix error code path in acpi_ds_call_control_method()
> 
> Mia Kanashi <chad@redpilled.dev>
>    ACPI: EC: Add quirk for the HP Pavilion Gaming 15-cx0041ur
> 
> Li Zhong <floridsleeves@gmail.com>
>    ACPI: processor: idle: Check acpi_fetch_acpi_dev() return value
> 
> Hoi Pok Wu <wuhoipok@gmail.com>
>    fs: jfs: fix shift-out-of-bounds in dbDiscardAG
> 
> Dr. David Alan Gilbert <linux@treblig.org>
>    jfs: Fix fortify moan in symlink
> 
> Shigeru Yoshida <syoshida@redhat.com>
>    udf: Avoid double brelse() in udf_rename()
> 
> Dongliang Mu <mudongliangabcd@gmail.com>
>    fs: jfs: fix shift-out-of-bounds in dbAllocAG
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    arm64: dts: qcom: sm6350: Add apps_smmu with streamID to SDHCI 1/2 nodes
> 
> Liu Shixin <liushixin2@huawei.com>
>    binfmt_misc: fix shift-out-of-bounds in check_special_flags
> 
> Gaurav Kohli <gauravkohli@linux.microsoft.com>
>    x86/hyperv: Remove unregister syscore call from Hyper-V cleanup
> 
> Guilherme G. Piccoli <gpiccoli@igalia.com>
>    video: hyperv_fb: Avoid taking busy spinlock on panic path
> 
> Adriana Kobylak <anoo@us.ibm.com>
>    ARM: dts: aspeed: rainier,everest: Move reserved memory regions
> 
> Mark Rutland <mark.rutland@arm.com>
>    arm64: make is_ttbrX_addr() noinstr-safe
> 
> Zqiang <qiang1.zhang@intel.com>
>    rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state()
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    HID: amd_sfh: Add missing check for dma_alloc_coherent
> 
> Matt Johnston <matt@codeconstruct.com.au>
>    mctp: Remove device type check at unregister
> 
> Jeremy Kerr <jk@codeconstruct.com.au>
>    mctp: serial: Fix starting value for frame check sequence
> 
> Eric Dumazet <edumazet@google.com>
>    net: stream: purge sk_error_queue in sk_stream_kill_queues()
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    myri10ge: Fix an error handling path in myri10ge_probe()
> 
> David Howells <dhowells@redhat.com>
>    rxrpc: Fix missing unlock in rxrpc_do_sendmsg()
> 
> Cong Wang <cong.wang@bytedance.com>
>    net_sched: reject TCF_EM_SIMPLE case for complex ematch module
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mailbox: zynq-ipi: fix error handling while device_register() fails
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mailbox: arm_mhuv2: Fix return value check in mhuv2_probe()
> 
> Conor Dooley <conor.dooley@microchip.com>
>    mailbox: mpfs: read the system controller's status
> 
> Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com>
>    skbuff: Account for tail adjustment during pull operations
> 
> Jakub Kicinski <kuba@kernel.org>
>    devlink: protect devlink dump by the instance lock
> 
> Chen-Yu Tsai <wenst@chromium.org>
>    arm64: dts: mt8183: Fix Mali GPU clock
> 
> Chun-Jie Chen <chun-jie.chen@mediatek.com>
>    soc: mediatek: pm-domains: Fix the power glitch issue
> 
> Eelco Chaudron <echaudro@redhat.com>
>    openvswitch: Fix flow lookup to use unmasked key
> 
> Jakub Kicinski <kuba@kernel.org>
>    selftests: devlink: fix the fd redirect in dummy_reporter_test
> 
> Jakub Kicinski <kuba@kernel.org>
>    devlink: hold region lock when flushing snapshots
> 
> GUO Zihua <guozihua@huawei.com>
>    rtc: mxc_v2: Add missing clk_disable_unprepare()
> 
> Tan Tee Min <tee.min.tan@linux.intel.com>
>    igc: Set Qbv start_time and end_time to end_time if not being configured in GCL
> 
> Tan Tee Min <tee.min.tan@linux.intel.com>
>    igc: recalculate Qbv end_time by considering cycle time
> 
> Tan Tee Min <tee.min.tan@linux.intel.com>
>    igc: allow BaseTime 0 enrollment for Qbv
> 
> Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
>    igc: Add checking for basetime less than zero
> 
> Vinicius Costa Gomes <vinicius.gomes@intel.com>
>    igc: Use strict cycles for Qbv scheduling
> 
> Vinicius Costa Gomes <vinicius.gomes@intel.com>
>    igc: Enhance Qbv scheduling by using first flag bit
> 
> Vladimir Oltean <vladimir.oltean@nxp.com>
>    net: dsa: mv88e6xxx: avoid reg_lock deadlock in mv88e6xxx_setup_port()
> 
> Li Zetao <lizetao1@huawei.com>
>    r6040: Fix kmemleak in probe and remove
> 
> Kirill Tkhai <tkhai@ya.ru>
>    unix: Fix race in SOCK_SEQPACKET's unix_dgram_sendmsg()
> 
> Minsuk Kang <linuxlovemin@yonsei.ac.kr>
>    nfc: pn533: Clear nfc_target before being used
> 
> Vladimir Oltean <vladimir.oltean@nxp.com>
>    net: enetc: avoid buffer leaks on xdp_do_redirect() failure
> 
> Hans Verkuil <hverkuil-cisco@xs4all.nl>
>    media: v4l2-ctrls-api.c: add back dropped ctrl->is_new = 1
> 
> Milan Landaverde <milan@mdaverde.com>
>    bpf: prevent leak of lsm program after failed attach
> 
> Song Liu <song@kernel.org>
>    selftests/bpf: Select CONFIG_FUNCTION_ERROR_INJECTION
> 
> Yu Kuai <yukuai3@huawei.com>
>    block, bfq: fix possible uaf for 'bfqq->bic'
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under spin_lock_irqsave()
> 
> Hangbin Liu <liuhangbin@gmail.com>
>    bonding: do failover when high prio link up
> 
> Hangbin Liu <liuhangbin@gmail.com>
>    bonding: add missed __rcu annotation for curr_active_slave
> 
> Emeel Hakim <ehakim@nvidia.com>
>    net: macsec: fix net device access prior to holding a lock
> 
> Dan Aloni <dan.aloni@vastdata.com>
>    nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure
> 
> Dan Carpenter <error27@gmail.com>
>    iommu/mediatek: Fix forever loop in error handling
> 
> Alexandre Belloni <alexandre.belloni@bootlin.com>
>    rtc: pcf85063: fix pcf85063_clkout_control
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe()
> 
> Qingfang DENG <dqfext@gmail.com>
>    netfilter: flowtable: really fix NAT IPv6 offload
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mfd: pm8008: Fix return value check in pm8008_probe()
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    mfd: qcom_rpm: Fix an error handling path in qcom_rpm_probe()
> 
> Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
>    mfd: bd957x: Fix Kconfig dependency on REGMAP_IRQ
> 
> Samuel Holland <samuel@sholland.org>
>    mfd: axp20x: Do not sleep in the power off handler
> 
> Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>    dt-bindings: mfd: qcom,spmi-pmic: Drop PWM reg dependency
> 
> Nathan Lynch <nathanl@linux.ibm.com>
>    powerpc/pseries/eeh: use correct API for error log size
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    remoteproc: qcom: q6v5: Fix missing clk_disable_unprepare() in q6v5_wcss_qcs404_power_on()
> 
> Yuan Can <yuancan@huawei.com>
>    remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in adsp_alloc_memory_region()
> 
> Luca Weiss <luca.weiss@fairphone.com>
>    remoteproc: qcom_q6v5_pas: detach power domains on remove
> 
> Luca Weiss <luca.weiss@fairphone.com>
>    remoteproc: qcom_q6v5_pas: disable wakeup on probe fail or remove
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    remoteproc: qcom: q6v5: Fix potential null-ptr-deref in q6v5_wcss_init_mmio()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev()
> 
> Anup Patel <apatel@ventanamicro.com>
>    RISC-V: KVM: Fix reg_val check in kvm_riscv_vcpu_set_reg_config()
> 
> Daniel Golle <daniel@makrotopia.org>
>    pwm: mediatek: always use bus clock for PWM on MT7622
> 
> xinlei lee <xinlei.lee@mediatek.com>
>    pwm: mtk-disp: Fix the parameters calculated by the enabled flag of disp_pwm
> 
> Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>    pwm: sifive: Call pwm_sifive_update_clock() while mutex is held
> 
> Jason Gunthorpe <jgg@ziepe.ca>
>    iommu/sun50i: Remove IOMMU_DOMAIN_IDENTITY
> 
> Guenter Roeck <groeck@chromium.org>
>    iommu/mediatek: Validate number of phandles associated with "mediatek,larbs"
> 
> Yong Wu <yong.wu@mediatek.com>
>    iommu/mediatek: Add error path for loop of mm_dts_parse
> 
> Yong Wu <yong.wu@mediatek.com>
>    iommu/mediatek: Use component_match_add
> 
> Yong Wu <yong.wu@mediatek.com>
>    iommu/mediatek: Add platform_device_put for recovering the device refcnt
> 
> Miaoqian Lin <linmq006@gmail.com>
>    selftests/powerpc: Fix resource leaks
> 
> Kajol Jain <kjain@linux.ibm.com>
>    powerpc/hv-gpci: Fix hv_gpci event list
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in of_fsl_spi_probe()
> 
> Nicholas Piggin <npiggin@gmail.com>
>    powerpc/perf: callchain validate kernel stack pointer bounds
> 
> Pali Rohár <pali@kernel.org>
>    powerpc: dts: turris1x.dts: Add channel labels for temperature sensor
> 
> Li Huafei <lihuafei1@huawei.com>
>    kprobes: Fix check for probe enabled in kill_kprobe()
> 
> Nayna Jain <nayna@linux.ibm.com>
>    powerpc/pseries: fix plpks_read_var() code for different consumers
> 
> Nayna Jain <nayna@linux.ibm.com>
>    powerpc/pseries: Return -EIO instead of -EINTR for H_ABORTED error
> 
> Nayna Jain <nayna@linux.ibm.com>
>    powerpc/pseries: Fix the H_CALL error code in PLPKS driver
> 
> Nayna Jain <nayna@linux.ibm.com>
>    powerpc/pseries: fix the object owners enum value in plpks driver
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    powerpc/xive: add missing iounmap() in error path in xive_spapr_populate_irq_data()
> 
> Gustavo A. R. Silva <gustavoars@kernel.org>
>    powerpc/xmon: Fix -Wswitch-unreachable warning in bpt_cmds
> 
> Miaoqian Lin <linmq006@gmail.com>
>    cxl: Fix refcount leak in cxl_calc_capp_routing
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    powerpc/52xx: Fix a resource leak in an error handling path
> 
> Xie Shaowen <studentxswpy@163.com>
>    macintosh/macio-adb: check the return value of ioremap()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    macintosh: fix possible memory leak in macio_add_one_device()
> 
> Yuan Can <yuancan@huawei.com>
>    iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    iommu/amd: Fix pci device refcount leak in ppr_notifier()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    iommu/mediatek: Check return value after calling platform_get_resource()
> 
> Alexander Stein <alexander.stein@ew.tq-group.com>
>    rtc: pcf85063: Fix reading alarm
> 
> Stefan Eichenberger <stefan.eichenberger@toradex.com>
>    rtc: snvs: Allow a time difference on clock register read
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    rtc: cmos: Disable ACPI RTC event on removal
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    rtc: cmos: Rename ACPI-related functions
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    rtc: cmos: Eliminate forward declarations of some functions
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    rtc: cmos: Call rtc_wake_setup() from cmos_do_probe()
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    rtc: cmos: Call cmos_wake_setup() from cmos_do_probe()
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    rtc: class: Fix potential memleak in devm_rtc_allocate_device()
> 
> Yushan Zhou <katrinzhou@tencent.com>
>    rtc: rzn1: Check return value in rzn1_rtc_probe
> 
> Fenghua Yu <fenghua.yu@intel.com>
>    dmaengine: idxd: Fix crc_val field for completion record
> 
> Abdun Nihaal <abdun.nihaal@gmail.com>
>    fs/ntfs3: Fix slab-out-of-bounds read in ntfs_trim_fs
> 
> Manivannan Sadhasivam <mani@kernel.org>
>    phy: qcom-qmp-pcie: Fix sm8450_qmp_gen4x2_pcie_pcs_tbl[] register names
> 
> Jon Hunter <jonathanh@nvidia.com>
>    pwm: tegra: Ensure the clock rate is not less than needed
> 
> Jon Hunter <jonathanh@nvidia.com>
>    pwm: tegra: Improve required rate calculation
> 
> Matt Redfearn <matt.redfearn@mips.com>
>    include/uapi/linux/swab: Fix potentially missing __always_inline
> 
> Justin Chen <justinpopo6@gmail.com>
>    phy: usb: Fix clock imbalance for suspend/resume
> 
> Justin Chen <justinpopo6@gmail.com>
>    phy: usb: Use slow clock for wake enabled suspend
> 
> Al Cooper <alcooperx@gmail.com>
>    phy: usb: s2 WoL wakeup_count not incremented for USB->Eth devices
> 
> Michael Riesch <michael.riesch@wolfvision.net>
>    iommu/rockchip: fix permission bits in page table entries v2
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    iommu/sun50i: Implement .iotlb_sync_map
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    iommu/sun50i: Fix flush size
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    iommu/sun50i: Fix R/W permission check
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    iommu/sun50i: Consider all fault sources for reset
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    iommu/sun50i: Fix reset release
> 
> Niklas Schnelle <schnelle@linux.ibm.com>
>    iommu/s390: Fix duplicate domain attachments
> 
> Johan Hovold <johan+linaro@kernel.org>
>    phy: qcom-qmp-pcie: fix ipq8074-gen3 initialisation
> 
> Martin Povišer <povik+lin@cutebit.org>
>    dmaengine: apple-admac: Allocate cache SRAM to channels
> 
> Martin Povišer <povik+lin@cutebit.org>
>    dmaengine: apple-admac: Do not use devres for IRQs
> 
> Johan Hovold <johan+linaro@kernel.org>
>    phy: qcom-qmp-pcie: drop bogus register update
> 
> Pali Rohár <pali@kernel.org>
>    phy: marvell: phy-mvebu-a3700-comphy: Reset COMPHY registers before USB 3.0 power on
> 
> Dan Carpenter <dan.carpenter@oracle.com>
>    fs/ntfs3: Harden against integer overflows
> 
> Shigeru Yoshida <syoshida@redhat.com>
>    fs/ntfs3: Avoid UBSAN error on true_sectors_per_clst()
> 
> Arnd Bergmann <arnd@arndb.de>
>    RDMA/siw: Fix pointer cast warning
> 
> Namhyung Kim <namhyung@kernel.org>
>    perf stat: Do not delay the workload with --delay
> 
> Ard Biesheuvel <ardb@kernel.org>
>    ftrace: Allow WITH_ARGS flavour of graph tracer with shadow call stack
> 
> Namhyung Kim <namhyung@kernel.org>
>    perf off_cpu: Fix a typo in BTF tracepoint name, it should be 'btf_trace_sched_switch'
> 
> Luca Weiss <luca@z3ntu.xyz>
>    leds: is31fl319x: Fix setting current limit for is31fl319{0,1,3}
> 
> ruanjinjie <ruanjinjie@huawei.com>
>    power: supply: fix null pointer dereferencing in power_supply_get_battery_info
> 
> Hans de Goede <hdegoede@redhat.com>
>    power: supply: bq25890: Ensure pump_express_work is cancelled on remove
> 
> Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>    power: supply: bq25890: Convert to i2c's .probe_new()
> 
> Marek Vasut <marex@denx.de>
>    power: supply: bq25890: Factor out regulator registration code
> 
> Yuan Can <yuancan@huawei.com>
>    power: supply: ab8500: Fix error handling in ab8500_charger_init()
> 
> Yuan Can <yuancan@huawei.com>
>    HSI: omap_ssi_core: Fix error handling in ssi_init()
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    power: supply: cw2015: Fix potential null-ptr-deref in cw_bat_probe()
> 
> Zheyu Ma <zheyuma97@gmail.com>
>    power: supply: cw2015: Use device managed API to simplify the code
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    power: supply: z2_battery: Fix possible memleak in z2_batt_probe()
> 
> Ajay Kaher <akaher@vmware.com>
>    perf symbol: correction while adjusting symbol
> 
> Leo Yan <leo.yan@linaro.org>
>    perf trace: Handle failure when trace point folder is missed
> 
> Leo Yan <leo.yan@linaro.org>
>    perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number
> 
> Leo Yan <leo.yan@linaro.org>
>    perf trace: Return error if a system call doesn't exist
> 
> Mika Westerberg <mika.westerberg@linux.intel.com>
>    watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running
> 
> Zeng Heng <zengheng4@huawei.com>
>    power: supply: fix residue sysfs file in error handle route of __power_supply_register()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    HSI: omap_ssi_core: fix possible memory leak in ssi_probe()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    HSI: omap_ssi_core: fix unbalanced pm_runtime_disable()
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    led: qcom-lpg: Fix sleeping in atomic
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    fbdev: uvesafb: Fixes an error handling path in uvesafb_probe()
> 
> Randy Dunlap <rdunlap@infradead.org>
>    fbdev: uvesafb: don't build on UML
> 
> Randy Dunlap <rdunlap@infradead.org>
>    fbdev: geode: don't build on UML
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    fbdev: ep93xx-fb: Add missing clk_disable_unprepare in ep93xxfb_probe()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    fbdev: vermilion: decrease reference count in error path
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    fbdev: via: Fix error in via_core_init()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    fbdev: pm2fb: fix missing pci_disable_device()
> 
> Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>    fbdev: ssd1307fb: Drop optional dependency
> 
> Bjorn Andersson <andersson@kernel.org>
>    thermal/drivers/qcom/lmh: Fix irq handler return value
> 
> Luca Weiss <luca.weiss@fairphone.com>
>    thermal/drivers/qcom/temp-alarm: Fix inaccurate warning for gen2
> 
> Keerthy <j-keerthy@ti.com>
>    thermal/drivers/k3_j72xx_bandgap: Fix the debug print message
> 
> Marcus Folkesson <marcus.folkesson@gmail.com>
>    thermal/drivers/imx8mm_thermal: Validate temperature range
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe()
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    ksmbd: Fix resource leak in ksmbd_session_rpc_open()
> 
> Zheng Yejian <zhengyejian1@huawei.com>
>    tracing/hist: Fix issue of losting command info in error_log
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    usb: typec: wusb3801: fix fwnode refcount leak in wusb3801_probe()
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    usb: storage: Add check for kcalloc
> 
> Zheyu Ma <zheyuma97@gmail.com>
>    i2c: ismt: Fix an out-of-bounds bug in ismt_access()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    i2c: mux: reg: check return value after calling platform_get_resource()
> 
> Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>    gpiolib: protect the GPIO device against being dropped while in use by user-space
> 
> Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
>    gpiolib: cdev: fix NULL-pointer dereferences
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    vme: Fix error not catched in fake_init()
> 
> YueHaibing <yuehaibing@huawei.com>
>    staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor()
> 
> Dan Carpenter <error27@gmail.com>
>    staging: rtl8192u: Fix use after free in ieee80211_rx()
> 
> Hui Tang <tanghui20@huawei.com>
>    i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    chardev: fix error handling in cdev_device_add()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mcb: mcb-parse: fix error handing in chameleon_parse_gdd()
> 
> Zhengchao Shao <shaozhengchao@huawei.com>
>    drivers: mcb: fix resource leak in mcb_probe()
> 
> John Keeping <john@metanate.com>
>    usb: gadget: f_hid: fix refcount leak on error path
> 
> John Keeping <john@metanate.com>
>    usb: gadget: f_hid: fix f_hidg lifetime vs cdev
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    usb: core: hcd: Fix return value check in usb_hcd_setup_local_mem()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    usb: roles: fix of node refcount leak in usb_role_switch_is_parent()
> 
> Beau Belgrave <beaub@linux.microsoft.com>
>    tracing/user_events: Fix call print_fmt leak
> 
> Yang Shen <shenyang39@huawei.com>
>    coresight: trbe: remove cpuhp instance node before remove cpuhp state
> 
> Fabrice Gasnier <fabrice.gasnier@foss.st.com>
>    counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update
> 
> Ramona Bolboaca <ramona.bolboaca@analog.com>
>    iio: adis: add '__adis_enable_irq()' implementation
> 
> Cosmin Tanislav <cosmin.tanislav@analog.com>
>    iio: temperature: ltc2983: make bulk write buffer DMA-safe
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    firmware: raspberrypi: fix possible memory leak in rpi_firmware_probe()
> 
> Zheng Wang <zyytlz.wz@163.com>
>    misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault and gru_handle_user_call_os
> 
> ruanjinjie <ruanjinjie@huawei.com>
>    misc: tifm: fix possible memory leak in tifm_7xx1_switch_media()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    ocxl: fix pci device refcount leak when calling get_function_0()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    misc: ocxl: fix possible name leak in ocxl_file_register_afu()
> 
> Zhengchao Shao <shaozhengchao@huawei.com>
>    test_firmware: fix memory leak in test_firmware_init()
> 
> Yuan Can <yuancan@huawei.com>
>    serial: sunsab: Fix error handling in sunsab_init()
> 
> Gabriel Somlo <gsomlo@gmail.com>
>    serial: altera_uart: fix locking in polling mode
> 
> Jiri Slaby <jirislaby@kernel.org>
>    tty: serial: altera_uart_{r,t}x_chars() need only uart_port
> 
> Jiri Slaby <jirislaby@kernel.org>
>    tty: serial: clean up stop-tx part in altera_uart_tx_chars()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    serial: pch: Fix PCI device refcount leak in pch_request_dma()
> 
> Valentin Caron <valentin.caron@foss.st.com>
>    serial: stm32: move dma_request_chan() before clk_prepare_enable()
> 
> delisun <delisun@pateo.com.cn>
>    serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle.
> 
> Jiamei Xie <jiamei.xie@arm.com>
>    serial: amba-pl011: avoid SBSA UART accessing DMACR register
> 
> Jiantao Zhang <water.zhangjiantao@huawei.com>
>    USB: gadget: Fix use-after-free during usb config switch
> 
> Marek Vasut <marex@denx.de>
>    extcon: usbc-tusb320: Update state on probe even if no IRQ pending
> 
> Marek Vasut <marex@denx.de>
>    extcon: usbc-tusb320: Add USB TYPE-C support
> 
> Marek Vasut <marex@denx.de>
>    extcon: usbc-tusb320: Factor out extcon into dedicated functions
> 
> Tony Lindgren <tony@atomide.com>
>    usb: musb: omap2430: Fix probe regression for missing resources
> 
> Sven Peter <sven@svenpeter.dev>
>    usb: typec: tipd: Fix typec_unregister_port error paths
> 
> Sven Peter <sven@svenpeter.dev>
>    usb: typec: tipd: Fix spurious fwnode_handle_put in error path
> 
> Sven Peter <sven@svenpeter.dev>
>    usb: typec: tipd: Cleanup resources if devm_tps6598_psy_register fails
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    usb: typec: tcpci: fix of node refcount leak in tcpci_register_port()
> 
> Sven Peter <sven@svenpeter.dev>
>    usb: typec: Check for ops->exit instead of ops->enter in altmode_exit
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    staging: vme_user: Fix possible UAF in tsi148_dma_list_add
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    interconnect: qcom: sc7180: fix dropped const of qcom_icc_bcm
> 
> Linus Walleij <linus.walleij@linaro.org>
>    usb: fotg210-udc: Fix ages old endianness issues
> 
> Rafael Mendonca <rafaelmendsr@gmail.com>
>    uio: uio_dmem_genirq: Fix deadlock between irq config and handling
> 
> Rafael Mendonca <rafaelmendsr@gmail.com>
>    uio: uio_dmem_genirq: Fix missing unlock in irq configuration
> 
> Rafael Mendonca <rafaelmendsr@gmail.com>
>    vfio: platform: Do not pass return buffer to ACPI _RST method
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    class: fix possible memory leak in __class_register()
> 
> Duoming Zhou <duoming@zju.edu.cn>
>    drivers: staging: r8188eu: Fix sleep-in-atomic-context bug in rtw_join_timeout_handler
> 
> Yuan Can <yuancan@huawei.com>
>    serial: 8250_bcm7271: Fix error handling in brcmuart_init()
> 
> Kartik <kkartik@nvidia.com>
>    serial: tegra: Read DMA status before terminating
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    drivers: dio: fix possible memory leak in dio_init()
> 
> Alexandre Ghiti <alexghiti@rivosinc.com>
>    riscv: Fix P4D_SHIFT definition for 3-level page table mode
> 
> Yangtao Li <frank.li@vivo.com>
>    f2fs: fix iostat parameter for discard
> 
> Palmer Dabbelt <palmer@rivosinc.com>
>    RISC-V: Align the shadow stack
> 
> Dragos Tatulea <dtatulea@nvidia.com>
>    IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    hwrng: geode - Fix PCI device refcount leak
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    hwrng: amd - Fix PCI device refcount leak
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    crypto: img-hash - Fix variable dereferenced before check 'hdev->req'
> 
> Samuel Holland <samuel@sholland.org>
>    riscv: Fix crash during early errata patching
> 
> Anup Patel <apatel@ventanamicro.com>
>    RISC-V: Fix MEMREMAP_WB for systems with Svpbmt
> 
> Andrew Bresticker <abrestic@rivosinc.com>
>    RISC-V: Fix unannoted hardirqs-on in return to userspace slow-path
> 
> Chengchang Tang <tangchengchang@huawei.com>
>    RDMA/hns: Fix XRC caps on HIP08
> 
> Chengchang Tang <tangchengchang@huawei.com>
>    RDMA/hns: Fix error code of CMD
> 
> Chengchang Tang <tangchengchang@huawei.com>
>    RDMA/hns: Fix page size cap from firmware
> 
> Chengchang Tang <tangchengchang@huawei.com>
>    RDMA/hns: Fix PBL page MTR find
> 
> Chengchang Tang <tangchengchang@huawei.com>
>    RDMA/hns: Fix AH attr queried by query_qp
> 
> Yixing Liu <liuyixing1@huawei.com>
>    RDMA/hns: Fix the gid problem caused by free mr
> 
> Wenpeng Liang <liangwenpeng@huawei.com>
>    RDMA/hns: Remove redundant DFX file and DFX ops structure
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    orangefs: Fix sysfs not cleanup when dev init failed
> 
> Francisco Munoz <francisco.munoz.ruiz@linux.intel.com>
>    PCI: vmd: Fix secondary bus reset for Intel bridges
> 
> Wang Yufen <wangyufen@huawei.com>
>    RDMA/srp: Fix error return code in srp_parse_options()
> 
> Wang Yufen <wangyufen@huawei.com>
>    RDMA/hfi1: Fix error return code in parse_platform_config()
> 
> Randy Dunlap <rdunlap@infradead.org>
>    RDMA: Disable IB HW for UML
> 
> Tong Tiangen <tongtiangen@huawei.com>
>    riscv/mm: add arch hook arch_clear_hugepage_flags
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe()
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    crypto: amlogic - Remove kcalloc without check
> 
> Wang Yufen <wangyufen@huawei.com>
>    crypto: qat - fix error return code in adf_probe
> 
> Mark Zhang <markzhang@nvidia.com>
>    RDMA/nldev: Fix failure to send large messages
> 
> Yonggil Song <yonggil.song@samsung.com>
>    f2fs: avoid victim selection from previous victim section
> 
> Sheng Yong <shengyong@oppo.com>
>    f2fs: fix to enable compress for newly created file if extension matches
> 
> Sheng Yong <shengyong@oppo.com>
>    f2fs: set zstd compress level correctly
> 
> Yuan Can <yuancan@huawei.com>
>    RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps()
> 
> Bart Van Assche <bvanassche@acm.org>
>    scsi: ufs: core: Fix the polling implementation
> 
> Jie Zhan <zhanjie9@hisilicon.com>
>    scsi: hisi_sas: Fix SATA devices missing issue during I_T nexus reset
> 
> Jie Zhan <zhanjie9@hisilicon.com>
>    scsi: libsas: Add smp_ata_check_ready_type()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    scsi: snic: Fix possible UAF in snic_tgt_create()
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    scsi: ipr: Fix WARNING in ipr_init()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    scsi: scsi_debug: Fix possible name leak in sdebug_add_host_helper()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    scsi: fcoe: Fix possible name leak when device_register() fails
> 
> Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
>    scsi: scsi_debug: Fix a warning in resp_report_zones()
> 
> Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
>    scsi: scsi_debug: Fix a warning in resp_verify()
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    scsi: efct: Fix possible memleak in efct_device_init()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    scsi: hpsa: Fix error handling in hpsa_add_sas_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add()
> 
> Daniel Jordan <daniel.m.jordan@oracle.com>
>    padata: Fix list iterator in padata_do_serial()
> 
> Daniel Jordan <daniel.m.jordan@oracle.com>
>    padata: Always leave BHs disabled when running ->parallel()
> 
> Zhang Yiqun <zhangyiqun@phytium.com.cn>
>    crypto: tcrypt - Fix multibuffer skcipher speed test mem leak
> 
> Yuan Can <yuancan@huawei.com>
>    scsi: hpsa: Fix possible memory leak in hpsa_init_one()
> 
> Frank Li <frank.li@nxp.com>
>    PCI: endpoint: pci-epf-vntb: Fix call pci_epc_mem_free_addr() in error path
> 
> Serge Semin <Sergey.Semin@baikalelectronics.ru>
>    dt-bindings: visconti-pcie: Fix interrupts array max constraints
> 
> Serge Semin <Sergey.Semin@baikalelectronics.ru>
>    dt-bindings: imx6q-pcie: Fix clock names for imx6sx and imx8mq
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create failed
> 
> Zhengchao Shao <shaozhengchao@huawei.com>
>    RDMA/hns: fix memory leak in hns_roce_alloc_mr()
> 
> Mustafa Ismail <mustafa.ismail@intel.com>
>    RDMA/irdma: Initialize net_type before checking it
> 
> Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
>    crypto: ccree - Make cc_debugfs_global_fini() available for module init function
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    RDMA/hfi: Decrease PCI device reference count in error path
> 
> Zeng Heng <zengheng4@huawei.com>
>    PCI: Check for alloc failure in pci_request_irq()
> 
> Luoyouming <luoyouming@huawei.com>
>    RDMA/hns: Fix incorrect sge nums calculation
> 
> Luoyouming <luoyouming@huawei.com>
>    RDMA/hns: Fix ext_sge num error when post send
> 
> Luoyouming <luoyouming@huawei.com>
>    RDMA/hns: Repacing 'dseg_len' by macros in fill_ext_sge_inl_data()
> 
> Li Zhijian <lizhijian@fujitsu.com>
>    RDMA/rxe: Fix mr->map double free
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    crypto: hisilicon/qm - add missing pci_dev_put() in q_num_set()
> 
> Herbert Xu <herbert@gondor.apana.org.au>
>    crypto: cryptd - Use request context instead of stack for sub-request
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    crypto: ccree - Remove debugfs when platform_driver_register failed
> 
> Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
>    scsi: scsi_debug: Fix a warning in resp_write_scat()
> 
> Mustafa Ismail <mustafa.ismail@intel.com>
>    RDMA/irdma: Do not request 2-level PBLEs for CQ alloc
> 
> Mustafa Ismail <mustafa.ismail@intel.com>
>    RDMA/irdma: Fix RQ completion opcode
> 
> Mustafa Ismail <mustafa.ismail@intel.com>
>    RDMA/irdma: Fix inline for multiple SGE's
> 
> Bernard Metzler <bmt@zurich.ibm.com>
>    RDMA/siw: Set defined status for work completion with undefined status
> 
> Mark Zhang <markzhang@nvidia.com>
>    RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port
> 
> Mark Zhang <markzhang@nvidia.com>
>    RDMA/core: Make sure "ib_port" is valid when access sysfs node
> 
> Mark Zhang <markzhang@nvidia.com>
>    RDMA/restrack: Release MR restrack when delete
> 
> Sascha Hauer <s.hauer@pengutronix.de>
>    PCI: imx6: Initialize PHY before deasserting core reset
> 
> Nirmal Patel <nirmal.patel@linux.intel.com>
>    PCI: vmd: Disable MSI remapping after suspend
> 
> Leonid Ravich <lravich@gmail.com>
>    IB/mad: Don't call to function that might sleep while in atomic context
> 
> Bernard Metzler <bmt@zurich.ibm.com>
>    RDMA/siw: Fix immediate work request flush to completion queue
> 
> Bart Van Assche <bvanassche@acm.org>
>    scsi: qla2xxx: Fix set-but-not-used variable warnings
> 
> Shiraz Saleem <shiraz.saleem@intel.com>
>    RDMA/irdma: Report the correct link speed
> 
> Chao Yu <chao@kernel.org>
>    f2fs: fix to destroy sbi->post_read_wq in error path of f2fs_fill_super()
> 
> Mukesh Ojha <quic_mojha@quicinc.com>
>    f2fs: fix the assign logic of iocb
> 
> Jaegeuk Kim <jaegeuk@kernel.org>
>    f2fs: allow to set compression for inlined file
> 
> Dongdong Zhang <zhangdongdong1@oppo.com>
>    f2fs: fix normal discard process
> 
> Chao Yu <chao@kernel.org>
>    f2fs: fix to invalidate dcc->f2fs_issue_discard in error path
> 
> Kees Cook <keescook@chromium.org>
>    fortify: Do not cast to "unsigned char"
> 
> Kees Cook <keescook@chromium.org>
>    fortify: Use SIZE_MAX instead of (size_t)-1
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    apparmor: Fix memleak in alloc_ns()
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - rework by using crypto_engine
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - remove non-aligned handling
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - better handle cipher key
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - add fallback for ahash
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - add fallback for cipher
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - do not store mode globally
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: rockchip - do not do custom power management
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    f2fs: Fix the race condition of resize flag between resizefs
> 
> Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
>    PCI: pci-epf-test: Register notifier if only core_init_notifier is enabled
> 
> Leon Romanovsky <leon@kernel.org>
>    RDMA/core: Fix order of nldev_exit call
> 
> Vidya Sagar <vidyas@nvidia.com>
>    PCI: dwc: Fix n_fts[] array overrun
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    apparmor: Use pointer to struct aa_label for lbs_cred
> 
> Bart Van Assche <bvanassche@acm.org>
>    scsi: core: Fix a race between scsi_done() and scsi_timeout()
> 
> Robert Elliott <elliott@hpe.com>
>    crypto: tcrypt - fix return value for multiple subtests
> 
> Natalia Petrova <n.petrova@fintech.ru>
>    crypto: nitrox - avoid double free on error path in nitrox_sriov_init()
> 
> Corentin Labbe <clabbe@baylibre.com>
>    crypto: sun8i-ss - use dma_addr instead u32
> 
> Weili Qian <qianweili@huawei.com>
>    crypto: hisilicon/qm - re-enable communicate interrupt before notifying PF
> 
> Weili Qian <qianweili@huawei.com>
>    crypto: hisilicon/qm - get hardware features from hardware registers
> 
> Weili Qian <qianweili@huawei.com>
>    crypto: hisilicon/qm - fix missing destroy qp_idr
> 
> John Johansen <john.johansen@canonical.com>
>    apparmor: Fix regression in stacking due to label flags
> 
> John Johansen <john.johansen@canonical.com>
>    apparmor: Fix abi check to include v8 abi
> 
> John Johansen <john.johansen@canonical.com>
>    apparmor: fix lockdep warning when removing a namespace
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    apparmor: fix a memleak in multi_transaction_new()
> 
> Vladimir Oltean <vladimir.oltean@nxp.com>
>    net: dsa: tag_8021q: avoid leaking ctx on dsa_tag_8021q_register() error path
> 
> Bartosz Staszewski <bartoszx.staszewski@intel.com>
>    i40e: Fix the inability to attach XDP program on downed interface
> 
> Piergiorgio Beruto <piergiorgio.beruto@gmail.com>
>    stmmac: fix potential division by 0
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave()
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    Bluetooth: btintel: Fix missing free skb in btintel_setup_combined()
> 
> Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>    Bluetooth: hci_conn: Fix crash on hci_create_cis_sync
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    Bluetooth: Fix EALREADY and ELOOP cases in bt_status()
> 
> Inga Stotland <inga.stotland@intel.com>
>    Bluetooth: MGMT: Fix error report for ADD_EXT_ADV_PARAMS
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    Bluetooth: hci_core: fix error handling in hci_register_dev()
> 
> Firo Yang <firo.yang@suse.com>
>    sctp: sysctl: make extra pointers netns aware
> 
> Eric Pilmore <epilmore@gigaio.com>
>    ntb_netdev: Use dev_kfree_skb_any() in interrupt context
> 
> Jerry Ray <jerry.ray@microchip.com>
>    net: lan9303: Fix read error execution path
> 
> Roger Quadros <rogerq@kernel.org>
>    net: ethernet: ti: am65-cpsw: Fix PM runtime leakage in am65_cpsw_nuss_ndo_slave_open()
> 
> Markus Schneider-Pargmann <msp@baylibre.com>
>    can: tcan4x5x: Fix use of register error status mask
> 
> Vivek Yadav <vivek.2311@samsung.com>
>    can: m_can: Call the RAM init directly from m_can_chip_config
> 
> Markus Schneider-Pargmann <msp@baylibre.com>
>    can: tcan4x5x: Remove invalid write in clear_interrupts
> 
> Tom Lendacky <thomas.lendacky@amd.com>
>    net: amd-xgbe: Check only the minimum speed for active/passive cables
> 
> Tom Lendacky <thomas.lendacky@amd.com>
>    net: amd-xgbe: Fix logic around active and passive cables
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    af_unix: call proto_unregister() in the error path in af_unix_init()
> 
> Richard Gobert <richardbgobert@gmail.com>
>    net: setsockopt: fix IPV6_UNICAST_IF option for connected sockets
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    hamradio: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> Hangbin Liu <liuhangbin@gmail.com>
>    net/tunnel: wait until all sk_user_data reader finish before releasing the sock
> 
> Li Zetao <lizetao1@huawei.com>
>    net: farsync: Fix kmemleak when rmmods farsync
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave()
> 
> ruanjinjie <ruanjinjie@huawei.com>
>    of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry() and find_dup_cset_prop()
> 
> Julian Anastasov <ja@ssi.bg>
>    ipvs: use u64_stats_t for the per-cpu counters
> 
> Thomas Gleixner <tglx@linutronix.de>
>    net: Remove the obsolte u64_stats_fetch_*_irq() users (net).
> 
> Yuan Can <yuancan@huawei.com>
>    drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    net: stmmac: fix possible memory leak in stmmac_dvr_probe()
> 
> Zhang Changzhong <zhangchangzhong@huawei.com>
>    net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload()
> 
> Yongqiang Liu <liuyongqiang13@huawei.com>
>    net: defxx: Fix missing err handling in dfx_init()
> 
> Artem Chernyshev <artem.chernyshev@red-soft.ru>
>    net: vmw_vsock: vmci: Check memcpy_from_msg()
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    clk: socfpga: Fix memory leak in socfpga_gate_init()
> 
> Björn Töpel <bjorn@rivosinc.com>
>    bpf: Do not zero-extend kfunc return values
> 
> Yang Jihong <yangjihong1@huawei.com>
>    blktrace: Fix output non-blktrace event when blk_classic option enabled
> 
> Wang Yufen <wangyufen@huawei.com>
>    wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware()
> 
> Bitterblue Smith <rtl8821cerfe2@gmail.com>
>    wifi: rtl8xxxu: Fix the channel width reporting
> 
> Bitterblue Smith <rtl8821cerfe2@gmail.com>
>    wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h
> 
> Kris Bahnsen <kris@embeddedTS.com>
>    spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    clk: samsung: Fix memory leak in _samsung_clk_register_pll()
> 
> Geert Uytterhoeven <geert+renesas@glider.be>
>    media: staging: stkwebcam: Restore MEDIA_{USB,CAMERA}_SUPPORT dependencies
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    media: coda: Add check for kmalloc
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    media: coda: Add check for dcoda_iram_alloc
> 
> Liang He <windhl@126.com>
>    media: c8sectpfe: Add of_node_put() when breaking out of loop
> 
> Yuan Can <yuancan@huawei.com>
>    regulator: qcom-labibb: Fix missing of_node_put() in qcom_labibb_regulator_probe()
> 
> Zhen Lei <thunder.leizhen@huawei.com>
>    mmc: core: Normalize the error handling branch in sd_read_ext_regs()
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    memstick/ms_block: Add check for alloc_ordered_workqueue
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    mmc: renesas_sdhi: alway populate SCC pointer
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: mmci: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: wbsd: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: via-sdmmc: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: meson-gx: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: omap_hsmmc: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: atmel-mci: fix return value check of mmc_add_host()
> 
> Gabriel Somlo <gsomlo@gmail.com>
>    mmc: litex_mmc: ensure `host->irq == 0` if polling
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: wmt-sdmmc: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: vub300: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: toshsd: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: rtsx_pci: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: pxamci: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: mxcmmc: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: moxart: fix return value check of mmc_add_host()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    mmc: alcor: fix return value check of mmc_add_host()
> 
> Miaoqian Lin <linmq006@gmail.com>
>    bpftool: Fix memory leak in do_build_table_cb
> 
> Pu Lehui <pulehui@huawei.com>
>    riscv, bpf: Emit fixed-length instructions for BPF_PSEUDO_FUNC
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4.x: Fail client initialisation if state manager thread can't run
> 
> Anna Schumaker <Anna.Schumaker@Netapp.com>
>    NFS: Allow very small rsize & wsize again
> 
> Anna Schumaker <Anna.Schumaker@Netapp.com>
>    NFSv4.2: Set the correct size scratch buffer for decoding READ_PLUS
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    SUNRPC: Fix missing release socket in rpc_sockname()
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    pinctrl: thunderbay: fix possible memory leak in thunderbay_build_functions()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt
> 
> Guoniu.zhou <guoniu.zhou@nxp.com>
>    media: ov5640: set correct default link frequency
> 
> Liu Shixin <liushixin2@huawei.com>
>    media: saa7164: fix missing pci_disable_device()
> 
> Takashi Iwai <tiwai@suse.de>
>    ALSA: pcm: Set missing stop_operating flag at undoing trigger start
> 
> Eric Dumazet <edumazet@google.com>
>    bpf, sockmap: fix race in sock_map_free()
> 
> Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>    hwmon: (jc42) Restore the min/max/critical temperatures on resume
> 
> Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>    hwmon: (jc42) Convert register access and caching to regmap/regcache
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    regulator: core: fix resource leak in regulator_register()
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    configfs: fix possible memory leak in configfs_create_dir()
> 
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>    hsr: Synchronize sequence number updates.
> 
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>    hsr: Synchronize sending frames to have always incremented outgoing seq nr.
> 
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>    hsr: Disable netpoll.
> 
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>    hsr: Avoid double remove of a node.
> 
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>    hsr: Add a rcu-read lock to hsr_forward_skb().
> 
> Sebastian Andrzej Siewior <bigeasy@linutronix.de>
>    Revert "net: hsr: use hlist_head instead of list_head for mac addresses"
> 
> Christian Marangi <ansuelsmth@gmail.com>
>    clk: qcom: clk-krait: fix wrong div2 functions
> 
> Douglas Anderson <dianders@chromium.org>
>    clk: qcom: lpass-sc7180: Fix pm_runtime usage
> 
> Douglas Anderson <dianders@chromium.org>
>    clk: qcom: lpass-sc7280: Fix pm_runtime usage
> 
> Taniya Das <quic_tdas@quicinc.com>
>    clk: qcom: lpass: Add support for resets & external mclk for SC7280
> 
> Taniya Das <quic_tdas@quicinc.com>
>    clk: qcom: lpass: Handle the regmap overlap of lpasscc and lpass_aon
> 
> Taniya Das <quic_tdas@quicinc.com>
>    dt-bindings: clock: Add support for external MCLKs for LPASS on SC7280
> 
> Taniya Das <quic_tdas@quicinc.com>
>    dt-bindings: clock: Add resets for LPASS audio clock controller for SC7280
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    regulator: core: fix module refcount leak in set_supply()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    mt76: mt7915: Fix PCI device refcount leak in mt7915_pci_init_hif2()
> 
> Deren Wu <deren.wu@mediatek.com>
>    wifi: mt76: fix coverity overrun-call in mt76_get_txpower()
> 
> Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
>    wifi: mt76: mt7915: Fix chainmask calculation on mt7915 DBDC
> 
> Shayne Chen <shayne.chen@mediatek.com>
>    wifi: mt76: mt7915: rework eeprom tx paths and streams init
> 
> Lorenzo Bianconi <lorenzo@kernel.org>
>    wifi: mt76: mt7921: fix reporting of TX AGGR histogram
> 
> Lorenzo Bianconi <lorenzo@kernel.org>
>    wifi: mt76: mt7915: fix reporting of TX AGGR histogram
> 
> Ryder Lee <ryder.lee@mediatek.com>
>    wifi: mt76: mt7915: fix mt7915_mac_set_timing()
> 
> Sean Wang <sean.wang@mediatek.com>
>    wifi: mt76: mt7921: fix antenna signal are way off in monitor mode
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys() fails
> 
> Íñigo Huguet <ihuguet@redhat.com>
>    wifi: mac80211: fix maybe-unused warning
> 
> Zhengchao Shao <shaozhengchao@huawei.com>
>    wifi: mac80211: fix memory leak in ieee80211_if_add()
> 
> Yuan Can <yuancan@huawei.com>
>    wifi: nl80211: Add checks for nla_nest_start() in nl80211_send_iface()
> 
> Alexander Sverdlin <alexander.sverdlin@siemens.com>
>    spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
> 
> Dan Carpenter <error27@gmail.com>
>    bonding: uninitialized variable in bond_miimon_inspect()
> 
> Pengcheng Yang <yangpc@wangsu.com>
>    bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect
> 
> Pengcheng Yang <yangpc@wangsu.com>
>    bpf, sockmap: Fix missing BPF_F_INGRESS flag when using apply_bytes
> 
> Pengcheng Yang <yangpc@wangsu.com>
>    bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data
> 
> Randy Dunlap <rdunlap@infradead.org>
>    Input: wistron_btns - disable on UML
> 
> Florian Westphal <fw@strlen.de>
>    netfilter: conntrack: set icmpv6 redirects as RELATED
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    clk: visconti: Fix memory leak in visconti_register_pll()
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe
> 
> Xia Fukun <xiafukun@huawei.com>
>    drm/i915/bios: fix a memory leak in generate_lfp_data_ptrs
> 
> Konstantin Meskhidze <konstantin.meskhidze@huawei.com>
>    drm/amdkfd: Fix memory leakage
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios()
> 
> Veerabadhran Gopalakrishnan <veerabadhran.gopalakrishnan@amd.com>
>    amdgpu/nv.c: Corrected typo in the video capabilities resolution
> 
> Guchun Chen <guchun.chen@amd.com>
>    drm/amd/pm/smu11: BACO is supported when it's in BACO state
> 
> Daniel Golle <daniel@makrotopia.org>
>    clk: mediatek: fix dependency of MT7986 ADC clocks
> 
> Ricardo Ribalda <ribalda@chromium.org>
>    ASoC: mediatek: mt8173: Enable IRQ when pdata is ready
> 
> zhichao.liu <zhichao.liu@mediatek.com>
>    spi: mt65xx: Add dma max segment size declaration
> 
> Ben Greear <greearb@candelatech.com>
>    wifi: iwlwifi: mvm: fix double free on tx path.
> 
> Bitterblue Smith <rtl8821cerfe2@gmail.com>
>    wifi: rtl8xxxu: Fix use after rcu_read_unlock in rtl8xxxu_bss_info_changed
> 
> Ziyang Xuan <william.xuanziyang@huawei.com>
>    wifi: plfxlc: fix potential memory leak in __lf_x_usb_enable_rx()
> 
> Liu Shixin <liushixin2@huawei.com>
>    ALSA: asihpi: fix missing pci_disable_device()
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFS: Fix an Oops in nfs_d_automount()
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4: Fix a credential leak in _nfs4_discover_trunking()
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4.2: Fix initialisation of struct nfs4_label
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4.2: Fix a memory stomp in decode_attr_security_label
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4.2: Always decode the security label
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    drm/msm/mdp5: fix reading hw revision on db410c platform
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd
> 
> Dmitry Torokhov <dmitry.torokhov@gmail.com>
>    ASoC: dt-bindings: wcd9335: fix reset line polarity in example
> 
> Zhang Zekun <zhangzekun11@huawei.com>
>    drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe()
> 
> Aakarsh Jain <aakarsh.jain@samsung.com>
>    media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC
> 
> Yunfei Dong <yunfei.dong@mediatek.com>
>    media: mediatek: vcodec: Core thread depends on core_list
> 
> Yunfei Dong <yunfei.dong@mediatek.com>
>    media: mediatek: vcodec: Setting lat buf to lat_list when lat decode error
> 
> Yunfei Dong <yunfei.dong@mediatek.com>
>    media: mediatek: vcodec: Fix h264 set lat buffer error
> 
> Yunfei Dong <yunfei.dong@mediatek.com>
>    media: mediatek: vcodec: Fix getting NULL pointer for dst buffer
> 
> Ming Qian <ming.qian@nxp.com>
>    media: amphion: lock and check m2m_ctx in event handler
> 
> Ming Qian <ming.qian@nxp.com>
>    media: amphion: cancel vpu before release instance
> 
> Ming Qian <ming.qian@nxp.com>
>    media: amphion: try to wakeup vpu core to avoid failure
> 
> Paul Kocialkowski <paul.kocialkowski@bootlin.com>
>    media: sun8i-a83t-mipi-csi2: Register async subdev with no sensor attached
> 
> Paul Kocialkowski <paul.kocialkowski@bootlin.com>
>    media: sun6i-mipi-csi2: Register async subdev with no sensor attached
> 
> Paul Kocialkowski <paul.kocialkowski@bootlin.com>
>    media: sun8i-a83t-mipi-csi2: Require both pads to be connected for streaming
> 
> Paul Kocialkowski <paul.kocialkowski@bootlin.com>
>    media: sun6i-mipi-csi2: Require both pads to be connected for streaming
> 
> Juergen Gross <jgross@suse.com>
>    x86/boot: Skip realmode init code when running as Xen PV guest
> 
> Baisong Zhong <zhongbaisong@huawei.com>
>    media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    media: dvb-core: Fix ignored return value in dvb_register_frontend()
> 
> ZhangPeng <zhangpeng362@huawei.com>
>    pinctrl: pinconf-generic: add missing of_node_put()
> 
> Dario Binacchi <dario.binacchi@amarulasolutions.com>
>    clk: imx8mn: fix imx8mn_enet_phy_sels clocks list
> 
> Dario Binacchi <dario.binacchi@amarulasolutions.com>
>    clk: imx8mn: fix imx8mn_sai2_sels clocks list
> 
> Dario Binacchi <dario.binacchi@amarulasolutions.com>
>    clk: imx: rename video_pll1 to video_pll
> 
> Dario Binacchi <dario.binacchi@amarulasolutions.com>
>    clk: imx: replace osc_hdmi with dummy
> 
> Dario Binacchi <dario.binacchi@amarulasolutions.com>
>    clk: imx8mn: rename vpu_pll to m7_alt_pll
> 
> Marek Vasut <marex@denx.de>
>    media: mt9p031: Drop bogus v4l2_subdev_get_try_crop() call from mt9p031_init_cfg()
> 
> Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>    media: imx: imx7-media-csi: Clear BIT_MIPI_DOUBLE_CMPNT for <16b formats
> 
> Gautam Menghani <gautammenghani201@gmail.com>
>    media: imon: fix a race condition in send_packet()
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    media: vimc: Fix wrong function called when vimc_init() fails
> 
> Yuan Can <yuancan@huawei.com>
>    ASoC: qcom: Add checks for devm_kcalloc
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    drbd: destroy workqueue when drbd device was freed
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    drbd: remove call to memset before free device/resource/connection
> 
> Zheng Yongjun <zhengyongjun3@huawei.com>
>    mtd: maps: pxa2xx-flash: fix memory leak in probe
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    mtd: core: Fix refcount error in del_mtd_device()
> 
> Jonathan Toppins <jtoppins@redhat.com>
>    bonding: fix link recovery in mode 2 when updelay is nonzero
> 
> Stanislav Fomichev <sdf@google.com>
>    selftests/bpf: Mount debugfs in setns_by_fd
> 
> Stanislav Fomichev <sdf@google.com>
>    selftests/bpf: Make sure zero-len skbs aren't redirectable
> 
> Jani Nikula <jani.nikula@intel.com>
>    drm/i915/guc: make default_lists const data
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    drm/amdgpu: fix pci device refcount leak
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    clk: rockchip: Fix memory leak in rockchip_clk_register_pll()
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    regulator: core: use kfree_const() to free space conditionally
> 
> Baisong Zhong <zhongbaisong@huawei.com>
>    ALSA: seq: fix undefined behavior in bit shift for SNDRV_SEQ_FILTER_USE_EVENT
> 
> Baisong Zhong <zhongbaisong@huawei.com>
>    ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT
> 
> Cezary Rojewski <cezary.rojewski@intel.com>
>    ASoC: Intel: avs: Lock substream before snd_pcm_stop()
> 
> Zong-Zhe Yang <kevin_yang@realtek.com>
>    wifi: rtw89: fix physts IE page check
> 
> ZhangPeng <zhangpeng362@huawei.com>
>    pinctrl: k210: call of_node_put()
> 
> Giulio Benetti <giulio.benetti@benettiengineering.com>
>    clk: imx: imxrt1050: fix IMXRT1050_CLK_LCDIF_APB offsets
> 
> Marcus Folkesson <marcus.folkesson@gmail.com>
>    HID: hid-sensor-custom: set fixed size for custom attributes
> 
> Stanislav Fomichev <sdf@google.com>
>    bpf: Move skb->len == 0 checks into __bpf_redirect
> 
> Peng Fan <peng.fan@nxp.com>
>    clk: imx93: correct enet clock
> 
> Peng Fan <peng.fan@nxp.com>
>    clk: imx93: unmap anatop base in error handling path
> 
> Dmitry Torokhov <dmitry.torokhov@gmail.com>
>    HID: i2c: let RMI devices decide what constitutes wakeup event
> 
> Haibo Chen <haibo.chen@nxp.com>
>    clk: imx93: correct the flexspi1 clock setting
> 
> Allen-KH Cheng <allen-kh.cheng@mediatek.com>
>    mtd: spi-nor: Fix the number of bytes for the dummy cycles
> 
> Michael Walle <michael@walle.cc>
>    mtd: spi-nor: hide jedec_id sysfs attribute if not present
> 
> Kuniyuki Iwashima <kuniyu@amazon.com>
>    net: Return errno in sk->sk_prot->get_port().
> 
> Kuniyuki Iwashima <kuniyu@amazon.com>
>    udp: Clean up some functions.
> 
> Lorenzo Bianconi <lorenzo@kernel.org>
>    net: ethernet: mtk_eth_soc: fix RSTCTRL_PPE{0,1} definitions
> 
> Christoph Hellwig <hch@lst.de>
>    media: videobuf-dma-contig: use dma_mmap_coherent
> 
> Yuan Can <yuancan@huawei.com>
>    media: amphion: Fix error handling in vpu_driver_init()
> 
> Yuan Can <yuancan@huawei.com>
>    media: platform: exynos4-is: Fix error handling in fimc_md_init()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    media: solo6x10: fix possible memory leak in solo_sysfs_init()
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    media: vidtv: Fix use-after-free in vidtv_bridge_dvb_init()
> 
> Ming Qian <ming.qian@nxp.com>
>    media: amphion: apply vb2_queue_error instead of setting manually
> 
> Ming Qian <ming.qian@nxp.com>
>    media: amphion: add lock around vdec_g_fmt
> 
> Lorenzo Bianconi <lorenzo@kernel.org>
>    net: ethernet: mtk_eth_soc: do not overwrite mtu configuration running reset routine
> 
> Douglas Anderson <dianders@chromium.org>
>    Input: elants_i2c - properly handle the reset GPIO when power is off
> 
> Hui Tang <tanghui20@huawei.com>
>    mtd: lpddr2_nvm: Fix possible null-ptr-deref
> 
> Rob Clark <robdclark@chromium.org>
>    drm/msm/a6xx: Fix speed-bin detection vs probe-defer
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    wifi: ath10k: Fix return value in ath10k_pci_init()
> 
> Wang Yufen <wangyufen@huawei.com>
>    selftests/bpf: fix memory leak of lsm_cgroup
> 
> Christoph Hellwig <hch@lst.de>
>    dm: track per-add_disk holder relations in DM
> 
> Yu Kuai <yukuai3@huawei.com>
>    dm: make sure create and remove dm device won't race with open and close table
> 
> Christoph Hellwig <hch@lst.de>
>    dm: cleanup close_table_device
> 
> Christoph Hellwig <hch@lst.de>
>    dm: cleanup open_table_device
> 
> Christoph Hellwig <hch@lst.de>
>    block: clear ->slave_dir when dropping the main slave_dir reference
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    ima: Fix misuse of dereference of pointer in template_desc_init_fields()
> 
> GUO Zihua <guozihua@huawei.com>
>    integrity: Fix memory leakage in keyring allocation error path
> 
> Brian Starkey <brian.starkey@arm.com>
>    drm/fourcc: Fix vsub/hsub for Q410 and Q401
> 
> Konrad Dybcio <konrad.dybcio@linaro.org>
>    regulator: qcom-rpmh: Fix PMR735a S3 regulator spec
> 
> Christophe JAILLET <christophe.jaillet@wanadoo.fr>
>    wifi: rtw89: Fix some error handling path in rtw89_core_sta_assoc()
> 
> Joel Granados <j.granados@samsung.com>
>    nvme: return err on nvme_init_non_mdts_limits fail
> 
> Dan Carpenter <error27@gmail.com>
>    amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    regulator: core: fix unbalanced of node refcount in regulator_dev_lookup()
> 
> Christoph Hellwig <hch@lst.de>
>    nvmet: only allocate a single slab for bvecs
> 
> Zeng Heng <zengheng4@huawei.com>
>    ASoC: pxa: fix null-pointer dereference in filter()
> 
> Xinlei Lee <xinlei.lee@mediatek.com>
>    drm/mediatek: Modify dpi power on/off sequence.
> 
> Yang Jihong <yangjihong1@huawei.com>
>    selftests/bpf: Fix xdp_synproxy compilation failure in 32-bit arch
> 
> Randy Dunlap <rdunlap@infradead.org>
>    ASoC: codecs: wsa883x: use correct header file
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    ASoC: codecs: wsa883x: Use proper shutdown GPIO polarity
> 
> Miaoqian Lin <linmq006@gmail.com>
>    module: Fix NULL vs IS_ERR checking for module_get_next_page
> 
> Johannes Berg <johannes.berg@intel.com>
>    wifi: iwlwifi: mei: fix potential NULL-ptr deref after clone
> 
> Avraham Stern <avraham.stern@intel.com>
>    wifi: iwlwifi: mei: avoid blocking sap messages handling due to rtnl lock
> 
> Emmanuel Grumbach <emmanuel.grumbach@intel.com>
>    wifi: iwlwifi: mei: fix tx DHCP packet for devices with new Tx API
> 
> Emmanuel Grumbach <emmanuel.grumbach@intel.com>
>    wifi: iwlwifi: mei: don't send SAP commands if AMT is disabled
> 
> Avraham Stern <avraham.stern@intel.com>
>    wifi: iwlwifi: mei: make sure ownership confirmed message is sent
> 
> Sam Shih <sam.shih@mediatek.com>
>    pinctrl: mediatek: fix the pinconf register offset of some pins
> 
> Frank Wunderlich <frank-w@public-files.de>
>    dt-bindings: pinctrl: update uart/mmc bindings for MT7986 SoC
> 
> Hanjun Guo <guohanjun@huawei.com>
>    drm/radeon: Add the missed acpi_put_table() to fix memory leak
> 
> Khazhismel Kumykov <khazhy@chromium.org>
>    bfq: fix waker_bfqq inconsistency crash
> 
> Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
>    drbd: use blk_queue_max_discard_sectors helper
> 
> Yassine Oudjana <y.oudjana@protonmail.com>
>    regmap-irq: Use the new num_config_regs property in regmap_add_irq_chip_fwnode
> 
> Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>    drm: rcar-du: Drop leftovers dependencies from Kconfig
> 
> Ping-Ke Shih <pkshih@realtek.com>
>    wifi: rtw89: use u32_encode_bits() to fill MAC quota value
> 
> Marek Vasut <marex@denx.de>
>    drm: lcdif: Set and enable FIFO Panic threshold
> 
> David Howells <dhowells@redhat.com>
>    rxrpc: Fix ack.bufferSize to be 0 when generating an ack
> 
> David Howells <dhowells@redhat.com>
>    net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write()
> 
> Cole Robinson <crobinso@redhat.com>
>    virt/sev-guest: Add a MODULE_ALIAS
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    clk: renesas: r8a779f0: Fix SCIF parent clocks
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    clk: renesas: r8a779f0: Fix HSCIF parent clocks
> 
> Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
>    media: camss: Do not attach an already attached power domain on MSM8916 platform
> 
> Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
>    media: camss: Clean up received buffers on failed start of streaming
> 
> Marek Vasut <marex@denx.de>
>    wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port
> 
> Randy Dunlap <rdunlap@infradead.org>
>    Input: joystick - fix Kconfig warning for JOYSTICK_ADC
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    mtd: core: fix possible resource leak in init_mtd()
> 
> Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
>    mtd: Fix device name leak when register device failed in add_mtd_device()
> 
> Manivannan Sadhasivam <mani@kernel.org>
>    clk: qcom: gcc-sm8250: Use retention mode for USB GDSCs
> 
> Konrad Dybcio <konrad.dybcio@somainline.org>
>    clk: qcom: dispcc-sm6350: Add CLK_OPS_PARENT_ENABLE to pixel&byte src
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    clk: qcom: gcc-ipq806x: use parent_data for the last remaining entry
> 
> Andrii Nakryiko <andrii@kernel.org>
>    bpf: propagate precision across all frames, not just the last one
> 
> Andrii Nakryiko <andrii@kernel.org>
>    bpf: propagate precision in ALU/ALU64 operations
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    media: platform: exynos4-is: fix return value check in fimc_md_probe()
> 
> Liu Shixin <liushixin2@huawei.com>
>    media: vivid: fix compose size exceed boundary
> 
> Andrzej Pietrasiewicz <andrzej.p@collabora.com>
>    media: rkvdec: Add required padding
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Prevent signed BPG offsets from bleeding into adjacent bits
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Disallow 8 BPC DSC configuration for alternative BPC values
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Account for DSC's bits_per_pixel having 4 fractional bits
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Migrate to drm_dsc_compute_rc_parameters()
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Appropriately set dsc->mux_word_size based on bpc
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Reuse earlier computed dsc->slice_chunk_size
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Use DIV_ROUND_UP instead of conditional increment on modulo
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Remove repeated calculation of slice_per_intf
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dsi: Remove useless math in DSC calculations
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    drm/msm/dsi: use drm_dsc_config instead of msm_display_dsc_config
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    drm/msm/dpu1: Account for DSC's bits_per_pixel having 4 fractional bits
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    drm/msm/dpu: use drm_dsc_config instead of msm_display_dsc_config
> 
> Kumar Kartikeya Dwivedi <memxor@gmail.com>
>    bpf: Fix slot type check in check_stack_write_var_off
> 
> Kumar Kartikeya Dwivedi <memxor@gmail.com>
>    bpf: Clobber stack slot when writing over spilled PTR_TO_BTF_ID
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    drm/msm/hdmi: use devres helper for runtime PM management
> 
> GUO Zihua <guozihua@huawei.com>
>    ima: Handle -ESTALE returned by ima_filter_rule_match()
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    drm/msm/mdp5: stop overriding drvdata
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    drm/ttm: fix undefined behavior in bit shift for TTM_TT_FLAG_PRIV_POPULATED
> 
> Marek Vasut <marex@denx.de>
>    drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure
> 
> Jonathan Neuschäfer <j.neuschaefer@gmx.net>
>    spi: Update reference to struct spi_controller
> 
> Marco Felsch <m.felsch@pengutronix.de>
>    drm: lcdif: change burst size to 256B
> 
> Marek Vasut <marex@denx.de>
>    clk: renesas: r9a06g032: Repair grave increment error
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    drm/rockchip: lvds: fix PM usage counter unbalance in poweron
> 
> Haiyi Zhou <Haiyi.Zhou@amd.com>
>    drm/amd/display: wait for vblank during pipe programming
> 
> Sakari Ailus <sakari.ailus@linux.intel.com>
>    dw9768: Enable low-power probe on ACPI
> 
> Alan Previn <alan.previn.teres.alexis@intel.com>
>    drm/i915/guc: Fix GuC error capture sizing estimation and reporting
> 
> Alan Previn <alan.previn.teres.alexis@intel.com>
>    drm/i915/guc: Add error-capture init warnings when needed
> 
> John Harrison <John.C.Harrison@Intel.com>
>    drm/i915/guc: Make GuC log sizes runtime configurable
> 
> John Harrison <John.C.Harrison@Intel.com>
>    drm/i915/guc: Fix capture size warning and bump the size
> 
> Alan Previn <alan.previn.teres.alexis@intel.com>
>    drm/i915/guc: Add a helper for log buffer size
> 
> Nícolas F. R. A. Prado <nfraprado@collabora.com>
>    ASoC: dt-bindings: rt5682: Set sound-dai-cells to 1
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    clk: renesas: r8a779a0: Fix SD0H clock name
> 
> Jimmy Assarsson <extja@kvaser.com>
>    can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming
> 
> Jimmy Assarsson <extja@kvaser.com>
>    can: kvaser_usb: Add struct kvaser_usb_busparams
> 
> Anssi Hannula <anssi.hannula@bitwise.fi>
>    can: kvaser_usb_leaf: Fix bogus restart events
> 
> Anssi Hannula <anssi.hannula@bitwise.fi>
>    can: kvaser_usb_leaf: Fix wrong CAN state after stopping
> 
> Anssi Hannula <anssi.hannula@bitwise.fi>
>    can: kvaser_usb_leaf: Fix improved state not being reported
> 
> Anssi Hannula <anssi.hannula@bitwise.fi>
>    can: kvaser_usb_leaf: Set Warning state even without bus errors
> 
> Jimmy Assarsson <extja@kvaser.com>
>    can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT
> 
> Jimmy Assarsson <extja@kvaser.com>
>    can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event
> 
> Jimmy Assarsson <extja@kvaser.com>
>    can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
> 
> Alan Maguire <alan.maguire@oracle.com>
>    libbpf: Btf dedup identical struct test needs check for nested structs/arrays
> 
> Marek Szyprowski <m.szyprowski@samsung.com>
>    media: exynos4-is: don't rely on the v4l2_async_subdev internals
> 
> Rafael Mendonca <rafaelmendsr@gmail.com>
>    media: i2c: ov5648: Free V4L2 fwnode data on unbind
> 
> Kuniyuki Iwashima <kuniyu@amazon.com>
>    soreuseport: Fix socket selection for SO_INCOMING_CPU.
> 
> Tang Bin <tangbin@cmss.chinamobile.com>
>    venus: pm_helpers: Fix error check in vcodec_domains_get()
> 
> Ricardo Ribalda <ribalda@chromium.org>
>    media: i2c: ad5820: Fix error path
> 
> Rafael Mendonca <rafaelmendsr@gmail.com>
>    media: i2c: hi846: Fix memory leak in hi846_parse_dt()
> 
> John Harrison <John.C.Harrison@Intel.com>
>    drm/i915: Fix compute pre-emption w/a to apply to compute engines
> 
> John Harrison <John.C.Harrison@Intel.com>
>    drm/i915/guc: Limit scheduling properties to avoid overflow
> 
> Yunfei Dong <yunfei.dong@mediatek.com>
>    media: mediatek: vcodec: fix h264 cavlc bitstream fail
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    media: cedrus: hevc: Fix offset adjustments
> 
> Jernej Skrabec <jernej.skrabec@gmail.com>
>    media: v4l2-ioctl.c: Unify YCbCr/YUV terms in format descriptions
> 
> Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
>    media: adv748x: afe: Select input port when initializing AFE
> 
> Ming Qian <ming.qian@nxp.com>
>    media: amphion: reset instance if it's aborted before codec header parsed
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    media: coda: jpeg: Add check for kmalloc
> 
> Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
>    media: v4l2-ctrls: Fix off-by-one error in integer menu control check
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - protect against undefined slider size
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - report malformed properties
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - drop unused device node references
> 
> Jeff LaBundy <jeff@labundy.com>
>    Input: iqs7222 - set all ULP entry masks by default
> 
> Pin-yen Lin <treapking@chromium.org>
>    drm/bridge: it6505: Initialize AUX channel in it6505_i2c_probe
> 
> Gerhard Engleder <gerhard@engleder-embedded.com>
>    samples/bpf: Fix MAC address swapping in xdp2_kern
> 
> Gerhard Engleder <gerhard@engleder-embedded.com>
>    samples/bpf: Fix map iteration in xdp1_user
> 
> Rafael Mendonca <rafaelmendsr@gmail.com>
>    drm/amdgpu/powerplay/psm: Fix memory leak in power state init
> 
> Andrew Jeffery <andrew@aj.id.au>
>    ipmi: kcs: Poll OBF briefly to reduce OBE latency
> 
> Cezary Rojewski <cezary.rojewski@intel.com>
>    ASoC: Intel: avs: Fix potential RX buffer overflow
> 
> Cezary Rojewski <cezary.rojewski@intel.com>
>    ASoC: Intel: avs: Fix DMA mask assignment
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    pinctrl: ocelot: add missing destroy_workqueue() in error path in ocelot_pinctrl_probe()
> 
> Niklas Cassel <niklas.cassel@wdc.com>
>    ata: libata: fix NCQ autosense logic
> 
> Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>    drm: lcdif: Switch to limited range for RGB to YUV conversion
> 
> Shung-Hsi Yu <shung-hsi.yu@suse.com>
>    libbpf: Fix null-pointer dereference in find_prog_by_sec_insn()
> 
> Shung-Hsi Yu <shung-hsi.yu@suse.com>
>    libbpf: Deal with section with no data gracefully
> 
> Shung-Hsi Yu <shung-hsi.yu@suse.com>
>    libbpf: Use elf_getshdrnum() instead of e_shnum
> 
> Andrii Nakryiko <andrii@kernel.org>
>    libbpf: Reject legacy 'maps' ELF section
> 
> Xu Kuohai <xukuohai@huawei.com>
>    selftest/bpf: Fix error usage of ASSERT_OK in xdp_adjust_tail.c
> 
> Xu Kuohai <xukuohai@huawei.com>
>    selftests/bpf: Fix error failure of case test_xdp_adjust_tail_grow
> 
> Xu Kuohai <xukuohai@huawei.com>
>    selftest/bpf: Fix memory leak in kprobe_multi_test
> 
> Xu Kuohai <xukuohai@huawei.com>
>    selftests/bpf: Fix memory leak caused by not destroying skeleton
> 
> Yonghong Song <yhs@fb.com>
>    selftests/bpf: Add struct argument tests with fentry/fexit programs.
> 
> Xu Kuohai <xukuohai@huawei.com>
>    libbpf: Fix memory leak in parse_usdt_arg()
> 
> Xu Kuohai <xukuohai@huawei.com>
>    libbpf: Fix use-after-free in btf_dump_name_dups
> 
> Abhinav Kumar <quic_abhinavk@quicinc.com>
>    drm/bridge: adv7533: remove dynamic lane switching from adv7533 bridge
> 
> Aditya Kumar Singh <quic_adisi@quicinc.com>
>    wifi: ath11k: fix firmware assert during bandwidth change for peer sta
> 
> Aditya Kumar Singh <quic_adisi@quicinc.com>
>    wifi: ath11k: move firmware stats out of debugfs
> 
> Bitterblue Smith <rtl8821cerfe2@gmail.com>
>    wifi: rtl8xxxu: Fix reading the vendor of combo chips
> 
> Fedor Pchelkin <pchelkin@ispras.ru>
>    wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb()
> 
> Fedor Pchelkin <pchelkin@ispras.ru>
>    wifi: ath9k: hif_usb: fix memory leak of urbs in ath9k_hif_usb_dealloc_tx_urbs()
> 
> Thomas Zimmermann <tzimmermann@suse.de>
>    drm/atomic-helper: Don't allocate new plane state in CRTC check
> 
> Johannes Berg <johannes.berg@intel.com>
>    wifi: mac80211: fix ifdef symbol name
> 
> Johannes Berg <johannes.berg@intel.com>
>    wifi: mac80211: check link ID in auth/assoc continuation
> 
> Johannes Berg <johannes.berg@intel.com>
>    wifi: mac80211: mlme: fix null-ptr deref on failed assoc
> 
> Johannes Berg <johannes.berg@intel.com>
>    wifi: fix multi-link element subelement iteration
> 
> James Hurley <jahurley@nvidia.com>
>    platform/mellanox: mlxbf-pmc: Fix event typo
> 
> Zhengchao Shao <shaozhengchao@huawei.com>
>    ipc: fix memory leak in init_mqueue_fs()
> 
> Cai Xinchen <caixinchen1@huawei.com>
>    rapidio: devices: fix missing put_device in mport_cdev_open
> 
> ZhangPeng <zhangpeng362@huawei.com>
>    hfs: Fix OOB Write in hfs_asc2mac
> 
> Gavrilov Ilia <Ilia.Gavrilov@infotecs.ru>
>    relay: fix type mismatch when allocating memory in relay_create_buf()
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD
> 
> Wang Weiyang <wangweiyang2@huawei.com>
>    rapidio: fix possible UAF when kfifo_alloc() fails
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    fs: sysv: Fix sysv_nblocks() returns wrong value
> 
> Brian Foster <bfoster@redhat.com>
>    NFSD: pass range end to vfs_fsync_range() instead of count
> 
> Jeff Layton <jlayton@kernel.org>
>    nfsd: return error if nfs4_setacl fails
> 
> Trond Myklebust <trond.myklebust@hammerspace.com>
>    lockd: set other missing fields when unlocking files
> 
> Ladislav Michl <ladis@linux-mips.org>
>    MIPS: OCTEON: warn only once if deprecated link status is being used
> 
> Anastasia Belova <abelova@astralinux.ru>
>    MIPS: BCM63xx: Add check for NULL for clk in clk_enable
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    platform/x86: intel_scu_ipc: fix possible name leak in __intel_scu_ipc_register()
> 
> Yu Liao <liaoyu15@huawei.com>
>    platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]()
> 
> Victor Ding <victording@chromium.org>
>    platform/chrome: cros_ec_typec: zero out stale pointers
> 
> Prashant Malani <pmalani@chromium.org>
>    platform/chrome: cros_ec_typec: Get retimer handle
> 
> Prashant Malani <pmalani@chromium.org>
>    platform/chrome: cros_ec_typec: Cleanup switch handle return paths
> 
> Gao Xiang <xiang@kernel.org>
>    erofs: validate the extent length for uncompressed pclusters
> 
> Yue Hu <huyue2@coolpad.com>
>    erofs: support interlaced uncompressed data for compressed files
> 
> Gao Xiang <xiang@kernel.org>
>    erofs: fix missing unmap if z_erofs_get_extent_compressedlen() fails
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    erofs: Fix pcluster memleak when its block address is zero
> 
> Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>    PM: runtime: Do not call __rpm_callback() from rpm_idle()
> 
> Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
>    xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource()
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    x86/xen: Fix memory leak in xen_init_lock_cpu()
> 
> Xiu Jianfeng <xiujianfeng@huawei.com>
>    x86/xen: Fix memory leak in xen_smp_intr_init{_pv}()
> 
> Oleg Nesterov <oleg@redhat.com>
>    uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix
> 
> Li Zetao <lizetao1@huawei.com>
>    ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    clocksource/drivers/timer-ti-dm: Fix missing clk_disable_unprepare in dmtimer_systimer_init_clock()
> 
> Tony Lindgren <tony@atomide.com>
>    clocksource/drivers/timer-ti-dm: Fix warning for omap_timer_match
> 
> Vincent Donnefort <vdonnefort@google.com>
>    cpu/hotplug: Do not bail-out in DYING/STARTING sections
> 
> Phil Auld <pauld@redhat.com>
>    cpu/hotplug: Make target_store() a nop when target == state
> 
> Alexey Izbyshev <izbyshev@ispras.ru>
>    futex: Resend potentially swallowed owner death notification
> 
> John Thomson <git@johnthomson.fastmail.com.au>
>    mips: ralink: mt7621: do not use kzalloc too early
> 
> John Thomson <git@johnthomson.fastmail.com.au>
>    mips: ralink: mt7621: soc queries and tests as functions
> 
> John Thomson <git@johnthomson.fastmail.com.au>
>    mips: ralink: mt7621: define MT7621_SYSC_BASE with __iomem
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    clocksource/drivers/sh_cmt: Access registers according to spec
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    rapidio: rio: fix possible name leak in rio_register_mport()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    rapidio: fix possible name leaks when rio_add_device() fails
> 
> Li Zetao <ocfs2-devel@oss.oracle.com>
>    ocfs2: fix memory leak in ocfs2_mount_volume()
> 
> Akinobu Mita <akinobu.mita@gmail.com>
>    debugfs: fix error when writing negative value to atomic_t debugfs file
> 
> Akinobu Mita <akinobu.mita@gmail.com>
>    lib/notifier-error-inject: fix error when writing -errno to debugfs file
> 
> Akinobu Mita <akinobu.mita@gmail.com>
>    libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    cpufreq: amd_freq_sensitivity: Add missing pci_dev_put()
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    genirq/irqdesc: Don't try to remove non-existing sysfs files
> 
> Jeff Layton <jlayton@kernel.org>
>    nfsd: don't call nfsd_file_put from client states seqfile display
> 
> Chuck Lever <chuck.lever@oracle.com>
>    NFSD: Finish converting the NFSv3 GETACL result encoder
> 
> Chuck Lever <chuck.lever@oracle.com>
>    NFSD: Finish converting the NFSv2 GETACL result encoder
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper()
> 
> Liu Peibao <liupeibao@loongson.cn>
>    irqchip/loongson-liointc: Fix improper error handling in liointc_init()
> 
> Wei Yongjun <weiyongjun1@huawei.com>
>    irqchip/wpcm450: Fix memory leak in wpcm450_aic_of_init()
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe()
> 
> Jianmin Lv <lvjianmin@loongson.cn>
>    irqchip/loongson-pch-pic: Fix translate callback for DT path
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    thermal: core: fix some possible name leaks in error paths
> 
> Yuan Can <yuancan@huawei.com>
>    platform/chrome: cros_usbpd_notify: Fix error handling in cros_usbpd_notify_init()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    perf/x86/intel/uncore: Fix reference count leak in __uncore_imc_init_box()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    perf/x86/intel/uncore: Fix reference count leak in snr_uncore_mmio_map()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox()
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    perf/x86/intel/uncore: Fix reference count leak in sad_cfg_iio_topology()
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    ACPI: pfr_update: use ACPI_FREE() to free acpi_object
> 
> Wang ShaoBo <bobo.shaobowang@huawei.com>
>    ACPI: pfr_telemetry: use ACPI_FREE() to free acpi_object
> 
> Huisong Li <lihuisong@huawei.com>
>    mailbox: pcc: Reset pcc_chan_count to zero in case of PCC probe failure
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    PNP: fix name memory leak in pnp_alloc_dev()
> 
> Zhao Gongyi <zhaogongyi@huawei.com>
>    selftests/efivarfs: Add checking of the test return value
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    MIPS: vpe-cmp: fix possible memory leak while module exiting
> 
> Yang Yingliang <yangyingliang@huawei.com>
>    MIPS: vpe-mt: fix possible memory leak while module exiting
> 
> Manivannan Sadhasivam <mani@kernel.org>
>    cpufreq: qcom-hw: Fix the frequency returned by cpufreq_driver->get()
> 
> YueHaibing <yuehaibing@huawei.com>
>    selftests: cgroup: fix unsigned comparison with less than zero
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    ocfs2: fix memory leak in ocfs2_stack_glue_init()
> 
> Gaosheng Cui <cuigaosheng1@huawei.com>
>    lib/fonts: fix undefined behavior in bit shift for get_default_font
> 
> Alexey Dobriyan <adobriyan@gmail.com>
>    proc: fixup uptime selftest
> 
> Barnabás Pőcze <pobrn@protonmail.com>
>    timerqueue: Use rb_entry_safe() in timerqueue_getnext()
> 
> Barnabás Pőcze <pobrn@protonmail.com>
>    platform/x86: huawei-wmi: fix return value calculation
> 
> wuchi <wuchi.zero@gmail.com>
>    lib/debugobjects: fix stat count and optimize debug_objects_mem_init
> 
> Chen Zhongjin <chenzhongjin@huawei.com>
>    perf: Fix possible memleak in pmu_dev_alloc()
> 
> Yipeng Zou <zouyipeng@huawei.com>
>    selftests/ftrace: event_triggers: wait longer for test_event_enable
> 
> Xiongfeng Wang <wangxiongfeng2@huawei.com>
>    ACPI: irq: Fix some kernel-doc issues
> 
> Guilherme G. Piccoli <gpiccoli@igalia.com>
>    x86/split_lock: Add sysctl to control the misery mode
> 
> Chen Hui <judy.chenhui@huawei.com>
>    cpufreq: qcom-hw: Fix memory leak in qcom_cpufreq_hw_read_lut()
> 
> Ondrej Mosnacek <omosnace@redhat.com>
>    fs: don't audit the capability check in simple_xattr_list()
> 
> xiongxin <xiongxin@kylinos.cn>
>    PM: hibernate: Fix mistake in kerneldoc comment
> 
> Reinette Chatre <reinette.chatre@intel.com>
>    x86/sgx: Reduce delay and interference of enclave release
> 
> Hao Lee <haolee.swjtu@gmail.com>
>    sched/psi: Fix possible missing or delayed pending event
> 
> Al Viro <viro@zeniv.linux.org.uk>
>    alpha: fix syscall entry in !AUDUT_SYSCALL case
> 
> Al Viro <viro@zeniv.linux.org.uk>
>    alpha: fix TIF_NOTIFY_SIGNAL handling
> 
> Ulf Hansson <ulf.hansson@linaro.org>
>    cpuidle: dt: Return the correct numbers of parsed idle states
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Cater for uclamp in find_energy_efficient_cpu()'s early exit condition
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Make cpu_overutilized() use util_fits_cpu()
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Make asym_fits_capacity() use util_fits_cpu()
> 
> Dietmar Eggemann <dietmar.eggemann@arm.com>
>    sched/core: Introduce sched_asym_cpucap_active()
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Make select_idle_capacity() use util_fits_cpu()
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Fix fits_capacity() check in feec()
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Make task_fits_capacity() use util_fits_cpu()
> 
> Qais Yousef <qais.yousef@arm.com>
>    sched/uclamp: Fix relationship between uclamp and migration margin
> 
> Amir Goldstein <amir73il@gmail.com>
>    ovl: remove privs in ovl_fallocate()
> 
> Amir Goldstein <amir73il@gmail.com>
>    ovl: remove privs in ovl_copyfile()
> 
> Michael Kelley <mikelley@microsoft.com>
>    tpm/tpm_crb: Fix error message in __crb_relinquish_locality()
> 
> Yuan Can <yuancan@huawei.com>
>    tpm/tpm_ftpm_tee: Fix error handling in ftpm_mod_init()
> 
> Eddie James <eajames@linux.ibm.com>
>    tpm: Add flag to use default cancellation policy
> 
> Eddie James <eajames@linux.ibm.com>
>    tpm: tis_i2c: Fix sanity check interrupt enable mask
> 
> Janne Grunau <j@jannau.net>
>    arch: arm64: apple: t8103: Use standard "iommu" node name
> 
> Stephen Boyd <swboyd@chromium.org>
>    pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
> 
> Doug Brown <doug@schmorgal.com>
>    ARM: mmp: fix timer_read delay
> 
> Wang Yufen <wangyufen@huawei.com>
>    pstore/ram: Fix error return code in ramoops_probe()
> 
> Kuniyuki Iwashima <kuniyu@amazon.com>
>    seccomp: Move copy_seccomp() to no failure path.
> 
> Yicong Yang <yangyicong@hisilicon.com>
>    drivers/perf: hisi: Fix some event id for hisi-pcie-pmu
> 
> Sven Peter <sven@svenpeter.dev>
>    soc: apple: rtkit: Stop casting function pointer signatures
> 
> Sven Peter <sven@svenpeter.dev>
>    soc: apple: sart: Stop casting function pointer signatures
> 
> Pali Rohár <pali@kernel.org>
>    arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-39x: Fix compatible string for gpios
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-38x: Fix compatible string for gpios
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: turris-omnia: Add switch port 6 node
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: turris-omnia: Add ethernet aliases
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port
> 
> Pali Rohár <pali@kernel.org>
>    ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mediatek: pumpkin-common: Fix devicetree warnings
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mt2712-evb: Fix usb vbus regulators unit names
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mt2712e: Fix unit address for pinctrl node
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mt6779: Fix devicetree build warnings
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mt7896a: Fix unit_address_vs_reg warning for oscillator
> 
> AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>    arm64: dts: mediatek: mt8195: Fix CPUs capacity-dmips-mhz
> 
> Jonathan Neuschäfer <j.neuschaefer@gmx.net>
>    ARM: dts: nuvoton: Remove bogus unit addresses from fixed-partition nodes
> 
> Keerthy <j-keerthy@ti.com>
>    arm64: dts: ti: k3-j721s2: Fix the interrupt ranges property for main & wkup gpio intr
> 
> Jayesh Choudhary <j-choudhary@ti.com>
>    arm64: dts: ti: k3-j721e-main: Drop dma-coherent in crypto node
> 
> Jayesh Choudhary <j-choudhary@ti.com>
>    arm64: dts: ti: k3-am65-main: Drop dma-coherent in crypto node
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init()
> 
> Shang XiaoJing <shangxiaojing@huawei.com>
>    perf/arm_dmc620: Fix hotplug callback leak in dmc620_pmu_init()
> 
> Yuan Can <yuancan@huawei.com>
>    drivers: perf: marvell_cn10k: Fix hotplug callback leak in tad_pmu_init()
> 
> Yuan Can <yuancan@huawei.com>
>    perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init()
> 
> Mark Rutland <mark.rutland@arm.com>
>    arm64: mm: kfence: only handle translation faults
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe
> 
> Zhang Qilong <zhangqilong3@huawei.com>
>    soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe
> 
> Kory Maincent <kory.maincent@bootlin.com>
>    arm: dts: spear600: Fix clcd interrupt
> 
> Frank Wunderlich <frank-w@public-files.de>
>    arm64: dts: mt7986: fix trng node name
> 
> Conor Dooley <conor.dooley@microchip.com>
>    dt-bindings: pwm: fix microchip corePWM's pwm-cells
> 
> Fabrizio Castro <fabrizio.castro.jz@renesas.com>
>    arm64: dts: renesas: r9a09g011: Fix unit address format error
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    arm64: dts: renesas: r8a779f0: Fix SCIF "brg_int" clock
> 
> Wolfram Sang <wsa+renesas@sang-engineering.com>
>    arm64: dts: renesas: r8a779f0: Fix HSCIF "brg_int" clock
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sm6125: fix SDHCI CQE reg names
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    arm64: dts: qcom: pm6350: Include header for KEY_POWER
> 
> Jiasheng Jiang <jiasheng@iscas.ac.cn>
>    soc: qcom: apr: Add check for idr_alloc and of_property_read_string_index
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm6350: drop bogus DP PHY clock
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm8250: drop bogus DP PHY clock
> 
> Dmitry Torokhov <dmitry.torokhov@gmail.com>
>    arm64: dts: qcom: sm8250-mtp: fix reset line polarity
> 
> Dmitry Torokhov <dmitry.torokhov@gmail.com>
>    arm64: dts: qcom: msm8996: fix sound card reset line polarity
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: use GPIO flags for tlmm
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm8450: fix UFS PHY registers
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm8350: fix UFS PHY registers
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm8250: fix UFS PHY registers
> 
> Johan Hovold <johan+linaro@kernel.org>
>    arm64: dts: qcom: sm8150: fix UFS PHY registers
> 
> Luca Weiss <luca.weiss@fairphone.com>
>    soc: qcom: llcc: make irq truly optional
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sc7180-trogdor-homestar: fully configure secondary I2S pins
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sm8250: correct LPASS pin pull down
> 
> Marijn Suijten <marijn.suijten@somainline.org>
>    arm64: dts: qcom: pm660: Use unique ADC5_VCOIN address in node name
> 
> Georgi Vlaev <g-vlaev@ti.com>
>    firmware: ti_sci: Fix polled mode during system suspend
> 
> Chen Jiahao <chenjiahao16@huawei.com>
>    drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static
> 
> Marek Vasut <marex@denx.de>
>    ARM: dts: stm32: Fix AV96 WLAN regulator gpio property
> 
> Marek Vasut <marex@denx.de>
>    ARM: dts: stm32: Drop stm32mp15xc.dtsi from Avenger96
> 
> Marco Elver <elver@google.com>
>    objtool, kcsan: Add volatile read/write instrumentation to whitelist
> 
> Cong Dang <cong.dang.xn@renesas.com>
>    memory: renesas-rpc-if: Clear HS bit during hardware initialization
> 
> Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
>    arm64: dts: fsd: fix drive strength values as per FSD HW UM
> 
> Padmanabhan Rajanbabu <p.rajanbabu@samsung.com>
>    arm64: dts: fsd: fix drive strength macros as per FSD HW UM
> 
> Stephan Gerhold <stephan.gerhold@kernkonzept.com>
>    arm64: dts: qcom: msm8916: Drop MSS fallback compatible
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sdm630: fix UART1 pin bias
> 
> Luca Weiss <luca@z3ntu.xyz>
>    ARM: dts: qcom: apq8064: fix coresight compatible
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    arm64: dts: qcom: msm8996: fix GPU OPP table
> 
> Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>    arm64: dts: qcom: msm8996: fix supported-hw in cpufreq OPP tables
> 
> Yassine Oudjana <y.oudjana@protonmail.com>
>    arm64: dts: qcom: msm8996: Add MSM8996 Pro support
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sdm845-xiaomi-polaris: fix codec pin conf name
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: sm8250-sony-xperia-edo: fix touchscreen bias-disable
> 
> Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>    arm64: dts: qcom: ipq6018-cp01-c1: use BLSPI1 pins
> 
> Geert Uytterhoeven <geert+renesas@glider.be>
>    arm64: dts: renesas: r8a779g0: Fix HSCIF0 "brg_int" clock
> 
> Paulo Alcantara <pc@cjr.nz>
>    cifs: fix oops during encryption
> 
> Paulo Alcantara <pc@cjr.nz>
>    cifs: improve symlink handling for smb2+
> 
> Enzo Matsumiya <ematsumiya@suse.de>
>    cifs: replace kfree() with kfree_sensitive() for sensitive data
> 
> Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
>    usb: musb: remove extra check in musb_gadget_vbus_draw
> 
> Martin Kaiser <martin@kaiser.cx>
>    staging: r8188eu: fix led register settings
> 
> Martin Kaiser <martin@kaiser.cx>
>    staging: r8188eu: don't check bSurpriseRemoved in SwLedOff
> 
> Martin Kaiser <martin@kaiser.cx>
>    staging: r8188eu: remove duplicate bSurpriseRemoved check
> 
> 
> -------------
> 
> Diffstat:
> 
> .../ABI/testing/sysfs-bus-spi-devices-spi-nor      |   3 +
> Documentation/admin-guide/sysctl/kernel.rst        |  23 +
> .../bindings/clock/qcom,sc7280-lpasscorecc.yaml    |  19 +-
> .../devicetree/bindings/input/azoteq,iqs7222.yaml  |  25 +-
> .../devicetree/bindings/mfd/qcom,spmi-pmic.yaml    |   8 +-
> .../devicetree/bindings/pci/fsl,imx6q-pcie.yaml    |  46 +-
> .../bindings/pci/toshiba,visconti-pcie.yaml        |   7 +-
> .../bindings/pinctrl/mediatek,mt7986-pinctrl.yaml  |  46 +-
> .../devicetree/bindings/pwm/microchip,corepwm.yaml |   4 +-
> .../devicetree/bindings/sound/qcom,wcd9335.txt     |   2 +-
> Documentation/devicetree/bindings/sound/rt5682.txt |   2 +-
> Documentation/driver-api/spi.rst                   |   4 +-
> Documentation/fault-injection/fault-injection.rst  |  10 +-
> Makefile                                           |   4 +-
> arch/Kconfig                                       |   2 +-
> arch/alpha/include/asm/thread_info.h               |   2 +-
> arch/alpha/kernel/entry.S                          |   4 +-
> arch/arm/boot/dts/armada-370.dtsi                  |   2 +-
> arch/arm/boot/dts/armada-375.dtsi                  |   2 +-
> arch/arm/boot/dts/armada-380.dtsi                  |   4 +-
> arch/arm/boot/dts/armada-385-turris-omnia.dts      |  18 +-
> arch/arm/boot/dts/armada-385.dtsi                  |   6 +-
> arch/arm/boot/dts/armada-38x.dtsi                  |   4 +-
> arch/arm/boot/dts/armada-39x.dtsi                  |  10 +-
> arch/arm/boot/dts/armada-xp-mv78230.dtsi           |   8 +-
> arch/arm/boot/dts/armada-xp-mv78260.dtsi           |  16 +-
> arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts       |  17 +-
> arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts       |  16 +-
> arch/arm/boot/dts/dove.dtsi                        |   2 +-
> arch/arm/boot/dts/nuvoton-npcm730-gbs.dts          |   2 +-
> arch/arm/boot/dts/nuvoton-npcm730-gsj.dts          |   2 +-
> arch/arm/boot/dts/nuvoton-npcm730-kudo.dts         |   6 +-
> arch/arm/boot/dts/nuvoton-npcm750-evb.dts          |   4 +-
> .../boot/dts/nuvoton-npcm750-runbmc-olympus.dts    |   6 +-
> arch/arm/boot/dts/qcom-apq8064.dtsi                |   2 +-
> arch/arm/boot/dts/spear600.dtsi                    |   2 +-
> arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts  |   1 -
> arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi |   2 +-
> arch/arm/mach-mmp/time.c                           |  11 +-
> arch/arm64/boot/dts/apple/t8103.dtsi               |   6 +-
> .../boot/dts/marvell/armada-3720-turris-mox.dts    |   3 +
> arch/arm64/boot/dts/mediatek/mt2712-evb.dts        |  12 +-
> arch/arm64/boot/dts/mediatek/mt2712e.dtsi          |  22 +-
> arch/arm64/boot/dts/mediatek/mt6779.dtsi           |   8 +-
> arch/arm64/boot/dts/mediatek/mt6797.dtsi           |   2 +-
> arch/arm64/boot/dts/mediatek/mt7986a.dtsi          |   4 +-
> arch/arm64/boot/dts/mediatek/mt8183.dtsi           |   2 +-
> arch/arm64/boot/dts/mediatek/mt8195.dtsi           |   8 +-
> arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi   |   6 +-
> arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts       |   2 +-
> arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts       |   2 +
> arch/arm64/boot/dts/qcom/msm8916.dtsi              |   2 +-
> .../dts/qcom/msm8994-sony-xperia-kitakami.dtsi     |   2 +-
> arch/arm64/boot/dts/qcom/msm8994.dtsi              |   3 +-
> arch/arm64/boot/dts/qcom/msm8996.dtsi              | 115 +++--
> arch/arm64/boot/dts/qcom/msm8996pro.dtsi           | 266 +++++++++++
> arch/arm64/boot/dts/qcom/pm6350.dtsi               |   1 +
> arch/arm64/boot/dts/qcom/pm660.dtsi                |   2 +-
> .../boot/dts/qcom/sc7180-trogdor-homestar.dtsi     |   6 +
> arch/arm64/boot/dts/qcom/sdm630.dtsi               |   2 +-
> arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi         |   4 +-
> arch/arm64/boot/dts/qcom/sdm845-db845c.dts         |   4 +-
> .../boot/dts/qcom/sdm845-xiaomi-beryllium.dts      |   2 +-
> arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts |   6 +-
> .../boot/dts/qcom/sdm850-lenovo-yoga-c630.dts      |   2 +-
> arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts   |   2 +-
> arch/arm64/boot/dts/qcom/sm6125.dtsi               |   2 +-
> arch/arm64/boot/dts/qcom/sm6350.dtsi               |  10 +-
> arch/arm64/boot/dts/qcom/sm8150.dtsi               |  10 +-
> arch/arm64/boot/dts/qcom/sm8250-mtp.dts            |   2 +-
> .../boot/dts/qcom/sm8250-sony-xperia-edo.dtsi      |   2 +-
> arch/arm64/boot/dts/qcom/sm8250.dtsi               |  20 +-
> arch/arm64/boot/dts/qcom/sm8350.dtsi               |  10 +-
> arch/arm64/boot/dts/qcom/sm8450.dtsi               |  10 +-
> arch/arm64/boot/dts/renesas/r8a779f0.dtsi          |  16 +-
> arch/arm64/boot/dts/renesas/r8a779g0.dtsi          |   2 +-
> arch/arm64/boot/dts/renesas/r9a09g011.dtsi         |   2 +-
> arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi         |  34 +-
> arch/arm64/boot/dts/tesla/fsd-pinctrl.h            |   6 +-
> arch/arm64/boot/dts/ti/k3-am65-main.dtsi           |   1 -
> arch/arm64/boot/dts/ti/k3-j721e-main.dtsi          |   1 -
> arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi         |   2 +-
> arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi   |   2 +-
> arch/arm64/include/asm/processor.h                 |   4 +-
> arch/arm64/mm/fault.c                              |   8 +-
> arch/mips/bcm63xx/clk.c                            |   2 +
> .../cavium-octeon/executive/cvmx-helper-board.c    |   2 +-
> arch/mips/cavium-octeon/executive/cvmx-helper.c    |   2 +-
> arch/mips/include/asm/mach-ralink/mt7621.h         |   4 +-
> arch/mips/kernel/vpe-cmp.c                         |   4 +-
> arch/mips/kernel/vpe-mt.c                          |   4 +-
> arch/mips/ralink/mt7621.c                          |  97 ++--
> arch/mips/ralink/of.c                              |   4 +-
> arch/powerpc/boot/dts/turris1x.dts                 |  14 +
> arch/powerpc/include/asm/hvcall.h                  |   3 +-
> arch/powerpc/perf/callchain.c                      |   1 +
> arch/powerpc/perf/hv-gpci-requests.h               |   4 +
> arch/powerpc/perf/hv-gpci.c                        |  35 +-
> arch/powerpc/perf/hv-gpci.h                        |   1 +
> arch/powerpc/perf/req-gen/perf.h                   |  20 +
> arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c      |   1 +
> arch/powerpc/platforms/83xx/mpc832x_rdb.c          |   2 +-
> arch/powerpc/platforms/pseries/eeh_pseries.c       |  11 +-
> arch/powerpc/platforms/pseries/plpks.c             |  32 +-
> arch/powerpc/platforms/pseries/plpks.h             |   2 +-
> arch/powerpc/sysdev/xive/spapr.c                   |   1 +
> arch/powerpc/xmon/xmon.c                           |   7 +-
> arch/riscv/include/asm/hugetlb.h                   |   6 +
> arch/riscv/include/asm/io.h                        |   5 +
> arch/riscv/include/asm/pgtable-64.h                |   6 +-
> arch/riscv/kernel/entry.S                          |  18 +-
> arch/riscv/kernel/signal.c                         |  34 +-
> arch/riscv/kernel/traps.c                          |   2 +-
> arch/riscv/kvm/vcpu.c                              |  11 +-
> arch/riscv/mm/physaddr.c                           |   2 +-
> arch/riscv/net/bpf_jit_comp64.c                    |  29 +-
> arch/x86/Kconfig                                   |   4 +-
> arch/x86/events/intel/uncore_snb.c                 |   3 +
> arch/x86/events/intel/uncore_snbep.c               |   5 +
> arch/x86/hyperv/hv_init.c                          |   2 -
> arch/x86/include/asm/apic.h                        |   3 +-
> arch/x86/include/asm/realmode.h                    |   1 +
> arch/x86/include/asm/x86_init.h                    |   4 +
> arch/x86/kernel/apic/apic.c                        |  13 +-
> arch/x86/kernel/cpu/intel.c                        |  63 ++-
> arch/x86/kernel/cpu/sgx/encl.c                     |  23 +-
> arch/x86/kernel/setup.c                            |   2 +-
> arch/x86/kernel/uprobes.c                          |   4 +-
> arch/x86/kernel/x86_init.c                         |   3 +
> arch/x86/realmode/init.c                           |   8 +-
> arch/x86/xen/enlighten_pv.c                        |   2 +
> arch/x86/xen/smp.c                                 |  24 +-
> arch/x86/xen/smp_pv.c                              |  12 +-
> arch/x86/xen/spinlock.c                            |   6 +-
> block/bfq-iosched.c                                |  16 +-
> block/blk-mq-sysfs.c                               |  11 +-
> block/blk-mq.c                                     |  56 ++-
> block/genhd.c                                      |   2 +
> crypto/cryptd.c                                    |  36 +-
> crypto/tcrypt.c                                    | 265 +++++------
> drivers/acpi/acpica/dsmethod.c                     |  10 +-
> drivers/acpi/acpica/utcopy.c                       |   7 -
> drivers/acpi/ec.c                                  |  10 +
> drivers/acpi/irq.c                                 |   5 +-
> drivers/acpi/pfr_telemetry.c                       |   6 +-
> drivers/acpi/pfr_update.c                          |   6 +-
> drivers/acpi/processor_idle.c                      |   3 +
> drivers/acpi/x86/utils.c                           |  24 +-
> drivers/ata/libata-sata.c                          |  11 +-
> drivers/base/class.c                               |   5 +
> drivers/base/power/runtime.c                       |  12 +-
> drivers/base/regmap/regmap-irq.c                   |  15 +-
> drivers/block/drbd/drbd_main.c                     |   9 +-
> drivers/block/drbd/drbd_nl.c                       |  10 +-
> drivers/block/floppy.c                             |   4 +-
> drivers/block/loop.c                               |  28 +-
> drivers/bluetooth/btintel.c                        |   5 +-
> drivers/bluetooth/btusb.c                          |   6 +-
> drivers/bluetooth/hci_bcm.c                        |  13 +-
> drivers/bluetooth/hci_bcsp.c                       |   2 +-
> drivers/bluetooth/hci_h5.c                         |   2 +-
> drivers/bluetooth/hci_ll.c                         |   2 +-
> drivers/bluetooth/hci_qca.c                        |   2 +-
> drivers/char/hw_random/amd-rng.c                   |  18 +-
> drivers/char/hw_random/geode-rng.c                 |  36 +-
> drivers/char/ipmi/ipmi_msghandler.c                |   8 +-
> drivers/char/ipmi/kcs_bmc_aspeed.c                 |  24 +-
> drivers/char/tpm/tpm_crb.c                         |   2 +-
> drivers/char/tpm/tpm_ftpm_tee.c                    |   8 +-
> drivers/char/tpm/tpm_tis_core.c                    |  20 +-
> drivers/char/tpm/tpm_tis_core.h                    |   1 +
> drivers/char/tpm/tpm_tis_i2c.c                     |   3 +-
> drivers/clk/imx/clk-imx8mn.c                       | 116 ++---
> drivers/clk/imx/clk-imx8mp.c                       |   4 +-
> drivers/clk/imx/clk-imx93.c                        |  19 +-
> drivers/clk/imx/clk-imxrt1050.c                    |   2 +-
> drivers/clk/mediatek/clk-mt7986-infracfg.c         |   2 +-
> drivers/clk/qcom/clk-krait.c                       |   2 +
> drivers/clk/qcom/dispcc-sm6350.c                   |   4 +-
> drivers/clk/qcom/gcc-ipq806x.c                     |   4 +-
> drivers/clk/qcom/gcc-sm8250.c                      |   4 +-
> drivers/clk/qcom/lpassaudiocc-sc7280.c             | 117 +++--
> drivers/clk/qcom/lpasscc-sc7280.c                  |  44 --
> drivers/clk/qcom/lpasscorecc-sc7180.c              |  24 +-
> drivers/clk/qcom/lpasscorecc-sc7280.c              |  33 ++
> drivers/clk/renesas/r8a779a0-cpg-mssr.c            |   2 +-
> drivers/clk/renesas/r8a779f0-cpg-mssr.c            |  29 +-
> drivers/clk/renesas/r9a06g032-clocks.c             |   3 +-
> drivers/clk/rockchip/clk-pll.c                     |   1 +
> drivers/clk/samsung/clk-pll.c                      |   1 +
> drivers/clk/socfpga/clk-gate.c                     |   5 +-
> drivers/clk/st/clkgen-fsyn.c                       |   5 +-
> drivers/clk/visconti/pll.c                         |   1 +
> drivers/clocksource/sh_cmt.c                       |  88 ++--
> drivers/clocksource/timer-ti-dm-systimer.c         |   4 +-
> drivers/clocksource/timer-ti-dm.c                  |   2 +-
> drivers/counter/stm32-lptimer-cnt.c                |   2 +-
> drivers/cpufreq/amd_freq_sensitivity.c             |   2 +
> drivers/cpufreq/qcom-cpufreq-hw.c                  |  43 +-
> drivers/cpuidle/dt_idle_states.c                   |   2 +-
> drivers/crypto/Kconfig                             |   5 +
> .../crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c    |   2 +-
> drivers/crypto/amlogic/amlogic-gxl-core.c          |   1 -
> drivers/crypto/amlogic/amlogic-gxl.h               |   2 +-
> drivers/crypto/cavium/nitrox/nitrox_mbx.c          |   1 +
> drivers/crypto/ccree/cc_debugfs.c                  |   2 +-
> drivers/crypto/ccree/cc_driver.c                   |  10 +-
> drivers/crypto/hisilicon/hpre/hpre_main.c          |  14 +-
> drivers/crypto/hisilicon/qm.c                      | 208 ++++++---
> drivers/crypto/hisilicon/sec2/sec_main.c           |   4 +-
> drivers/crypto/hisilicon/zip/zip_main.c            |   4 +-
> drivers/crypto/img-hash.c                          |   8 +-
> drivers/crypto/omap-sham.c                         |   2 +-
> drivers/crypto/qat/qat_4xxx/adf_drv.c              |   1 +
> drivers/crypto/rockchip/rk3288_crypto.c            | 193 +-------
> drivers/crypto/rockchip/rk3288_crypto.h            |  53 +--
> drivers/crypto/rockchip/rk3288_crypto_ahash.c      | 197 ++++----
> drivers/crypto/rockchip/rk3288_crypto_skcipher.c   | 413 +++++++++-------
> drivers/dio/dio.c                                  |   8 +
> drivers/dma/apple-admac.c                          | 129 ++++-
> drivers/edac/i10nm_base.c                          |   3 +-
> drivers/extcon/Kconfig                             |   2 +-
> drivers/extcon/extcon-usbc-tusb320.c               | 247 ++++++++--
> drivers/firmware/raspberrypi.c                     |   1 +
> drivers/firmware/ti_sci.c                          |   5 +-
> drivers/gpio/gpiolib-cdev.c                        | 204 +++++++-
> drivers/gpio/gpiolib.c                             |   4 +
> drivers/gpio/gpiolib.h                             |   5 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c   |   2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c           |   1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   4 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h           |   5 +-
> drivers/gpu/drm/amd/amdgpu/nv.c                    |  28 +-
> drivers/gpu/drm/amd/amdgpu/soc15.c                 |  24 +-
> drivers/gpu/drm/amd/amdgpu/soc21.c                 |   2 +-
> .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c  |  35 --
> drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c |  16 +-
> .../amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c |   2 +-
> .../gpu/drm/amd/display/dc/dce60/dce60_resource.c  |   3 +
> .../gpu/drm/amd/display/dc/dce80/dce80_resource.c  |   2 +
> .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c  |  30 +-
> drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c |  35 +-
> drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c  |   6 +-
> .../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c   |   7 +
> drivers/gpu/drm/amd/include/kgd_pp_interface.h     |   3 +-
> drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c   |   3 +-
> drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c    |   2 +
> .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c  |   3 +-
> drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c     |   4 +
> .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c   |  21 +-
> drivers/gpu/drm/bridge/adv7511/adv7511.h           |   3 +-
> drivers/gpu/drm/bridge/adv7511/adv7511_drv.c       |  18 +-
> drivers/gpu/drm/bridge/adv7511/adv7533.c           |  25 +-
> drivers/gpu/drm/bridge/ite-it6505.c                |   8 +-
> drivers/gpu/drm/drm_atomic_helper.c                |  10 +-
> drivers/gpu/drm/drm_edid.c                         |  12 +
> drivers/gpu/drm/drm_fourcc.c                       |   8 +-
> drivers/gpu/drm/etnaviv/etnaviv_gpu.c              |  11 +-
> drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c          |   5 +-
> drivers/gpu/drm/i915/display/intel_bios.c          |   2 +-
> drivers/gpu/drm/i915/display/intel_dp.c            |  59 ---
> drivers/gpu/drm/i915/gt/intel_engine.h             |   6 +
> drivers/gpu/drm/i915/gt/intel_engine_cs.c          |  91 +++-
> drivers/gpu/drm/i915/gt/sysfs_engines.c            |  25 +-
> drivers/gpu/drm/i915/gt/uc/intel_guc.c             |  53 +--
> drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c     | 147 ++++--
> drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h     |   1 -
> drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h        |  21 +
> drivers/gpu/drm/i915/gt/uc/intel_guc_log.c         | 227 +++++++--
> drivers/gpu/drm/i915/gt/uc/intel_guc_log.h         |  42 +-
> drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c  |   8 +
> drivers/gpu/drm/i915/i915_params.c                 |  12 +
> drivers/gpu/drm/i915/i915_params.h                 |   3 +
> drivers/gpu/drm/mediatek/mtk_dpi.c                 |  12 +-
> drivers/gpu/drm/mediatek/mtk_hdmi.c                |   7 +-
> drivers/gpu/drm/meson/meson_encoder_cvbs.c         |   7 +-
> drivers/gpu/drm/msm/adreno/a6xx_gpu.c              |  12 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c        |  25 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h        |   2 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c         |  79 ++--
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h         |   4 +-
> drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c           |  27 +-
> drivers/gpu/drm/msm/dp/dp_display.c                |   2 +-
> drivers/gpu/drm/msm/dsi/dsi.c                      |   2 +-
> drivers/gpu/drm/msm/dsi/dsi.h                      |   2 +-
> drivers/gpu/drm/msm/dsi/dsi_host.c                 | 204 +++-----
> drivers/gpu/drm/msm/hdmi/hdmi.c                    |   2 +-
> drivers/gpu/drm/msm/msm_drv.h                      |   9 +-
> drivers/gpu/drm/mxsfb/lcdif_kms.c                  |  48 +-
> drivers/gpu/drm/mxsfb/lcdif_regs.h                 |   5 +
> drivers/gpu/drm/panel/panel-sitronix-st7701.c      |  10 +-
> drivers/gpu/drm/radeon/radeon_bios.c               |  19 +-
> drivers/gpu/drm/rcar-du/Kconfig                    |   2 -
> drivers/gpu/drm/rockchip/cdn-dp-core.c             |   2 +-
> drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c    |   2 +-
> drivers/gpu/drm/rockchip/inno_hdmi.c               |   2 +-
> drivers/gpu/drm/rockchip/rk3066_hdmi.c             |   2 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c        |   4 +-
> drivers/gpu/drm/rockchip/rockchip_drm_vop2.c       |   2 +-
> drivers/gpu/drm/rockchip/rockchip_lvds.c           |  10 +-
> drivers/gpu/drm/sti/sti_dvo.c                      |   7 +-
> drivers/gpu/drm/sti/sti_hda.c                      |   7 +-
> drivers/gpu/drm/sti/sti_hdmi.c                     |   7 +-
> drivers/gpu/drm/tegra/dc.c                         |   4 +-
> drivers/hid/amd-sfh-hid/amd_sfh_client.c           |   4 +
> drivers/hid/hid-apple.c                            | 118 +++--
> drivers/hid/hid-input.c                            |   6 +
> drivers/hid/hid-logitech-hidpp.c                   |  11 +-
> drivers/hid/hid-mcp2221.c                          |  12 +-
> drivers/hid/hid-rmi.c                              |   2 +
> drivers/hid/hid-sensor-custom.c                    |   2 +-
> drivers/hid/i2c-hid/i2c-hid-core.c                 |   3 +-
> drivers/hid/wacom_sys.c                            |   8 +
> drivers/hid/wacom_wac.c                            |   4 +
> drivers/hid/wacom_wac.h                            |   1 +
> drivers/hsi/controllers/omap_ssi_core.c            |  14 +-
> drivers/hv/ring_buffer.c                           |  13 +
> drivers/hwmon/Kconfig                              |   1 +
> drivers/hwmon/jc42.c                               | 243 ++++++----
> drivers/hwmon/nct6775-platform.c                   |   7 +
> drivers/hwtracing/coresight/coresight-trbe.c       |   1 +
> drivers/i2c/busses/i2c-ismt.c                      |   3 +
> drivers/i2c/busses/i2c-pxa-pci.c                   |  10 +-
> drivers/i2c/muxes/i2c-mux-reg.c                    |   5 +-
> drivers/iio/adc/ad_sigma_delta.c                   |   8 +-
> drivers/iio/adc/ti-adc128s052.c                    |  14 +-
> drivers/iio/addac/ad74413r.c                       |   2 +-
> drivers/iio/imu/adis.c                             |  28 +-
> drivers/iio/industrialio-event.c                   |   4 +-
> drivers/iio/temperature/ltc2983.c                  |  10 +-
> drivers/infiniband/Kconfig                         |   2 +
> drivers/infiniband/core/device.c                   |   2 +-
> drivers/infiniband/core/mad.c                      |   5 -
> drivers/infiniband/core/nldev.c                    |   6 +-
> drivers/infiniband/core/restrack.c                 |   2 -
> drivers/infiniband/core/sysfs.c                    |  17 +-
> drivers/infiniband/hw/hfi1/affinity.c              |   2 +
> drivers/infiniband/hw/hfi1/firmware.c              |   6 +
> drivers/infiniband/hw/hns/Makefile                 |   2 +-
> drivers/infiniband/hw/hns/hns_roce_device.h        |  13 +-
> drivers/infiniband/hw/hns/hns_roce_hw_v2.c         | 257 +++++++---
> drivers/infiniband/hw/hns/hns_roce_hw_v2.h         |  14 +-
> drivers/infiniband/hw/hns/hns_roce_hw_v2_dfx.c     |  34 --
> drivers/infiniband/hw/hns/hns_roce_main.c          |  24 +-
> drivers/infiniband/hw/hns/hns_roce_mr.c            |   4 +-
> drivers/infiniband/hw/hns/hns_roce_qp.c            | 107 ++++-
> drivers/infiniband/hw/hns/hns_roce_restrack.c      |  35 +-
> drivers/infiniband/hw/irdma/uk.c                   | 170 ++++---
> drivers/infiniband/hw/irdma/user.h                 |  20 +-
> drivers/infiniband/hw/irdma/utils.c                |   2 +
> drivers/infiniband/hw/irdma/verbs.c                | 145 ++----
> drivers/infiniband/hw/irdma/verbs.h                |  53 +++
> drivers/infiniband/sw/rxe/rxe_mr.c                 |   9 +-
> drivers/infiniband/sw/rxe/rxe_qp.c                 |   6 +-
> drivers/infiniband/sw/siw/siw_cq.c                 |  24 +-
> drivers/infiniband/sw/siw/siw_qp_tx.c              |   2 +-
> drivers/infiniband/sw/siw/siw_verbs.c              |  40 +-
> drivers/infiniband/ulp/ipoib/ipoib_netlink.c       |   7 +
> drivers/infiniband/ulp/srp/ib_srp.c                |  96 +++-
> drivers/input/joystick/Kconfig                     |   1 +
> drivers/input/misc/Kconfig                         |   2 +-
> drivers/input/misc/iqs7222.c                       | 520 ++++++++++++---------
> drivers/input/touchscreen/elants_i2c.c             |   9 +-
> drivers/interconnect/qcom/sc7180.c                 |   2 +-
> drivers/iommu/amd/iommu_v2.c                       |   1 +
> drivers/iommu/fsl_pamu.c                           |   2 +-
> drivers/iommu/mtk_iommu.c                          |  53 ++-
> drivers/iommu/rockchip-iommu.c                     |  10 +-
> drivers/iommu/s390-iommu.c                         | 106 ++---
> drivers/iommu/sun50i-iommu.c                       |  89 +++-
> drivers/irqchip/irq-gic-pm.c                       |   2 +-
> drivers/irqchip/irq-loongson-liointc.c             |   5 +-
> drivers/irqchip/irq-loongson-pch-pic.c             |   3 +
> drivers/irqchip/irq-wpcm450-aic.c                  |   1 +
> drivers/isdn/hardware/mISDN/hfcmulti.c             |  19 +-
> drivers/isdn/hardware/mISDN/hfcpci.c               |  13 +-
> drivers/isdn/hardware/mISDN/hfcsusb.c              |  12 +-
> drivers/leds/leds-is31fl319x.c                     |   3 +-
> drivers/leds/rgb/leds-qcom-lpg.c                   |  18 +-
> drivers/macintosh/macio-adb.c                      |   4 +
> drivers/macintosh/macio_asic.c                     |   2 +-
> drivers/mailbox/arm_mhuv2.c                        |   4 +-
> drivers/mailbox/mailbox-mpfs.c                     |  31 +-
> drivers/mailbox/pcc.c                              |   1 +
> drivers/mailbox/zynqmp-ipi-mailbox.c               |   4 +-
> drivers/mcb/mcb-core.c                             |   4 +-
> drivers/mcb/mcb-parse.c                            |   2 +-
> drivers/md/dm.c                                    | 123 +++--
> drivers/md/md-bitmap.c                             |  27 +-
> drivers/md/raid0.c                                 |   1 -
> drivers/md/raid1.c                                 |   1 +
> drivers/md/raid10.c                                |   2 -
> drivers/media/dvb-core/dvb_ca_en50221.c            |   2 +-
> drivers/media/dvb-core/dvb_frontend.c              |  10 +-
> drivers/media/dvb-core/dvbdev.c                    |  32 +-
> drivers/media/dvb-frontends/bcm3510.c              |   1 +
> drivers/media/i2c/ad5820.c                         |  10 +-
> drivers/media/i2c/adv748x/adv748x-afe.c            |   4 +
> drivers/media/i2c/dw9768.c                         |  33 +-
> drivers/media/i2c/hi846.c                          |  14 +-
> drivers/media/i2c/mt9p031.c                        |   1 -
> drivers/media/i2c/ov5640.c                         |   3 +-
> drivers/media/i2c/ov5648.c                         |   1 +
> drivers/media/pci/saa7164/saa7164-core.c           |   4 +-
> drivers/media/pci/solo6x10/solo6x10-core.c         |   1 +
> drivers/media/platform/amphion/vdec.c              |  15 +-
> drivers/media/platform/amphion/vpu.h               |   1 +
> drivers/media/platform/amphion/vpu_cmds.c          |  39 +-
> drivers/media/platform/amphion/vpu_drv.c           |   6 +-
> drivers/media/platform/amphion/vpu_malone.c        |   1 +
> drivers/media/platform/amphion/vpu_msgs.c          |   2 +
> drivers/media/platform/amphion/vpu_v4l2.c          |  30 +-
> drivers/media/platform/amphion/vpu_windsor.c       |   1 +
> drivers/media/platform/chips-media/coda-bit.c      |  14 +-
> drivers/media/platform/chips-media/coda-jpeg.c     |  10 +-
> .../mediatek/vcodec/mtk_vcodec_dec_stateless.c     |  13 +-
> .../mediatek/vcodec/vdec/vdec_h264_req_multi_if.c  |  60 ++-
> .../mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c     |  15 +-
> .../platform/mediatek/vcodec/vdec_msg_queue.c      |   2 +-
> drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c  |   4 +-
> drivers/media/platform/qcom/camss/camss-video.c    |   3 +-
> drivers/media/platform/qcom/camss/camss.c          |  11 +
> drivers/media/platform/qcom/venus/pm_helpers.c     |   4 +-
> .../media/platform/samsung/exynos4-is/fimc-core.c  |   2 +-
> .../media/platform/samsung/exynos4-is/media-dev.c  |  12 +-
> drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c   |  17 +-
> .../platform/st/sti/c8sectpfe/c8sectpfe-core.c     |   1 +
> .../sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c        |  23 +-
> .../sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c    |  23 +-
> drivers/media/radio/si470x/radio-si470x-usb.c      |   4 +-
> drivers/media/rc/imon.c                            |   6 +-
> drivers/media/test-drivers/vidtv/vidtv_bridge.c    |  22 +-
> drivers/media/test-drivers/vimc/vimc-core.c        |   2 +-
> drivers/media/test-drivers/vivid/vivid-vid-cap.c   |   1 +
> drivers/media/usb/dvb-usb/az6027.c                 |   4 +
> drivers/media/usb/dvb-usb/dvb-usb-init.c           |   4 +-
> drivers/media/v4l2-core/v4l2-ctrls-api.c           |   1 +
> drivers/media/v4l2-core/v4l2-ctrls-core.c          |   2 +-
> drivers/media/v4l2-core/v4l2-ioctl.c               |  34 +-
> drivers/media/v4l2-core/videobuf-dma-contig.c      |  22 +-
> drivers/memory/renesas-rpc-if.c                    |   3 +
> drivers/memstick/core/ms_block.c                   |   9 +-
> drivers/mfd/Kconfig                                |   1 +
> drivers/mfd/axp20x.c                               |   2 +-
> drivers/mfd/qcom-pm8008.c                          |   4 +-
> drivers/mfd/qcom_rpm.c                             |  16 +-
> drivers/misc/cxl/guest.c                           |  24 +-
> drivers/misc/cxl/pci.c                             |  21 +-
> drivers/misc/lkdtm/cfi.c                           |   6 +-
> drivers/misc/ocxl/config.c                         |  20 +-
> drivers/misc/ocxl/file.c                           |   7 +-
> drivers/misc/sgi-gru/grufault.c                    |  13 +-
> drivers/misc/sgi-gru/grumain.c                     |  22 +-
> drivers/misc/sgi-gru/grutables.h                   |   2 +-
> drivers/misc/tifm_7xx1.c                           |   2 +-
> drivers/mmc/core/sd.c                              |  11 +-
> drivers/mmc/host/alcor.c                           |   5 +-
> drivers/mmc/host/atmel-mci.c                       |   9 +-
> drivers/mmc/host/litex_mmc.c                       |   1 +
> drivers/mmc/host/meson-gx-mmc.c                    |   4 +-
> drivers/mmc/host/mmci.c                            |   4 +-
> drivers/mmc/host/moxart-mmc.c                      |   4 +-
> drivers/mmc/host/mxcmmc.c                          |   4 +-
> drivers/mmc/host/omap_hsmmc.c                      |   4 +-
> drivers/mmc/host/pxamci.c                          |   7 +-
> drivers/mmc/host/renesas_sdhi.h                    |   1 +
> drivers/mmc/host/renesas_sdhi_core.c               |  14 +-
> drivers/mmc/host/renesas_sdhi_internal_dmac.c      |   4 +-
> drivers/mmc/host/rtsx_pci_sdmmc.c                  |   9 +-
> drivers/mmc/host/rtsx_usb_sdmmc.c                  |  11 +-
> drivers/mmc/host/sdhci_f_sdh30.c                   |   3 +
> drivers/mmc/host/toshsd.c                          |   6 +-
> drivers/mmc/host/via-sdmmc.c                       |   4 +-
> drivers/mmc/host/vub300.c                          |  11 +-
> drivers/mmc/host/wbsd.c                            |  12 +-
> drivers/mmc/host/wmt-sdmmc.c                       |   6 +-
> drivers/mtd/lpddr/lpddr2_nvm.c                     |   2 +
> drivers/mtd/maps/pxa2xx-flash.c                    |   2 +
> drivers/mtd/mtdcore.c                              |   9 +-
> drivers/mtd/spi-nor/core.c                         |   3 +-
> drivers/mtd/spi-nor/sysfs.c                        |  14 +
> drivers/net/bonding/bond_main.c                    |  37 +-
> drivers/net/can/m_can/m_can.c                      |  32 +-
> drivers/net/can/m_can/m_can_platform.c             |   4 -
> drivers/net/can/m_can/tcan4x5x-core.c              |  18 +-
> drivers/net/can/usb/kvaser_usb/kvaser_usb.h        |  30 +-
> drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c   | 115 ++++-
> drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c  | 160 +++++--
> drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c   | 437 +++++++++++++++--
> drivers/net/dsa/lan9303-core.c                     |   4 +-
> drivers/net/dsa/mv88e6xxx/chip.c                   |   9 +-
> drivers/net/ethernet/amd/atarilance.c              |   2 +-
> drivers/net/ethernet/amd/lance.c                   |   2 +-
> drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c        |  23 +-
> drivers/net/ethernet/apple/bmac.c                  |   2 +-
> drivers/net/ethernet/apple/mace.c                  |   2 +-
> drivers/net/ethernet/dnet.c                        |   4 +-
> drivers/net/ethernet/freescale/enetc/enetc.c       |  35 +-
> drivers/net/ethernet/intel/i40e/i40e_main.c        |  36 +-
> drivers/net/ethernet/intel/igb/igb_main.c          |   8 +-
> drivers/net/ethernet/intel/igc/igc.h               |   3 +
> drivers/net/ethernet/intel/igc/igc_defines.h       |   2 +
> drivers/net/ethernet/intel/igc/igc_main.c          | 210 +++++++--
> drivers/net/ethernet/intel/igc/igc_tsn.c           |  13 +-
> drivers/net/ethernet/mediatek/mtk_eth_soc.c        |  71 +--
> drivers/net/ethernet/mediatek/mtk_eth_soc.h        |  11 +-
> drivers/net/ethernet/myricom/myri10ge/myri10ge.c   |   1 +
> drivers/net/ethernet/neterion/s2io.c               |   2 +-
> drivers/net/ethernet/qlogic/qed/qed_debug.c        |   3 +-
> .../ethernet/qlogic/qlcnic/qlcnic_sriov_common.c   |   2 +
> drivers/net/ethernet/rdc/r6040.c                   |   5 +-
> .../net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c  |   3 +-
> drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |   4 +-
> drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h   |   2 +-
> .../net/ethernet/stmicro/stmmac/stmmac_selftests.c |   8 +-
> drivers/net/ethernet/ti/am65-cpsw-nuss.c           |  10 +-
> drivers/net/ethernet/ti/netcp_core.c               |   2 +-
> drivers/net/ethernet/xilinx/xilinx_emaclite.c      |   2 +-
> drivers/net/fddi/defxx.c                           |  22 +-
> drivers/net/hamradio/baycom_epp.c                  |   2 +-
> drivers/net/hamradio/scc.c                         |   6 +-
> drivers/net/macsec.c                               |  34 +-
> drivers/net/mctp/mctp-serial.c                     |   6 +-
> drivers/net/ntb_netdev.c                           |   4 +-
> drivers/net/ppp/ppp_generic.c                      |   2 +
> drivers/net/wan/farsync.c                          |   2 +
> drivers/net/wireless/ath/ar5523/ar5523.c           |   6 +
> drivers/net/wireless/ath/ath10k/core.c             |  16 +
> drivers/net/wireless/ath/ath10k/htc.c              |   9 +
> drivers/net/wireless/ath/ath10k/hw.h               |   2 +
> drivers/net/wireless/ath/ath10k/pci.c              |  20 +-
> drivers/net/wireless/ath/ath11k/core.c             |  46 ++
> drivers/net/wireless/ath/ath11k/core.h             |  14 +-
> drivers/net/wireless/ath/ath11k/debugfs.c          | 139 ++----
> drivers/net/wireless/ath/ath11k/debugfs.h          |   6 +-
> drivers/net/wireless/ath/ath11k/mac.c              | 122 +++--
> drivers/net/wireless/ath/ath11k/qmi.c              |   3 +
> drivers/net/wireless/ath/ath11k/wmi.c              |  48 +-
> drivers/net/wireless/ath/ath9k/hif_usb.c           |  46 +-
> .../broadcom/brcm80211/brcmfmac/firmware.c         |   5 +
> .../wireless/broadcom/brcm80211/brcmfmac/pcie.c    |   6 +-
> .../wireless/broadcom/brcm80211/brcmfmac/sdio.c    |   1 +
> drivers/net/wireless/intel/iwlwifi/mei/iwl-mei.h   |   7 +-
> drivers/net/wireless/intel/iwlwifi/mei/main.c      | 172 ++++---
> drivers/net/wireless/intel/iwlwifi/mei/net.c       |  10 +-
> drivers/net/wireless/intel/iwlwifi/mvm/fw.c        |   2 +
> drivers/net/wireless/intel/iwlwifi/mvm/mvm.h       |   4 +-
> drivers/net/wireless/intel/iwlwifi/mvm/ops.c       |   2 +-
> drivers/net/wireless/intel/iwlwifi/mvm/tx.c        |  20 +-
> drivers/net/wireless/mediatek/mt76/mt76.h          |   3 +-
> drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c |  58 +--
> drivers/net/wireless/mediatek/mt76/mt7915/eeprom.h |   5 -
> drivers/net/wireless/mediatek/mt76/mt7915/mac.c    |  23 +-
> drivers/net/wireless/mediatek/mt76/mt7915/pci.c    |  13 +-
> drivers/net/wireless/mediatek/mt76/mt7921/mac.c    |  34 +-
> drivers/net/wireless/mediatek/mt76/usb.c           |  11 +-
> drivers/net/wireless/purelifi/plfxlc/usb.c         |   1 +
> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h   |   2 +-
> .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c  |  28 +-
> drivers/net/wireless/realtek/rtw89/core.c          |   2 +-
> drivers/net/wireless/realtek/rtw89/mac.c           |   6 +-
> drivers/net/wireless/realtek/rtw89/phy.c           |   2 +-
> drivers/net/wireless/rsi/rsi_91x_core.c            |   4 +-
> drivers/net/wireless/rsi/rsi_91x_hal.c             |   6 +-
> drivers/nfc/pn533/pn533.c                          |   4 +
> drivers/nvme/host/core.c                           |  14 +-
> drivers/nvme/target/core.c                         |  22 +-
> drivers/nvme/target/io-cmd-file.c                  |  16 +-
> drivers/nvme/target/nvmet.h                        |   3 +-
> drivers/of/overlay.c                               |   4 +-
> drivers/pci/controller/dwc/pci-imx6.c              |  13 +-
> drivers/pci/controller/dwc/pcie-designware.c       |   2 +-
> drivers/pci/controller/vmd.c                       |  27 +-
> drivers/pci/endpoint/functions/pci-epf-test.c      |   2 +-
> drivers/pci/endpoint/functions/pci-epf-vntb.c      |   2 +-
> drivers/pci/irq.c                                  |   2 +
> drivers/pci/probe.c                                |   3 -
> drivers/perf/arm_dmc620_pmu.c                      |   8 +-
> drivers/perf/arm_dsu_pmu.c                         |   6 +-
> drivers/perf/arm_smmuv3_pmu.c                      |   8 +-
> drivers/perf/hisilicon/hisi_pcie_pmu.c             |   8 +-
> drivers/perf/marvell_cn10k_tad_pmu.c               |   6 +-
> drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c  |   9 +-
> drivers/phy/broadcom/phy-brcm-usb-init.h           |   1 -
> drivers/phy/broadcom/phy-brcm-usb.c                |  14 +-
> drivers/phy/marvell/phy-mvebu-a3700-comphy.c       |   3 +
> drivers/phy/qualcomm/phy-qcom-qmp-pcie.c           |  15 +-
> drivers/phy/qualcomm/phy-qcom-qmp-pcs-v5_20.h      |  14 +
> drivers/phy/qualcomm/phy-qcom-qmp.h                |   1 +
> drivers/pinctrl/mediatek/pinctrl-mt7986.c          |  24 +-
> drivers/pinctrl/pinconf-generic.c                  |   4 +-
> drivers/pinctrl/pinctrl-k210.c                     |   4 +-
> drivers/pinctrl/pinctrl-ocelot.c                   |  20 +-
> drivers/pinctrl/pinctrl-thunderbay.c               |   8 +-
> drivers/platform/chrome/cros_ec_typec.c            |  53 ++-
> drivers/platform/chrome/cros_usbpd_notify.c        |   6 +-
> drivers/platform/mellanox/mlxbf-pmc.c              |   2 +-
> drivers/platform/x86/huawei-wmi.c                  |  20 +-
> .../platform/x86/intel/int3472/clk_and_regulator.c |   3 +-
> drivers/platform/x86/intel_scu_ipc.c               |   2 +-
> drivers/platform/x86/mxm-wmi.c                     |   8 +-
> drivers/pnp/core.c                                 |   4 +-
> drivers/power/supply/ab8500_charger.c              |   9 +-
> drivers/power/supply/bq25890_charger.c             |  71 ++-
> drivers/power/supply/cw2015_battery.c              |  17 +-
> drivers/power/supply/power_supply_core.c           |   7 +-
> drivers/power/supply/z2_battery.c                  |   6 +-
> drivers/pwm/pwm-mediatek.c                         |   2 +-
> drivers/pwm/pwm-mtk-disp.c                         |   5 +-
> drivers/pwm/pwm-sifive.c                           |   5 +-
> drivers/pwm/pwm-tegra.c                            |  15 +-
> drivers/rapidio/devices/rio_mport_cdev.c           |  15 +-
> drivers/rapidio/rio-scan.c                         |   8 +-
> drivers/rapidio/rio.c                              |   9 +-
> drivers/regulator/core.c                           |  25 +-
> drivers/regulator/devres.c                         |   2 +-
> drivers/regulator/of_regulator.c                   |   2 +-
> drivers/regulator/qcom-labibb-regulator.c          |   1 +
> drivers/regulator/qcom-rpmh-regulator.c            |   2 +-
> drivers/regulator/stm32-vrefbuf.c                  |   2 +-
> drivers/remoteproc/qcom_q6v5_pas.c                 |   4 +
> drivers/remoteproc/qcom_q6v5_wcss.c                |   6 +-
> drivers/remoteproc/qcom_sysmon.c                   |   5 +-
> drivers/rtc/class.c                                |   4 +-
> drivers/rtc/rtc-cmos.c                             | 378 +++++++--------
> drivers/rtc/rtc-mxc_v2.c                           |   4 +-
> drivers/rtc/rtc-pcf85063.c                         |  10 +-
> drivers/rtc/rtc-pic32.c                            |   8 +-
> drivers/rtc/rtc-rzn1.c                             |   4 +-
> drivers/rtc/rtc-snvs.c                             |  16 +-
> drivers/rtc/rtc-st-lpc.c                           |   1 +
> drivers/s390/net/ctcm_main.c                       |  11 +-
> drivers/s390/net/lcs.c                             |   8 +-
> drivers/s390/net/netiucv.c                         |   9 +-
> drivers/scsi/elx/efct/efct_driver.c                |   1 +
> drivers/scsi/elx/libefc/efclib.h                   |   6 +-
> drivers/scsi/fcoe/fcoe.c                           |   1 +
> drivers/scsi/fcoe/fcoe_sysfs.c                     |  19 +-
> drivers/scsi/hisi_sas/hisi_sas_main.c              |   8 +-
> drivers/scsi/hpsa.c                                |   9 +-
> drivers/scsi/ipr.c                                 |  10 +-
> drivers/scsi/libsas/sas_ata.c                      |  25 +
> drivers/scsi/libsas/sas_expander.c                 |   4 +-
> drivers/scsi/libsas/sas_internal.h                 |   2 +
> drivers/scsi/lpfc/lpfc_sli.c                       |   6 +-
> drivers/scsi/mpt3sas/mpt3sas_transport.c           |   2 +
> drivers/scsi/qla2xxx/qla_def.h                     |  22 +-
> drivers/scsi/qla2xxx/qla_init.c                    |  20 +-
> drivers/scsi/qla2xxx/qla_inline.h                  |   4 +-
> drivers/scsi/qla2xxx/qla_os.c                      |   4 +-
> drivers/scsi/scsi_debug.c                          |  11 +-
> drivers/scsi/scsi_error.c                          |  14 +-
> drivers/scsi/smartpqi/smartpqi.h                   |   2 +-
> drivers/scsi/smartpqi/smartpqi_init.c              |  77 ++-
> drivers/scsi/snic/snic_disc.c                      |   3 +
> drivers/soc/apple/rtkit.c                          |   7 +-
> drivers/soc/apple/sart.c                           |   7 +-
> drivers/soc/mediatek/mtk-pm-domains.c              |   2 +-
> drivers/soc/qcom/apr.c                             |  15 +-
> drivers/soc/qcom/llcc-qcom.c                       |   2 +-
> drivers/soc/ti/knav_qmss_queue.c                   |   3 +-
> drivers/soc/ti/smartreflex.c                       |   1 +
> drivers/spi/spi-gpio.c                             |  16 +-
> drivers/spi/spi-mt65xx.c                           |   5 +
> drivers/spi/spidev.c                               |  21 +-
> drivers/staging/media/imx/imx7-media-csi.c         |   6 +-
> drivers/staging/media/rkvdec/rkvdec-vp9.c          |   3 +
> drivers/staging/media/stkwebcam/Kconfig            |   2 +-
> drivers/staging/media/sunxi/cedrus/cedrus_h265.c   |  25 +-
> drivers/staging/media/sunxi/cedrus/cedrus_regs.h   |   2 +
> drivers/staging/r8188eu/core/rtw_led.c             |  29 +-
> drivers/staging/r8188eu/core/rtw_pwrctrl.c         |   2 +-
> drivers/staging/rtl8192e/rtllib_rx.c               |   2 +-
> drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c  |   4 +-
> drivers/staging/vme_user/vme_fake.c                |   2 +
> drivers/staging/vme_user/vme_tsi148.c              |   1 +
> drivers/target/iscsi/iscsi_target_nego.c           |  12 +-
> drivers/thermal/imx8mm_thermal.c                   |   8 +-
> drivers/thermal/k3_j72xx_bandgap.c                 |   2 +-
> drivers/thermal/qcom/lmh.c                         |   2 +-
> drivers/thermal/qcom/qcom-spmi-temp-alarm.c        |   3 +-
> drivers/thermal/thermal_core.c                     |  18 +-
> drivers/tty/serial/8250/8250_bcm7271.c             |  10 +-
> drivers/tty/serial/altera_uart.c                   |  21 +-
> drivers/tty/serial/amba-pl011.c                    |  14 +-
> drivers/tty/serial/pch_uart.c                      |   4 +
> drivers/tty/serial/serial-tegra.c                  |   6 +-
> drivers/tty/serial/stm32-usart.c                   |  47 +-
> drivers/tty/serial/sunsab.c                        |   8 +-
> drivers/ufs/core/ufshcd.c                          |  37 +-
> drivers/uio/uio_dmem_genirq.c                      |  13 +-
> drivers/usb/cdns3/cdnsp-ring.c                     |  42 +-
> drivers/usb/core/hcd.c                             |   6 +-
> drivers/usb/dwc3/core.c                            |  23 +-
> drivers/usb/gadget/function/f_hid.c                |  53 ++-
> drivers/usb/gadget/udc/core.c                      |  12 +-
> drivers/usb/gadget/udc/fotg210-udc.c               |  12 +-
> drivers/usb/host/xhci-mtk.c                        |   1 -
> drivers/usb/host/xhci-ring.c                       |  14 +-
> drivers/usb/host/xhci.h                            |   2 +-
> drivers/usb/musb/musb_gadget.c                     |   2 -
> drivers/usb/musb/omap2430.c                        |  54 +++
> drivers/usb/roles/class.c                          |   5 +-
> drivers/usb/storage/alauda.c                       |   2 +
> drivers/usb/typec/bus.c                            |   2 +-
> drivers/usb/typec/tcpm/tcpci.c                     |   5 +-
> drivers/usb/typec/tipd/core.c                      |  11 +-
> drivers/usb/typec/wusb3801.c                       |   2 +-
> drivers/vfio/platform/vfio_platform_common.c       |   3 +-
> drivers/video/fbdev/Kconfig                        |   2 +-
> drivers/video/fbdev/core/fbcon.c                   |   3 +-
> drivers/video/fbdev/ep93xx-fb.c                    |   4 +-
> drivers/video/fbdev/geode/Kconfig                  |   1 +
> drivers/video/fbdev/hyperv_fb.c                    |   8 +-
> drivers/video/fbdev/pm2fb.c                        |   9 +-
> drivers/video/fbdev/uvesafb.c                      |   1 +
> drivers/video/fbdev/vermilion/vermilion.c          |   4 +-
> drivers/video/fbdev/via/via-core.c                 |   9 +-
> drivers/virt/coco/sev-guest/sev-guest.c            |   1 +
> drivers/watchdog/iTCO_wdt.c                        |  21 +-
> drivers/xen/privcmd.c                              |   2 +-
> fs/afs/fs_probe.c                                  |   5 +-
> fs/binfmt_misc.c                                   |   8 +-
> fs/btrfs/file.c                                    |  10 +-
> fs/char_dev.c                                      |   2 +-
> fs/cifs/cifsencrypt.c                              |  12 +-
> fs/cifs/cifsfs.c                                   |  31 +-
> fs/cifs/cifsglob.h                                 | 114 ++++-
> fs/cifs/cifsproto.h                                |  17 +-
> fs/cifs/connect.c                                  |   6 +-
> fs/cifs/dir.c                                      |  30 +-
> fs/cifs/file.c                                     |  41 +-
> fs/cifs/fs_context.c                               |  12 +-
> fs/cifs/inode.c                                    | 167 ++++---
> fs/cifs/link.c                                     | 107 +----
> fs/cifs/misc.c                                     |   6 +-
> fs/cifs/readdir.c                                  |   2 +
> fs/cifs/sess.c                                     |  30 +-
> fs/cifs/smb1ops.c                                  |  56 ++-
> fs/cifs/smb2file.c                                 | 127 ++++-
> fs/cifs/smb2inode.c                                | 169 +++----
> fs/cifs/smb2ops.c                                  | 252 ++++------
> fs/cifs/smb2pdu.c                                  |  20 +-
> fs/cifs/smb2pdu.h                                  |   3 +
> fs/cifs/smb2proto.h                                |  22 +-
> fs/configfs/dir.c                                  |   2 +
> fs/debugfs/file.c                                  |  28 +-
> fs/erofs/decompressor.c                            |  47 +-
> fs/erofs/erofs_fs.h                                |   2 +
> fs/erofs/internal.h                                |   1 +
> fs/erofs/zdata.c                                   |   3 +-
> fs/erofs/zmap.c                                    |  25 +-
> fs/f2fs/compress.c                                 |   2 +-
> fs/f2fs/f2fs.h                                     |   2 +-
> fs/f2fs/file.c                                     |   4 +
> fs/f2fs/gc.c                                       |  10 +-
> fs/f2fs/namei.c                                    | 329 +++++++------
> fs/f2fs/segment.c                                  |   8 +-
> fs/f2fs/super.c                                    |   2 +-
> fs/hfs/inode.c                                     |   2 +
> fs/hfs/trans.c                                     |   2 +-
> fs/hugetlbfs/inode.c                               |   6 +-
> fs/jfs/jfs_dmap.c                                  |  27 +-
> fs/jfs/namei.c                                     |   2 +-
> fs/ksmbd/mgmt/user_session.c                       |   8 +-
> fs/libfs.c                                         |  22 +-
> fs/lockd/svcsubs.c                                 |  17 +-
> fs/nfs/fs_context.c                                |   6 +
> fs/nfs/internal.h                                  |   6 +-
> fs/nfs/namespace.c                                 |   2 +-
> fs/nfs/nfs42xdr.c                                  |   2 +-
> fs/nfs/nfs4proc.c                                  |  38 +-
> fs/nfs/nfs4state.c                                 |   2 +
> fs/nfs/nfs4xdr.c                                   |  22 +-
> fs/nfsd/nfs2acl.c                                  |  10 -
> fs/nfsd/nfs3acl.c                                  |  30 +-
> fs/nfsd/nfs4callback.c                             |   4 +-
> fs/nfsd/nfs4proc.c                                 |   7 +-
> fs/nfsd/nfs4state.c                                |  51 +-
> fs/nilfs2/the_nilfs.c                              |  73 ++-
> fs/ntfs3/bitmap.c                                  |   2 +-
> fs/ntfs3/super.c                                   |   2 +-
> fs/ntfs3/xattr.c                                   |   2 +-
> fs/ocfs2/journal.c                                 |   2 +-
> fs/ocfs2/journal.h                                 |   1 +
> fs/ocfs2/stackglue.c                               |   8 +-
> fs/ocfs2/super.c                                   |   5 +-
> fs/orangefs/orangefs-debugfs.c                     |  29 +-
> fs/orangefs/orangefs-mod.c                         |   8 +-
> fs/orangefs/orangefs-sysfs.c                       |  71 ++-
> fs/overlayfs/file.c                                |  28 +-
> fs/overlayfs/super.c                               |   7 +-
> fs/pstore/Kconfig                                  |   1 +
> fs/pstore/pmsg.c                                   |   7 +-
> fs/pstore/ram.c                                    |   2 +
> fs/pstore/ram_core.c                               |   6 +-
> fs/reiserfs/namei.c                                |   4 +
> fs/reiserfs/xattr_security.c                       |   2 +-
> fs/sysv/itree.c                                    |   2 +-
> fs/udf/namei.c                                     |   8 +-
> fs/xattr.c                                         |   2 +-
> include/drm/drm_connector.h                        |   6 +
> include/drm/ttm/ttm_tt.h                           |   2 +-
> include/dt-bindings/clock/imx8mn-clock.h           |  24 +-
> include/dt-bindings/clock/imx8mp-clock.h           |   3 +-
> .../dt-bindings/clock/qcom,lpassaudiocc-sc7280.h   |   5 +
> .../dt-bindings/clock/qcom,lpasscorecc-sc7280.h    |   2 +
> include/linux/btf_ids.h                            |   2 +-
> include/linux/debugfs.h                            |  19 +-
> include/linux/eventfd.h                            |   2 +-
> include/linux/fortify-string.h                     |  31 +-
> include/linux/fs.h                                 |  12 +-
> include/linux/hisi_acc_qm.h                        |  37 +-
> include/linux/hyperv.h                             |   2 +
> include/linux/ieee80211.h                          |   2 +-
> include/linux/iio/imu/adis.h                       |  13 +-
> include/linux/netdevice.h                          |  58 ++-
> include/linux/proc_fs.h                            |   2 +
> include/linux/regulator/driver.h                   |   3 +-
> include/linux/skmsg.h                              |   1 +
> include/linux/timerqueue.h                         |   2 +-
> include/media/dvbdev.h                             |  32 +-
> include/net/bluetooth/hci.h                        |  20 +
> include/net/bluetooth/hci_core.h                   |   7 +-
> include/net/dst.h                                  |   5 +-
> include/net/ip_vs.h                                |  10 +-
> include/net/mrp.h                                  |   1 +
> include/net/sock_reuseport.h                       |   2 +
> include/net/tcp.h                                  |   4 +-
> include/scsi/sas_ata.h                             |   6 +
> include/sound/hda_codec.h                          |   2 +-
> include/sound/hdaudio.h                            |   1 +
> include/sound/pcm.h                                |  36 +-
> include/trace/events/f2fs.h                        |  34 +-
> include/trace/events/ib_mad.h                      |  13 +-
> include/uapi/linux/idxd.h                          |   2 +-
> include/uapi/linux/swab.h                          |   2 +-
> include/uapi/rdma/hns-abi.h                        |  15 +
> include/uapi/sound/asequencer.h                    |   8 +-
> io_uring/msg_ring.c                                |   2 +
> io_uring/net.c                                     |   2 +-
> io_uring/timeout.c                                 |   4 +-
> ipc/mqueue.c                                       |   6 +-
> kernel/acct.c                                      |   2 +
> kernel/bpf/btf.c                                   |   5 +
> kernel/bpf/syscall.c                               |   6 +-
> kernel/bpf/verifier.c                              | 108 +++--
> kernel/cpu.c                                       |  60 ++-
> kernel/events/core.c                               |   8 +-
> kernel/fork.c                                      |  17 +-
> kernel/futex/core.c                                |  26 +-
> kernel/gcov/gcc_4_7.c                              |   5 +
> kernel/irq/internals.h                             |   2 +
> kernel/irq/irqdesc.c                               |  15 +-
> kernel/kprobes.c                                   |  16 +-
> kernel/module/decompress.c                         |   8 +-
> kernel/padata.c                                    |  15 +-
> kernel/power/snapshot.c                            |   4 +-
> kernel/rcu/tree.c                                  |   2 +-
> kernel/relay.c                                     |   4 +-
> kernel/sched/core.c                                |  10 +-
> kernel/sched/cpudeadline.c                         |   2 +-
> kernel/sched/deadline.c                            |   4 +-
> kernel/sched/fair.c                                | 231 +++++++--
> kernel/sched/psi.c                                 |   8 +-
> kernel/sched/rt.c                                  |   4 +-
> kernel/sched/sched.h                               |  56 ++-
> kernel/trace/blktrace.c                            |   3 +-
> kernel/trace/trace_events_hist.c                   |   2 +-
> kernel/trace/trace_events_user.c                   |   1 +
> lib/debugobjects.c                                 |  10 +
> lib/fonts/fonts.c                                  |   4 +-
> lib/notifier-error-inject.c                        |   2 +-
> lib/test_firmware.c                                |   1 +
> mm/gup.c                                           |   3 +
> net/802/mrp.c                                      |  18 +-
> net/8021q/vlan_dev.c                               |   4 +-
> net/9p/client.c                                    |   5 +
> net/bluetooth/hci_conn.c                           |   2 +-
> net/bluetooth/hci_core.c                           |   4 +-
> net/bluetooth/hci_sync.c                           |   2 +-
> net/bluetooth/lib.c                                |   4 +-
> net/bluetooth/mgmt.c                               |   2 +-
> net/bluetooth/rfcomm/core.c                        |   2 +-
> net/bpf/test_run.c                                 |   3 -
> net/bridge/br_multicast.c                          |   4 +-
> net/bridge/br_vlan.c                               |   4 +-
> net/core/dev.c                                     |  18 +-
> net/core/devlink.c                                 |   9 +-
> net/core/drop_monitor.c                            |   8 +-
> net/core/filter.c                                  |  11 +-
> net/core/gen_stats.c                               |  16 +-
> net/core/skbuff.c                                  |   3 +
> net/core/skmsg.c                                   |   9 +-
> net/core/sock.c                                    |   2 +-
> net/core/sock_map.c                                |   2 +
> net/core/sock_reuseport.c                          |  94 +++-
> net/core/stream.c                                  |   6 +
> net/dsa/slave.c                                    |   4 +-
> net/dsa/tag_8021q.c                                |  11 +-
> net/ethtool/ioctl.c                                |   3 +-
> net/hsr/hsr_debugfs.c                              |  40 +-
> net/hsr/hsr_device.c                               |  32 +-
> net/hsr/hsr_forward.c                              |  14 +-
> net/hsr/hsr_framereg.c                             | 222 ++++-----
> net/hsr/hsr_framereg.h                             |  17 +-
> net/hsr/hsr_main.h                                 |   9 +-
> net/hsr/hsr_netlink.c                              |   4 +-
> net/ipv4/af_inet.c                                 |   8 +-
> net/ipv4/inet_connection_sock.c                    |   5 +-
> net/ipv4/ping.c                                    |   2 +-
> net/ipv4/tcp_bpf.c                                 |  19 +-
> net/ipv4/udp.c                                     |  39 +-
> net/ipv4/udp_tunnel_core.c                         |   1 +
> net/ipv6/af_inet6.c                                |   4 +-
> net/ipv6/datagram.c                                |  15 +-
> net/ipv6/seg6_local.c                              |   4 +-
> net/ipv6/sit.c                                     |  22 +-
> net/ipv6/udp.c                                     |  12 +-
> net/mac80211/cfg.c                                 |   2 +-
> net/mac80211/ieee80211_i.h                         |   1 +
> net/mac80211/iface.c                               |   1 +
> net/mac80211/mlme.c                                |  15 +-
> net/mac80211/sta_info.c                            |   8 +-
> net/mac80211/tx.c                                  |   2 +-
> net/mctp/device.c                                  |  14 +-
> net/mpls/af_mpls.c                                 |   4 +-
> net/netfilter/ipvs/ip_vs_core.c                    |  30 +-
> net/netfilter/ipvs/ip_vs_ctl.c                     |  14 +-
> net/netfilter/ipvs/ip_vs_est.c                     |  20 +-
> net/netfilter/nf_conntrack_proto_icmpv6.c          |  53 +++
> net/netfilter/nf_flow_table_offload.c              |   6 +-
> net/netfilter/nf_tables_api.c                      |   4 +-
> net/openvswitch/datapath.c                         |  29 +-
> net/openvswitch/flow_table.c                       |   9 +-
> net/rxrpc/output.c                                 |   2 +-
> net/rxrpc/sendmsg.c                                |   2 +-
> net/sched/ematch.c                                 |   2 +
> net/sctp/sysctl.c                                  |  73 +--
> net/sunrpc/clnt.c                                  |   2 +-
> net/sunrpc/xprtrdma/verbs.c                        |   2 +-
> net/tls/tls_sw.c                                   |   6 +-
> net/unix/af_unix.c                                 |  12 +-
> net/vmw_vsock/vmci_transport.c                     |   6 +-
> net/wireless/nl80211.c                             |   3 +
> net/wireless/reg.c                                 |   4 +-
> samples/bpf/xdp1_user.c                            |   2 +-
> samples/bpf/xdp2_kern.c                            |   4 +
> samples/vfio-mdev/mdpy-fb.c                        |   8 +-
> security/Kconfig.hardening                         |   3 +
> security/apparmor/apparmorfs.c                     |   4 +-
> security/apparmor/label.c                          |  12 +-
> security/apparmor/lsm.c                            |   4 +-
> security/apparmor/policy.c                         |   2 +-
> security/apparmor/policy_ns.c                      |   2 +-
> security/apparmor/policy_unpack.c                  |   2 +-
> security/integrity/digsig.c                        |   6 +-
> security/integrity/ima/ima_policy.c                |  51 +-
> security/integrity/ima/ima_template.c              |   4 +-
> security/loadpin/loadpin.c                         |  30 +-
> sound/core/pcm_native.c                            |   4 +-
> sound/drivers/mts64.c                              |   3 +
> sound/hda/hdac_stream.c                            |  17 +-
> sound/pci/asihpi/hpioctl.c                         |   2 +-
> sound/pci/hda/hda_codec.c                          |   3 +-
> sound/pci/hda/hda_controller.c                     |   4 +-
> sound/pci/hda/patch_hdmi.c                         | 273 ++++++-----
> sound/pci/hda/patch_realtek.c                      |  27 ++
> sound/soc/amd/yc/acp6x-mach.c                      |   7 +
> sound/soc/codecs/hda.c                             |   3 -
> sound/soc/codecs/hdac_hda.c                        |   3 -
> sound/soc/codecs/pcm512x.c                         |   8 +-
> sound/soc/codecs/rt298.c                           |   7 +
> sound/soc/codecs/rt5670.c                          |   2 -
> sound/soc/codecs/wm8994.c                          |   5 +
> sound/soc/codecs/wsa883x.c                         |   6 +-
> sound/soc/generic/audio-graph-card.c               |   4 +-
> sound/soc/intel/avs/boards/rt298.c                 |  24 +-
> sound/soc/intel/avs/core.c                         |   2 +-
> sound/soc/intel/avs/ipc.c                          |   6 +-
> sound/soc/intel/boards/sof_es8336.c                |   2 +-
> sound/soc/intel/skylake/skl.c                      |   5 +-
> sound/soc/mediatek/common/mtk-btcvsd.c             |   6 +-
> sound/soc/mediatek/mt8173/mt8173-afe-pcm.c         |  20 +-
> sound/soc/mediatek/mt8173/mt8173-rt5650-rt5514.c   |   7 +-
> .../mt8183/mt8183-mt6358-ts3a227-max98357.c        |  14 +-
> sound/soc/pxa/mmp-pcm.c                            |   2 +-
> sound/soc/qcom/lpass-sc7180.c                      |   3 +
> sound/soc/rockchip/rockchip_pdm.c                  |   1 +
> sound/soc/rockchip/rockchip_spdif.c                |   1 +
> sound/usb/quirks-table.h                           |   2 +
> tools/bpf/bpftool/common.c                         |   1 +
> tools/lib/bpf/bpf.h                                |   7 +
> tools/lib/bpf/btf.c                                |   8 +-
> tools/lib/bpf/btf_dump.c                           |  29 +-
> tools/lib/bpf/libbpf.c                             |  30 +-
> tools/lib/bpf/usdt.c                               |  11 +-
> tools/objtool/check.c                              |  10 +
> tools/perf/builtin-stat.c                          |  33 +-
> tools/perf/builtin-trace.c                         |  32 +-
> tools/perf/tests/shell/stat_all_pmu.sh             |  13 +-
> tools/perf/util/bpf_off_cpu.c                      |   2 +-
> tools/perf/util/debug.c                            |   4 +
> tools/perf/util/symbol-elf.c                       |   2 +-
> .../selftests/bpf/bpf_testmod/bpf_testmod.c        |  48 ++
> tools/testing/selftests/bpf/config                 |   1 +
> tools/testing/selftests/bpf/network_helpers.c      |   4 +
> tools/testing/selftests/bpf/prog_tests/empty_skb.c | 146 ++++++
> .../selftests/bpf/prog_tests/kprobe_multi_test.c   |  26 +-
> .../testing/selftests/bpf/prog_tests/lsm_cgroup.c  |  17 +-
> tools/testing/selftests/bpf/prog_tests/map_kptr.c  |   3 +-
> .../selftests/bpf/prog_tests/tracing_struct.c      |  64 +++
> .../selftests/bpf/prog_tests/xdp_adjust_tail.c     |   7 +-
> .../selftests/bpf/prog_tests/xdp_do_redirect.c     |   2 +-
> .../selftests/bpf/prog_tests/xdp_synproxy.c        |   2 +-
> tools/testing/selftests/bpf/progs/bpf_iter_ksym.c  |   6 +-
> tools/testing/selftests/bpf/progs/empty_skb.c      |  37 ++
> tools/testing/selftests/bpf/progs/lsm_cgroup.c     |   8 +
> tools/testing/selftests/bpf/progs/tracing_struct.c | 120 +++++
> tools/testing/selftests/bpf/xdp_synproxy.c         |   5 +-
> tools/testing/selftests/cgroup/cgroup_util.c       |   5 +-
> .../selftests/drivers/net/netdevsim/devlink.sh     |   4 +-
> tools/testing/selftests/efivarfs/efivarfs.sh       |   5 +
> .../ftrace/test.d/ftrace/func_event_triggers.tc    |  15 +-
> .../selftests/netfilter/conntrack_icmp_related.sh  |  36 +-
> .../selftests/powerpc/dscr/dscr_sysfs_test.c       |   5 +-
> tools/testing/selftests/proc/proc-uptime-002.c     |   3 +-
> 1027 files changed, 12883 insertions(+), 6780 deletions(-)
> 
> 

^ permalink raw reply	[relevance 0%]

* [GIT PULL] Networking for 5.19
@ 2022-05-24 20:31  1% Jakub Kicinski
  0 siblings, 0 replies; 77+ results
From: Jakub Kicinski @ 2022-05-24 20:31 UTC (permalink / raw)
  To: torvalds; +Cc: kuba, davem, netdev, linux-kernel

Hi Linus!

We have a conflict with the sysctl changes, delete both sides:
https://lore.kernel.org/all/20220414112812.652190b5@canb.auug.org.au/
(the resolution from Stephen is a bit hard to read, but just delete).

There may be a warning if you pull after the bitmap tree PR, too:
https://lore.kernel.org/all/20220524082256.3b8033a9@canb.auug.org.au/

The following changes since commit d904c8cc0302393640bc29ee62193f88ddc53126:

  Merge tag 'net-5.18-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net (2022-05-19 05:50:29 -1000)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git tags/net-next-5.19

for you to fetch changes up to 57d7becda9c9e612e6b00676f2eecfac3e719e88:

  Merge branch 'ptp-ocp-various-updates' (2022-05-24 11:40:01 -0700)

----------------------------------------------------------------
Networking changes for 5.19.

Core
----

 - Support TCPv6 segmentation offload with super-segments larger than
   64k bytes using the IPv6 Jumbogram extension header (AKA BIG TCP).

 - Generalize skb freeing deferral to per-cpu lists, instead of
   per-socket lists.

 - Add a netdev statistic for packets dropped due to L2 address
   mismatch (rx_otherhost_dropped).

 - Continue work annotating skb drop reasons.

 - Accept alternative netdev names (ALT_IFNAME) in more netlink
   requests.

 - Add VLAN support for AF_PACKET SOCK_RAW GSO.

 - Allow receiving skb mark from the socket as a cmsg.

 - Enable memcg accounting for veth queues, sysctl tables and IPv6.

BPF
---

 - Add libbpf support for User Statically-Defined Tracing (USDTs).

 - Speed up symbol resolution for kprobes multi-link attachments.

 - Support storing typed pointers to referenced and unreferenced
   objects in BPF maps.

 - Add support for BPF link iterator.

 - Introduce access to remote CPU map elements in BPF per-cpu map.

 - Allow middle-of-the-road settings for the
   kernel.unprivileged_bpf_disabled sysctl.

 - Implement basic types of dynamic pointers e.g. to allow for
   dynamically sized ringbuf reservations without extra memory copies.

Protocols
---------

 - Retire port only listening_hash table, add a second bind table
   hashed by port and address. Avoid linear list walk when binding
   to very popular ports (e.g. 443).

 - Add bridge FDB bulk flush filtering support allowing user space
   to remove all FDB entries matching a condition.

 - Introduce accept_unsolicited_na sysctl for IPv6 to implement
   router-side changes for RFC9131.

 - Support for MPTCP path manager in user space.

 - Add MPTCP support for fallback to regular TCP for connections
   that have never connected additional subflows or transmitted
   out-of-sequence data (partial support for RFC8684 fallback).

 - Avoid races in MPTCP-level window tracking, stabilize and improve
   throughput.

 - Support lockless operation of GRE tunnels with seq numbers enabled.

 - WiFi support for host based BSS color collision detection.

 - Add support for SO_TXTIME/SCM_TXTIME on CAN sockets.

 - Support transmission w/o flow control in CAN ISOTP (ISO 15765-2).

 - Support zero-copy Tx with TLS 1.2 crypto offload (sendfile).

 - Allow matching on the number of VLAN tags via tc-flower.

 - Add tracepoint for tcp_set_ca_state().

Driver API
----------

 - Improve error reporting from classifier and action offload.

 - Add support for listing line cards in switches (devlink).

 - Add helpers for reporting page pool statistics with ethtool -S.

 - Add support for reading clock cycles when using PTP virtual clocks,
   instead of having the driver convert to time before reporting.
   This makes it possible to report time from different vclocks.

 - Support configuring low-latency Tx descriptor push via ethtool.

 - Separate Clause 22 and Clause 45 MDIO accesses more explicitly.

New hardware / drivers
----------------------

 - Ethernet:
   - Marvell's Octeon NIC PCI Endpoint support (octeon_ep)
   - Sunplus SP7021 SoC (sp7021_emac)
   - Add support for Renesas RZ/V2M (in ravb)
   - Add support for MediaTek mt7986 switches (in mtk_eth_soc)

 - Ethernet PHYs:
   - ADIN1100 industrial PHYs (w/ 10BASE-T1L and SQI reporting)
   - TI DP83TD510 PHY
   - Microchip LAN8742/LAN88xx PHYs

 - WiFi:
   - Driver for pureLiFi X, XL, XC devices (plfxlc)
   - Driver for Silicon Labs devices (wfx)
   - Support for WCN6750 (in ath11k)
   - Support Realtek 8852ce devices (in rtw89)

 - Mobile:
   - MediaTek T700 modems (Intel 5G 5000 M.2 cards)

 - CAN:
  - ctucanfd: add support for CTU CAN FD open-source IP core
    from Czech Technical University in Prague

Drivers
-------

 - Delete a number of old drivers still using virt_to_bus().

 - Ethernet NICs:
   - intel: support TSO on tunnels MPLS
   - broadcom: support multi-buffer XDP
   - nfp: support VF rate limiting
   - sfc: use hardware tx timestamps for more than PTP
   - mlx5: multi-port eswitch support
   - hyper-v: add support for XDP_REDIRECT
   - atlantic: XDP support (including multi-buffer)
   - macb: improve real-time perf by deferring Tx processing to NAPI

 - High-speed Ethernet switches:
   - mlxsw: implement basic line card information querying
   - prestera: add support for traffic policing on ingress and egress

 - Embedded Ethernet switches:
   - lan966x: add support for packet DMA (FDMA)
   - lan966x: add support for PTP programmable pins
   - ti: cpsw_new: enable bc/mc storm prevention

 - Qualcomm 802.11ax WiFi (ath11k):
   - Wake-on-WLAN support for QCA6390 and WCN6855
   - device recovery (firmware restart) support
   - support setting Specific Absorption Rate (SAR) for WCN6855
   - read country code from SMBIOS for WCN6855/QCA6390
   - enable keep-alive during WoWLAN suspend
   - implement remain-on-channel support

 - MediaTek WiFi (mt76):
   - support Wireless Ethernet Dispatch offloading packet movement
     between the Ethernet switch and WiFi interfaces
   - non-standard VHT MCS10-11 support
   - mt7921 AP mode support
   - mt7921 IPv6 NS offload support

 - Ethernet PHYs:
   - micrel: ksz9031/ksz9131: cabletest support
   - lan87xx: SQI support for T1 PHYs
   - lan937x: add interrupt support for link detection

Signed-off-by: Jakub Kicinski <kuba@kernel.org>

----------------------------------------------------------------
Abhishek Kumar (1):
      ath10k: skip ath10k_halt during suspend for driver state RESTARTING

Ahmad Fatoum (1):
      Bluetooth: hci_sync: use hci_skb_event() helper

Ajay Singh (5):
      wilc1000: increase firmware version array size
      wilc1000: use fixed function base register value to access SDIO_FBR_ENABLE_CSA
      wilc1000: fix crash observed in AP mode with cfg80211_register_netdevice()
      wilc1000: use 'u64' datatype for cookie variable
      wilc1000: add valid vmm_entry check before fetching from TX queue

Akira Yokosawa (1):
      docs: ctucanfd: Use 'kernel-figure' directive instead of 'figure'

Alaa Mohamed (6):
      selftests: net: fib_rule_tests: add support to select a test to run
      igb: Convert kmap() to kmap_local_page()
      rtnetlink: add extack support in fdb del handlers
      net: vxlan: Add extack support to vxlan_fdb_delete
      net: vxlan: Fix kernel coding style
      net: mscc: fix the alignment in ocelot_port_fdb_del()

Alan Maguire (11):
      libbpf: auto-resolve programs/libraries when necessary for uprobes
      libbpf: Support function name-based attach uprobes
      libbpf: Add auto-attach for uprobes based on section name
      selftests/bpf: Add tests for u[ret]probe attach by name
      selftests/bpf: Add tests for uprobe auto-attach via skeleton
      libbpf: Improve library identification for uprobe binary path resolution
      libbpf: Improve string parsing for uprobe auto-attach
      selftests/bpf: Uprobe tests should verify param/return values
      libbpf: Usdt aarch64 arg parsing support
      bpf: refine kernel.unprivileged_bpf_disabled behaviour
      selftests/bpf: add tests verifying unprivileged bpf behaviour

Alex Elder (17):
      net: ipa: compute proper aggregation limit
      net: ipa: drop an unneeded transaction reference
      net: ipa: rename a GSI error code
      net: ipa: ignore endianness if there is no header
      net: ipa: open-code ether_setup()
      net: ipa: move endpoint configuration data definitions
      net: ipa: rename a few endpoint config data types
      net: ipa: save a copy of endpoint default config
      net: ipa: make endpoint HOLB drop configurable
      net: ipa: support hard aggregation limits
      net: ipa: specify RX aggregation time limit in config data
      net: ipa: kill gsi_trans_commit_wait_timeout()
      net: ipa: count the number of modem TX endpoints
      net: ipa: get rid of ipa_cmd_info->direction
      net: ipa: remove command direction argument
      net: ipa: remove command info pool
      net: ipa: use data space for command opcodes

Alexander Duyck (2):
      net: allow gso_max_size to exceed 65536
      net: allow gro_max_size to exceed 65536

Alexander Lobakin (6):
      samples: bpf: Fix linking xdp_router_ipv4 after migration
      ice: switch: add and use u16[] aliases to ice_adv_lkup_elem::{h, m}_u
      ice: switch: unobscurify bitops loop in ice_fill_adv_dummy_packet()
      ice: switch: use a struct to pass packet template params
      ice: switch: use convenience macros to declare dummy pkt templates
      ice: switch: convert packet template match code to rodata

Alexander Wetzel (1):
      rtl818x: Prevent using not initialized queues

Alexandru Ardelean (1):
      net: phy: adin1100: Add initial support for ADIN1100 industrial PHY

Alexandru Tachici (6):
      ethtool: Add 10base-T1L link mode entry
      net: phy: Add 10-BaseT1L registers
      net: phy: Add BaseT1 auto-negotiation registers
      net: phy: Add 10BASE-T1L support in phy-c45
      net: phy: adin1100: Add SQI support
      dt-bindings: net: phy: Add 10-baseT1L 2.4 Vpp

Alexei Starovoitov (15):
      Merge branch 'Add libbpf support for USDTs'
      Merge branch 'Ensure type tags are always ordered first in BTF'
      Merge branch 'Introduce typed pointer support in BPF maps'
      Merge branch 'Teach libbpf to "fix up" BPF verifier log'
      Merge branch 'libbpf: allow to opt-out from BPF map creation'
      Merge branch 'Add source ip in bpf tunnel key'
      Merge branch 'bpf: bpf link iterator'
      Merge branch 'bpf: Speed up symbol resolving in kprobe multi link'
      Merge branch 'selftests: xsk: add busy-poll testing plus various fixes'
      Merge branch 'Follow ups for kptr series'
      Merge branch 'Introduce access remote cpu elem support in BPF percpu map'
      bpf: Fix combination of jit blinding and pointers to bpf subprogs.
      selftests/bpf: Check combination of jit blinding and pointers to bpf subprogs.
      Merge branch 'Start libbpf 1.0 dev cycle'
      Merge branch 'bpf: refine kernel.unprivileged_bpf_disabled behaviour'

Alvin Šipraga (1):
      net: dsa: realtek: rtl8366rb: Serialize indirect PHY register access

Amit Cohen (2):
      selftests: fib_nexthops: Make the test more robust
      selftests: fib_nexthops: Make ping timeout configurable

Andrea Parri (Microsoft) (1):
      hv_netvsc: Print value of invalid ID in netvsc_send_{completion,tx_complete}()

Andrejs Cainikovs (2):
      mwifiex: Select firmware based on strapping
      mwifiex: Add SD8997 SDIO-UART firmware

Andrew Lunn (5):
      net: phylink: Convert to mdiobus_c45_{read|write}
      net: phy: Convert to mdiobus_c45_{read|write}
      net: phy: bcm87xx: Use mmd helpers
      net: dsa: sja1105: Convert to mdiobus_c45_read
      net: pcs: pcs-xpcs: Convert to mdiobus_c45_read

Andrii Nakryiko (63):
      Merge branch 'libbpf: name-based u[ret]probe attach'
      Merge branch 'bpf/bpftool: add program & link type names'
      libbpf: Add BPF-side of USDT support
      libbpf: Wire up USDT API and bpf_link integration
      libbpf: Add USDT notes parsing and resolution logic
      libbpf: Wire up spec management and other arch-independent USDT logic
      libbpf: Add x86-specific USDT arg spec parsing logic
      selftests/bpf: Add basic USDT selftests
      selftests/bpf: Add urandom_read shared lib and USDTs
      Merge branch 'libbpf: uprobe name-based attach followups'
      libbpf: Fix use #ifdef instead of #if to avoid compiler warning
      Merge branch 'Add USDT support for s390'
      libbpf: Use strlcpy() in path resolution fallback logic
      libbpf: Allow WEAK and GLOBAL bindings during BTF fixup
      libbpf: Don't error out on CO-RE relos for overriden weak subprogs
      libbpf: Use weak hidden modifier for USDT BPF-side API functions
      selftests/bpf: Add CO-RE relos into linked_funcs selftests
      Merge branch 'bpf: RLIMIT_MEMLOCK cleanups'
      libbpf: Support opting out from autoloading BPF programs declaratively
      selftests/bpf: Use non-autoloaded programs in few tests
      Merge branch 'Support riscv libbpf USDT arg parsing logic'
      bpf: Allow attach TRACING programs through LINK_CREATE command
      libbpf: Teach bpf_link_create() to fallback to bpf_raw_tracepoint_open()
      selftests/bpf: Switch fexit_stress to bpf_link_create() API
      libbpf: Fix anonymous type check in CO-RE logic
      libbpf: Drop unhelpful "program too large" guess
      libbpf: Fix logic for finding matching program for CO-RE relocation
      libbpf: Avoid joining .BTF.ext data with BPF programs by section name
      selftests/bpf: Add CO-RE relos and SEC("?...") to linked_funcs selftests
      libbpf: Record subprog-resolved CO-RE relocations unconditionally
      libbpf: Refactor CO-RE relo human description formatting routine
      libbpf: Simplify bpf_core_parse_spec() signature
      libbpf: Fix up verifier log for unguarded failed CO-RE relos
      selftests/bpf: Add libbpf's log fixup logic selftests
      libbpf: Allow "incomplete" basic tracing SEC() definitions
      libbpf: Support target-less SEC() definitions for BTF-backed programs
      selftests/bpf: Use target-less SEC() definitions in various tests
      libbpf: Append "..." in fixed up log if CO-RE spec is truncated
      libbpf: Use libbpf_mem_ensure() when allocating new map
      libbpf: Allow to opt-out from creating BPF maps
      selftests/bpf: Test bpf_map__set_autocreate() and related log fixup logic
      selftests/bpf: Prevent skeleton generation race
      libbpf: Make __kptr and __kptr_ref unconditionally use btf_type_tag() attr
      libbpf: Improve usability of field-based CO-RE helpers
      selftests/bpf: Use both syntaxes for field-based CO-RE helpers
      libbpf: Complete field-based CO-RE helpers with field offset helper
      selftests/bpf: Add bpf_core_field_offset() tests
      libbpf: Provide barrier() and barrier_var() in bpf_helpers.h
      libbpf: Automatically fix up BPF_MAP_TYPE_RINGBUF size, if necessary
      selftests/bpf: Test libbpf's ringbuf size fix up logic
      Merge branch 'bpftool: fix feature output when helper probes fail'
      Merge branch 'Attach a cookie to a tracing program.'
      libbpf: Clean up ringbuf size adjustment implementation
      selftests/bpf: make fexit_stress test run in serial mode
      libbpf: Add safer high-level wrappers for map operations
      selftests/bpf: Convert some selftests to high-level BPF map APIs
      selftests/bpf: Fix usdt_400 test case
      libbpf: fix memory leak in attach_tp for target-less tracepoint program
      libbpf: fix up global symbol counting logic
      libbpf: start 1.0 development cycle
      libbpf: remove bpf_create_map*() APIs
      Merge branch 'bpf: mptcp: Support for mptcp_sock'
      Merge branch 'Dynamic pointers'

Andy Gospodarek (11):
      bnxt: refactor bnxt_rx_xdp to separate xdp_init_buff/xdp_prepare_buff
      bnxt: add flag to denote that an xdp program is currently attached
      bnxt: refactor bnxt_rx_pages operate on skb_shared_info
      bnxt: rename bnxt_rx_pages to bnxt_rx_agg_pages_skb
      bnxt: adding bnxt_rx_agg_pages_xdp for aggregated xdp
      bnxt: set xdp_buff pfmemalloc flag if needed
      bnxt: change receive ring space parameters
      bnxt: add page_pool support for aggregation ring when using xdp
      bnxt: adding bnxt_xdp_build_skb to build skb from multibuffer xdp_buff
      bnxt: support transmit and free of aggregation buffers
      bnxt: XDP multibuffer enablement

Andy Shevchenko (2):
      firmware: tee_bnxt: Use UUID API for exporting the UUID
      bcma: gpio: Switch to use fwnode instead of of_node

Anilkumar Kolli (1):
      ath11k: Reuse the available memory after firmware reload

Ansuel Smith (6):
      net: dsa: qca8k: drop MTU tracking from qca8k_priv
      net: dsa: qca8k: drop port_sts from qca8k_priv
      net: dsa: qca8k: rework and simplify mdiobus logic
      net: dsa: qca8k: drop dsa_switch_ops from qca8k_priv
      net: dsa: qca8k: correctly handle mdio read error
      net: dsa: qca8k: unify bus id naming with legacy and OF mdio bus

Artem Savkov (4):
      selftests/bpf: Use bpf_num_possible_cpus() in per-cpu map allocations
      selftests/bpf: Fix attach tests retcode checks
      selftests/bpf: Fix prog_tests uprobe_autoattach compilation error
      selftests/bpf: Fix map tests errno checks

Arun Ajith S (2):
      net/ipv6: Introduce accept_unsolicited_na knob to implement router-side changes for RFC9131
      net/ipv6: Enforce limits for accept_unsolicited_na sysctl

Arun Ramadoss (13):
      net: phy: LAN87xx: add ethtool SQI support
      MAINTAINERS: Add maintainers for Microchip T1 Phy driver
      net: phy: LAN937x: add interrupt support for link detection
      net: dsa: ksz: added the generic port_stp_state_set function
      net: dsa: ksz9477: move get_stats64 to ksz_common.c
      net: dsa: microchip: ksz8795: update the port_cnt value in ksz_chip_data
      net: dsa: microchip: move ksz_chip_data to ksz_common
      net: dsa: microchip: perform the compatibility check for dev probed
      net: dsa: microchip: move struct mib_names to ksz_chip_data
      net: dsa: microchip: move port memory allocation to ksz_common
      net: dsa: microchip: move get_strings to ksz_common
      net: dsa: microchip: add the phylink get_caps
      net: dsa: microchip: remove unused members in ksz_device

Arınç ÜNAL (1):
      net: bridge: offload BR_HAIRPIN_MODE, BR_ISOLATED, BR_MULTICAST_TO_UNICAST

Avraham Stern (1):
      iwlwifi: mei: clear the sap data header before sending

Aya Levin (1):
      net/mlx5e: Allow relaxed ordering over VFs

Baochen Qiang (8):
      ath11k: enable PLATFORM_CAP_PCIE_GLOBAL_RESET QMI host capability
      ath11k: Remove unnecessary delay in ath11k_core_suspend
      ath11k: Add support for SAR
      ath11k: Don't use GFP_KERNEL in atomic context
      ath11k: Handle keepalive during WoWLAN suspend and resume
      ath11k: Implement remain-on-channel support
      ath11k: Don't check arvif->is_started before sending management frames
      ath11k: Designating channel frequency when sending management frames

Baowen Zheng (1):
      nfp: support 802.1ad VLAN assingment to VF

Benjamin Stürz (1):
      wcn36xx: Improve readability of wcn36xx_caps_name

Benjamin Tissoires (1):
      bpf: Allow kfunc in tracing and syscall programs.

Bernard Zhao (1):
      ethernet/ti: delete if NULL check befort devm_kfree

Bert Kenward (1):
      sfc: use hardware tx timestamps for more than PTP

Biju Das (1):
      dt-bindings: can: renesas,rcar-canfd: Document RZ/G2UL support

Bin Chen (2):
      rtnetlink: verify rate parameters for calls to ndo_set_vf_rate
      nfp: VF rate limit support

Bjorn Helgaas (2):
      net: wan: atp: remove unused eeprom_delay()
      net: remove comments that mention obsolete __SLOW_DOWN_IO

Björn Töpel (1):
      xsk: Improve xdp_do_redirect() error codes

Bo Jiao (2):
      mt76: mt7915: disable RX_HDR_TRANS_SHORT
      mt76: mt7615/mt7915: do reset_work with mt76's work queue

Boris Pismenny (1):
      tls: Add opt-in zerocopy mode of sendfile()

Boris Sukholitko (5):
      net/sched: flower: Helper function for vlan ethtype checks
      net/sched: flower: Reduce identation after is_key_vlan refactoring
      flow_dissector: Add number of vlan tags dissector
      net/sched: flower: Add number of vlan tags filter
      net/sched: flower: Consider the number of tags for vlan filters

Borislav Petkov (2):
      IB/mlx5: Fix undefined behavior due to shift overflowing the constant
      bnx2x: Fix undefined behavior due to shift overflowing the constant

Brian Gix (1):
      Bluetooth: Keep MGMT pending queue ordered FIFO

Carl Huang (6):
      ath11k: Add basic WoW functionalities
      ath11k: Add WoW net-detect functionality
      ath11k: implement hardware data filter
      ath11k: purge rx pktlog when entering WoW
      ath11k: support ARP and NS offload
      ath11k: support GTK rekey offload

Casper Andersson (1):
      net: sparx5: Add handling of host MDB entries

Chandrashekar Devegowda (1):
      net: wwan: t7xx: Add AT and MBIM WWAN ports

Chia-Yuan Li (5):
      rtw89: pci: refine pci pre_init function
      rtw89: ser: configure D-MAC interrupt mask
      rtw89: ser: configure C-MAC interrupt mask
      rtw89: 8852c: disable firmware watchdog if CPU disabled
      rtw89: 8852c: add 8852c specific BT-coexistence initial function

Chih-Kang Chang (3):
      rtw88: add HT MPDU density value for each chip
      rtw88: fix not disabling beacon filter after disconnection
      rtw88: fix hw scan may cause disconnect issue

Chin-Yen Lee (1):
      rtw88: adjust adaptivity option to 1

Ching-Te Ku (1):
      rtw89: coex: Add case for scan offload

Chris Chiu (2):
      rtl8xxxu: feed antenna information for cfg80211
      rtl8xxxu: fill up txrate info for gen1 chips

Chris Packham (3):
      dt-bindings: net: orion-mdio: Convert to JSON schema
      arm64: dts: armada-3720-turris-mox: Correct reg property for mdio devices
      dt-bindings: net: marvell,orion-mdio: Set unevaluatedProperties to false

Christophe JAILLET (4):
      mt76: mt7921: Fix the error handling path of mt7921_pci_probe()
      octeon_ep: Fix a memory leak in the error handling path of octep_request_irqs()
      octeon_ep: Fix irq releasing in the error handling path of octep_request_irqs()
      hinic: Avoid some over memory allocation

Christophe Leroy (4):
      orinoco: Prepare cleanup of powerpc's asm/prom.h
      can: mscan: mpc5xxx_can: Prepare cleanup of powerpc's asm/prom.h
      sungem: Prepare cleanup of powerpc's asm/prom.h
      net: ethernet: Prepare cleanup of powerpc's asm/prom.h

Coco Li (2):
      fou: Remove XRFM from NET_FOU Kconfig
      ipv6: Add hop-by-hop header to jumbograms in ip6_output

Colin Foster (4):
      net: mdio: mscc-miim: add local dev variable to cleanup probe function
      net: ethernet: ocelot: remove the need for num_stats initializer
      net: mscc: ocelot: remove unnecessary variable
      net: mscc: ocelot: add missed parentheses around macro argument

Colin Ian King (11):
      libbpf: Fix spelling mistake "libaries" -> "libraries"
      ath11k: Fix spelling mistake "reseting" -> "resetting"
      octeon_ep: Fix spelling mistake "inerrupts" -> "interrupts"
      myri10ge: remove redundant assignment to variable status
      net: hns3: Fix spelling mistake "actvie" -> "active"
      x25: remove redundant pointer dev
      ath11k: remove redundant assignment to variables vht_mcs and he_mcs
      net: ethernet: SP7021: Fix spelling mistake "Interrput" -> "Interrupt"
      mt76: mt7915: make read-only array ppet16_ppet8_ru3_ru0 static const
      mt76: mt7921: make read-only array ppet16_ppet8_ru3_ru0 static const
      selftests/bpf: Fix spelling mistake: "unpriviliged" -> "unprivileged"

Dan Carpenter (5):
      net: ethernet: mtk_eth_soc: use after free in __mtk_ppe_check_skb()
      ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix
      net: ethernet: mtk_eth_soc: add check for allocation failure
      net: ethernet: SP7021: fix a use after free of skb->len
      net: ethernet: mtk_eth_soc: fix error code in mtk_flow_offload_replace()

Daniel Borkmann (1):
      Merge branch 'pr/bpf-sysctl' into bpf-next

Daniel Müller (1):
      selftests/bpf: Enable CONFIG_FPROBE for self tests

Daniele Palmas (1):
      net: usb: qmi_wwan: add Telit 0x1057 composition

Danielle Ratson (1):
      selftests: netdevsim: Increase sleep time in hw_stats_l3.sh test

David Ahern (1):
      net: Make msg_zerocopy_alloc static

David Bentham (1):
      net: ethernet: mtk_eth_soc: add ipv6 flow offload support

David Howells (12):
      rxrpc: Allow list of in-use local UDP endpoints to be viewed in /proc
      rxrpc: Use refcount_t rather than atomic_t
      rxrpc: Fix locking issue
      rxrpc: Automatically generate trace tag enums
      rxrpc: Return an error to sendmsg if call failed
      rxrpc, afs: Fix selection of abort codes
      afs: Adjust ACK interpretation to try and cope with NAT
      rxrpc: Fix listen() setting the bar too high for the prealloc rings
      rxrpc: Don't try to resend the request if we're receiving the reply
      rxrpc: Fix overlapping ACK accounting
      rxrpc: Don't let ack.previousPacket regress
      rxrpc: Fix decision on when to generate an IDLE ACK

David Ober (1):
      net: usb: r8152: Add in new Devices that are supported for Mac-Passthru

David S. Miller (80):
      Merge branch 'mscc-miim'
      Merge branch 'mtk_eth_soc-flo-offload-plus-wireless'
      Merge branch 'tls-rx-refactor-part-1'
      Merge branch 'bnxt-xdp-multi-buffer'
      Merge branch 'aspeed-mdio-c45'
      Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/nex t-queue
      Merge branch 'net-sched-offload-failure-error-reporting'
      Merge branch 'tls-rx-refactoring-part-2'
      Merge branch 'icmp-skb-reason'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next
      Merge branch 'mptcp-next'
      Merge branch 'tls-rx-refactor-part-3'
      Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
      Merge branch 'net-ti-storm-prevention-support'
      Merge branch 'br-flush-filtering'
      Merge branch 'octeon_ep-driver'
      Merge branch 'ip-ingress-skb-reason'
      Merge branch 'mneta-page_pool_get_stats'
      Merge branch 'mlxsw-line-card-prep'
      Merge branch 'emaclite-cleanups'
      Merge branch 'qca8k_preiv-shrink'
      Merge branch 'tcp-drop-reason-additions'
      Merge branch 'mlxsw-line-card'
      Merge branch 'dsa-cross-chip-notifier-cleanup'
      Merge branch 'atlantic-xdp-multi-buffer'
      Merge branch 'hns3-next'
      Merge branch 'net-sched-flower-num-vlan-tags'
      Merge tag 'linux-can-next-for-5.19-20220419' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
      Merge branch 'mlxsw-line-card-status-tracking'
      Merge branch 'ipv6-only-sock'
      Merge branch 'zynqmp-phy-config-optional'
      Merge branch 'ipv6-RT_ONLINK-remove-prep'
      Merge branch 'mptcp-tcp-fallback'
      Merge branch 'dsa-selftests'
      Merge branch 'mlxsw-line-card-model'
      Merge branch 'mptcp-MP_FAIL-timeout'
      Merge branch 'lan966x-ptp-programmable-pins'
      Merge branch 'remove-virt_to_bus-drivers'
      Merge branch 'remove-NAPI_POLL_WEIGHT-copies'
      Merge branch 'ipv6-net-opts'
      Merge branch 'lan966x-phy-reset-remove'
      Merge branch 'UDP-sock_wfree-opts'
      Merge branch 'adin1100-industrial-PHY-support'
      Merge branch 'mptcp-pathmanager-api'
      Merge tag 'mlx5-updates-2022-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux
      Merge branch 'sfc-Siena-subdir'
      Merge branch 'mlxsw-updates'
      Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
      Merge branch 'nfp-flower-rework'
      Merge branch 'tso-gso-limit-split'
      Merge branch 'switch-drivers-to-netif_napi_add_weight'
      Merge branch 'mlxsw-dedicated-router-notification-block'
      Merge tag 'batadv-next-pullrequest-20220508' of git://git.open-mesh.org/linux-merge
      Merge branch 'wwan-t7xx'
      Merge branch 'vxlan_fdb_delete-extack'
      Merge branch 'add-ti-dp83td510-support'
      Merge branch 'lan8742-phy'
      Merge branch 'hns3-next'
      Merge tag 'mlx5-updates-2022-05-09' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux
      Merge branch 'debug-net'
      Merge branch 'lan95xx-no-polling'
      Merge branch 'bnxt_en-next'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next
      Merge branch 'Renesas-RSZ-V2M-support'
      Merge branch 'big-tcp'
      Merge branch 'sk_bound_dev_if-annotations'
      Merge branch 'skb-drop-reason-boundary'
      Merge branch 'net-skb-defer-freeing-polish'
      Merge tag 'mlx5-updates-2022-05-17' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux
      Merge branch 'dsa-microchip-ksz_switch-refactor'
      Merge branch 'armada-3720-turris-mox-and-orion-mdio'
      Merge branch 'net-ipa-next'
      Merge branch 'ipa-next'
      Merge branch 'rxrpc-misc'
      Merge branch 'rxrpc-fixes'
      Merge branch 'ocelot-selftests'
      Merge branch 'dpaa2-swtso-fixes'
      Merge branch 'net-gcc12-warnings'
      Merge branch 'mt7986-support'
      Merge branch 'dsa-multi-cpu-port-part-two'

David Thompson (2):
      mlxbf_gige: increase MDIO polling rate to 5us
      mlxbf_gige: remove driver-managed interrupt counts

Deren Wu (2):
      mt76: fix antenna config missing in 6G cap
      mt76: mt7921: add ipv6 NS offload support

Dimitri John Ledkov (1):
      cfg80211: declare MODULE_FIRMWARE for regulatory.db

Dmitrii Dolgov (4):
      bpf: Add bpf_link iterator
      selftests/bpf: Fix result check for test_bpf_hash_map
      selftests/bpf: Use ASSERT_* instead of CHECK
      selftests/bpf: Add bpf link iter test

Dominique Martinet (2):
      bpftool, musl compat: Replace nftw with FTW_ACTIONRETVAL
      bpftool, musl compat: Replace sys/fcntl.h by fcntl.h

Dongliang Mu (1):
      rtlwifi: Use pr_warn instead of WARN_ONCE

Duoming Zhou (1):
      NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx

Dylan Hung (3):
      dt-bindings: net: add reset property for aspeed, ast2600-mdio binding
      net: mdio: add reset control for Aspeed MDIO
      ARM: dts: aspeed: add reset properties into MDIO nodes

Dylan Muller (1):
      nfp: update nfp_X logging definitions

Edmond Gagnon (1):
      wcn36xx: Implement tx_rate reporting

Eli Cohen (3):
      net/mlx5: Lag, refactor lag state machine
      net/mlx5: Remove unused argument
      net/mlx5: Support multiport eswitch mode

Emmanuel Grumbach (2):
      iwlwifi: mvm: fix assert 1F04 upon reconfig
      iwlwifi: mvm: always tell the firmware to accept MCAST frames in BSS

Eric Dumazet (47):
      tcp: add accessors to read/set tp->snd_cwnd
      net_sched: make qdisc_reset() smaller
      ipv6: fix NULL deref in ip6_rcv_core()
      tcp: consume incoming skb leading to a reset
      tcp: get rid of rst_seq_match
      tcp: add drop reason support to tcp_validate_incoming()
      tcp: make tcp_rcv_state_process() drop monitor friendly
      tcp: add drop reasons to tcp_rcv_state_process()
      tcp: add two drop reasons for tcp_ack()
      tcp: add drop reason support to tcp_prune_ofo_queue()
      tcp: make tcp_rcv_synsent_state_process() drop monitor friend
      tcp: add drop reasons to tcp_rcv_synsent_state_process()
      tcp: add drop reason support to tcp_ofo_queue()
      tcp: fix signed/unsigned comparison
      net: generalize skb freeing deferral to per-cpu lists
      net: make sure net_rx_action() calls skb_defer_free_flush()
      tcp: drop skb dst in tcp_rcv_established()
      net: add include/net/net_debug.h
      net: add CONFIG_DEBUG_NET
      net: warn if transport header was not set
      net: remove two BUG() from skb_checksum_help()
      net: add more debug info in skb_checksum_help()
      inet: add READ_ONCE(sk->sk_bound_dev_if) in INET_MATCH()
      net: add IFLA_TSO_{MAX_SIZE|SEGS} attributes
      net: limit GSO_MAX_SIZE to 524280 bytes
      tcp_cubic: make hystart_ack_delay() aware of BIG TCP
      ipv6: add struct hop_jumbo_hdr definition
      ipv6/gso: remove temporary HBH/jumbo header
      ipv6/gro: insert temporary HBH/jumbo header
      net: loopback: enable BIG TCP packets
      veth: enable BIG TCP packets
      mlx4: support BIG TCP packets
      mlx5: support BIG TCP packets
      net: annotate races around sk->sk_bound_dev_if
      sctp: read sk->sk_bound_dev_if once in sctp_rcv()
      tcp: sk->sk_bound_dev_if once in inet_request_bound_dev_if()
      net: core: add READ_ONCE/WRITE_ONCE annotations for sk->sk_bound_dev_if
      dccp: use READ_ONCE() to read sk->sk_bound_dev_if
      inet: add READ_ONCE(sk->sk_bound_dev_if) in inet_csk_bind_conflict()
      net_sched: em_meta: add READ_ONCE() in var_sk_bound_if()
      l2tp: use add READ_ONCE() to fetch sk->sk_bound_dev_if
      ipv6: add READ_ONCE(sk->sk_bound_dev_if) in INET6_MATCH()
      inet: rename INET_MATCH()
      net: fix possible race in skb_attempt_defer_free()
      net: use napi_consume_skb() in skb_defer_free_flush()
      net: add skb_defer_max sysctl
      net: call skb_defer_free_flush() before each napi_poll()

Erik Stromdahl (2):
      ath10k: add support for MSDU IDs for USB devices
      ath10k: enable napi on RX path for usb

Erin MacNeil (1):
      net: SO_RCVMARK socket option for SO_MARK with recvmsg()

Ethan Yang (1):
      net: usb: qmi_wwan: add support for Sierra Wireless EM7590

Evelyn Tsai (1):
      mt76: fix MBSS index condition in DBDC mode

Eyal Birger (2):
      selftests/bpf: Remove unused variable from bpf_sk_assign test
      net: align SO_RCVMARK required privileges with SO_MARK

Fabio Estevam (2):
      net: phy: micrel: Allow probing without .driver_data
      net: phy: micrel: Use the kszphy probe/suspend/resume

Fei Qin (1):
      nfp: support VxLAN inner TSO with GSO_PARTIAL offload

Felix Fietkau (27):
      net: ethernet: mtk_eth_soc: add support for coherent DMA
      arm64: dts: mediatek: mt7622: add support for coherent DMA
      net: ethernet: mtk_eth_soc: add support for Wireless Ethernet Dispatch (WED)
      net: ethernet: mtk_eth_soc: implement flow offloading to WED devices
      arm64: dts: mediatek: mt7622: introduce nodes for Wireless Ethernet Dispatch
      net: ethernet: mtk_eth_soc: support TC_SETUP_BLOCK for PPE offload
      net: ethernet: mtk_eth_soc: allocate struct mtk_ppe separately
      net: ethernet: mtk_eth_soc: rework hardware flow table management
      net: ethernet: mtk_eth_soc: remove bridge flow offload type entry support
      net: ethernet: mtk_eth_soc: support creating mac address based offload entries
      net: ethernet: mtk_eth_soc/wed: fix sparse endian warnings
      mac80211: upgrade passive scan to active scan on DFS channels after beacon rx
      mt76: mt7915: fix DBDC default band selection on MT7915D
      mt76: mt7915: rework hardware/phy initialization
      mt76: reduce tx queue lock hold time
      mt76: dma: use kzalloc instead of devm_kzalloc for txwi
      mt76: mt7915: accept rx frames with non-standard VHT MCS10-11
      mt76: mt7921: accept rx frames with non-standard VHT MCS10-11
      mt76: fix use-after-free by removing a non-RCU wcid pointer
      mt76: fix rx reordering with non explicit / psmp ack policy
      mt76: do not attempt to reorder received 802.3 packets without agg session
      mt76: fix encap offload ethernet type check
      mt76: fix tx status related use-after-free race on station removal
      mt76: dma: add wrapper macro for accessing queue registers
      mt76: add support for overriding the device used for DMA mapping
      mt76: make number of tokens configurable dynamically
      mt76: mt7915: add Wireless Ethernet Dispatch support

Feng Zhou (3):
      bpf: add bpf_map_lookup_percpu_elem for percpu map
      selftests/bpf: add test case for bpf_map_lookup_percpu_elem
      selftests/bpf: Fix some bugs in map_lookup_percpu_elem testcase

Florent Fourcot (5):
      rtnetlink: return ENODEV when ifname does not exist and group is given
      rtnetlink: enable alt_ifname for setlink/newlink
      rtnetlink: return ENODEV when IFLA_ALT_IFNAME is used in dellink
      rtnetlink: return EINVAL when request cannot succeed
      Revert "rtnetlink: return EINVAL when request cannot succeed"

Florian Westphal (26):
      netfilter: ecache: move to separate structure
      netfilter: conntrack: split inner loop of list dumping to own function
      netfilter: cttimeout: inc/dec module refcount per object, not per use refcount
      selftests: netfilter: add fib expression forward test case
      mptcp: diag: switch to context structure
      mptcp: remove locking in mptcp_diag_fill_info
      mptcp: listen diag dump support
      selftests/mptcp: add diag listen tests
      mptcp: netlink: split mptcp_pm_parse_addr into two functions
      mptcp: netlink: allow userspace-driven subflow establishment
      netfilter: ecache: use dedicated list for event redelivery
      netfilter: conntrack: include ecache dying list in dumps
      netfilter: conntrack: remove the percpu dying list
      netfilter: cttimeout: decouple unlink and free on netns destruction
      netfilter: remove nf_ct_unconfirmed_destroy helper
      netfilter: extensions: introduce extension genid count
      netfilter: cttimeout: decouple unlink and free on netns destruction
      netfilter: conntrack: remove __nf_ct_unconfirmed_destroy
      netfilter: conntrack: remove unconfirmed list
      netfilter: conntrack: avoid unconditional local_bh_disable
      netfilter: nfnetlink: allow to detect if ctnetlink listeners exist
      netfilter: conntrack: un-inline nf_ct_ecache_ext_add
      netfilter: conntrack: add nf_conntrack_events autodetect mode
      netfilter: prefer extension check to pointer check
      netfilter: conntrack: remove pr_debug callsites from tcp tracker
      mptcp: sockopt: add TCP_DEFER_ACCEPT support

GONG, Ruiqi (1):
      net: mpls: fix memdup.cocci warning

Gal Pressman (4):
      net/mlx5e: Remove unused mlx5e_dcbnl_build_rep_netdev function
      net/mlx5e: IPoIB, Improve ethtool rxnfc callback structure in IPoIB
      net/mlx5e: Support partial GSO for tunnels over vlans
      net/mlx5e: Add XDP SQs to uplink representors steering tables

Gaosheng Cui (1):
      libbpf: Remove redundant non-null checks on obj_elf

Gavin Li (2):
      net/mlx5: Add exit route when waiting for FW
      net/mlx5: Increase FW pre-init timeout for health recovery

Geert Uytterhoeven (3):
      can: ctucanfd: Let users select instead of depend on CAN_CTUCANFD
      dt-bindings: can: renesas,rcar-canfd: Make interrupt-names required
      net: smc911x: Fix min() use in debug code

Geliang Tang (25):
      mptcp: add pm_nl_pernet helpers
      selftests/bpf: Drop duplicate max/min definitions
      mptcp: don't send RST for single subflow
      mptcp: add the fallback check
      mptcp: track and update contiguous data status
      mptcp: infinite mapping sending
      mptcp: infinite mapping receiving
      mptcp: add mib for infinite map sending
      mptcp: dump infinite_map field in mptcp_dump_mpext
      selftests: mptcp: add infinite map mibs check
      selftests: mptcp: add infinite map testcase
      mptcp: use mptcp_stop_timer
      mptcp: add data lock for sk timers
      mptcp: add MP_FAIL response support
      mptcp: reset subflow when MP_FAIL doesn't respond
      selftests: mptcp: check MP_FAIL response mibs
      selftests: mptcp: print extra msg in chk_csum_nr
      selftests: mptcp: fix a mp_fail test warning
      selftests: mptcp: add MP_FAIL reset testcase
      bpf: Add bpf_skc_to_mptcp_sock_proto
      selftests/bpf: Enable CONFIG_IKCONFIG_PROC in config
      selftests/bpf: Test bpf_skc_to_mptcp_sock
      selftests/bpf: Verify token of struct mptcp_sock
      selftests/bpf: Verify ca_name of struct mptcp_sock
      selftests/bpf: Verify first of struct mptcp_sock

Gerhard Engleder (6):
      ptp: Add cycles support for virtual clocks
      ptp: Request cycles for TX timestamp
      ptp: Pass hwtstamp to ptp_convert_timestamp()
      ptp: Support late timestamp determination
      ptp: Speed up vclock lookup
      tsnep: Add free running cycle counter support

Grant Seltzer (4):
      libbpf: Add error returns to two API functions
      libbpf: Update API functions usage to check error
      libbpf: Add documentation to API functions
      libbpf: Improve libbpf API documentation link position

Grygorii Strashko (4):
      net: ethernet: ti: cpsw: drop CPSW_HEADROOM define
      drivers: net: cpsw: ale: add broadcast/multicast rate limit support
      net: ethernet: ti: am65-cpsw: enable bc/mc storm prevention support
      net: ethernet: ti: cpsw_new: enable bc/mc storm prevention support

Guangbin Huang (2):
      net: hns3: add query vf ring and vector map relation
      net: hns3: fix incorrect type of argument in declaration of function hclge_comm_get_rss_indir_tbl

Guangguan Wang (3):
      net/smc: align the connect behaviour with TCP
      net/smc: send cdc msg inline if qp has sufficient inline space
      net/smc: rdma write inline if qp has sufficient inline space

Guillaume Nault (9):
      ipv4: Use dscp_t in struct fib_rt_info
      ipv4: Use dscp_t in struct fib_entry_notifier_info
      netdevsim: Use dscp_t in struct nsim_fib4_rt
      mlxsw: Use dscp_t in struct mlxsw_sp_fib4_entry
      net: marvell: prestera: Use dscp_t in struct prestera_kern_fib_cache
      ipv4: Don't reset ->flowi4_scope in ip_rt_fix_tos().
      ipv4: Avoid using RTO_ONLINK with ip_route_connect().
      ipv4: Initialise ->flowi4_scope properly in ICMP handlers.
      qed: Remove IP services API.

Guo Zhengkui (3):
      ipv6: exthdrs: use swap() instead of open coding it
      rtlwifi: btcoex: fix if == else warning
      net: smc911x: replace ternary operator with min()

Gustavo A. R. Silva (2):
      iwlwifi: fw: Replace zero-length arrays with flexible-array members
      iwlwifi: mei: Replace zero-length array with flexible-array member

H. Nikolaus Schaller (1):
      wl1251: dynamically allocate memory used for DMA

Haijun Liu (10):
      net: wwan: t7xx: Add control DMA interface
      net: wwan: t7xx: Add core components
      net: wwan: t7xx: Add port proxy infrastructure
      net: wwan: t7xx: Add control port
      net: wwan: t7xx: Data path HW layer
      net: wwan: t7xx: Add data path interface
      net: wwan: t7xx: Add WWAN network interface
      net: wwan: t7xx: Introduce power management
      net: wwan: t7xx: Runtime PM
      net: wwan: t7xx: Device deep sleep lock/unlock

Haim Dreyfuss (1):
      iwlwifi: mvm: use NULL instead of ERR_PTR when parsing wowlan status

Haiyang Zhang (1):
      hv_netvsc: Add support for XDP_REDIRECT

Haiyue Wang (1):
      bpf: Correct the comment for BTF kind bitfield

Hamid Zamani (1):
      brcmfmac: use ISO3166 country code and 0 rev as fallback on brcmfmac43602 chips

Hangbin Liu (3):
      net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO
      selftests/bpf: Add missed ima_setup.sh in Makefile
      bonding: fix missed rcu protection

Hangyu Hua (1):
      mac80211: tx: delete a redundant if statement in ieee80211_check_fast_xmit()

Hao Chen (4):
      net: hns3: refactor hns3_set_ringparam()
      net: hns3: add log for setting tx spare buf size
      net: hns3: remove unnecessary line wrap for hns3_set_tunable
      net: hns3: fix access null pointer issue when set tx-buf-size as 0

Haowen Bai (12):
      selftests/bpf: Return true/false (not 1/0) from bool functions
      b43legacy: Fix assigning negative value to unsigned variable
      b43: Fix assigning negative value to unsigned variable
      ipw2x00: Fix potential NULL dereference in libipw_xmit()
      libbpf: Potential NULL dereference in usdt_manager_attach_usdt()
      sfc: ef10: Fix assigning negative value to unsigned variable
      ar5523: Use kzalloc instead of kmalloc/memset
      net: eql: Use kzalloc instead of kmalloc/memset
      tsnep: Remove useless null check before call of_node_put()
      net: mscc: ocelot: Remove useless code
      net/mlx5: Remove useless kfree
      net: thunderx: remove null check after call container_of()

Hari Chandrakanthan (2):
      ath11k: change fw build id format in driver init log
      ath11k: disable spectral scan during spectral deinit

Harini Katakam (1):
      net: macb: Fix PTP one step sync support

Hongbin Wang (1):
      ip6_tunnel: Remove duplicate assignments

Horatiu Vultur (11):
      net: lan966x: Add registers that are used for FDMA.
      net: lan966x: Expose functions that are needed by FDMA
      net: lan966x: Add FDMA functionality
      net: lan966x: Update FDMA to change MTU.
      dt-bindings: net: lan966x: Extend with the ptp external interrupt.
      net: lan966x: Change the PTP pin used to read/write the PHC.
      net: lan966x: Add registers used to configure the PTP pin
      net: lan966x: Add support for PTP_PF_PEROUT
      net: lan966x: Add support for PTP_PF_EXTTS
      net: lan966x: Fix compilation error
      net: lan966x: Fix use of pointer after being freed

Hsuan Hung (1):
      rtw89: 8852c: add settings to decrease the effect of DC

Ian Wienand (1):
      net: ethernet: set default assignment identifier to NET_NAME_ENUM

Ido Schimmel (17):
      net/sched: matchall: Take verbose flag into account when logging error messages
      net/sched: flower: Take verbose flag into account when logging error messages
      net/sched: act_api: Add extack to offload_act_setup() callback
      net/sched: act_gact: Add extack messages for offload failure
      net/sched: act_mirred: Add extack message for offload failure
      net/sched: act_mpls: Add extack messages for offload failure
      net/sched: act_pedit: Add extack message for offload failure
      net/sched: act_police: Add extack messages for offload failure
      net/sched: act_skbedit: Add extack messages for offload failure
      net/sched: act_tunnel_key: Add extack message for offload failure
      net/sched: act_vlan: Add extack message for offload failure
      net/sched: cls_api: Add extack message for unsupported action offload
      net/sched: matchall: Avoid overwriting error messages
      net/sched: flower: Avoid overwriting error messages
      mlxsw: spectrum_acl: Do not report activity for multicast routes
      mlxsw: spectrum_switchdev: Only query FDB notifications when necessary
      mlxsw: spectrum_router: Only query neighbour activity when necessary

Ilya Leoshkevich (5):
      selftests/bpf: Define SYS_NANOSLEEP_KPROBE_NAME for aarch64
      libbpf: Support Debian in resolve_full_path()
      libbpf: Minor style improvements in USDT code
      libbpf: Make BPF-side of USDT support work on big-endian machines
      libbpf: Add s390-specific USDT arg spec parsing logic

Ioana Ciornei (3):
      dpaa2-eth: retrieve the virtual address before dma_unmap
      dpaa2-eth: use the correct software annotation field
      dpaa2-eth: unmap the SGT buffer before accessing its contents

Ismael Luceno (1):
      Bluetooth: btusb: Add 0x0bda:0x8771 Realtek 8761BUV devices

Jacob Keller (6):
      ice: add newline to dev_dbg in ice_vf_fdir_dump_info
      ice: always check VF VSI pointer values
      ice: remove return value comment for ice_reset_all_vfs
      ice: fix wording in comment for ice_reset_vf
      ice: add a function comment for ice_cfg_mac_antispoof
      ice: remove period on argument description in ice_for_each_vf

Jaehee Park (2):
      selftests: net: vrf_strict_mode_test: add support to select a test to run
      wfx: use container_of() to get vif

Jakob Koschel (3):
      bpf: Replace usage of supported with dedicated list iterator variable
      netfilter: nf_tables: replace unnecessary use of list_for_each_entry_continue()
      rtlwifi: replace usage of found with dedicated list iterator variable

Jakub Kicinski (180):
      net: wan: remove the lanmedia (lmc) driver
      net: hyperv: remove use of bpf_op_t
      net: unexport a handful of dev_* functions
      net: extract a few internals from netdevice.h
      Merge branch 'net-create-a-net-core-internal-header'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      tls: rx: jump to a more appropriate label
      tls: rx: drop pointless else after goto
      tls: rx: don't store the record type in socket context
      tls: rx: don't store the decryption status in socket context
      tls: rx: init decrypted status in tls_read_size()
      tls: rx: use a define for tag length
      tls: rx: replace 'back' with 'offset'
      tls: rx: don't issue wake ups when data is decrypted
      tls: rx: refactor decrypt_skb_update()
      tls: hw: rx: use return value of tls_device_decrypted() to carry status
      net: atm: remove the ambassador driver
      Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
      tls: rx: drop unnecessary arguments from tls_setup_from_iter()
      tls: rx: don't report text length from the bowels of decrypt
      tls: rx: wrap decryption arguments in a structure
      tls: rx: simplify async wait
      tls: rx: factor out writing ContentType to cmsg
      tls: rx: don't handle async in tls_sw_advance_skb()
      tls: rx: don't track the async count
      tls: rx: pull most of zc check out of the loop
      tls: rx: inline consuming the skb at the end of the loop
      tls: rx: clear ctx->recv_pkt earlier
      tls: rx: jump out for cases which need to leave skb on list
      Merge branch 'ipv4-convert-several-tos-fields-to-dscp_t'
      Merge branch 'mlx5-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux
      Merge branch 'net-lan966x-add-support-for-fdma'
      Merge branch 'mlxsw-extend-device-registers-for-line-cards-support'
      tls: rx: consistently use unlocked accessors for rx_list
      tls: rx: reuse leave_on_list label for psock
      tls: rx: move counting TlsDecryptErrors for sync
      tls: rx: don't handle TLS 1.3 in the async crypto callback
      tls: rx: assume crypto always calls our callback
      tls: rx: treat process_rx_list() errors as transient
      tls: rx: return the already-copied data on crypto error
      tls: rx: use async as an in-out argument
      tls: rx: use MAX_IV_SIZE for allocations
      tls: rx: only copy IV from the packet for TLS 1.2
      Merge branch 'net-ethool-add-support-to-get-set-tx-push-by-ethtool-g-g'
      Merge branch 'ibmvnic-use-a-set-of-ltbs-per-pool'
      Merge branch 'add-ethtool-sqi-support-for-lan87xx-t1-phy'
      net: tls: fix async vs NIC crypto offload
      net: atm: remove support for Fujitsu FireStream ATM devices
      net: atm: remove support for Madge Horizon ATM devices
      net: atm: remove support for ZeitNet ZN122x ATM devices
      net: wan: remove support for COSA and SRP synchronous serial boards
      net: wan: remove support for Z85230-based devices
      net: hamradio: remove support for DMA SCC devices
      Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      eth: remove copies of the NAPI_POLL_WEIGHT define
      eth: smsc: remove a copy of the NAPI_POLL_WEIGHT define
      eth: cpsw: remove a copy of the NAPI_POLL_WEIGHT define
      eth: pch_gbe: remove a copy of the NAPI_POLL_WEIGHT define
      eth: mtk_eth_soc: remove a copy of the NAPI_POLL_WEIGHT define
      usb: lan78xx: remove a copy of the NAPI_POLL_WEIGHT define
      slic: remove a copy of the NAPI_POLL_WEIGHT define
      net: bgmac: remove a copy of the NAPI_POLL_WEIGHT define
      eth: atlantic: remove a copy of the NAPI_POLL_WEIGHT define
      eth: benet: remove a copy of the NAPI_POLL_WEIGHT define
      eth: gfar: remove a copy of the NAPI_POLL_WEIGHT define
      eth: vxge: remove a copy of the NAPI_POLL_WEIGHT define
      eth: spider: remove a copy of the NAPI_POLL_WEIGHT define
      eth: velocity: remove a copy of the NAPI_POLL_WEIGHT define
      qeth: remove a copy of the NAPI_POLL_WEIGHT define
      Merge branch 'net-phy-micrel-add-coma-mode-support'
      Merge branch 'mptcp-path-manager-mode-selection'
      Merge branch 'tcp-pass-back-data-left-in-socket-after-receive' of git://git.kernel.org/pub/scm/linux/kernel/git/kuba/linux
      eth: remove remaining copies of the NAPI_POLL_WEIGHT define
      can: m_can: remove a copy of the NAPI_POLL_WEIGHT define
      rtnl: allocate more attr tables on the heap
      rtnl: split __rtnl_newlink() into two functions
      rtnl: move rtnl_newlink_create()
      ath10k: remove a copy of the NAPI_POLL_WEIGHT define
      wil6210: use NAPI_POLL_WEIGHT for napi budget
      rtw88: remove a copy of the NAPI_POLL_WEIGHT define
      Stefan Schmidt says:
      Merge branch 'ocelot-stats-improvement'
      Merge branch 'vsock-virtio-add-support-for-device-suspend-resume'
      Merge branch 'mptcp-userspace-path-manager-prerequisites'
      netdev: reshuffle netif_napi_add() APIs to allow dropping weight
      Merge tag 'wireless-next-2022-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
      Merge branch 'ocelot-vcap-cleanups'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      Revert "Merge branch 'mlxsw-line-card-model'"
      jme: remove an unnecessary indirection
      net: switch to netif_napi_add_tx()
      net: move snowflake callers to netif_napi_add_tx_weight()
      Merge branch 'mptcp-improve-mptcp-level-window-tracking'
      wil6210: switch to netif_napi_add_tx()
      mt76: switch to netif_napi_add_tx()
      qtnfmac: switch to netif_napi_add_weight()
      net: add netif_inherit_tso_max()
      net: don't allow user space to lift the device limits
      net: make drivers set the TSO limit not the GSO limit
      net: move netif_set_gso_max helpers
      Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
      Merge branch 'simplify-migration-of-host-filtered-addresses-in-felix-driver'
      um: vector: switch to netif_napi_add_weight()
      caif_virtio: switch to netif_napi_add_weight()
      eth: switch to netif_napi_add_weight()
      r8152: switch to netif_napi_add_weight()
      net: virtio: switch to netif_napi_add_weight()
      net: wan: switch to netif_napi_add_weight()
      Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
      Merge branch 'nfp-support-corigine-pcie-vendor-id'
      eth: dpaa2-mac: remove a dead-code NULL check on fwnode parent
      Merge branch 'move-siena-into-a-separate-subdirectory'
      net: fix kdoc on __dev_queue_xmit()
      skbuff: add a basic intro doc
      skbuff: rewrite the doc for data-only skbs
      skbuff: render the checksum comment to documentation
      Merge branch 'docs-document-some-aspects-of-struct-sk_buff'
      Merge branch 'net-phy-add-comments-for-lan8742-phy-support'
      net: appletalk: remove Apple/Farallon LocalTalk PC support
      eth: amd: remove NI6510 support (ni65)
      Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue
      Merge branch 'macb-napi-improvements'
      Merge branch 'count-tc-taprio-window-drops-in-enetc-driver'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      skbuff: replace a BUG_ON() with the new DEBUG_NET_WARN_ON_ONCE()
      net: update the register_netdevice() kdoc
      Merge branch 'dsa-changes-for-multiple-cpu-ports-part-1'
      Merge branch 'restructure-struct-ocelot_port'
      Merge branch 'make-sfc-siena-ko-specific-to-siena'
      Merge branch 'net-inet-retire-port-only-listening_hash'
      Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next
      eth: sfc: remove remnants of the out-of-tree napi_weight module param
      Merge branch 'mptcp-updates-for-net-next'
      Merge branch 'net-skb-remove-skb_data_area_size'
      Merge tag 'linux-can-next-for-5.19-20220516' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
      Merge branch 'net-smc-send-and-write-inline-optimization-for-smc'
      Merge branch 'adin-add-support-for-clock-output'
      Merge branch 'octeon_ep-fix-the-error-handling-path-of-octep_request_irqs'
      net/mlx5: fix multiple definitions of mlx5_lag_mpesw_init / mlx5_lag_mpesw_cleanup
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      Merge tag 'wireless-next-2022-05-19' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
      can: can-dev: move to netif_napi_add_weight()
      Merge tag 'linux-can-next-for-5.19-20220519' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
      net: tls: fix messing up lists when bpf enabled
      Merge branch 'mtk_eth_soc-phylink-updates'
      Merge branch 'lantiq_gswip-two-small-fixes'
      net: wwan: iosm: remove pointless null check
      net: ipa: don't proceed to out-of-bound write
      docs: change the title of networking docs
      Merge branch 'mptcp-miscellaneous-fixes-and-a-new-test-case'
      eth: mtk_ppe: fix up after merge
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next
      tcp_ipv6: set the drop_reason in the right place
      net: stmmac: fix out-of-bounds access in a selftest
      net: avoid strange behavior with skb_defer_max == 1
      Merge branch 'amt-fix-several-bugs-in-gateway-mode'
      eth: bnxt: make ulp_id unsigned to make GCC 12 happy
      wwan: iosm: use a flexible array rather than allocate short objects
      Merge branch 'add-a-bhash2-table-hashed-by-port-address'
      net: wrap the wireless pointers in struct net_device in an ifdef
      eth: mtk_eth_soc: silence the GCC 12 array-bounds warning
      eth: ice: silence the GCC 12 array-bounds warning
      eth: tg3: silence the GCC 12 array-bounds warning
      wifi: plfxlc: remove redundant NULL-check for GCC 12
      wifi: ath9k: silence array-bounds warning on GCC 12
      wifi: rtlwifi: remove always-true condition pointed out by GCC 12
      wifi: ath6k: silence false positive -Wno-dangling-pointer warning on GCC 12
      wifi: iwlwifi: use unsigned to silence a GCC 12 warning
      wifi: brcmfmac: work around a GCC 12 -Warray-bounds warning
      wifi: carl9170: silence a GCC 12 -Warray-bounds warning
      Merge branch 'fix-silence-gcc-12-warnings-in-drivers-net-wireless'
      eth: de4x5: remove support for Generic DECchip & DIGITAL EtherWORKS PCI/EISA
      can: kvaser_usb: silence a GCC 12 -Warray-bounds warning
      Merge tag 'for-net-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
      Merge tag 'for-net-next-2022-05-23' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
      Merge tag 'linux-can-next-for-5.19-20220523' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
      Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      Merge branch 'ptp-ocp-various-updates'

Jason Wang (1):
      bpftool: Declare generator name

Jeff Daly (1):
      ixgbe: Fix module_param allow_unsupported_sfp type

Jeffrey Ji (1):
      net-core: rx_otherhost_dropped to core_stats

Jeremy Sowden (2):
      netfilter: bitwise: replace hard-coded size with `sizeof` expression
      netfilter: bitwise: improve error goto labels

Jerome Marchand (1):
      samples: bpf: Don't fail for a missing VMLINUX_BTF when VMLINUX_H is provided

Jian Shen (1):
      net: hns3: refine the definition for struct hclge_pf_to_vf_msg

Jiapeng Chong (7):
      bpf: Use swap() instead of open coding it
      plfxlc: Remove unused include <linux/version.h>
      can: ctucanfd: remove unused including <linux/version.h>
      can: ctucanfd: ctucan_platform_probe(): remove unnecessary print function dev_err()
      ROSE: Remove unused code and clean up some inconsistent indenting
      ssb: remove unreachable code
      net: ethernet: Use swap() instead of open coding it

Jie Wang (7):
      net: ethtool: extend ringparam set/get APIs for tx_push
      net: ethtool: move checks before rtnl_lock() in ethnl_set_rings
      net: hns3: add tx push support in hns3 ring param process
      net: hns3: add failure logs in hclge_set_vport_mtu
      net: hns3: add byte order conversion for PF to VF mailbox message
      net: hns3: add byte order conversion for VF to PF mailbox message
      net: page_pool: add page allocation stats for two fast page allocate path

Jimmy Hon (2):
      rtw88: 8821ce: add support for device ID 0xb821
      rtw88: 8821ce: Disable PCIe ASPM L1 for 8821CE using chip ID

Jiri Olsa (6):
      kallsyms: Make kallsyms_on_each_symbol generally available
      ftrace: Add ftrace_lookup_symbols function
      fprobe: Resolve symbols with ftrace_lookup_symbols
      bpf: Resolve symbols with ftrace_lookup_symbols for kprobe multi link
      selftests/bpf: Add attach bench test
      libbpf: Add bpf_program__set_insns function

Jiri Pirko (30):
      devlink: add support to create line card and expose to user
      devlink: implement line card provisioning
      devlink: implement line card active state
      devlink: add port to line card relationship set
      mlxsw: spectrum: Allow lane to start from non-zero index
      mlxsw: spectrum: Allocate port mapping array of structs instead of pointers
      mlxsw: reg: Add Ports Mapping Event Configuration Register
      mlxsw: Narrow the critical section of devl_lock during ports creation/removal
      mlxsw: spectrum: Introduce port mapping change event processing
      mlxsw: reg: Add Management DownStream Device Query Register
      mlxsw: reg: Add Management DownStream Device Control Register
      mlxsw: reg: Add Management Binary Code Transfer Register
      mlxsw: core_linecards: Add line card objects and implement provisioning
      mlxsw: core_linecards: Implement line card activation process
      mlxsw: core: Extend driver ops by remove selected ports op
      mlxsw: spectrum: Add port to linecard mapping
      selftests: mlxsw: Introduce devlink line card provision/unprovision/activation tests
      mlxsw: core_linecards: Introduce ops for linecards status change tracking
      mlxsw: core_linecards: Fix size of array element during ini_files allocation
      devlink: introduce line card devices support
      devlink: introduce line card info get message
      devlink: introduce line card device info infrastructure
      mlxsw: reg: Extend MDDQ by device_info
      mlxsw: core_linecards: Probe provisioned line cards for devices and attach them
      selftests: mlxsw: Check devices on provisioned line card
      mlxsw: core_linecards: Expose HW revision and INI version
      selftests: mlxsw: Check line card info on provisioned line card
      mlxsw: reg: Extend MDDQ device_info by FW version fields
      mlxsw: core_linecards: Expose device FW version over device info
      selftests: mlxsw: Check device info on activated line card

Joachim Wiberg (4):
      net: bridge: add support for host l2 mdb entries
      selftests: forwarding: new test, verify host mdb entries
      selftests: forwarding: add TCPDUMP_EXTRA_FLAGS to lib.sh
      selftests: forwarding: multiple instances in tcpdump helper

Joanne Koong (9):
      bpf: Add MEM_UNINIT as a bpf_type_flag
      net: Add a second bind table hashed by port and address
      selftests: Add test for timing a bind request to a port with a populated bhash entry
      bpf: Add verifier support for dynptrs
      bpf: Add bpf_dynptr_from_mem for local dynptrs
      bpf: Dynptr support for ring buffers
      bpf: Add bpf_dynptr_read and bpf_dynptr_write
      bpf: Add dynptr data slices
      selftests/bpf: Dynptr tests

Joe Damato (3):
      i40e: Add support for MPLS + TSO
      ice: Add mpls+tso support
      i40e: Add tx_stopped stat

Joe Perches (1):
      rtw89: rtw89_ser: add const to struct state_ent and event_ent

Johannes Berg (21):
      net: ensure net_todo_list is processed quickly
      nl80211: show SSID for P2P_GO interfaces
      cfg80211: remove cfg80211_get_chan_state()
      nl80211: don't hold RTNL in color change request
      nl80211: rework internal_flags usage
      wil6210: remove 'freq' debugfs
      mac80211: unify CCMP/GCMP AAD construction
      mac80211: fix typo in documentation
      mac80211: remove stray multi_sta_back_32bit docs
      mac80211: mlme: move in RSSI reporting code
      mac80211: use ifmgd->bssid instead of ifmgd->associated->bssid
      mac80211: mlme: use local SSID copy
      mac80211: remove unused argument to ieee80211_sta_connection_lost()
      mac80211: remove useless bssid copy
      mac80211: mlme: track assoc_bss/associated separately
      cfg80211: fix kernel-doc for cfg80211_beacon_data
      mac80211: refactor freeing the next_beacon
      iwlwifi: pcie: simplify MSI-X cause mapping
      iwlwifi: mvm: clean up authorized condition
      iwlwifi: fw: init SAR GEO table only if data is present
      iwlwifi: mei: fix potential NULL-ptr deref

Johnson Lin (3):
      rtw89: packed IGI configuration flow into function for DIG feature
      rtw89: disabled IGI configuration for unsupported hardware
      rtw89: Skip useless dig gain and igi related settings for 8852C

Jonas Jelonek (2):
      mac80211: extend current rate control tx status API
      mac80211: minstrel_ht: support ieee80211_rate_status

Jonathan Lemon (8):
      ptp: ocp: 32-bit fixups for pci start address
      ptp: ocp: Remove #ifdefs around PCI IDs
      ptp: ocp: revise firmware display
      ptp: ocp: parameterize input/output sma selectors
      ptp: ocp: constify selectors
      ptp: ocp: vectorize the sma accessor functions
      ptp: ocp: add .init function for sma_op vector
      ptp: ocp: fix PPS source selector debugfs reporting

Jonathan Neuschäfer (1):
      net: calxedaxgmac: Fix typo (doubled "the")

Josua Mayer (3):
      dt-bindings: net: adin: document phy clock output properties
      net: phy: adin: add support for clock output
      ARM: dts: imx6qdl-sr-som: update phy configuration for som revision 1.9

Julia Lawall (12):
      ath6kl: fix typos in comments
      net: sparx5: switchdev: fix typo in comment
      net: mvpp2: fix typo in comment
      net/mlx5: fix typo in comment
      net: qed: fix typos in comments
      cirrus: cs89x0: fix typo in comment
      net: marvell: prestera: fix typo in comment
      nfp: flower: fix typo in comment
      qed: fix typos in comments
      libbpf: Fix typo in comment
      s390/bpf: Fix typo in comment
      can: peak_usb: fix typo in comment

Jérôme Pouiller (1):
      wfx: get out from the staging area

KP Singh (2):
      bpf: Fix usage of trace RCU in local storage.
      bpftool: bpf_link_get_from_fd support for LSM programs in lskel

Kaixi Fan (3):
      bpf: Add source ip in "struct bpf_tunnel_key"
      selftests/bpf: Move vxlan tunnel testcases to test_progs
      selftests/bpf: Replace bpf_trace_printk in tunnel kernel code

Kalesh AP (1):
      bnxt_en: parse and report result field when NVRAM package install fails

Kalle Valo (10):
      ath11k: mhi: remove state machine
      ath11k: mhi: add error handling for suspend and resume
      ath11k: mhi: remove unnecessary goto from ath11k_mhi_start()
      Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
      Merge branch 'wfx-move-out-of-staging'
      Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
      ath11k: mac: fix too long line
      ath10k: mac: fix too long lines
      Merge tag 'mt76-for-kvalo-2022-05-12' of https://github.com/nbd168/wireless
      Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

Karthikeyan Kathirvel (1):
      ath11k: Change max no of active probe SSID and BSSID to fw capability

Karthikeyan Periyasamy (2):
      ath11k: Refactor the peer delete
      ath11k: Add peer rhash table support

Kees Cook (1):
      fortify: Provide a memcpy trap door for sharp corners

Kevin Lo (1):
      rtw88: use the correct bit in the REG_HCI_OPT_CTRL register

Kevin Mitchell (1):
      netfilter: conntrack: skip verification of zero UDP checksum

Kishen Maloor (17):
      mptcp: bypass in-kernel PM restrictions for non-kernel PMs
      mptcp: store remote id from MP_JOIN SYN/ACK in local ctx
      mptcp: reflect remote port (not 0) in ANNOUNCED events
      mptcp: establish subflows from either end of connection
      mptcp: expose server_side attribute in MPTCP netlink events
      mptcp: allow ADD_ADDR reissuance by userspace PMs
      mptcp: handle local addrs announced by userspace PMs
      mptcp: read attributes of addr entries managed by userspace PMs
      mptcp: netlink: Add MPTCP_PM_CMD_ANNOUNCE
      selftests: mptcp: support MPTCP_PM_CMD_ANNOUNCE
      mptcp: netlink: Add MPTCP_PM_CMD_REMOVE
      selftests: mptcp: support MPTCP_PM_CMD_REMOVE
      selftests: mptcp: support MPTCP_PM_CMD_SUBFLOW_CREATE
      selftests: mptcp: support MPTCP_PM_CMD_SUBFLOW_DESTROY
      selftests: mptcp: capture netlink events
      selftests: mptcp: create listeners to receive MPJs
      selftests: mptcp: functional tests for the userspace PM type

Kris Bahnsen (1):
      can: Fix Links to Technologic Systems web resources

Kui-Feng Lee (5):
      bpf, x86: Generate trampolines from bpf_tramp_links
      bpf, x86: Create bpf_tramp_run_ctx on the caller thread's stack
      bpf, x86: Attach a cookie to fentry/fexit/fmod_ret/lsm.
      libbpf: Assign cookies to links in libbpf.
      selftest/bpf: The test cases of BPF cookie for fentry/fexit/fmod_ret/lsm.

Kumar Kartikeya Dwivedi (27):
      bpf: Do write access check for kfunc and global func
      bpf: Check PTR_TO_MEM | MEM_RDONLY in check_helper_mem_access
      bpf: Reject writes for PTR_TO_MAP_KEY in check_helper_mem_access
      selftests/bpf: Test passing rdonly mem to global func
      selftests/bpf: Test for writes to map key from BPF helpers
      bpf: Ensure type tags precede modifiers in BTF
      selftests/bpf: Add tests for type tag order validation
      bpf: Make btf_find_field more generic
      bpf: Move check_ptr_off_reg before check_map_access
      bpf: Allow storing unreferenced kptr in map
      bpf: Tag argument to be released in bpf_func_proto
      bpf: Allow storing referenced kptr in map
      bpf: Prevent escaping of kptr loaded from maps
      bpf: Adapt copy_map_value for multiple offset case
      bpf: Populate pairs of btf_id and destructor kfunc in btf
      bpf: Wire up freeing of referenced kptr
      bpf: Teach verifier about kptr_get kfunc helpers
      bpf: Make BTF type match stricter for release arguments
      libbpf: Add kptr type tag macros to bpf_helpers.h
      selftests/bpf: Add C tests for kptr
      selftests/bpf: Add verifier tests for kptr
      selftests/bpf: Add test for strict BTF type check
      bpf: Fix sparse warning for bpf_kptr_xchg_proto
      bpf: Prepare prog_test_struct kfuncs for runtime tests
      selftests/bpf: Add negative C tests for kptrs
      selftests/bpf: Add tests for kptr_ref refcounting
      bpf: Suppress 'passing zero to PTR_ERR' warning

Kuniyuki Iwashima (2):
      ipv6: Remove __ipv6_only_sock().
      ipv6: Use ipv6_only_sock() helper in condition.

Larysa Zaremba (1):
      bpftool: Use sysfs vmlinux when dumping BTF by ID

Lavanya Suresh (1):
      mac80211: disable BSS color collision detection in case of no free colors

Lech Perczak (3):
      cdc_ether: export usbnet_cdc_zte_rx_fixup
      rndis_host: enable the bogus MAC fixup for ZTE devices from cdc_ether
      rndis_host: limit scope of bogus MAC address detection to ZTE devices

Leon Romanovsky (48):
      net/mlx5_fpga: Drop INNOVA TLS support
      net/mlx5: Reliably return TLS device capabilities
      net/mlx5: Remove indirection in TLS build
      net/mlx5: Remove tls vs. ktls separation as it is the same
      net/mlx5: Cleanup kTLS function names and their exposure
      net/mlx5_fpga: Drop INNOVA IPsec support
      net/mlx5: Delete metadata handling logic
      net/mlx5: Remove not-used IDA field from IPsec struct
      net/mlx5: Remove XFRM no_trailer flag
      net/mlx5: Remove FPGA ipsec specific statistics
      RDMA/mlx5: Delete never supported IPsec flow action
      RDMA/mlx5: Drop crypto flow steering API
      RDMA/core: Delete IPsec flow action logic from the core
      net/mlx5: Remove ipsec vs. ipsec offload file separation
      net/mlx5: Remove useless IPsec device checks
      net/mlx5: Unify device IPsec capabilities check
      net/mlx5: Align flow steering allocation namespace to common style
      net/mlx5: Remove not-needed IPsec config
      net/mlx5: Move IPsec file to relevant directory
      net/mlx5: Reduce kconfig complexity while building crypto support
      net/mlx5: Remove ipsec_ops function table
      net/mlx5: Remove not-implemented IPsec capabilities
      octeon_ep: Remove custom driver version
      net/mlx5: Simplify IPsec flow steering init/cleanup functions
      net/mlx5: Check IPsec TX flow steering namespace in advance
      net/mlx5: Don't hide fallback to software IPsec in FS code
      net/mlx5: Reduce useless indirection in IPsec FS add/delete flows
      net/mlx5: Store IPsec ESN update work in XFRM state
      net/mlx5: Remove useless validity check
      net/mlx5: Merge various control path IPsec headers into one file
      net/mlx5: Remove indirections from esp functions
      net/mlx5: Simplify HW context interfaces by using SA entry
      net/mlx5: Clean IPsec FS add/delete rules
      net/mlx5: Make sure that no dangling IPsec FS pointers exist
      net/mlx5: Don't advertise IPsec netdev support for non-IPsec device
      net/mlx5: Simplify IPsec capabilities logic
      net/mlx5: Remove not-supported ICV length
      net/mlx5: Cleanup XFRM attributes struct
      net/mlx5: Don't perform lookup after already known sec_path
      net/mlx5: Allow future addition of IPsec object modifiers
      xfrm: free not used XFRM_ESP_NO_TRAILER flag
      xfrm: delete not used number of external headers
      xfrm: rename xfrm_state_offload struct to allow reuse
      xfrm: store and rely on direction to construct offload flags
      ixgbe: propagate XFRM offload state direction instead of flags
      netdevsim: rely on XFRM state direction instead of flags
      net/mlx5e: Use XFRM state direction instead of flags
      xfrm: drop not needed flags variable in XFRM offload struct

Leszek Polak (1):
      net: phy: marvell: Add errata section 5.1 for Alaska PHY

Lin Ma (1):
      NFC: NULL out the dev->rfkill to prevent UAF

Linus Walleij (1):
      Bluetooth: btbcm: Support per-board firmware variants

Liu Jian (4):
      bpf: Enlarge offset check value to INT_MAX in bpf_skb_{load,store}_bytes
      net: Change skb_ensure_writable()'s write_len param to unsigned int type
      selftests/bpf: Add test for skb_load_bytes
      bpf, sockmap: Call skb_linearize only when required in sk_psock_skb_ingress_enqueue

Lorenzo Bianconi (41):
      samples: bpf: Convert xdp_router_ipv4 to XDP samples helper
      dt-bindings: net: mediatek: add optional properties for the SoC ethernet core
      dt-bindings: arm: mediatek: document WED binding for MT7622
      dt-bindings: arm: mediatek: document the pcie mirror node on MT7622
      net: netfilter: Reports ct direction in CT lookup helpers for XDP and TC-BPF
      samples, bpf: Move routes monitor in xdp_router_ipv4 in a dedicated thread
      mac80211: protect ieee80211_assign_beacon with next_beacon check
      mac80211: introduce BSS color collision detection
      page_pool: Add recycle stats to page_pool_put_page_bulk
      net: ethernet: mtk_eth_soc: use standard property for cci-control-port
      net: page_pool: introduce ethtool stats
      net: mvneta: add support for page_pool_get_stats
      dt-bindings: net: mediatek,net: convert to the json-schema
      mt76: mt7921u: add suspend/resume support
      mt76: mt7921: rely on mt76_dev rxfilter in mt7921_configure_filter
      mt76: mt7921: honor pm user configuration in mt7921_sniffer_interface_iter
      mt76: mt7915: fix unbounded shift in mt7915_mcu_beacon_mbss
      mt76: mt7915: fix possible uninitialized pointer dereference in mt7986_wmac_gpio_setup
      mt76: mt7915: fix possible NULL pointer dereference in mt7915_mac_fill_rx_vector
      mt76: mt7915: do not pass data pointer to mt7915_mcu_muru_debug_set
      mt76: mt7915: report rx mode value in mt7915_mac_fill_rx_rate
      mt76: mt7915: use 0xff to initialize bitrate_mask in mt7915_init_bitrate_mask
      mt76: mt7915: configure soc clocks in mt7986_wmac_init
      mt76: add gfp to mt76_mcu_msg_alloc signature
      ixgbe: add xdp frags support to ndo_xdp_xmit
      arm64: dts: mediatek: mt7986: introduce ethernet nodes
      dt-bindings: net: mediatek,net: add mt7986-eth binding
      net: ethernet: mtk_eth_soc: rely on GFP_KERNEL for dma_alloc_coherent whenever possible
      net: ethernet: mtk_eth_soc: move tx dma desc configuration in mtk_tx_set_dma_desc
      net: ethernet: mtk_eth_soc: add txd_size to mtk_soc_data
      net: ethernet: mtk_eth_soc: rely on txd_size in mtk_tx_alloc/mtk_tx_clean
      net: ethernet: mtk_eth_soc: rely on txd_size in mtk_desc_to_tx_buf
      net: ethernet: mtk_eth_soc: rely on txd_size in txd_to_idx
      net: ethernet: mtk_eth_soc: add rxd_size to mtk_soc_data
      net: ethernet: mtk_eth_soc: rely on txd_size field in mtk_poll_tx/mtk_poll_rx
      net: ethernet: mtk_eth_soc: rely on rxd_size field in mtk_rx_alloc/mtk_rx_clean
      net: ethernet: mtk_eth_soc: introduce device register map
      net: ethernet: mtk_eth_soc: introduce MTK_NETSYS_V2 support
      net: ethernet: mtk_eth_soc: convert ring dma pointer to void
      net: ethernet: mtk_eth_soc: convert scratch_ring pointer to void
      net: ethernet: mtk_eth_soc: introduce support for mt7986 chipset

Louis Peens (10):
      nfp: flower: add infrastructure for pre_tun rework
      nfp: flower: add/remove predt_list entries
      nfp: flower: enforce more strict pre_tun checks
      nfp: flower: fixup ipv6/ipv4 route lookup for neigh events
      nfp: flower: update nfp_tun_neigh structs
      nfp: flower: rework tunnel neighbour configuration
      nfp: flower: link pre_tun flow rules with neigh entries
      nfp: flower: remove unused neighbour cache
      nfp: flower: enable decap_v2 bit
      nfp: flower: fix 'variable 'flow6' set but not used'

Lu Wei (2):
      net/mlxbf_gige: use eth_zero_addr() to clear mac address
      ax25: merge repeat codes in ax25_dev_device_down()

Luiz Angelo Daros de Luca (4):
      docs: net: dsa: describe issues with checksum offload
      dt-bindings: net: dsa: realtek: cleanup compatible strings
      net: dsa: realtek: remove realtek,rtl8367s string
      net: dsa: OF-ware slave_mii_bus

Luiz Augusto von Dentz (7):
      Bluetooth: HCI: Add HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN quirk
      Bluetooth: Print broken quirks
      Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN for QCA
      Bluetooth: MGMT: Add conditions for setting HCI_CONN_FLAG_REMOTE_WAKEUP
      Bluetooth: hci_sync: Fix attempting to suspend with unfiltered passive scan
      Bluetooth: eir: Add helpers for managing service data
      Bluetooth: hci_conn: Fix hci_connect_le_sync

Lukas Bulwahn (1):
      MAINTAINERS: rectify entry for XILINX CAN DRIVER

Lukas Wunner (8):
      net: phy: Deduplicate interrupt disablement on PHY attach
      usbnet: Run unregister_netdev() before unbind() again
      usbnet: smsc95xx: Don't clear read-only PHY interrupt
      usbnet: smsc95xx: Don't reset PHY behind PHY driver's back
      usbnet: smsc95xx: Avoid link settings race on interrupt reception
      usbnet: smsc95xx: Forward PHY interrupts to PHY driver to avoid polling
      net: phy: smsc: Cache interrupt mask
      net: phy: smsc: Cope with hot-removal in interrupt handler

Lv Ruyi (5):
      bnx2x: Fix spelling mistake "regiser" -> "register"
      sfc: Fix spelling mistake "writting" -> "writing"
      rtlwifi: Fix spelling mistake "cacluated" -> "calculated"
      rtlwifi: rtl8192cu: Fix spelling mistake "writting" -> "writing"
      ixp4xx_eth: fix error check return value of platform_get_irq()

Maciej Fijalkowski (16):
      xsk: Diversify return codes in xsk_rcv_check()
      ice, xsk: Decorate ICE_XDP_REDIR with likely()
      ixgbe, xsk: Decorate IXGBE_XDP_REDIR with likely()
      ice, xsk: Terminate Rx side of NAPI when XSK Rx queue gets full
      i40e, xsk: Terminate Rx side of NAPI when XSK Rx queue gets full
      ixgbe, xsk: Terminate Rx side of NAPI when XSK Rx queue gets full
      ice, xsk: Diversify return values from xsk_wakeup call paths
      i40e, xsk: Diversify return values from xsk_wakeup call paths
      ixgbe, xsk: Diversify return values from xsk_wakeup call paths
      mlx5, xsk: Diversify return values from xsk_wakeup call paths
      stmmac, xsk: Diversify return values from xsk_wakeup call paths
      ice, xsk: Avoid refilling single Rx descriptors
      xsk: Drop ternary operator from xskq_cons_has_entries
      ixgbe, xsk: Get rid of redundant 'fallthrough'
      i40e, xsk: Get rid of redundant 'fallthrough'
      ice: introduce common helper for retrieving VSI by vsi_num

Magnus Karlsson (10):
      selftests: xsk: cleanup bash scripts
      selftests: xsk: do not send zero-length packets
      selftests: xsk: run all tests for busy-poll
      selftests: xsk: fix reporting of failed tests
      selftests: xsk: add timeout to tests
      selftests: xsk: cleanup veth pair at ctrl-c
      selftests: xsk: introduce validation functions
      selftests: xsk: make the stats tests normal tests
      selftests: xsk: make stat tests not spin on getsockopt
      MAINTAINERS: Add maintainer to AF_XDP

Manikanta Pubbisetty (19):
      ath11k: PCI changes to support WCN6750
      ath11k: Refactor PCI code to support WCN6750
      ath11k: Choose MSI config based on HW revision
      ath11k: Refactor MSI logic to support WCN6750
      ath11k: Remove core PCI references from PCI common code
      ath11k: Do not put HW in DBS mode for WCN6750
      ath11k: WMI changes to support WCN6750
      ath11k: Update WBM idle ring HP after FW mode on
      dt: bindings: net: add bindings of WCN6750 for ath11k
      ath11k: Move parameters in bus_params to hw_params
      ath11k: Add HW params for WCN6750
      ath11k: Add register access logic for WCN6750
      ath11k: Fetch device information via QMI for WCN6750
      ath11k: Add QMI changes for WCN6750
      ath11k: HAL changes to support WCN6750
      ath11k: Datapath changes to support WCN6750
      ath11k: Add support for WCN6750 device
      ath11k: Add support for targets without trustzone
      ath11k: Fix RX de-fragmentation issue on WCN6750

Marc Kleine-Budde (9):
      can: rx-offload: rename can_rx_offload_queue_sorted() -> can_rx_offload_queue_timestamp()
      can: bittiming: can_calc_bittiming(): prefer small bit rate pre-scalers over larger ones
      can: xilinx_can: mark bit timing constants as const
      dt-binding: can: mcp251xfd: add binding information for mcp251863
      can: mcp251xfd: add support for mcp251863
      can: raw: raw_sendmsg(): remove not needed setting of skb->sk
      can: raw: add support for SO_TXTIME/SCM_TXTIME
      dt-bindings: can: ctucanfd: include common CAN controller bindings
      can: ctucanfd: platform: add missing dependency to HAS_IOMEM

Marcel Ziswiler (1):
      net: stmmac: dwmac-imx: comment spelling fix

Marcin Szycik (1):
      Revert "ice: Hide bus-info in ethtool for PRs in switchdev mode"

Marcin Wojtas (1):
      net: dsa: remove unused headers

Marek Behún (1):
      net: dsa: mv88e6xxx: Cosmetic change spaces to tabs in dsa_switch_ops

Marek Vasut (1):
      net: phy: micrel: ksz9031/ksz9131: add cabletest support

Mark Bloch (22):
      net/mlx5e: TC, set proper dest type
      net/mlx5: fs, split software and IFC flow destination definitions
      net/mlx5: fs, refactor software deletion rule
      net/mlx5: fs, jump to exit point and don't fall through
      net/mlx5: fs, add unused destination type
      net/mlx5: fs, do proper bookkeeping for forward destinations
      net/mlx5: fs, delete the FTE when there are no rules attached to it
      net/mlx5: fs, call the deletion function of the node
      net/mlx5: fs, an FTE should have no dests when deleted
      net/mlx5: Lag, expose number of lag ports
      net/mlx5: devcom only supports 2 ports
      net/mlx5: Lag, move E-Switch prerequisite check into lag code
      net/mlx5: Lag, use lag lock
      net/mlx5: Lag, filter non compatible devices
      net/mlx5: Lag, store number of ports inside lag object
      net/mlx5: Lag, support single FDB only on 2 ports
      net/mlx5: Lag, use hash when in roce lag on 4 ports
      net/mlx5: Lag, use actual number of lag ports
      net/mlx5: Support devices with more than 2 ports
      net/mlx5: Lag, refactor dmesg print
      net/mlx5: Lag, use buckets in hash mode
      net/mlx5: Lag, add debugfs to query hardware lag state

Martin Blumenstingl (2):
      net: dsa: lantiq_gswip: Fix start index in gswip_port_fdb()
      net: dsa: lantiq_gswip: Fix typo in gswip_port_fdb_dump() error print

Martin Habets (23):
      sfc: efx_default_channel_type APIs can be static
      sfc: Remove duplicate definition of efx_xmit_done
      sfc: Remove global definition of efx_reset_type_names
      sfc: Disable Siena support
      sfc: Copy a subset of mcdi_pcol.h to siena
      sfc: Move Siena specific files
      sfc: Copy shared files needed for Siena (part 1)
      sfc: Copy shared files needed for Siena (part 2)
      sfc/siena: Remove build references to missing functionality
      sfc/siena: Rename functions in efx headers to avoid conflicts with sfc
      sfc/siena: Rename RX/TX functions to avoid conflicts with sfc
      sfc/siena: Rename peripheral functions to avoid conflicts with sfc
      sfc/siena: Rename functions in mcdi headers to avoid conflicts with sfc
      sfc/siena: Rename functions in nic_common.h to avoid conflicts with sfc
      sfc/siena: Inline functions in sriov.h to avoid conflicts with sfc
      sfc: Add a basic Siena module
      siena: Make MTD support specific for Siena
      siena: Make SRIOV support specific for Siena
      siena: Make HWMON support specific for Siena
      sfc/siena: Make MCDI logging support specific for Siena
      sfc/siena: Make PTP and reset support specific for Siena
      sfc/siena: Reinstate SRIOV init/fini function calls
      sfc/siena: Remove duplicate check on segments

Martin Jerabek (1):
      can: ctucanfd: add support for CTU CAN FD open-source IP core - bus independent part.

Martin KaFai Lau (4):
      net: inet: Remove count from inet_listen_hashbucket
      net: inet: Open code inet_hash2 and inet_unhash2
      net: inet: Retire port only listening_hash
      net: selftests: Stress reuseport listen

Martin Liška (1):
      eth: sun: cassini: remove dead code

Martin Willi (1):
      netfilter: Use l3mdev flow key when re-routing mangled packets

Mat Martineau (9):
      mptcp: Remove redundant assignments in path manager init
      mptcp: Add a member to mptcp_pm_data to track kernel vs userspace mode
      mptcp: Bypass kernel PM when userspace PM is enabled
      mptcp: Make kernel path manager check for userspace-managed sockets
      mptcp: Add a per-namespace sysctl to set the default path manager type
      selftests: mptcp: Add tests for userspace PM type
      selftests: mptcp: ADD_ADDR echo test with missing userspace daemon
      mptcp: Check for orphaned subflow before handling MP_FAIL timer
      mptcp: Do not traverse the subflow connection list without lock

Mateusz Palczewski (1):
      i40e: Add Ethernet Connection X722 for 10GbE SFP+ support

Max Chou (1):
      Bluetooth: btrtl: Add support for RTL8852C

Maxim Mikityanskiy (1):
      net/mlx5e: Drop error CQE handling from the XSK RX handler

MeiChia Chiu (1):
      mt76: mt7915: add support for 6G in-band discovery

Meng Tang (2):
      ath10k: Use of_device_get_match_data() helper
      ipw2x00: use DEVICE_ATTR_*() macro

Menglong Dong (18):
      net: sock: introduce sock_queue_rcv_skb_reason()
      net: skb: rename SKB_DROP_REASON_PTYPE_ABSENT
      net: icmp: introduce __ping_queue_rcv_skb() to report drop reasons
      net: icmp: add skb drop reasons to icmp protocol
      skb: add some helpers for skb drop reasons
      net: ipv4: add skb drop reasons to ip_error()
      net: ipv6: add skb drop reasons to ip6_pkt_drop()
      net: ip: add skb drop reasons to ip forwarding
      net: icmp: introduce function icmpv6_param_prob_reason()
      net: ipv6: remove redundant statistics in ipv6_hop_jumbo()
      net: ipv6: add skb drop reasons to TLV parse
      net: ipv6: add skb drop reasons to ip6_rcv_core()
      net: ipv6: add skb drop reasons to ip6_protocol_deliver_rcu()
      bpf: Compute map_btf_id during build time
      net: dm: check the boundary of skb drop reasons
      net: skb: check the boundrary of drop reason in kfree_skb_reason()
      net: skb: change the definition SKB_DR_SET()
      net: tcp: reset 'drop_reason' to NOT_SPCIFIED in tcp_v{4,6}_rcv()

Michael Chan (1):
      bnxt_en: Update firmware interface to 1.10.2.95

Michael Trimarchi (1):
      net: fec: Avoid allocating rx buffer using ATOMIC in ndo_open

Michael Walle (9):
      dt-bindings: net: convert mscc-miim to YAML format
      dt-bindings: net: mscc-miim: add clock and clock-frequency
      net: phy: mscc-miim: add support to set MDIO bus frequency
      dt-bindings: net: micrel: add coma-mode-gpios property
      net: phy: micrel: move the PHY timestamping check
      net: phy: micrel: add coma mode GPIO
      dt-bindings: net: lan966x: remove PHY reset
      net: lan966x: remove PHY reset support
      dt-bindings: net: lan966x: fix example

Michal Simek (1):
      net: emaclite: Update copyright text to correct format

Michal Swiatkowski (2):
      ice: get switch id on switchdev devices
      ice: link representors to PCI device

Milan Landaverde (5):
      bpftool: Add syscall prog type
      bpftool: Add missing link types
      bpftool: Handle libbpf_probe_prog_type errors
      bpftool: Adjust for error codes from libbpf probes
      bpftool: Output message if no helpers found in feature probing

Min Li (2):
      ptp: ptp_clockmatrix: Add PTP_CLK_REQ_EXTTS support
      ptp: ptp_clockmatrix: return -EBUSY if phase pull-in is in progress

Minghao Chi (28):
      ath9k: Use platform_get_irq() to get the interrupt
      net: stmmac: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      net/cadence: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      wlcore: debugfs: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      net: ethernet: ti: cpsw: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      net: ethernet: ti: am65-cpsw-nuss: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      net: ethernet: ti: cpsw_new: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      net: stmmac: stmmac_main: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      net: ethernet: ti: cpsw_priv: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      net: ethernet: ti: davinci_emac: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      can: flexcan: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      drivers: net: davinci_mdio: using pm_runtime_resume_and_get instead of pm_runtime_get_sync
      net: ethernet: ti: am65-cpsw-ethtool: use pm_runtime_resume_and_get
      wlcore: main: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wlcore: sysfs: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wlcore: testmode: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wlcore: vendor_cmd: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wlcore: sdio: using pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wlcore: cmd: using pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wil6210: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wl18xx: debugfs: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wl12xx: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      wl12xx: scan: use pm_runtime_resume_and_get() instead of pm_runtime_get_sync()
      net/funeth: simplify the return expression of fun_dl_info_get()
      octeontx2-pf: Remove unnecessary synchronize_irq() before free_irq()
      qed: Remove unnecessary synchronize_irq() before free_irq()
      net: vxge: Remove unnecessary synchronize_irq() before free_irq()
      net: qede: Remove unnecessary synchronize_irq() before free_irq()

Miquel Raynal (15):
      net: ieee802154: ca8210: Fix lifs/sifs periods
      net: mac802154: Convert the symbol duration into nanoseconds
      net: mac802154: Set durations automatically
      net: ieee802154: Drop duration settings when the core does it already
      net: ieee802154: Enhance/fix the names of the MLME return codes
      net: ieee802154: Fill the list of MLME return codes
      net: mac802154: Save a global error code on transmissions
      net: mac802154: Create an offloaded transmission error helper
      net: mac802154: Create an error helper for asynchronous offloading errors
      net: ieee802154: at86rf230: Call _xmit_hw_error() when failing to offload frames
      net: ieee802154: at86rf230: Forward Tx trac errors
      net: ieee802154: atusb: Call _xmit_hw_error() upon transmission error
      net: ieee802154: ca8210: Use core return codes instead of hardcoding them
      net: ieee802154: ca8210: Call _xmit_error() when a transmission fails
      net: mac802154: Fix symbol durations

Miri Korenblit (1):
      iwlwifi: mvm: remove vif_count

Mordechay Goodstein (1):
      iwlwifi: mvm: add OTP info in case of init failure

Moshe Shemesh (1):
      net/mlx5: Add last command failure syndrome to debugfs

Moshe Tal (1):
      net/mlx5e: Correct the calculation of max channels for rep

Muhammad Usama Anjum (1):
      net: selftests: Add stress_reuseport_listen to .gitignore

Muna Sinada (2):
      cfg80211: support disabling EHT mode
      mac80211: support disabling EHT mode

Mykola Lysenko (6):
      selftests/bpf: Improve by-name subtest selection logic in prog_tests
      selftests/bpf: Refactor prog_tests logging and test execution
      bpf/selftests: Add granular subtest output for prog_test
      selftests/bpf: Fix two memory leaks in prog_tests
      selftests/bpf: Fix subtest number formatting in test_progs
      selftests/bpf: Remove filtered subtests from output

Nabil S. Alramli (1):
      i40e: Add vsi.tx_restart to i40e ethtool stats

Nagarajan Maran (1):
      ath11k: fix driver initialization failure with WoW unsupported hw

Nathan Chancellor (1):
      ath6kl: Use cc-disable-warning to disable -Wdangling-pointer

Nathan Rossi (1):
      net: dsa: mv88e6xxx: Single chip mode detection for MV88E6*41

Nick Desaulniers (1):
      net, uapi: remove inclusion of arpa/inet.h

Nicolas Rybowski (1):
      selftests/bpf: Add MPTCP test base

Niels Dossche (7):
      ath11k: acquire ab->base_lock in unassign when finding the peer by addr
      mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
      ipv6: fix locking issues with loops over idev->addr_list
      octeontx2-af: debugfs: fix error return of allocations
      Bluetooth: use hdev lock in activate_scan for hci_is_adv_monitoring
      Bluetooth: use hdev lock for accept_list and reject_list in conn req
      Bluetooth: protect le accept and resolv lists with hdev->lock

Nikolay Aleksandrov (12):
      net: rtnetlink: add msg kind names
      net: rtnetlink: add helper to extract msg type's kind
      net: rtnetlink: use BIT for flag values
      net: netlink: add NLM_F_BULK delete request modifier
      net: rtnetlink: add bulk delete support flag
      net: add ndo_fdb_del_bulk
      net: rtnetlink: add NLM_F_BULK support to rtnl_fdb_del
      net: bridge: fdb: add ndo_fdb_del_bulk
      net: bridge: fdb: add support for fine-grained flushing
      net: rtnetlink: add ndm flags and state mask attributes
      net: bridge: fdb: add support for flush filtering based on ndm flags and state
      net: bridge: fdb: add support for flush filtering based on ifindex and vlan

Nikolay Borisov (1):
      selftests/bpf: Fix vfs_link kprobe definition

Nobuhiro Iwamatsu (1):
      dt-bindings: net: toshiba,visconti-dwmac: Update the common clock properties

Oleksij Rempel (7):
      net: phy: genphy_c45_baset1_an_config_aneg: do no set unknown configuration
      net: phy: introduce genphy_c45_pma_baset1_setup_master_slave()
      net: phy: genphy_c45_pma_baset1_setup_master_slave: do no set unknown configuration
      net: phy: introduce genphy_c45_pma_baset1_read_master_slave()
      net: phy: genphy_c45_pma_baset1_read_master_slave: read actual configuration
      net: phy: export genphy_c45_baset1_read_status()
      net: phy: dp83td510: Add support for the DP83TD510 Ethernet PHY

Oliver Hartkopp (6):
      net: remove noblock parameter from skb_recv_datagram()
      net: remove noblock parameter from recvmsg() entities
      can: isotp: add support for transmission without flow control
      can: isotp: isotp_bind(): return -EINVAL on incorrect CAN ID formatting
      can: isotp: isotp_bind(): do not validate unused address information
      can: can-dev: remove obsolete CAN LED support

Pablo Neira Ayuso (2):
      netfilter: nft_fib: reverse path filter for policy-based routing on iif
      netfilter: conntrack: add nf_ct_iter_data object for nf_ct_iterate_cleanup*()

Paolo Abeni (30):
      mptcp: optimize release_cb for the common case
      mptcp: reset the packet scheduler on incoming MP_PRIO
      mptcp: reset the packet scheduler on PRIO change
      Merge branch 'net-bridge-add-support-for-host-l2-mdb-entries'
      Merge branch 'net-dsa-mt7530-updates-for-phylink-changes'
      Merge branch 'sfc-remove-some-global-definitions'
      Merge branch 'rndis_host-handle-bogus-mac-addresses-in-zte-rndis-devices'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      geneve: avoid indirect calls in GRO path, when possible
      Merge branch 'net-sched-allow-user-to-select-txqueue'
      Merge branch 'rtnetlink-improve-alt_ifname-config-and-fix-dangerous-group-usage'
      Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
      Merge branch 'add-reset-deassertion-for-aspeed-mdio'
      Merge branch 'devices-always-netif_f_lltx'
      Merge tag 'linux-can-next-for-5.19-20220502' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
      Merge branch 'use-mmd-c45-helpers'
      Merge branch 'net-more-heap-allocation-and-split-of-rtnl_newlink'
      Merge branch 'use-standard-sysctl-macro'
      Merge branch 'mlxsw-remove-size-limitations-on-egress-descriptor-buffer'
      Merge tag 'mlx5-updates-2022-05-02' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux
      mptcp: really share subflow snd_wnd
      mptcp: add mib for xmit window sharing
      tcp: allow MPTCP to update the announced window
      mptcp: never shrink offered window
      mptcp: add more offered MIBs counter
      Merge branch 'ptp-support-hardware-clocks-with-additional-free-running-cycle-counter'
      Merge branch 'this-is-a-patch-series-for-ethernet-driver-of-sunplus-sp7021-soc'
      Merge branch 'nfp-vf-rate-limit-support'
      Revert "mptcp: add data lock for sk timers"
      mptcp: stop using the mptcp_has_another_subflow() helper

Pavan Chebbi (2):
      bnxt_en: Configure ptp filters during bnxt open
      bnxt_en: Enable packet timestamping for all RX packets

Pavel Begunkov (9):
      net: inline sock_alloc_send_skb
      net: inline skb_zerocopy_iter_dgram
      net: inline dev_queue_xmit()
      ipv6: help __ip6_finish_output() inlining
      ipv6: refactor ip6_finish_output2()
      sock: dedup sock_def_write_space wmem_alloc checks
      sock: optimise UDP sock_wfree() refcounting
      sock: optimise sock_def_write_space barriers
      tcp: optimise skb_zerocopy_iter_stream()

Pavel Löbl (1):
      brcmfmac: allow setting wlan MAC address using device tree

Pavel Pisa (11):
      dt-bindings: vendor-prefix: add prefix for the Czech Technical University in Prague.
      dt-bindings: net: can: binding for CTU CAN FD open-source IP core.
      can: ctucanfd: CTU CAN FD open-source IP core - PCI bus support.
      can: ctucanfd: CTU CAN FD open-source IP core - platform/SoC support.
      docs: ctucanfd: CTU CAN FD open-source IP core documentation.
      MAINTAINERS: Add maintainers for CTU CAN FD IP core driver
      docs: networking: device drivers: can: add ctucanfd to index
      docs: networking: device drivers: can: ctucanfd: update author e-mail
      can: ctucanfd: remove inline keyword from local static functions
      can: ctucanfd: remove debug statements
      can: ctucanfd: remove PCI module debug parameters

Peilin Ye (2):
      ip_gre: Make GRE and GRETAP devices always NETIF_F_LLTX
      ip6_gre: Make IP6GRE and IP6GRETAP devices always NETIF_F_LLTX

Peng Li (3):
      net: hns3: update the comment of function hclgevf_get_mbx_resp
      net: hns3: fix the wrong words in comments
      net: hns3: replace magic value by HCLGE_RING_REG_OFFSET

Pengcheng Yang (1):
      tcp: use tcp_skb_sent_after() instead in RACK

Peter Chiu (4):
      mt76: mt7915: update mt7986 patch in mt7986_wmac_adie_patch_7976()
      mt76: mt7915: fix twt table_mask to u16 in mt7915_dev
      mt76: mt7915: reject duplicated twt flows
      mt76: mt7915: limit minimum twt duration

Peter Seiderer (3):
      mac80211: minstrel_ht: fix where rate stats are stored (fixes debugfs output)
      ath9k: fix ath_get_rate_txpower() to respect the rate list end tag
      mac80211: minstrel_ht: fill all requested rates

Petr Machata (19):
      mlxsw: reg: Add "desc" field to SBPR
      mlxsw: Configure descriptor buffers
      selftests: forwarding: lib: Add start_traffic_pktsize() helpers
      selftests: mlxsw: Add a test for soaking up a burst of traffic
      selftests: mlxsw: bail_on_lldpad before installing the cleanup trap
      selftests: router_vid_1: Add a diagram, fix coding style
      selftests: router.sh: Add a diagram
      mlxsw: spectrum_dcb: Do not warn about priority changes
      mlxsw: Treat LLDP packets as control
      mlxsw: spectrum: Tolerate enslaving of various devices to VRF
      mlxsw: spectrum_router: Add a dedicated notifier block
      mlxsw: spectrum: Move handling of VRF events to router code
      mlxsw: spectrum: Move handling of HW stats events to router code
      mlxsw: spectrum: Move handling of router events to router code
      mlxsw: spectrum: Move handling of tunnel events to router code
      mlxsw: spectrum: Update a comment
      mlxsw: spectrum_router: Take router lock in router notifier handler
      selftests: lib: Add a generic helper for obtaining HW stats
      selftests: forwarding: Add a tunnel-based test for L3 HW stats

Phil Edworthy (5):
      dt-bindings: net: renesas,etheravb: Document RZ/V2M SoC
      ravb: Separate handling of irq enable/disable regs into feature
      ravb: Support separate Line0 (Desc), Line1 (Err) and Line2 (Mgmt) irqs
      ravb: Use separate clock for gPTP
      ravb: Add support for RZ/V2M

Phil Sutter (3):
      netfilter: nf_log_syslog: Merge MAC header dumpers
      netfilter: nf_log_syslog: Don't ignore unknown protocols
      netfilter: nf_log_syslog: Consolidate entry checks

Pieter Jansen van Vuuren (1):
      sfc: add EF100 VF support via a write to sriov_numvfs

Ping Gan (1):
      tcp: Add tracepoint for tcp_set_ca_state

Ping-Ke Shih (79):
      rtw89: reduce export symbol number of mac size and quota
      rtw89: add chip_info::h2c_desc_size/fill_txdesc_fwcmd to support new chips
      rtw89: pci: support variant of fill_txaddr_info
      rtw89: support variant of fill_txdesc
      rtw89: support hardware generate security header
      rtw89: read RX bandwidth from v1 type RX descriptor
      rtw89: handle potential uninitialized variable
      rtw89: pci: add register definition to rtw89_pci_info to generalize pci code
      rtw89: pci: add pci attributes to configure operating mode
      rtw89: pci: add LTR setting for v1 chip
      rtw89: pci: set address info registers depends on chips
      rtw89: pci: add deglitch setting
      rtw89: pci: add L1 settings
      rtw89: extend dmac_pre_init to support 8852C
      rtw89: update STA scheduler parameters for v1 chip
      rtw89: add chip_ops::{enable,disable}_bb_rf to support v1 chip
      rtw89: Turn on CR protection of CMAC
      rtw89: 8852c: update security engine setting
      rtw89: update scheduler setting
      rtw89: initialize NAV control
      rtw89: update TMAC parameters
      rtw89: update ptcl_init
      rtw89: ser: configure top ERR IMR for firmware to recover
      rtw89: change station scheduler setting for hardware TX mode
      rtw89: reset BA CAM
      rtw88: do PHY calibration while starting AP
      rtw89: extend H2C of CMAC control info
      rtw89: add new H2C to configure security CAM via DCTL for V1 chip
      rtw89: configure security CAM for V1 chip
      rtw89: pci: correct return value handling of rtw89_write16_mdio_mask()
      rtw89: 8852c: add BB and RF parameters tables
      rtw89: 8852c: add TX power by rate and limit tables
      rtw89: 8852c: phy: configure TSSI bandedge
      rtw89: 8852c: add BB initial and reset functions
      rtw89: 8852c: add efuse gain offset parser
      rtw89: 8852c: add HFC parameters
      rtw89: 8852c: add set channel function of RF part
      rtw89: 8852c: set channel of MAC part
      rtw89: 8852c: add set channel of BB part
      rtw89: 8852c: add help function of set channel
      rtw89: pci: add variant IMR/ISR and configure functions
      rtw89: pci: add variant RPWM/CPWM to enter low power mode
      rtw89: pci: reclaim TX BD only if it really need
      rtw89: pci: add a separate interrupt handler for low power mode
      rtw89: ser: re-enable interrupt in threadfn if under_recovery
      rtw89: ps: access TX/RX rings via another registers in low power mode
      rtw89: pci: allow to process RPP prior to TX BD
      rtw89: don't flush hci queues and send h2c if power is off
      rtw89: add RF H2C to notify firmware
      rtw89: 8852c: configure default BB TX/RX path
      rtw89: 8852c: implement chip_ops related to TX power
      rtw89: 8852c: implement chip_ops::get_thermal
      rtw89: 8852c: fill freq and band of RX status by PPDU report
      rtw89: 8852c: add chip_ops related to BTC
      rtw89: 8852c: rfk: add RFK tables
      rtw89: 8852c: rfk: add DACK
      rtw89: 8852c: rfk: add LCK
      rtw89: 8852c: rfk: add TSSI
      rtw89: 8852c: rfk: add RCK
      rtw89: 8852c: rfk: add RX DCK
      rtw89: 8852c: rfk: add IQK
      rtw89: 8852c: rfk: add DPK
      rtw89: 8852c: rfk: get calibrated channels to notify firmware
      rtw89: 8852c: add chip_ops::bb_ctrl_btc_preagc
      rtw89: 8852c: add basic and remaining chip_info
      rtw89: ps: fine tune polling interval while changing low power mode
      rtw89: correct AID settings of beamformee
      rtw89: 8852c: correct register definitions used by 8852c
      rtw89: 8852c: fix warning of FIELD_PREP() mask type
      rtw89: 8852c: add 8852ce to Makefile and Kconfig
      mac80211: consider Order bit to fill CCMP AAD
      rtw89: correct setting of RX MPDU length
      rtw89: correct CCA control
      rtw89: add debug select to dump MAC pages 0x30 to 0x33
      rtw89: add debug entry to dump BSSID CAM
      rtw89: add ieee80211::sta_rc_update ops
      rtw89: 8852c: set TX antenna path
      rtw89: cfo: check mac_id to avoid out-of-bounds
      rtw89: pci: only mask out INT indicator register for disable interrupt v1

Po Hao Huang (3):
      rtw89: change idle mode condition during hw_scan
      rtw89: packet offload handler to avoid warning
      rtw89: fix misconfiguration on hw_scan channel time

Po Liu (1):
      net: enetc: count the tc-taprio window drops

Po-Hao Huang (8):
      rtw88: change idle mode condition during hw_scan
      rtw88: add ieee80211:sta_rc_update ops
      rtw88: fix incorrect frequency reported
      rtw88: Add update beacon flow for AP mode
      rtw88: 8821c: Enable TX report for management frames
      rtw88: 8821c: fix debugfs rssi value
      rtw88: fix uninitialized 'tim_offset' warning
      rtw88: pci: 8821c: Disable 21ce completion timeout

Potin Lai (3):
      net: mdio: aspeed: move reg accessing part into separate functions
      net: mdio: aspeed: Introduce read write function for c22 and c45
      net: mdio: aspeed: Add c45 support

Prabhakar Kushwaha (1):
      qede: Reduce verbosity of ptp tx timestamp

Prasanna Vengateshan (1):
      net: dsa: move mib->cnt_ptr reset code to ksz_common.c

Pu Lehui (3):
      riscv, bpf: Implement more atomic operations for RV64
      libbpf: Fix usdt_cookie being cast to 32 bits
      libbpf: Support riscv USDT argument parsing logic

Quentin Monnet (1):
      selftests/bpf: Fix parsing of prog types in UAPI hdr for bpftool sync

Radhey Shyam Pandey (3):
      net: emaclite: Fix coding style
      dt-bindings: net: cdns,macb: Drop phy-names property for ZynqMP SGMII PHY
      net: macb: In ZynqMP initialization make SGMII phy configuration optional

Rameshkumar Sundaram (1):
      nl80211: Parse NL80211_ATTR_HE_BSS_COLOR as a part of nl80211_parse_beacon

Randy Dunlap (1):
      net: dsa: restrict SMSC_LAN9303_I2C kconfig

Ren Zhijie (1):
      sfc: siena: Fix Kconfig dependencies

Ricardo Martinez (6):
      list: Add list_next_entry_circular() and list_prev_entry_circular()
      net: skb: introduce skb_data_area_size()
      net: wwan: t7xx: Add maintainers and documentation
      net: wwan: t7xx: Avoid calls to skb_data_area_size()
      net: skb: Remove skb_data_area_size()
      net: wwan: t7xx: Fix smatch errors

Rikard Falkeborn (1):
      Bluetooth: btintel: Constify static struct regmap_bus

Robert Hancock (5):
      net: phy: marvell: update abilities and advertising when switching to SGMII
      net: macb: simplify/cleanup NAPI reschedule checking
      net: macb: use NAPI for TX completion path
      net: axienet: Be more careful about updating tx_bd_tail
      net: axienet: Use NAPI for TX completion path

Robert Marko (1):
      ath10k: support bus and device specific API 1 BDF selection

Robin Murphy (1):
      sfc: Stop using iommu_present()

Rolf Eike Beer (2):
      net: tulip: convert to devres
      net: tulip: fix build with CONFIG_GSC

Runqing Yang (1):
      libbpf: Fix a bug with checking bpf_probe_read_kernel() support in old kernels

Russell King (1):
      net: mtk_eth_soc: correct 802.3z duplex setting

Russell King (Oracle) (22):
      net: dsa: mt7530: 1G can also support 1000BASE-X link mode
      net: dsa: mt7530: populate supported_interfaces and mac_capabilities
      net: dsa: mt7530: remove interface checks
      net: dsa: mt7530: drop use of phylink_helper_basex_speed()
      net: dsa: mt7530: only indicate linkmodes that can be supported
      net: dsa: mt7530: switch to use phylink_get_linkmodes()
      net: dsa: mt7530: partially convert to phylink_pcs
      net: dsa: mt7530: move autoneg handling to PCS validation
      net: dsa: mt7530: mark as non-legacy
      net: phylink: remove phylink_helper_basex_speed()
      net: dsa: mt753x: fix pcs conversion regression
      net: mtk_eth_soc: remove unused mac->mode
      net: mtk_eth_soc: remove unused sgmii flags
      net: mtk_eth_soc: add mask and update PCS speed definitions
      net: mtk_eth_soc: correct 802.3z speed setting
      net: mtk_eth_soc: stop passing phylink state to sgmii setup
      net: mtk_eth_soc: provide mtk_sgmii_config()
      net: mtk_eth_soc: add fixme comment for state->speed use
      net: mtk_eth_soc: move MAC_MCR setting to mac_finish()
      net: mtk_eth_soc: move restoration of SYSCFG0 to mac_finish()
      net: mtk_eth_soc: convert code structure to suit split PCS support
      net: mtk_eth_soc: partially convert to phylink_pcs

Ryder Lee (7):
      mt76: mt7915: always call mt7915_wfsys_reset() during init
      mt76: mt7915: remove SCS feature
      mt76: mt7915: rework SER debugfs knob
      mt76: mt7915: introduce mt7915_mac_severe_check()
      mt76: mt7915: move MT_INT_MASK_CSR to init.c
      mt76: mt7915: improve error handling for fw_debug knobs
      mt76: mt7915: add more statistics from fw_util debugfs knobs

Saeed Mahameed (3):
      net/mlx5: sparse: error: context imbalance in 'mlx5_vf_get_core_dev'
      net/mlx5e: CT: Add ct driver counters
      sfc: siena: Have a unique wrapper ifndef for efx channels header

Sasha Neftin (3):
      igc: Remove igc_set_spd_dplx method
      igc: Remove unused phy_type enum
      igc: Change type of the 'igc_check_downshift' method

Sean Wang (8):
      mt76: mt7921: Add AP mode support
      mt76: mt7921: fix kernel crash at mt7921_pci_remove
      mt76: connac: use skb_put_data instead of open coding
      Bluetooth: mt7921s: Fix the incorrect pointer check
      Bluetooth: btusb: Add a new PID/VID 0489/e0c8 for MT7921
      Bluetooth: btmtksdio: fix use-after-free at btmtksdio_recv_event
      Bluetooth: btmtksdio: fix possible FW initialization failure
      Bluetooth: btmtksdio: fix the reset takes too long

Shay Drory (2):
      net/mlx5: Delete redundant default assignment of runtime devlink params
      net/mlx5: Print initializing field in case of timeout

Shayne Chen (1):
      mt76: mt7915: add debugfs knob for RF registers read/write

Shravya Kumbham (1):
      net: emaclite: Remove custom BUFFER_ALIGN macro

Simon Wunderlich (1):
      batman-adv: Start new development cycle

Song Chen (1):
      sample: bpf: syscall_tp_user: Print result of verify_map

Song Liu (3):
      bpf: Fill new bpf_prog_pack with illegal instructions
      x86/alternative: Introduce text_poke_set
      bpf: Introduce bpf_arch_text_invalidate for bpf_prog_pack

Sridhar Samudrala (1):
      ice: Expose RSS indirection tables for queue groups via ethtool

Srinivasan R (1):
      wireless: Fix Makefile to be in alphabetical order

Srinivasan Raju (2):
      wireless: add plfxlc driver for pureLiFi X, XL, XC devices
      plfxlc: fix le16_to_cpu warning for beacon_interval

Sriram R (1):
      mac80211: prepare sta handling for MLO support

Stanislav Fomichev (2):
      bpf: Move rcu lock management out of BPF_PROG_RUN routines
      bpf: Use bpf_prog_run_array_cg_flags everywhere

Stefano Garzarella (2):
      vsock/virtio: factor our the code to initialize and delete VQs
      vsock/virtio: add support for device suspend/resume

Steffen Klassert (1):
      Merge  branch 'Be explicit with XFRM offload direction'

Stephen Rothwell (1):
      netfilter: ctnetlink: fix up for "netfilter: conntrack: remove unconfirmed list"

Steven Rostedt (1):
      Bluetooth: hci_qca: Use del_timer_sync() before freeing

Sukadev Bhattiprolu (6):
      ibmvnic: rename local variable index to bufidx
      ibmvnic: define map_rxpool_buf_to_ltb()
      ibmvnic: define map_txpool_buf_to_ltb()
      ibmvnic: convert rxpool ltb to a set of ltbs
      ibmvnic: Allow multiple ltbs in rxpool ltb_set
      ibmvnic: Allow multiple ltbs in txpool ltb_set

Suman Ghosh (1):
      octeontx2-pf: Add support for adaptive interrupt coalescing

Sven Auhagen (1):
      netfilter: flowtable: nft_flow_route use more data for reverse route

Taehee Yoo (5):
      net: atlantic: Implement xdp control plane
      net: atlantic: Implement xdp data plane
      net: atlantic: Implement .ndo_xdp_xmit handler
      amt: fix gateway mode stuck
      amt: fix memory leak for advertisement message

Takshak Chahande (2):
      bpf: Extend batch operations for map-in-map bpf-maps
      selftests/bpf: Handle batch operations for map-in-map bpf-maps

Tariq Toukan (5):
      net/mlx5: Inline db alloc API function
      net/mlx5: Allocate virtually contiguous memory in vport.c
      net/mlx5: Allocate virtually contiguous memory in pci_irq.c
      net/mlx5e: Allocate virtually contiguous memory for VLANs list
      net/mlx5e: Allocate virtually contiguous memory for reps structures

Tetsuo Handa (2):
      wwan_hwsim: Avoid flush_scheduled_work() usage
      wfx: avoid flush_workqueue(system_highpri_wq) usage

Thibaut VARÈNE (1):
      ath9k: fix QCA9561 PA bias level

Tiezhu Yang (5):
      bpf, docs: Remove duplicated word "instructions"
      bpf, docs: BPF_FROM_BE exists as alias for BPF_TO_BE
      bpf, docs: Fix typo "respetively" to "respectively"
      net: sysctl: Use SYSCTL_TWO instead of &two
      bpf: Print some info if disable bpf_jit_enable failed

Tim Harvey (1):
      Bluetooth: btbcm: Add entry for BCM4373A0 UART Bluetooth

Toke Høiland-Jørgensen (1):
      mac80211: Improve confusing comment around tx_info clearing

Tom Rix (3):
      mlxsw: spectrum_router: simplify list unwinding
      USB2NET : SR9800 : change SR9800_BULKIN_SIZE from global to static
      net: fddi: skfp: smt: Remove extra parameters to vararg macro

Tommaso Merciai (1):
      net: phy: DP83822: enable rgmii mode if phy_interface_is_rgmii

Tonghao Zhang (5):
      net: sched: use queue_mapping to pick tx queue
      net: sched: support hash selecting tx queue
      net: sysctl: use shared sysctl macro
      net: sysctl: introduce sysctl SYSCTL_THREE
      selftests/sysctl: add sysctl macro test

Ulf Hansson (1):
      brcmfmac: Avoid keeping power to SDIO card unless WOWL is used

Uwe Kleine-König (2):
      net: fec: Do proper error checking for optional clks
      net: fec: Do proper error checking for enet_out clk

Vadim Fedorenko (2):
      ptp: ocp: add Celestica timecard PCI ids
      ptp: ocp: Add firmware header checks

Vadim Pasternak (22):
      mlxsw: reg: Extend MTMP register with new slot number field
      mlxsw: reg: Extend MTBR register with new slot number field
      mlxsw: reg: Extend MCIA register with new slot number field
      mlxsw: reg: Extend MCION register with new slot number field
      mlxsw: reg: Extend PMMP register with new slot number field
      mlxsw: reg: Extend MGPIR register with new slot fields
      mlxsw: core_env: Pass slot index during PMAOS register write call
      mlxsw: reg: Add new field to Management General Peripheral Information Register
      mlxsw: core: Extend interfaces for cable info access with slot argument
      mlxsw: core: Extend port module data structures for line cards
      mlxsw: core: Move port module events enablement to a separate function
      mlxsw: core_hwmon: Extend internal structures to support multi hwmon objects
      mlxsw: core_hwmon: Introduce slot parameter in hwmon interfaces
      mlxsw: core_thermal: Extend internal structures to support multi thermal areas
      mlxsw: core_thermal: Add line card id prefix to line card thermal zone name
      mlxsw: core_thermal: Use exact name of cooling devices for binding
      mlxsw: core_thermal: Use common define for thermal zone name length
      mlxsw: core: Add bus argument to environment init API
      mlxsw: core_env: Split module power mode setting to a separate function
      mlxsw: core_env: Add interfaces for line card initialization and de-initialization
      mlxsw: core_thermal: Add interfaces for line card initialization and de-initialization
      mlxsw: core_hwmon: Add interfaces for line card initialization and de-initialization

Vasily Averin (2):
      net: enable memcg accounting for veth queues
      memcg: accounting for objects allocated for new netdevice

Vasyl Vavrychuk (1):
      Bluetooth: core: Fix missing power_on work cancel on HCI close

Veerasenareddy Burru (7):
      octeon_ep: Add driver framework and device initialization
      octeon_ep: add hardware configuration APIs
      octeon_ep: Add mailbox for control commands
      octeon_ep: add Tx/Rx ring resource setup and cleanup
      octeon_ep: add support for ndo ops
      octeon_ep: add Tx/Rx processing and interrupt support
      octeon_ep: add ethtool support for Octeon PCI Endpoint NIC

Vincent Mailhol (2):
      can: slcan: slc_xmit(): use can_dropped_invalid_skb() instead of manual check
      can: mcp251xfd: silence clang's -Wunaligned-access warning

Vincent Whitchurch (1):
      net: stmmac: remove unused get_addr() callback

Vladimir Isaev (1):
      libbpf: Add ARC support to bpf_tracing.h

Vladimir Oltean (48):
      net: dsa: move reset of VLAN filtering to dsa_port_switchdev_unsync_attrs
      net: dsa: make cross-chip notifiers more efficient for host events
      net: dsa: use dsa_tree_for_each_user_port in dsa_slave_change_mtu
      net: dsa: avoid one dsa_to_port() in dsa_slave_change_mtu
      net: dsa: drop dsa_slave_priv from dsa_slave_change_mtu
      net: dsa: don't emit targeted cross-chip notifiers for MTU change
      selftests: forwarding: add option to run tests with stable MAC addresses
      selftests: forwarding: add helpers for IP multicast group joins/leaves
      selftests: forwarding: add helper for retrieving IPv6 link-local address of interface
      selftests: forwarding: add a no_forwarding.sh test
      selftests: forwarding: add a test for local_termination.sh
      selftests: drivers: dsa: add a subset of forwarding selftests
      selftests: forwarding: add Per-Stream Filtering and Policing test for Ocelot
      selftests: forwarding: add basic QoS classification test for Ocelot switches
      net: mscc: ocelot: use list_add_tail in ocelot_vcap_filter_add_to_block()
      net: mscc: ocelot: add to tail of empty list in ocelot_vcap_filter_add_to_block
      net: mscc: ocelot: use list_for_each_entry in ocelot_vcap_filter_add_to_block
      net: mscc: ocelot: drop port argument from qos_policer_conf_set
      net: mscc: ocelot: don't use magic numbers for OCELOT_POLICER_DISCARD
      net: dsa: felix: use PGID_CPU for FDB entry migration on NPI port
      net: dsa: felix: stop migrating FDBs back and forth on tag proto change
      net: dsa: felix: perform MDB migration based on ocelot->multicast list
      net: dsa: delete dsa_port_walk_{fdbs,mdbs}
      selftests: forwarding: tc_actions: allow mirred egress test to run on non-offloaded h2
      net: dsa: ocelot: accept 1000base-X for VSC9959 and VSC9953
      net: enetc: manage ENETC_F_QBV in priv->active_offloads only when enabled
      net: enetc: kill PHY-less mode for PFs
      net: dsa: felix: program host FDB entries towards PGID_CPU for tag_8021q too
      net: dsa: felix: bring the NPI port indirection for host MDBs to surface
      net: dsa: felix: bring the NPI port indirection for host flooding to surface
      net: dsa: introduce the dsa_cpu_ports() helper
      net: dsa: felix: manage host flooding using a specific driver callback
      net: dsa: remove port argument from ->change_tag_protocol()
      net: dsa: felix: dynamically determine tag_8021q CPU port for traps
      net: dsa: felix: reimplement tagging protocol change with function pointers
      net: mscc: ocelot: delete ocelot_port :: xmit_template
      net: mscc: ocelot: minimize holes in struct ocelot_port
      net: mscc: ocelot: move ocelot_port_private :: chip_port to ocelot_port :: index
      selftests: ocelot: tc_flower_chains: streamline test output
      selftests: ocelot: tc_flower_chains: use conventional interface names
      selftests: ocelot: tc_flower_chains: reorder interfaces
      net: mscc: ocelot: offload tc action "ok" using an empty action vector
      net: dsa: fix missing adjustment of host broadcast flooding
      net: dsa: felix: move the updating of PGID_CPU to the ocelot lib
      net: dsa: felix: update bridge fwd mask from ocelot lib when changing tag_8021q CPU
      net: dsa: felix: directly call ocelot_port_{set,unset}_dsa_8021q_cpu
      net: mscc: ocelot: switch from {,un}set to {,un}assign for tag_8021q CPU ports
      net: dsa: felix: tag_8021q preparation for multiple CPU ports

Volodymyr Mytnyk (2):
      prestera: acl: add action hw_stats support
      net: prestera: add police action support

Wan Jiabing (4):
      ath10k: simplify if-if to if-else
      wil6210: simplify if-if to if-else
      ath9k: hif_usb: simplify if-if to if-else
      ice: use min_t() to make code cleaner in ice_gnss

Wang Qing (2):
      net: ethernet: xilinx: use of_property_read_bool() instead of of_get_property
      net: usb: remove duplicate assignment

Wells Lu (3):
      devicetree: bindings: net: Add bindings doc for Sunplus SP7021.
      net: ethernet: Add driver for Sunplus SP7021
      net: ethernet: Fix unmet direct dependencies detected for NVMEM_SUNPLUS_OCOTP

Wen Gong (16):
      ath11k: remove unused ATH11K_BD_IE_BOARD_EXT
      ath11k: disable regdb support for QCA6390
      ath11k: add support for device recovery for QCA6390/WCN6855
      ath11k: add synchronization operation between reconfigure of mac80211 and ath11k_base
      ath11k: Add hw-restart option to simulate_fw_crash
      ath11k: fix the warning of dev_wake in mhi_pm_disable_transition()
      ath11k: add fallback board name without variant while searching board-2.bin
      ath11k: add read variant from SMBIOS for download board data
      ath11k: store and send country code to firmware after recovery
      ath11k: add support to search regdb data in board-2.bin for WCN6855
      ath11k: reduce the wait time of 11d scan and hw scan while add interface
      ath11k: add support for extended wmi service bit
      ath11k: read country code from SMBIOS for WCN6855/QCA6390
      ath11k: fix warning of not found station for bssid in message
      ath11k: change management tx queue to avoid connection timed out
      ath11k: reset 11d state in process of recovery

Wenli Looi (7):
      ath9k: make ATH_SREV macros more consistent
      ath9k: split set11nRateFlags and set11nChainSel
      ath9k: use AR9300_MAX_CHAINS when appropriate
      ath9k: fix ar9003_get_eepmisc
      ath9k: refactor ar9003_hw_spur_mitigate_ofdm
      ath9k: add functions to get paprd rate mask
      ath9k: make is2ghz consistent in ar9003_eeprom

William Tu (1):
      netfilter: nf_conncount: reduce unnecessary GC

Wojciech Drewek (1):
      ice: return ENOSPC when exceeding ICE_MAX_CHAIN_WORDS

Wolfram Sang (1):
      dt-bindings: can: renesas,rcar-canfd: document r8a77961 support

Xiaomeng Tong (2):
      qed: remove an unneed NULL check on list iterator
      carl9170: tx: fix an incorrect use of list iterator

Xin Long (2):
      dn_route: set rt neigh to blackhole_netdev instead of loopback_dev in ifdown
      Documentation: add description for net.core.gro_normal_batch

Xiu Jianfeng (2):
      octeontx2-pf: Use memset_startat() helper in otx2_stop()
      stcp: Use memset_after() to zero sctp_stream_out_ext

Xu Kuohai (6):
      arm64, insn: Add ldr/str with immediate offset
      bpf, arm64: Optimize BPF store/load using arm64 str/ldr(immediate offset)
      bpf, arm64: Adjust the offset of str/ldr(immediate) to positive number
      bpf, tests: Add tests for BPF_LDX/BPF_STX with different offsets
      bpf, tests: Add load store test case for tail call
      bpf, arm64: Sign return address for JITed code

Yafang Shao (4):
      samples/bpf: Use libbpf 1.0 API mode instead of RLIMIT_MEMLOCK
      selftests/bpf: Use libbpf 1.0 API mode instead of RLIMIT_MEMLOCK
      bpftool: Use libbpf 1.0 API mode instead of RLIMIT_MEMLOCK
      tools/runqslower: Use libbpf 1.0 API mode instead of RLIMIT_MEMLOCK

Yajun Deng (1):
      arp: fix unused variable warnning when CONFIG_PROC_FS=n

Yan Zhu (1):
      bpf: Move BPF sysctls from kernel/sysctl.c to BPF core

Yang Li (4):
      wcn36xx: clean up some inconsistent indenting
      ath9k: Remove unnecessary print function dev_err()
      rtw89: remove unneeded semicolon
      net: ethernet: fix platform_no_drv_owner.cocci warning

Yang Yingliang (6):
      net: ethernet: mtk_eth_soc: fix return value check in mtk_wed_add_hw()
      octeon_ep: fix error return code in octep_probe()
      ath11k: fix missing unlock on error in ath11k_wow_op_resume()
      ethernet: broadcom/sb1250-mac: remove BUG_ON in sbmac_probe()
      net: ethernet: sunplus: add missing of_node_put() in spl2sw_mdio_init()
      net: wwan: t7xx: use GFP_ATOMIC under spin lock in t7xx_cldma_gpd_set_next_ptr()

Yauheni Kaliuta (1):
      bpf, test_offload.py: Skip base maps without names

Ying Hsu (1):
      Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout

Yinjun Zhang (2):
      nfp: flower: utilize the tuple iifidx in offloading ct flows
      nfp: flower: support ct merging when mangle action exists

Yonghong Song (4):
      selftests/bpf: Limit unroll_count for pyperf600 test
      selftests/bpf: Workaround a verifier issue for test exhandler
      selftests/bpf: fix a few clang compilation errors
      selftests/bpf: fix btf_dump/btf_dump due to recent clang change

Yongzhi Liu (1):
      hv_netvsc: Fix potential dereference of NULL pointer

Yosry Ahmed (1):
      selftests/bpf: Fix building bpf selftests statically

Youghandhar Chintala (1):
      ath10k: Trigger sta disconnect on hardware restart

Yu Xiao (2):
      nfp: vendor neutral strings for chip and Corigne in strings for driver
      nfp: support Corigine PCIE vendor ID

Yu Zhe (3):
      bpf: Remove unnecessary type castings
      batman-adv: remove unnecessary type castings
      ipv4: remove unnecessary type castings

Yuchung Cheng (1):
      tcp: improve PRR loss recovery

YueHaibing (3):
      net: ethernet: ti: am65-cpsw: Fix build error without PHYLINK
      ath11k: Fix build warning without CONFIG_IPV6
      net: wwan: t7xx: Fix return type of t7xx_dl_add_timedout()

Yufeng Mo (2):
      net: hns3: add ethtool parameter check for CQE/EQE mode
      net: hns3: remove the affinity settings of vector0

Yuiko Oshino (4):
      net: phy: microchip: update LAN88xx phy ID and phy ID mask.
      net: phy: smsc: add LAN8742 phy support.
      net: phy: microchip: add comments for the modified LAN88xx phy ID mask.
      net: phy: smsc: add comments for the LAN8742 phy ID mask.

Yunbo Yu (2):
      net: cdc-ncm: Move spin_lock_bh() to spin_lock()
      mt76: mt7603: move spin_lock_bh() to spin_lock()

Yuntao Wang (12):
      bpf: Remove redundant assignment to smap->map.value_size
      selftests/bpf: Fix cd_flavor_subdir() of test_progs
      libbpf: Don't return -EINVAL if hdr_len < offsetofend(core_relo_len)
      selftests/bpf: Fix file descriptor leak in load_kallsyms()
      selftests/bpf: Fix issues in parse_num_list()
      selftests/bpf: Fix return value checks in perf_event_stackmap test
      bpf: Fix excessive memory allocation in stack_map_alloc()
      bpf: Remove redundant assignment to meta.seq in __task_seq_show()
      libbpf: Remove unnecessary type cast
      bpf: Remove unused parameter from find_kfunc_desc_btf()
      bpf: Fix potential array overflow in bpf_trampoline_get_progs()
      selftests/bpf: Add missing trampoline program type to trampoline_count test

Zheng Bin (2):
      net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init
      octeon_ep: add missing destroy_workqueue in octep_init_module

Zhengchao Shao (2):
      samples/bpf: Reduce the sampling interval in xdp1_user
      samples/bpf: Detach xdp prog when program exits unexpectedly in xdp_rxq_info_user

Zijun Hu (2):
      Bluetooth: btusb: add support for Qualcomm WCN785x
      Bluetooth: btusb: Set HCI_QUIRK_BROKEN_ERR_DATA_REPORTING for QCA

Ziyang Xuan (2):
      net/mlx5: use kvfree() for kvzalloc() in mlx5_ct_fs_smfs_matcher_create
      octeon_ep: delete unnecessary NULL check

Zong-Zhe Yang (17):
      rtw89: ser: fix CAM leaks occurring in L2 reset
      rtw89: mac: move table of mem base addr to common
      rtw89: mac: correct decision on error status by scenario
      rtw89: ser: control hci interrupts on/off by state
      rtw89: ser: dump memory for fw payload engine while L2 reset
      rtw89: ser: dump fw backtrace while L2 reset
      rtw89: reconstruct fw feature
      rtw89: support FW crash simulation
      rtw89: add UK to regulation type
      rtw89: 8852a: update txpwr tables to HALRF_027_00_038
      rtw89: regd: consider 6G band
      rtw89: regd: update mapping table to R59-R32
      rtw89: ser: fix unannotated fall-through
      rtw89: 8852c: add TX power track tables
      rtw89: 8852c: support bb gain info
      rtw89: 8852c: update txpwr tables to HALRF_027_00_052
      rtw89: convert rtw89_band to nl80211_band precisely

jianghaoran (1):
      ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL

liuyacan (3):
      net/smc: postpone sk_refcnt increment in connect()
      net/smc: fix listen processing for SMC-Rv2
      Revert "net/smc: fix listen processing for SMC-Rv2"

 Documentation/admin-guide/devices.txt              |     2 +-
 Documentation/admin-guide/sysctl/net.rst           |    17 +
 Documentation/bpf/instruction-set.rst              |     4 +-
 Documentation/bpf/libbpf/index.rst                 |     3 +-
 .../arm/mediatek/mediatek,mt7622-pcie-mirror.yaml  |    42 +
 .../bindings/arm/mediatek/mediatek,mt7622-wed.yaml |    50 +
 .../devicetree/bindings/net/adi,adin.yaml          |    15 +
 .../bindings/net/aspeed,ast2600-mdio.yaml          |     6 +
 .../devicetree/bindings/net/can/ctu,ctucanfd.yaml  |    66 +
 .../bindings/net/can/microchip,mcp251xfd.yaml      |    19 +-
 .../bindings/net/can/renesas,rcar-canfd.yaml       |     5 +-
 .../devicetree/bindings/net/cdns,macb.yaml         |     8 -
 .../devicetree/bindings/net/ethernet-phy.yaml      |     9 +
 .../bindings/net/marvell,orion-mdio.yaml           |    60 +
 .../devicetree/bindings/net/marvell-orion-mdio.txt |    54 -
 .../devicetree/bindings/net/mediatek,net.yaml      |   434 +
 .../devicetree/bindings/net/mediatek-net.txt       |    98 -
 Documentation/devicetree/bindings/net/micrel.txt   |     9 +
 .../bindings/net/microchip,lan966x-switch.yaml     |     8 +-
 .../devicetree/bindings/net/mscc,miim.yaml         |    61 +
 .../devicetree/bindings/net/mscc-miim.txt          |    26 -
 .../devicetree/bindings/net/renesas,etheravb.yaml  |    82 +-
 .../bindings/net/sunplus,sp7021-emac.yaml          |   141 +
 .../bindings/net/toshiba,visconti-dwmac.yaml       |     3 +-
 .../bindings/net/wireless/qcom,ath11k.yaml         |   361 +-
 .../{staging => }/net/wireless/silabs,wfx.yaml     |     2 +-
 .../devicetree/bindings/vendor-prefixes.yaml       |     2 +
 .../networking/device_drivers/appletalk/index.rst  |     1 -
 .../networking/device_drivers/appletalk/ltpc.rst   |   144 -
 .../device_drivers/can/ctu/ctucanfd-driver.rst     |   639 +
 .../device_drivers/can/ctu/fsm_txt_buffer_user.svg |   151 +
 .../networking/device_drivers/can/index.rst        |     1 +
 .../device_drivers/ethernet/dec/de4x5.rst          |   189 -
 .../networking/device_drivers/ethernet/index.rst   |     2 +-
 .../device_drivers/ethernet/marvell/octeon_ep.rst  |    35 +
 Documentation/networking/device_drivers/index.rst  |     1 -
 .../networking/device_drivers/wan/index.rst        |    18 -
 .../networking/device_drivers/wan/z8530book.rst    |   256 -
 .../networking/device_drivers/wwan/index.rst       |     1 +
 .../networking/device_drivers/wwan/t7xx.rst        |   120 +
 .../networking/devlink/devlink-linecard.rst        |   122 +
 Documentation/networking/devlink/index.rst         |     1 +
 Documentation/networking/dsa/dsa.rst               |    17 +
 Documentation/networking/ethtool-netlink.rst       |     8 +
 Documentation/networking/index.rst                 |     5 +-
 Documentation/networking/ip-sysctl.rst             |    27 +
 Documentation/networking/mptcp-sysctl.rst          |    18 +
 Documentation/networking/nf_conntrack-sysctl.rst   |     5 +-
 Documentation/networking/skbuff.rst                |    37 +
 MAINTAINERS                                        |    63 +-
 arch/alpha/include/uapi/asm/socket.h               |     2 +
 arch/arm/boot/dts/aspeed-g6.dtsi                   |     4 +
 arch/arm/boot/dts/imx6qdl-sr-som.dtsi              |    10 +
 .../boot/dts/marvell/armada-3720-turris-mox.dts    |    12 +-
 arch/arm64/boot/dts/mediatek/mt7622.dtsi           |    32 +-
 arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts       |    74 +
 arch/arm64/boot/dts/mediatek/mt7986a.dtsi          |    39 +
 arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts       |    70 +
 arch/arm64/include/asm/insn.h                      |     9 +
 arch/arm64/lib/insn.c                              |    67 +-
 arch/arm64/net/bpf_jit.h                           |    17 +
 arch/arm64/net/bpf_jit_comp.c                      |   255 +-
 arch/mips/configs/gpr_defconfig                    |     5 -
 arch/mips/configs/mtx1_defconfig                   |     6 -
 arch/mips/include/uapi/asm/socket.h                |     2 +
 arch/parisc/include/uapi/asm/socket.h              |     2 +
 arch/powerpc/configs/chrp32_defconfig              |     1 -
 arch/powerpc/configs/ppc6xx_defconfig              |     1 -
 arch/riscv/net/bpf_jit.h                           |    67 +
 arch/riscv/net/bpf_jit_comp64.c                    |   110 +-
 arch/s390/net/bpf_jit_comp.c                       |     2 +-
 arch/sparc/include/uapi/asm/socket.h               |     1 +
 arch/um/drivers/vector_kern.c                      |     3 +-
 arch/x86/include/asm/text-patching.h               |     1 +
 arch/x86/kernel/alternative.c                      |    67 +-
 arch/x86/net/bpf_jit_comp.c                        |    79 +-
 drivers/atm/Kconfig                                |    79 -
 drivers/atm/Makefile                               |     4 -
 drivers/atm/ambassador.c                           |  2400 ---
 drivers/atm/ambassador.h                           |   648 -
 drivers/atm/firestream.c                           |  2057 --
 drivers/atm/firestream.h                           |   502 -
 drivers/atm/horizon.c                              |  2853 ---
 drivers/atm/horizon.h                              |   492 -
 drivers/atm/nicstarmac.c                           |     5 -
 drivers/atm/uPD98401.h                             |   293 -
 drivers/atm/uPD98402.c                             |   266 -
 drivers/atm/uPD98402.h                             |   107 -
 drivers/atm/zatm.c                                 |  1652 --
 drivers/atm/zatm.h                                 |   104 -
 drivers/bcma/driver_gpio.c                         |     7 +-
 drivers/bluetooth/btbcm.c                          |    53 +-
 drivers/bluetooth/btintel.c                        |     2 +-
 drivers/bluetooth/btmtksdio.c                      |    26 +-
 drivers/bluetooth/btrtl.c                          |    13 +
 drivers/bluetooth/btusb.c                          |    23 +-
 drivers/bluetooth/hci_qca.c                        |     4 +-
 drivers/firmware/broadcom/tee_bnxt_fw.c            |     2 +-
 drivers/infiniband/core/device.c                   |     2 -
 .../infiniband/core/uverbs_std_types_flow_action.c |   383 +-
 drivers/infiniband/hw/mlx5/fs.c                    |   223 +-
 drivers/infiniband/hw/mlx5/gsi.c                   |     2 +-
 drivers/infiniband/hw/mlx5/main.c                  |    32 +-
 drivers/infiniband/hw/mlx5/mlx5_ib.h               |     1 +
 drivers/infiniband/hw/mlx5/qp.c                    |     2 +-
 drivers/isdn/mISDN/socket.c                        |     2 +-
 drivers/media/rc/bpf-lirc.c                        |     8 +-
 drivers/net/Space.c                                |     3 -
 drivers/net/amt.c                                  |    11 +-
 drivers/net/appletalk/Kconfig                      |    11 -
 drivers/net/appletalk/Makefile                     |     1 -
 drivers/net/appletalk/ltpc.c                       |  1277 --
 drivers/net/appletalk/ltpc.h                       |    74 -
 drivers/net/bonding/bond_main.c                    |    29 +-
 drivers/net/caif/caif_virtio.c                     |     3 +-
 drivers/net/can/Kconfig                            |    18 +-
 drivers/net/can/Makefile                           |     1 +
 drivers/net/can/at91_can.c                         |    12 +-
 drivers/net/can/c_can/c_can_main.c                 |    19 +-
 drivers/net/can/ctucanfd/Kconfig                   |    34 +
 drivers/net/can/ctucanfd/Makefile                  |    10 +
 drivers/net/can/ctucanfd/ctucanfd.h                |    82 +
 drivers/net/can/ctucanfd/ctucanfd_base.c           |  1452 ++
 drivers/net/can/ctucanfd/ctucanfd_kframe.h         |    77 +
 drivers/net/can/ctucanfd/ctucanfd_kregs.h          |   325 +
 drivers/net/can/ctucanfd/ctucanfd_pci.c            |   294 +
 drivers/net/can/ctucanfd/ctucanfd_platform.c       |   131 +
 drivers/net/can/dev/Makefile                       |     2 -
 drivers/net/can/dev/bittiming.c                    |     2 +-
 drivers/net/can/dev/dev.c                          |     5 -
 drivers/net/can/dev/rx-offload.c                   |    11 +-
 drivers/net/can/flexcan/flexcan-core.c             |    23 +-
 drivers/net/can/grcan.c                            |     2 +-
 drivers/net/can/ifi_canfd/ifi_canfd.c              |     9 -
 drivers/net/can/janz-ican3.c                       |     2 +-
 drivers/net/can/led.c                              |   140 -
 drivers/net/can/m_can/m_can.c                      |    22 +-
 drivers/net/can/m_can/m_can.h                      |     1 -
 drivers/net/can/mscan/mpc5xxx_can.c                |     2 +
 drivers/net/can/mscan/mscan.c                      |     2 +-
 drivers/net/can/pch_can.c                          |     2 +-
 drivers/net/can/rcar/rcar_can.c                    |    12 +-
 drivers/net/can/rcar/rcar_canfd.c                  |    11 +-
 drivers/net/can/sja1000/Kconfig                    |     2 +-
 drivers/net/can/sja1000/sja1000.c                  |    11 -
 drivers/net/can/sja1000/tscan1.c                   |     7 +-
 drivers/net/can/slcan.c                            |     4 +-
 drivers/net/can/spi/hi311x.c                       |     8 -
 drivers/net/can/spi/mcp251x.c                      |    10 -
 drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c     |    25 +-
 drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c       |     2 +-
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h          |    14 +-
 drivers/net/can/sun4i_can.c                        |     7 -
 drivers/net/can/ti_hecc.c                          |    12 +-
 drivers/net/can/usb/kvaser_usb/Makefile            |     5 +
 drivers/net/can/usb/mcba_usb.c                     |     8 -
 drivers/net/can/usb/peak_usb/pcan_usb.c            |     2 +-
 drivers/net/can/usb/usb_8dev.c                     |    11 -
 drivers/net/can/xilinx_can.c                       |    16 +-
 drivers/net/dsa/Kconfig                            |     3 +-
 drivers/net/dsa/lantiq_gswip.c                     |     9 +-
 drivers/net/dsa/microchip/ksz8795.c                |   287 +-
 drivers/net/dsa/microchip/ksz8795_reg.h            |     3 -
 drivers/net/dsa/microchip/ksz8795_spi.c            |    35 +-
 drivers/net/dsa/microchip/ksz8863_smi.c            |    10 +-
 drivers/net/dsa/microchip/ksz9477.c                |   331 +-
 drivers/net/dsa/microchip/ksz9477_i2c.c            |    30 +-
 drivers/net/dsa/microchip/ksz9477_reg.h            |     4 -
 drivers/net/dsa/microchip/ksz9477_spi.c            |    30 +-
 drivers/net/dsa/microchip/ksz_common.c             |   621 +-
 drivers/net/dsa/microchip/ksz_common.h             |    89 +-
 drivers/net/dsa/mt7530.c                           |   332 +-
 drivers/net/dsa/mt7530.h                           |    26 +-
 drivers/net/dsa/mv88e6xxx/chip.c                   |    78 +-
 drivers/net/dsa/ocelot/felix.c                     |   695 +-
 drivers/net/dsa/ocelot/felix.h                     |    18 +-
 drivers/net/dsa/ocelot/felix_vsc9959.c             |     7 +-
 drivers/net/dsa/ocelot/seville_vsc9953.c           |     6 +-
 drivers/net/dsa/qca8k.c                            |   145 +-
 drivers/net/dsa/qca8k.h                            |    12 +-
 drivers/net/dsa/realtek/rtl8365mb.c                |     2 +-
 drivers/net/dsa/realtek/rtl8366rb.c                |    37 +-
 drivers/net/dsa/sja1105/sja1105_main.c             |     5 +-
 drivers/net/eql.c                                  |     3 +-
 drivers/net/ethernet/3com/typhoon.c                |     2 +-
 drivers/net/ethernet/Kconfig                       |     1 +
 drivers/net/ethernet/Makefile                      |     1 +
 drivers/net/ethernet/adaptec/starfire.c            |     2 +-
 drivers/net/ethernet/alacritech/slic.h             |     2 -
 drivers/net/ethernet/alacritech/slicoss.c          |     2 +-
 drivers/net/ethernet/amazon/ena/ena_netdev.c       |     4 +-
 drivers/net/ethernet/amd/Kconfig                   |    10 -
 drivers/net/ethernet/amd/Makefile                  |     1 -
 drivers/net/ethernet/amd/amd8111e.c                |     2 +-
 drivers/net/ethernet/amd/ni65.c                    |  1251 --
 drivers/net/ethernet/amd/ni65.h                    |   121 -
 drivers/net/ethernet/amd/pcnet32.c                 |     3 +-
 drivers/net/ethernet/amd/xgbe/xgbe.h               |     3 +-
 drivers/net/ethernet/apple/bmac.c                  |     1 -
 drivers/net/ethernet/apple/mace.c                  |     1 -
 drivers/net/ethernet/aquantia/atlantic/aq_cfg.h    |     3 +-
 .../net/ethernet/aquantia/atlantic/aq_ethtool.c    |     9 +
 drivers/net/ethernet/aquantia/atlantic/aq_main.c   |    87 +
 drivers/net/ethernet/aquantia/atlantic/aq_main.h   |     2 +
 drivers/net/ethernet/aquantia/atlantic/aq_nic.c    |   136 +
 drivers/net/ethernet/aquantia/atlantic/aq_nic.h    |     5 +
 drivers/net/ethernet/aquantia/atlantic/aq_ptp.c    |     2 +-
 drivers/net/ethernet/aquantia/atlantic/aq_ring.c   |   409 +-
 drivers/net/ethernet/aquantia/atlantic/aq_ring.h   |    21 +-
 drivers/net/ethernet/aquantia/atlantic/aq_vec.c    |    25 +-
 drivers/net/ethernet/aquantia/atlantic/aq_vec.h    |     6 +
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c  |     6 +-
 .../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c  |    10 +-
 drivers/net/ethernet/arc/emac_main.c               |     3 +-
 drivers/net/ethernet/atheros/ag71xx.c              |     3 +-
 drivers/net/ethernet/atheros/atl1e/atl1e_main.c    |     2 +-
 drivers/net/ethernet/broadcom/Makefile             |     5 +
 drivers/net/ethernet/broadcom/bcm4908_enet.c       |     2 +-
 drivers/net/ethernet/broadcom/bcm63xx_enet.c       |     4 +-
 drivers/net/ethernet/broadcom/bcmsysport.c         |     2 +-
 drivers/net/ethernet/broadcom/bgmac.c              |     2 +-
 drivers/net/ethernet/broadcom/bgmac.h              |     2 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h    |    10 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c          |   313 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.h          |    18 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c  |     2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c  |    86 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h  |     2 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h      |   415 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c      |    80 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h      |     2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c      |    12 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h      |    12 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c      |   191 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h      |    16 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet.c     |     3 +-
 drivers/net/ethernet/broadcom/sb1250-mac.c         |     9 +-
 drivers/net/ethernet/brocade/bna/bnad.c            |     3 +-
 drivers/net/ethernet/cadence/macb.h                |     6 +-
 drivers/net/ethernet/cadence/macb_main.c           |   353 +-
 drivers/net/ethernet/cadence/macb_ptp.c            |     4 +-
 drivers/net/ethernet/calxeda/xgmac.c               |     2 +-
 drivers/net/ethernet/cavium/liquidio/lio_main.c    |     2 +-
 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c |     2 +-
 drivers/net/ethernet/cavium/thunder/nicvf_main.c   |     3 -
 .../chelsio/inline_crypto/ch_ktls/chcr_ktls.c      |     2 +-
 .../ethernet/chelsio/inline_crypto/chtls/chtls.h   |     2 +-
 .../chelsio/inline_crypto/chtls/chtls_io.c         |    22 +-
 drivers/net/ethernet/cirrus/cs89x0.c               |     2 +-
 drivers/net/ethernet/cortina/gemini.c              |     4 +-
 drivers/net/ethernet/dec/tulip/Kconfig             |    15 -
 drivers/net/ethernet/dec/tulip/Makefile            |     1 -
 drivers/net/ethernet/dec/tulip/de4x5.c             |  5591 ------
 drivers/net/ethernet/dec/tulip/de4x5.h             |  1017 -
 drivers/net/ethernet/dec/tulip/eeprom.c            |     7 +-
 drivers/net/ethernet/dec/tulip/tulip_core.c        |    66 +-
 drivers/net/ethernet/dec/tulip/winbond-840.c       |     2 -
 drivers/net/ethernet/emulex/benet/be.h             |     3 +-
 drivers/net/ethernet/emulex/benet/be_main.c        |     4 +-
 drivers/net/ethernet/engleder/tsnep_hw.h           |     9 +-
 drivers/net/ethernet/engleder/tsnep_main.c         |    36 +-
 drivers/net/ethernet/engleder/tsnep_ptp.c          |    28 +
 drivers/net/ethernet/ezchip/nps_enet.c             |     4 +-
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c   |    12 +-
 drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c   |     3 -
 drivers/net/ethernet/freescale/enetc/enetc.c       |    13 +-
 drivers/net/ethernet/freescale/enetc/enetc.h       |     2 +
 .../net/ethernet/freescale/enetc/enetc_ethtool.c   |     2 +
 drivers/net/ethernet/freescale/enetc/enetc_hw.h    |     1 +
 drivers/net/ethernet/freescale/enetc/enetc_pf.c    |    30 +-
 drivers/net/ethernet/freescale/enetc/enetc_qos.c   |     6 +
 drivers/net/ethernet/freescale/fec_main.c          |    20 +-
 drivers/net/ethernet/freescale/fec_mpc52xx.c       |     2 +
 drivers/net/ethernet/freescale/fec_mpc52xx_phy.c   |     1 +
 .../net/ethernet/freescale/fs_enet/fs_enet-main.c  |     3 +-
 drivers/net/ethernet/freescale/gianfar.c           |     6 +-
 drivers/net/ethernet/freescale/gianfar.h           |     3 -
 .../net/ethernet/fungible/funeth/funeth_devlink.c  |     8 +-
 drivers/net/ethernet/fungible/funeth/funeth_main.c |     3 +-
 drivers/net/ethernet/hisilicon/hisi_femac.c        |     3 +-
 drivers/net/ethernet/hisilicon/hns/hns_enet.c      |     4 +-
 drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h    |    73 +-
 drivers/net/ethernet/hisilicon/hns3/hnae3.h        |     4 +
 .../hisilicon/hns3/hns3_common/hclge_comm_cmd.c    |     2 +
 .../hisilicon/hns3/hns3_common/hclge_comm_cmd.h    |     1 +
 .../hisilicon/hns3/hns3_common/hclge_comm_rss.h    |     2 +-
 drivers/net/ethernet/hisilicon/hns3/hns3_enet.c    |     5 +-
 drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c |   144 +-
 drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.h |     6 +
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c |     2 +-
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    |    30 +-
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.h    |     6 +-
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c |   195 +-
 .../ethernet/hisilicon/hns3/hns3pf/hclge_trace.h   |     2 +-
 .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c  |    62 +-
 .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h  |     2 +-
 .../ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c   |    88 +-
 .../ethernet/hisilicon/hns3/hns3vf/hclgevf_trace.h |     2 +-
 drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c  |     2 +
 drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c    |     2 +-
 drivers/net/ethernet/huawei/hinic/hinic_rx.c       |     3 +-
 drivers/net/ethernet/huawei/hinic/hinic_tx.c       |     3 +-
 drivers/net/ethernet/ibm/ehea/ehea.h               |     1 +
 drivers/net/ethernet/ibm/ehea/ehea_main.c          |     2 +
 drivers/net/ethernet/ibm/emac/mal.c                |     4 +-
 drivers/net/ethernet/ibm/ibmveth.c                 |     2 +-
 drivers/net/ethernet/ibm/ibmvnic.c                 |   311 +-
 drivers/net/ethernet/ibm/ibmvnic.h                 |    54 +-
 drivers/net/ethernet/intel/e100.c                  |     2 +-
 drivers/net/ethernet/intel/i40e/i40e.h             |     1 +
 drivers/net/ethernet/intel/i40e/i40e_common.c      |     1 +
 drivers/net/ethernet/intel/i40e/i40e_debugfs.c     |     5 +-
 drivers/net/ethernet/intel/i40e/i40e_devids.h      |     1 +
 drivers/net/ethernet/intel/i40e/i40e_ethtool.c     |     2 +
 drivers/net/ethernet/intel/i40e/i40e_main.c        |    25 +-
 drivers/net/ethernet/intel/i40e/i40e_txrx.c        |    49 +-
 drivers/net/ethernet/intel/i40e/i40e_txrx.h        |     1 +
 drivers/net/ethernet/intel/i40e/i40e_txrx_common.h |     1 +
 drivers/net/ethernet/intel/i40e/i40e_xsk.c         |    39 +-
 drivers/net/ethernet/intel/ice/Makefile            |     5 +
 drivers/net/ethernet/intel/ice/ice.h               |    15 +
 drivers/net/ethernet/intel/ice/ice_devlink.c       |    27 +-
 drivers/net/ethernet/intel/ice/ice_ethtool.c       |    77 +-
 drivers/net/ethernet/intel/ice/ice_gnss.c          |     3 +-
 drivers/net/ethernet/intel/ice/ice_idc.c           |    15 -
 drivers/net/ethernet/intel/ice/ice_main.c          |    22 +-
 drivers/net/ethernet/intel/ice/ice_repr.c          |     8 +-
 drivers/net/ethernet/intel/ice/ice_sriov.c         |    32 +-
 drivers/net/ethernet/intel/ice/ice_switch.c        |   494 +-
 drivers/net/ethernet/intel/ice/ice_switch.h        |    12 +-
 drivers/net/ethernet/intel/ice/ice_tc_lib.c        |     1 -
 drivers/net/ethernet/intel/ice/ice_txrx.c          |    29 +-
 drivers/net/ethernet/intel/ice/ice_txrx.h          |     1 +
 drivers/net/ethernet/intel/ice/ice_vf_lib.c        |    43 +-
 drivers/net/ethernet/intel/ice/ice_vf_lib.h        |     4 +-
 drivers/net/ethernet/intel/ice/ice_virtchnl.c      |    27 +-
 drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c |     9 +-
 drivers/net/ethernet/intel/ice/ice_xsk.c           |    53 +-
 drivers/net/ethernet/intel/igb/igb_ethtool.c       |     4 +-
 drivers/net/ethernet/intel/igc/igc.h               |     1 -
 drivers/net/ethernet/intel/igc/igc_base.c          |     2 -
 drivers/net/ethernet/intel/igc/igc_hw.h            |     7 -
 drivers/net/ethernet/intel/igc/igc_main.c          |    50 -
 drivers/net/ethernet/intel/igc/igc_phy.c           |    16 +-
 drivers/net/ethernet/intel/igc/igc_phy.h           |     2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c     |     9 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h     |     2 +-
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |   107 +-
 .../net/ethernet/intel/ixgbe/ixgbe_txrx_common.h   |     1 +
 drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c       |    53 +-
 drivers/net/ethernet/intel/ixgbevf/ipsec.c         |     6 +-
 drivers/net/ethernet/intel/ixgbevf/ipsec.h         |     2 +-
 drivers/net/ethernet/jme.c                         |     2 +-
 drivers/net/ethernet/jme.h                         |     2 -
 drivers/net/ethernet/lantiq_etop.c                 |     8 +-
 drivers/net/ethernet/lantiq_xrx200.c               |     4 +-
 drivers/net/ethernet/marvell/Kconfig               |     2 +
 drivers/net/ethernet/marvell/Makefile              |     1 +
 drivers/net/ethernet/marvell/mv643xx_eth.c         |     2 +-
 drivers/net/ethernet/marvell/mvneta.c              |    22 +-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c    |     4 +-
 drivers/net/ethernet/marvell/octeon_ep/Kconfig     |    20 +
 drivers/net/ethernet/marvell/octeon_ep/Makefile    |     9 +
 .../net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c |   737 +
 .../net/ethernet/marvell/octeon_ep/octep_config.h  |   204 +
 .../ethernet/marvell/octeon_ep/octep_ctrl_mbox.c   |   245 +
 .../ethernet/marvell/octeon_ep/octep_ctrl_mbox.h   |   170 +
 .../ethernet/marvell/octeon_ep/octep_ctrl_net.c    |   194 +
 .../ethernet/marvell/octeon_ep/octep_ctrl_net.h    |   299 +
 .../net/ethernet/marvell/octeon_ep/octep_ethtool.c |   463 +
 .../net/ethernet/marvell/octeon_ep/octep_main.c    |  1181 ++
 .../net/ethernet/marvell/octeon_ep/octep_main.h    |   357 +
 .../marvell/octeon_ep/octep_regs_cn9k_pf.h         |   367 +
 drivers/net/ethernet/marvell/octeon_ep/octep_rx.c  |   507 +
 drivers/net/ethernet/marvell/octeon_ep/octep_rx.h  |   199 +
 drivers/net/ethernet/marvell/octeon_ep/octep_tx.c  |   334 +
 drivers/net/ethernet/marvell/octeon_ep/octep_tx.h  |   284 +
 drivers/net/ethernet/marvell/octeontx2/Kconfig     |     1 +
 .../ethernet/marvell/octeontx2/af/rvu_debugfs.c    |     4 +-
 .../ethernet/marvell/octeontx2/nic/otx2_common.c   |     5 -
 .../ethernet/marvell/octeontx2/nic/otx2_common.h   |    10 +
 .../ethernet/marvell/octeontx2/nic/otx2_ethtool.c  |    45 +-
 .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c   |    29 +-
 .../net/ethernet/marvell/octeontx2/nic/otx2_txrx.c |    23 +
 .../net/ethernet/marvell/octeontx2/nic/otx2_txrx.h |     1 +
 .../net/ethernet/marvell/octeontx2/nic/otx2_vf.c   |     2 +-
 .../net/ethernet/marvell/prestera/prestera_acl.c   |    42 +-
 .../net/ethernet/marvell/prestera/prestera_acl.h   |    12 +
 .../ethernet/marvell/prestera/prestera_flower.c    |    28 +
 .../net/ethernet/marvell/prestera/prestera_hw.c    |    81 +
 .../net/ethernet/marvell/prestera/prestera_hw.h    |    13 +
 .../ethernet/marvell/prestera/prestera_router.c    |    11 +-
 .../net/ethernet/marvell/prestera/prestera_rxtx.c  |     2 +-
 drivers/net/ethernet/marvell/pxa168_eth.c          |     3 +-
 drivers/net/ethernet/marvell/skge.c                |     3 +-
 drivers/net/ethernet/marvell/sky2.c                |     3 +-
 drivers/net/ethernet/mediatek/Kconfig              |     4 +
 drivers/net/ethernet/mediatek/Makefile             |    10 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.c        |  1062 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h        |   360 +-
 drivers/net/ethernet/mediatek/mtk_ppe.c            |   369 +-
 drivers/net/ethernet/mediatek/mtk_ppe.h            |    89 +-
 drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c    |     1 -
 drivers/net/ethernet/mediatek/mtk_ppe_offload.c    |   191 +-
 drivers/net/ethernet/mediatek/mtk_sgmii.c          |   176 +-
 drivers/net/ethernet/mediatek/mtk_star_emac.c      |     3 +-
 drivers/net/ethernet/mediatek/mtk_wed.c            |   880 +
 drivers/net/ethernet/mediatek/mtk_wed.h            |   135 +
 drivers/net/ethernet/mediatek/mtk_wed_debugfs.c    |   175 +
 drivers/net/ethernet/mediatek/mtk_wed_ops.c        |     8 +
 drivers/net/ethernet/mediatek/mtk_wed_regs.h       |   251 +
 drivers/net/ethernet/mellanox/mlx4/en_cq.c         |     3 +-
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c     |     3 +
 drivers/net/ethernet/mellanox/mlx4/en_tx.c         |    47 +-
 drivers/net/ethernet/mellanox/mlx5/core/Kconfig    |    58 +-
 drivers/net/ethernet/mellanox/mlx5/core/Makefile   |    16 +-
 .../net/ethernet/mellanox/mlx5/core/accel/accel.h  |    36 -
 .../net/ethernet/mellanox/mlx5/core/accel/ipsec.c  |   179 -
 .../net/ethernet/mellanox/mlx5/core/accel/ipsec.h  |    96 -
 .../mellanox/mlx5/core/accel/ipsec_offload.c       |   385 -
 .../mellanox/mlx5/core/accel/ipsec_offload.h       |    38 -
 .../net/ethernet/mellanox/mlx5/core/accel/tls.c    |   125 -
 .../net/ethernet/mellanox/mlx5/core/accel/tls.h    |   156 -
 drivers/net/ethernet/mellanox/mlx5/core/alloc.c    |     6 -
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c      |     7 +-
 drivers/net/ethernet/mellanox/mlx5/core/debugfs.c  |     2 +
 drivers/net/ethernet/mellanox/mlx5/core/dev.c      |    49 +-
 drivers/net/ethernet/mellanox/mlx5/core/devlink.c  |    24 +-
 .../mellanox/mlx5/core/diag/fs_tracepoint.c        |     3 +
 drivers/net/ethernet/mellanox/mlx5/core/en.h       |     6 +-
 drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h |     2 -
 drivers/net/ethernet/mellanox/mlx5/core/en/fs.h    |     1 -
 .../net/ethernet/mellanox/mlx5/core/en/params.c    |    22 +-
 .../ethernet/mellanox/mlx5/core/en/tc/act/mirred.c |    14 +
 .../ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c |     2 +-
 .../net/ethernet/mellanox/mlx5/core/en/tc/sample.c |     1 +
 drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c |    53 +-
 .../net/ethernet/mellanox/mlx5/core/en/xsk/rx.c    |     6 -
 .../net/ethernet/mellanox/mlx5/core/en/xsk/rx.h    |     1 -
 .../net/ethernet/mellanox/mlx5/core/en/xsk/tx.c    |     2 +-
 .../mellanox/mlx5/core/en_accel/en_accel.h         |    11 +-
 .../ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c  |     2 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c   |   204 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h   |   110 +-
 .../mellanox/mlx5/core/en_accel/ipsec_fs.c         |   365 +-
 .../mellanox/mlx5/core/en_accel/ipsec_fs.h         |    11 +-
 .../mellanox/mlx5/core/en_accel/ipsec_offload.c    |   205 +
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.c       |   249 +-
 .../mellanox/mlx5/core/en_accel/ipsec_rxtx.h       |     3 -
 .../mellanox/mlx5/core/en_accel/ipsec_stats.c      |    65 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ktls.c    |    71 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ktls.h    |    86 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c |     2 +-
 .../core/en_accel/{tls_stats.c => ktls_stats.c}    |    51 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c |    20 +-
 .../mellanox/mlx5/core/en_accel/ktls_txrx.h        |    28 +-
 .../mellanox/mlx5/core/en_accel/ktls_utils.h       |     1 -
 .../net/ethernet/mellanox/mlx5/core/en_accel/tls.c |   247 -
 .../net/ethernet/mellanox/mlx5/core/en_accel/tls.h |   132 -
 .../mellanox/mlx5/core/en_accel/tls_rxtx.c         |   390 -
 .../mellanox/mlx5/core/en_accel/tls_rxtx.h         |    91 -
 .../net/ethernet/mellanox/mlx5/core/en_common.c    |     5 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c |     9 -
 drivers/net/ethernet/mellanox/mlx5/core/en_fs.c    |     4 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c  |    35 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_rep.c   |    36 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_rx.c    |    79 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_stats.c |     9 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_stats.h |     1 -
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    |    28 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.h    |     7 +
 drivers/net/ethernet/mellanox/mlx5/core/en_tx.c    |   105 +-
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |    28 +-
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.h  |     8 -
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c |     3 +
 .../net/ethernet/mellanox/mlx5/core/fpga/core.h    |     3 -
 .../net/ethernet/mellanox/mlx5/core/fpga/ipsec.c   |  1582 --
 .../net/ethernet/mellanox/mlx5/core/fpga/ipsec.h   |    62 -
 drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c |   622 -
 drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.h |    74 -
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c   |    20 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |    61 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.h  |     1 +
 drivers/net/ethernet/mellanox/mlx5/core/fw.c       |     3 +-
 drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c |     2 +-
 .../ethernet/mellanox/mlx5/core/ipoib/ethtool.c    |    14 +-
 .../net/ethernet/mellanox/mlx5/core/lag/debugfs.c  |   174 +
 drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c  |   681 +-
 drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h  |    55 +-
 drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c   |     4 +-
 .../net/ethernet/mellanox/mlx5/core/lag/mpesw.c    |   101 +
 .../net/ethernet/mellanox/mlx5/core/lag/mpesw.h    |    26 +
 .../net/ethernet/mellanox/mlx5/core/lag/port_sel.c |   129 +-
 .../net/ethernet/mellanox/mlx5/core/lag/port_sel.h |    15 +-
 .../net/ethernet/mellanox/mlx5/core/lib/devcom.c   |    16 +-
 .../net/ethernet/mellanox/mlx5/core/lib/devcom.h   |     2 +
 drivers/net/ethernet/mellanox/mlx5/core/lib/tout.c |     1 +
 drivers/net/ethernet/mellanox/mlx5/core/lib/tout.h |     1 +
 drivers/net/ethernet/mellanox/mlx5/core/main.c     |    67 +-
 .../net/ethernet/mellanox/mlx5/core/mlx5_core.h    |     3 +-
 drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c  |     8 +-
 .../ethernet/mellanox/mlx5/core/steering/dr_cmd.c  |    21 +-
 drivers/net/ethernet/mellanox/mlx5/core/vport.c    |    52 +-
 .../net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h  |     3 -
 .../mellanox/mlxbf_gige/mlxbf_gige_ethtool.c       |     8 +-
 .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_intr.c |     9 -
 .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c |     2 +-
 .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c |     6 +-
 drivers/net/ethernet/mellanox/mlxsw/Makefile       |     3 +-
 drivers/net/ethernet/mellanox/mlxsw/core.c         |    58 +-
 drivers/net/ethernet/mellanox/mlxsw/core.h         |    79 +-
 drivers/net/ethernet/mellanox/mlxsw/core_env.c     |   681 +-
 drivers/net/ethernet/mellanox/mlxsw/core_env.h     |    47 +-
 drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c   |   311 +-
 .../net/ethernet/mellanox/mlxsw/core_linecards.c   |  1142 ++
 drivers/net/ethernet/mellanox/mlxsw/core_thermal.c |   250 +-
 drivers/net/ethernet/mellanox/mlxsw/minimal.c      |    39 +-
 drivers/net/ethernet/mellanox/mlxsw/reg.h          |   465 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |   348 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     |    27 +-
 .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c    |     5 +-
 .../net/ethernet/mellanox/mlxsw/spectrum_buffers.c |    26 +
 drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c |    13 -
 .../net/ethernet/mellanox/mlxsw/spectrum_ethtool.c |    35 +-
 .../net/ethernet/mellanox/mlxsw/spectrum_router.c  |   201 +-
 .../net/ethernet/mellanox/mlxsw/spectrum_router.h  |     2 +
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |    31 +-
 .../net/ethernet/mellanox/mlxsw/spectrum_trap.c    |     2 +-
 drivers/net/ethernet/mellanox/mlxsw/trap.h         |     6 +
 drivers/net/ethernet/microchip/lan743x_main.c      |     6 +-
 drivers/net/ethernet/microchip/lan966x/Makefile    |     2 +-
 .../net/ethernet/microchip/lan966x/lan966x_fdma.c  |   842 +
 .../net/ethernet/microchip/lan966x/lan966x_main.c  |    84 +-
 .../net/ethernet/microchip/lan966x/lan966x_main.h  |   121 +
 .../net/ethernet/microchip/lan966x/lan966x_port.c  |     3 +
 .../net/ethernet/microchip/lan966x/lan966x_ptp.c   |   276 +-
 .../net/ethernet/microchip/lan966x/lan966x_regs.h  |   146 +
 .../net/ethernet/microchip/sparx5/sparx5_fdma.c    |     3 +-
 .../net/ethernet/microchip/sparx5/sparx5_port.c    |     2 +-
 .../ethernet/microchip/sparx5/sparx5_switchdev.c   |    12 +
 drivers/net/ethernet/microsoft/mana/mana_en.c      |     4 +-
 drivers/net/ethernet/moxa/moxart_ether.c           |     2 +-
 drivers/net/ethernet/mscc/ocelot.c                 |   244 +-
 drivers/net/ethernet/mscc/ocelot.h                 |     1 -
 drivers/net/ethernet/mscc/ocelot_fdma.c            |     4 +-
 drivers/net/ethernet/mscc/ocelot_flower.c          |    16 +
 drivers/net/ethernet/mscc/ocelot_net.c             |    79 +-
 drivers/net/ethernet/mscc/ocelot_police.c          |    26 +-
 drivers/net/ethernet/mscc/ocelot_police.h          |     2 +-
 drivers/net/ethernet/mscc/ocelot_vcap.c            |    42 +-
 drivers/net/ethernet/mscc/ocelot_vsc7514.c         |     2 +-
 drivers/net/ethernet/myricom/myri10ge/myri10ge.c   |     6 +-
 drivers/net/ethernet/natsemi/natsemi.c             |     2 -
 drivers/net/ethernet/neterion/vxge/vxge-main.c     |    13 +-
 drivers/net/ethernet/neterion/vxge/vxge-main.h     |     2 -
 drivers/net/ethernet/netronome/nfp/crypto/tls.c    |     2 +-
 drivers/net/ethernet/netronome/nfp/flower/action.c |     3 +-
 .../net/ethernet/netronome/nfp/flower/conntrack.c  |   268 +-
 .../net/ethernet/netronome/nfp/flower/lag_conf.c   |     2 +-
 drivers/net/ethernet/netronome/nfp/flower/main.h   |   110 +-
 drivers/net/ethernet/netronome/nfp/flower/match.c  |    51 +-
 .../net/ethernet/netronome/nfp/flower/metadata.c   |    19 +-
 .../net/ethernet/netronome/nfp/flower/offload.c    |    86 +-
 .../ethernet/netronome/nfp/flower/tunnel_conf.c    |   515 +-
 drivers/net/ethernet/netronome/nfp/nfp_main.c      |    38 +-
 .../net/ethernet/netronome/nfp/nfp_net_common.c    |    13 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_repr.c  |     5 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_sriov.c |    91 +-
 drivers/net/ethernet/netronome/nfp/nfp_net_sriov.h |    12 +
 .../net/ethernet/netronome/nfp/nfp_netvf_main.c    |    12 +-
 .../ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c  |    18 +-
 .../net/ethernet/netronome/nfp/nfpcore/nfp_cpp.h   |    26 +-
 .../net/ethernet/netronome/nfp/nfpcore/nfp_dev.h   |     8 +
 drivers/net/ethernet/nvidia/forcedeth.c            |     6 +-
 drivers/net/ethernet/nxp/lpc_eth.c                 |     2 +-
 .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |    12 +-
 drivers/net/ethernet/qlogic/qed/Makefile           |     3 +-
 drivers/net/ethernet/qlogic/qed/qed_dbg_hsi.h      |     2 +-
 drivers/net/ethernet/qlogic/qed/qed_main.c         |     1 -
 .../ethernet/qlogic/qed/qed_nvmetcp_ip_services.c  |   238 -
 drivers/net/ethernet/qlogic/qed/qed_vf.h           |     2 +-
 drivers/net/ethernet/qlogic/qede/qede_main.c       |     1 -
 drivers/net/ethernet/qlogic/qede/qede_ptp.c        |    10 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c     |     9 +-
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |     3 +-
 drivers/net/ethernet/realtek/8139cp.c              |     2 +-
 drivers/net/ethernet/realtek/atp.h                 |     4 -
 drivers/net/ethernet/realtek/r8169_main.c          |     8 +-
 drivers/net/ethernet/renesas/ravb.h                |     6 +
 drivers/net/ethernet/renesas/ravb_main.c           |   109 +-
 drivers/net/ethernet/renesas/ravb_ptp.c            |     6 +-
 drivers/net/ethernet/rocker/rocker_main.c          |     3 +-
 drivers/net/ethernet/sfc/Kconfig                   |    15 +-
 drivers/net/ethernet/sfc/Makefile                  |     5 +-
 drivers/net/ethernet/sfc/ef10.c                    |     2 +-
 drivers/net/ethernet/sfc/ef100.c                   |    27 +-
 drivers/net/ethernet/sfc/ef100_nic.c               |    18 +-
 drivers/net/ethernet/sfc/ef100_sriov.c             |    56 +
 drivers/net/ethernet/sfc/ef100_sriov.h             |    14 +
 drivers/net/ethernet/sfc/efx.c                     |    19 +-
 drivers/net/ethernet/sfc/efx.h                     |     1 -
 drivers/net/ethernet/sfc/efx_channels.c            |    59 +-
 drivers/net/ethernet/sfc/efx_channels.h            |     3 -
 drivers/net/ethernet/sfc/efx_common.c              |     4 +-
 drivers/net/ethernet/sfc/falcon/efx.c              |    10 +-
 drivers/net/ethernet/sfc/falcon/rx.c               |     4 +-
 drivers/net/ethernet/sfc/falcon/tx.c               |     3 +-
 drivers/net/ethernet/sfc/mcdi_pcol.h               |     4 +-
 drivers/net/ethernet/sfc/net_driver.h              |     5 -
 drivers/net/ethernet/sfc/nic.h                     |     4 -
 drivers/net/ethernet/sfc/siena/Kconfig             |    46 +
 drivers/net/ethernet/sfc/siena/Makefile            |    11 +
 drivers/net/ethernet/sfc/siena/bitfield.h          |   614 +
 drivers/net/ethernet/sfc/siena/efx.c               |  1325 ++
 drivers/net/ethernet/sfc/siena/efx.h               |   218 +
 drivers/net/ethernet/sfc/siena/efx_channels.c      |  1370 ++
 drivers/net/ethernet/sfc/siena/efx_channels.h      |    45 +
 drivers/net/ethernet/sfc/siena/efx_common.c        |  1408 ++
 drivers/net/ethernet/sfc/siena/efx_common.h        |   118 +
 drivers/net/ethernet/sfc/siena/enum.h              |   176 +
 drivers/net/ethernet/sfc/siena/ethtool.c           |   282 +
 drivers/net/ethernet/sfc/siena/ethtool_common.c    |  1340 ++
 drivers/net/ethernet/sfc/siena/ethtool_common.h    |    60 +
 drivers/net/ethernet/sfc/{ => siena}/farch.c       |    77 +-
 drivers/net/ethernet/sfc/siena/farch_regs.h        |  2929 +++
 drivers/net/ethernet/sfc/siena/filter.h            |   309 +
 drivers/net/ethernet/sfc/siena/io.h                |   310 +
 drivers/net/ethernet/sfc/siena/mcdi.c              |  2260 +++
 drivers/net/ethernet/sfc/siena/mcdi.h              |   386 +
 drivers/net/ethernet/sfc/siena/mcdi_mon.c          |   531 +
 drivers/net/ethernet/sfc/siena/mcdi_pcol.h         | 17204 ++++++++++++++++
 drivers/net/ethernet/sfc/siena/mcdi_port.c         |   110 +
 drivers/net/ethernet/sfc/siena/mcdi_port.h         |    17 +
 drivers/net/ethernet/sfc/siena/mcdi_port_common.c  |  1282 ++
 drivers/net/ethernet/sfc/siena/mcdi_port_common.h  |    58 +
 drivers/net/ethernet/sfc/siena/mtd.c               |   124 +
 drivers/net/ethernet/sfc/siena/net_driver.h        |  1715 ++
 drivers/net/ethernet/sfc/siena/nic.c               |   530 +
 drivers/net/ethernet/sfc/siena/nic.h               |   206 +
 drivers/net/ethernet/sfc/siena/nic_common.h        |   251 +
 drivers/net/ethernet/sfc/siena/ptp.c               |  2201 +++
 drivers/net/ethernet/sfc/siena/ptp.h               |    45 +
 drivers/net/ethernet/sfc/siena/rx.c                |   400 +
 drivers/net/ethernet/sfc/siena/rx_common.c         |  1094 ++
 drivers/net/ethernet/sfc/siena/rx_common.h         |   110 +
 drivers/net/ethernet/sfc/siena/selftest.c          |   807 +
 drivers/net/ethernet/sfc/siena/selftest.h          |    52 +
 drivers/net/ethernet/sfc/{ => siena}/siena.c       |   168 +-
 drivers/net/ethernet/sfc/{ => siena}/siena_sriov.c |    35 +-
 drivers/net/ethernet/sfc/{ => siena}/siena_sriov.h |     9 +-
 drivers/net/ethernet/sfc/siena/sriov.h             |    83 +
 drivers/net/ethernet/sfc/siena/tx.c                |   392 +
 drivers/net/ethernet/sfc/siena/tx.h                |    40 +
 drivers/net/ethernet/sfc/siena/tx_common.c         |   448 +
 drivers/net/ethernet/sfc/siena/tx_common.h         |    39 +
 drivers/net/ethernet/sfc/siena/vfdi.h              |   252 +
 drivers/net/ethernet/sfc/siena/workarounds.h       |    28 +
 drivers/net/ethernet/sfc/tx.c                      |     3 +-
 drivers/net/ethernet/sfc/tx_common.c               |     3 +-
 drivers/net/ethernet/smsc/smc911x.c                |     6 +-
 drivers/net/ethernet/smsc/smsc911x.c               |     3 +-
 drivers/net/ethernet/smsc/smsc9420.c               |     2 +-
 drivers/net/ethernet/smsc/smsc9420.h               |     1 -
 drivers/net/ethernet/socionext/sni_ave.c           |     3 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c    |     4 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c |     6 -
 .../net/ethernet/stmicro/stmmac/dwxgmac2_descs.c   |     6 -
 drivers/net/ethernet/stmicro/stmmac/enh_desc.c     |     6 -
 drivers/net/ethernet/stmicro/stmmac/hwif.h         |     4 -
 drivers/net/ethernet/stmicro/stmmac/norm_desc.c    |     6 -
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |    27 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  |    24 +-
 .../net/ethernet/stmicro/stmmac/stmmac_selftests.c |    13 +-
 drivers/net/ethernet/sun/cassini.c                 |     4 +-
 drivers/net/ethernet/sun/sungem.c                  |     1 -
 drivers/net/ethernet/sunplus/Kconfig               |    32 +
 drivers/net/ethernet/sunplus/Makefile              |     6 +
 drivers/net/ethernet/sunplus/spl2sw_define.h       |   270 +
 drivers/net/ethernet/sunplus/spl2sw_desc.c         |   228 +
 drivers/net/ethernet/sunplus/spl2sw_desc.h         |    19 +
 drivers/net/ethernet/sunplus/spl2sw_driver.c       |   565 +
 drivers/net/ethernet/sunplus/spl2sw_int.c          |   273 +
 drivers/net/ethernet/sunplus/spl2sw_int.h          |    13 +
 drivers/net/ethernet/sunplus/spl2sw_mac.c          |   274 +
 drivers/net/ethernet/sunplus/spl2sw_mac.h          |    18 +
 drivers/net/ethernet/sunplus/spl2sw_mdio.c         |   131 +
 drivers/net/ethernet/sunplus/spl2sw_mdio.h         |    12 +
 drivers/net/ethernet/sunplus/spl2sw_phy.c          |    92 +
 drivers/net/ethernet/sunplus/spl2sw_phy.h          |    12 +
 drivers/net/ethernet/sunplus/spl2sw_register.h     |    86 +
 drivers/net/ethernet/synopsys/dwc-xlgmac.h         |     3 +-
 drivers/net/ethernet/ti/Kconfig                    |     1 +
 drivers/net/ethernet/ti/am65-cpsw-ethtool.c        |     6 +-
 drivers/net/ethernet/ti/am65-cpsw-nuss.c           |    37 +-
 drivers/net/ethernet/ti/am65-cpsw-qos.c            |   193 +-
 drivers/net/ethernet/ti/am65-cpsw-qos.h            |     8 +
 drivers/net/ethernet/ti/cpsw.c                     |    45 +-
 drivers/net/ethernet/ti/cpsw_ale.c                 |    66 +
 drivers/net/ethernet/ti/cpsw_ale.h                 |     2 +
 drivers/net/ethernet/ti/cpsw_new.c                 |    46 +-
 drivers/net/ethernet/ti/cpsw_priv.c                |   235 +-
 drivers/net/ethernet/ti/cpsw_priv.h                |    10 +-
 drivers/net/ethernet/ti/davinci_emac.c             |    12 +-
 drivers/net/ethernet/ti/davinci_mdio.c             |    18 +-
 drivers/net/ethernet/ti/netcp_core.c               |     5 +-
 drivers/net/ethernet/toshiba/spider_net.c          |     3 +-
 drivers/net/ethernet/toshiba/spider_net.h          |     1 -
 drivers/net/ethernet/toshiba/tc35815.c             |     2 +-
 drivers/net/ethernet/via/via-velocity.c            |     3 +-
 drivers/net/ethernet/via/via-velocity.h            |     1 -
 drivers/net/ethernet/wiznet/w5100.c                |     2 +-
 drivers/net/ethernet/wiznet/w5300.c                |     2 +-
 drivers/net/ethernet/xilinx/ll_temac_main.c        |     2 +-
 drivers/net/ethernet/xilinx/xilinx_axienet.h       |    54 +-
 drivers/net/ethernet/xilinx/xilinx_axienet_main.c  |   168 +-
 drivers/net/ethernet/xilinx/xilinx_emaclite.c      |    55 +-
 drivers/net/ethernet/xscale/ixp4xx_eth.c           |     2 +-
 drivers/net/ethernet/xscale/ptp_ixp46x.c           |     2 +-
 drivers/net/fddi/skfp/smt.c                        |     2 +-
 drivers/net/geneve.c                               |    10 +-
 drivers/net/hamradio/Kconfig                       |    34 -
 drivers/net/hamradio/Makefile                      |     1 -
 drivers/net/hamradio/dmascc.c                      |  1450 --
 drivers/net/hyperv/hyperv_net.h                    |    69 +-
 drivers/net/hyperv/netvsc.c                        |    16 +-
 drivers/net/hyperv/netvsc_bpf.c                    |   101 +-
 drivers/net/hyperv/netvsc_drv.c                    |   155 +-
 drivers/net/hyperv/rndis_filter.c                  |     4 +-
 drivers/net/ieee802154/Kconfig                     |     7 -
 drivers/net/ieee802154/at86rf230.c                 |   163 +-
 drivers/net/ieee802154/atusb.c                     |    37 +-
 drivers/net/ieee802154/ca8210.c                    |   181 +-
 drivers/net/ieee802154/mcr20a.c                    |     5 -
 drivers/net/ipa/gsi.c                              |    20 +-
 drivers/net/ipa/gsi.h                              |     1 -
 drivers/net/ipa/gsi_reg.h                          |     2 +-
 drivers/net/ipa/gsi_trans.c                        |    38 +-
 drivers/net/ipa/gsi_trans.h                        |    24 +-
 drivers/net/ipa/ipa.h                              |     2 +
 drivers/net/ipa/ipa_cmd.c                          |    78 +-
 drivers/net/ipa/ipa_cmd.h                          |    11 -
 drivers/net/ipa/ipa_data-v3.1.c                    |     2 +
 drivers/net/ipa/ipa_data-v3.5.1.c                  |     2 +
 drivers/net/ipa/ipa_data-v4.11.c                   |     2 +
 drivers/net/ipa/ipa_data-v4.2.c                    |     2 +
 drivers/net/ipa/ipa_data-v4.5.c                    |     2 +
 drivers/net/ipa/ipa_data-v4.9.c                    |     2 +
 drivers/net/ipa/ipa_data.h                         |    70 +-
 drivers/net/ipa/ipa_endpoint.c                     |   214 +-
 drivers/net/ipa/ipa_endpoint.h                     |    85 +-
 drivers/net/ipa/ipa_interrupt.c                    |     6 +-
 drivers/net/ipa/ipa_modem.c                        |    13 +-
 drivers/net/ipvlan/ipvlan_main.c                   |     6 +-
 drivers/net/loopback.c                             |     2 +
 drivers/net/macvlan.c                              |     9 +-
 drivers/net/mdio/mdio-aspeed.c                     |   138 +-
 drivers/net/mdio/mdio-mscc-miim.c                  |    81 +-
 drivers/net/netdevsim/fib.c                        |     9 +-
 drivers/net/netdevsim/ipsec.c                      |     2 +-
 drivers/net/pcs/pcs-xpcs.c                         |     6 +-
 drivers/net/phy/Kconfig                            |    13 +
 drivers/net/phy/Makefile                           |     2 +
 drivers/net/phy/adin.c                             |    40 +
 drivers/net/phy/adin1100.c                         |   292 +
 drivers/net/phy/bcm87xx.c                          |    36 +-
 drivers/net/phy/dp83822.c                          |     9 +-
 drivers/net/phy/dp83td510.c                        |   209 +
 drivers/net/phy/marvell.c                          |    53 +-
 drivers/net/phy/micrel.c                           |   269 +-
 drivers/net/phy/microchip.c                        |    10 +-
 drivers/net/phy/microchip_t1.c                     |    50 +
 drivers/net/phy/phy-c45.c                          |   297 +-
 drivers/net/phy/phy-core.c                         |     3 +-
 drivers/net/phy/phy.c                              |    18 +-
 drivers/net/phy/phy_device.c                       |    10 +-
 drivers/net/phy/phylink.c                          |    64 +-
 drivers/net/phy/smsc.c                             |    59 +-
 drivers/net/ppp/pppoe.c                            |     3 +-
 drivers/net/sungem_phy.c                           |     6 +-
 drivers/net/tun.c                                  |     3 +-
 drivers/net/usb/aqc111.c                           |     2 +-
 drivers/net/usb/asix_devices.c                     |     6 +-
 drivers/net/usb/ax88179_178a.c                     |     2 +-
 drivers/net/usb/cdc_ether.c                        |     3 +-
 drivers/net/usb/cdc_ncm.c                          |     8 +-
 drivers/net/usb/lan78xx.c                          |     6 +-
 drivers/net/usb/qmi_wwan.c                         |     3 +-
 drivers/net/usb/r8152.c                            |    41 +-
 drivers/net/usb/rndis_host.c                       |    47 +-
 drivers/net/usb/smsc95xx.c                         |   152 +-
 drivers/net/usb/sr9800.h                           |     2 +-
 drivers/net/usb/usbnet.c                           |     6 +-
 drivers/net/veth.c                                 |     6 +-
 drivers/net/virtio_net.c                           |     9 +-
 drivers/net/vxlan/vxlan_core.c                     |    43 +-
 drivers/net/wan/Kconfig                            |    72 -
 drivers/net/wan/Makefile                           |     5 -
 drivers/net/wan/cosa.c                             |  2052 --
 drivers/net/wan/cosa.h                             |   104 -
 drivers/net/wan/fsl_ucc_hdlc.c                     |     2 +-
 drivers/net/wan/hd64572.c                          |     3 +-
 drivers/net/wan/hostess_sv11.c                     |   336 -
 drivers/net/wan/ixp4xx_hss.c                       |     2 +-
 drivers/net/wan/lapbether.c                        |     2 +-
 drivers/net/wan/lmc/Makefile                       |    18 -
 drivers/net/wan/lmc/lmc.h                          |    33 -
 drivers/net/wan/lmc/lmc_debug.c                    |    65 -
 drivers/net/wan/lmc/lmc_debug.h                    |    52 -
 drivers/net/wan/lmc/lmc_ioctl.h                    |   255 -
 drivers/net/wan/lmc/lmc_main.c                     |  2009 --
 drivers/net/wan/lmc/lmc_media.c                    |  1206 --
 drivers/net/wan/lmc/lmc_proto.c                    |   106 -
 drivers/net/wan/lmc/lmc_proto.h                    |    18 -
 drivers/net/wan/lmc/lmc_var.h                      |   468 -
 drivers/net/wan/sealevel.c                         |   352 -
 drivers/net/wan/z85230.c                           |  1641 --
 drivers/net/wan/z85230.h                           |   407 -
 drivers/net/wireless/Kconfig                       |     2 +
 drivers/net/wireless/Makefile                      |     4 +-
 drivers/net/wireless/ath/ar5523/ar5523.c           |     7 +-
 drivers/net/wireless/ath/ath10k/ahb.c              |     9 +-
 drivers/net/wireless/ath/ath10k/core.c             |    38 +-
 drivers/net/wireless/ath/ath10k/core.h             |     3 -
 drivers/net/wireless/ath/ath10k/hw.h               |     2 +
 drivers/net/wireless/ath/ath10k/mac.c              |   106 +-
 drivers/net/wireless/ath/ath10k/pci.c              |     2 +-
 drivers/net/wireless/ath/ath10k/sdio.c             |     2 +-
 drivers/net/wireless/ath/ath10k/snoc.c             |     2 +-
 drivers/net/wireless/ath/ath10k/usb.c              |    27 +
 drivers/net/wireless/ath/ath11k/Makefile           |     3 +-
 drivers/net/wireless/ath/ath11k/ahb.c              |   331 +-
 drivers/net/wireless/ath/ath11k/ahb.h              |     9 +
 drivers/net/wireless/ath/ath11k/ce.c               |     4 +-
 drivers/net/wireless/ath/ath11k/core.c             |   579 +-
 drivers/net/wireless/ath/ath11k/core.h             |   155 +-
 drivers/net/wireless/ath/ath11k/debugfs.c          |     4 +
 drivers/net/wireless/ath/ath11k/dp_tx.c            |     8 +-
 drivers/net/wireless/ath/ath11k/hal.c              |    15 +-
 drivers/net/wireless/ath/ath11k/hal.h              |    17 +-
 drivers/net/wireless/ath/ath11k/htc.c              |     6 +
 drivers/net/wireless/ath/ath11k/hw.c               |   209 +-
 drivers/net/wireless/ath/ath11k/hw.h               |    45 +-
 drivers/net/wireless/ath/ath11k/mac.c              |   722 +-
 drivers/net/wireless/ath/ath11k/mac.h              |     5 +
 drivers/net/wireless/ath/ath11k/mhi.c              |   285 +-
 drivers/net/wireless/ath/ath11k/mhi.h              |    17 +-
 drivers/net/wireless/ath/ath11k/pci.c              |   984 +-
 drivers/net/wireless/ath/ath11k/pci.h              |    28 +-
 drivers/net/wireless/ath/ath11k/pcic.c             |   748 +
 drivers/net/wireless/ath/ath11k/pcic.h             |    46 +
 drivers/net/wireless/ath/ath11k/peer.c             |   373 +-
 drivers/net/wireless/ath/ath11k/peer.h             |    10 +-
 drivers/net/wireless/ath/ath11k/qmi.c              |   286 +-
 drivers/net/wireless/ath/ath11k/qmi.h              |    28 +-
 drivers/net/wireless/ath/ath11k/reg.c              |     4 +
 drivers/net/wireless/ath/ath11k/spectral.c         |    17 +-
 drivers/net/wireless/ath/ath11k/wmi.c              |   856 +-
 drivers/net/wireless/ath/ath11k/wmi.h              |   448 +-
 drivers/net/wireless/ath/ath11k/wow.c              |   797 +
 drivers/net/wireless/ath/ath11k/wow.h              |    45 +
 drivers/net/wireless/ath/ath6kl/Makefile           |     5 +
 drivers/net/wireless/ath/ath6kl/htc_mbox.c         |     2 +-
 drivers/net/wireless/ath/ath9k/Makefile            |     5 +
 drivers/net/wireless/ath/ath9k/ahb.c               |    10 +-
 drivers/net/wireless/ath/ath9k/ar9002_mac.c        |     9 +-
 drivers/net/wireless/ath/ath9k/ar9003_calib.c      |     2 +-
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |    85 +-
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.h     |     2 +
 drivers/net/wireless/ath/ath9k/ar9003_mac.c        |     9 +-
 drivers/net/wireless/ath/ath9k/ar9003_paprd.c      |    10 +-
 drivers/net/wireless/ath/ath9k/ar9003_phy.c        |    25 +-
 drivers/net/wireless/ath/ath9k/ar9003_phy.h        |     2 +-
 drivers/net/wireless/ath/ath9k/debug_sta.c         |     4 +-
 drivers/net/wireless/ath/ath9k/hif_usb.c           |     5 +-
 drivers/net/wireless/ath/ath9k/htc_drv_main.c      |    20 +-
 drivers/net/wireless/ath/ath9k/htc_drv_txrx.c      |     8 +
 drivers/net/wireless/ath/ath9k/mac.h               |     6 +-
 drivers/net/wireless/ath/ath9k/main.c              |     2 +-
 drivers/net/wireless/ath/ath9k/reg.h               |    10 +-
 drivers/net/wireless/ath/ath9k/xmit.c              |     8 +-
 drivers/net/wireless/ath/carl9170/Makefile         |     5 +
 drivers/net/wireless/ath/carl9170/main.c           |     8 +-
 drivers/net/wireless/ath/carl9170/tx.c             |     8 +-
 drivers/net/wireless/ath/wcn36xx/hal.h             |     7 +-
 drivers/net/wireless/ath/wcn36xx/main.c            |   160 +-
 drivers/net/wireless/ath/wcn36xx/smd.c             |    98 +-
 drivers/net/wireless/ath/wcn36xx/smd.h             |     2 +
 drivers/net/wireless/ath/wcn36xx/txrx.c            |    29 +
 drivers/net/wireless/ath/wcn36xx/txrx.h            |     1 +
 drivers/net/wireless/ath/wil6210/cfg80211.c        |     5 +-
 drivers/net/wireless/ath/wil6210/debugfs.c         |    14 -
 drivers/net/wireless/ath/wil6210/netdev.c          |    14 +-
 drivers/net/wireless/ath/wil6210/pm.c              |     5 +-
 drivers/net/wireless/ath/wil6210/wil6210.h         |     1 -
 drivers/net/wireless/broadcom/b43/phy_n.c          |     2 +-
 drivers/net/wireless/broadcom/b43legacy/phy.c      |     2 +-
 .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c  |    39 +-
 .../broadcom/brcm80211/brcmfmac/cfg80211.c         |     3 +-
 .../wireless/broadcom/brcm80211/brcmfmac/common.c  |    23 +-
 .../wireless/broadcom/brcm80211/brcmfmac/common.h  |     1 +
 .../wireless/broadcom/brcm80211/brcmfmac/core.c    |     4 +-
 .../net/wireless/broadcom/brcm80211/brcmfmac/of.c  |     3 +
 .../broadcom/brcm80211/brcmsmac/mac80211_if.c      |     2 +-
 drivers/net/wireless/intel/ipw2x00/ipw2100.c       |    64 +-
 drivers/net/wireless/intel/ipw2x00/ipw2200.c       |   119 +-
 drivers/net/wireless/intel/ipw2x00/libipw_tx.c     |     2 +-
 drivers/net/wireless/intel/iwlegacy/3945-rs.c      |     6 +-
 drivers/net/wireless/intel/iwlegacy/4965-rs.c      |    22 +-
 drivers/net/wireless/intel/iwlegacy/common.c       |     6 +-
 drivers/net/wireless/intel/iwlwifi/dvm/rs.c        |    22 +-
 drivers/net/wireless/intel/iwlwifi/dvm/rxon.c      |     2 +-
 drivers/net/wireless/intel/iwlwifi/dvm/sta.c       |     4 +-
 drivers/net/wireless/intel/iwlwifi/fw/acpi.c       |     3 +
 .../net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h    |     4 +-
 drivers/net/wireless/intel/iwlwifi/fw/api/debug.h  |     4 +-
 drivers/net/wireless/intel/iwlwifi/fw/api/filter.h |     2 +-
 drivers/net/wireless/intel/iwlwifi/fw/api/scan.h   |     4 +-
 drivers/net/wireless/intel/iwlwifi/fw/api/sta.h    |     2 +-
 drivers/net/wireless/intel/iwlwifi/fw/api/tdls.h   |     2 +-
 drivers/net/wireless/intel/iwlwifi/fw/error-dump.h |     2 +-
 drivers/net/wireless/intel/iwlwifi/fw/file.h       |    10 +-
 drivers/net/wireless/intel/iwlwifi/iwl-prph.h      |     2 +
 drivers/net/wireless/intel/iwlwifi/mei/main.c      |     3 +
 drivers/net/wireless/intel/iwlwifi/mei/sap.h       |     2 +-
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c        |    24 +-
 drivers/net/wireless/intel/iwlwifi/mvm/fw.c        |    15 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c  |    32 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c  |    55 +-
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h       |     1 -
 drivers/net/wireless/intel/iwlwifi/mvm/power.c     |     3 +
 drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c     |    38 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rs.c        |    35 +-
 drivers/net/wireless/intel/iwlwifi/mvm/rx.c        |    44 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sf.c        |     8 +-
 drivers/net/wireless/intel/iwlwifi/mvm/sta.c       |    33 +-
 drivers/net/wireless/intel/iwlwifi/mvm/tx.c        |     6 +-
 drivers/net/wireless/intel/iwlwifi/pcie/trans.c    |    48 +-
 drivers/net/wireless/intersil/orinoco/airport.c    |     1 +
 drivers/net/wireless/mac80211_hwsim.c              |     4 +-
 drivers/net/wireless/marvell/mwifiex/11h.c         |     2 +
 drivers/net/wireless/marvell/mwifiex/sdio.c        |    23 +-
 drivers/net/wireless/marvell/mwifiex/sdio.h        |     6 +
 drivers/net/wireless/marvell/mwl8k.c               |    48 +-
 drivers/net/wireless/mediatek/mt76/agg-rx.c        |     8 +-
 drivers/net/wireless/mediatek/mt76/dma.c           |   215 +-
 drivers/net/wireless/mediatek/mt76/mac80211.c      |    14 +-
 drivers/net/wireless/mediatek/mt76/mcu.c           |     8 +-
 drivers/net/wireless/mediatek/mt76/mmio.c          |     9 +-
 drivers/net/wireless/mediatek/mt76/mt76.h          |    50 +-
 drivers/net/wireless/mediatek/mt76/mt7603/beacon.c |     8 +-
 drivers/net/wireless/mediatek/mt76/mt7603/dma.c    |    12 +-
 drivers/net/wireless/mediatek/mt76/mt7603/mac.c    |    16 +-
 drivers/net/wireless/mediatek/mt76/mt7603/main.c   |     8 +-
 drivers/net/wireless/mediatek/mt76/mt7615/dma.c    |    10 +-
 drivers/net/wireless/mediatek/mt76/mt7615/main.c   |     8 +-
 drivers/net/wireless/mediatek/mt76/mt7615/mmio.c   |     2 +-
 .../net/wireless/mediatek/mt76/mt76_connac_mcu.c   |    90 +-
 .../net/wireless/mediatek/mt76/mt76_connac_mcu.h   |     1 -
 drivers/net/wireless/mediatek/mt76/mt76x02_mac.c   |     4 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c  |     8 +-
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c  |    10 +-
 .../net/wireless/mediatek/mt76/mt7915/debugfs.c    |   205 +-
 drivers/net/wireless/mediatek/mt76/mt7915/dma.c    |    61 +-
 drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c |     2 +
 drivers/net/wireless/mediatek/mt76/mt7915/init.c   |   129 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mac.c    |   251 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mac.h    |     2 +
 drivers/net/wireless/mediatek/mt76/mt7915/main.c   |    72 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mcu.c    |   288 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mcu.h    |    39 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mmio.c   |    39 +-
 drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h |    26 +-
 drivers/net/wireless/mediatek/mt76/mt7915/pci.c    |    99 +-
 drivers/net/wireless/mediatek/mt76/mt7915/regs.h   |    61 +-
 drivers/net/wireless/mediatek/mt76/mt7915/soc.c    |    41 +-
 drivers/net/wireless/mediatek/mt76/mt7921/dma.c    |     6 +-
 drivers/net/wireless/mediatek/mt76/mt7921/init.c   |    15 +-
 drivers/net/wireless/mediatek/mt76/mt7921/mac.c    |    43 +-
 drivers/net/wireless/mediatek/mt76/mt7921/main.c   |   155 +-
 drivers/net/wireless/mediatek/mt76/mt7921/mcu.c    |   122 +-
 drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h |    15 +-
 drivers/net/wireless/mediatek/mt76/mt7921/pci.c    |    10 +-
 drivers/net/wireless/mediatek/mt76/mt7921/regs.h   |     5 +
 drivers/net/wireless/mediatek/mt76/mt7921/usb.c    |    62 +-
 .../net/wireless/mediatek/mt76/mt7921/usb_mac.c    |     7 +-
 drivers/net/wireless/mediatek/mt76/tx.c            |    53 +-
 drivers/net/wireless/mediatek/mt7601u/mac.c        |     2 +-
 drivers/net/wireless/mediatek/mt7601u/tx.c         |     4 +-
 drivers/net/wireless/microchip/wilc1000/hif.h      |     2 +-
 drivers/net/wireless/microchip/wilc1000/mon.c      |     4 +-
 drivers/net/wireless/microchip/wilc1000/netdev.c   |     3 +-
 drivers/net/wireless/microchip/wilc1000/sdio.c     |     2 +-
 drivers/net/wireless/microchip/wilc1000/wlan.c     |     7 +-
 drivers/net/wireless/purelifi/Kconfig              |    17 +
 drivers/net/wireless/purelifi/Makefile             |     2 +
 drivers/net/wireless/purelifi/plfxlc/Kconfig       |    14 +
 drivers/net/wireless/purelifi/plfxlc/Makefile      |     3 +
 drivers/net/wireless/purelifi/plfxlc/chip.c        |    98 +
 drivers/net/wireless/purelifi/plfxlc/chip.h        |    70 +
 drivers/net/wireless/purelifi/plfxlc/firmware.c    |   276 +
 drivers/net/wireless/purelifi/plfxlc/intf.h        |    52 +
 drivers/net/wireless/purelifi/plfxlc/mac.c         |   754 +
 drivers/net/wireless/purelifi/plfxlc/mac.h         |   184 +
 drivers/net/wireless/purelifi/plfxlc/usb.c         |   891 +
 drivers/net/wireless/purelifi/plfxlc/usb.h         |   198 +
 .../wireless/quantenna/qtnfmac/pcie/pearl_pcie.c   |     4 +-
 .../wireless/quantenna/qtnfmac/pcie/topaz_pcie.c   |     4 +-
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c     |     8 +-
 drivers/net/wireless/ralink/rt2x00/rt2x00queue.c   |     2 +-
 drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c |     8 +-
 .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c  |   146 +-
 drivers/net/wireless/realtek/rtlwifi/base.c        |    44 +-
 .../realtek/rtlwifi/btcoexist/halbtc8821a1ant.c    |    16 +-
 drivers/net/wireless/realtek/rtlwifi/core.c        |    40 +-
 drivers/net/wireless/realtek/rtlwifi/pci.c         |    15 +-
 drivers/net/wireless/realtek/rtlwifi/rc.c          |    20 +-
 .../net/wireless/realtek/rtlwifi/rtl8188ee/hw.c    |    26 +-
 .../net/wireless/realtek/rtlwifi/rtl8188ee/trx.c   |     8 +-
 .../net/wireless/realtek/rtlwifi/rtl8192ce/hw.c    |    26 +-
 .../net/wireless/realtek/rtlwifi/rtl8192ce/trx.c   |     6 +-
 .../net/wireless/realtek/rtlwifi/rtl8192cu/hw.c    |    30 +-
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c   |     2 +-
 .../net/wireless/realtek/rtlwifi/rtl8192de/hw.c    |    26 +-
 .../net/wireless/realtek/rtlwifi/rtl8192de/phy.c   |     5 +-
 .../net/wireless/realtek/rtlwifi/rtl8192de/trx.c   |     4 +-
 .../net/wireless/realtek/rtlwifi/rtl8192ee/hw.c    |    12 +-
 .../net/wireless/realtek/rtlwifi/rtl8192ee/trx.c   |     8 +-
 .../net/wireless/realtek/rtlwifi/rtl8192se/hw.c    |    26 +-
 .../net/wireless/realtek/rtlwifi/rtl8192se/trx.c   |     2 +-
 .../net/wireless/realtek/rtlwifi/rtl8723ae/hw.c    |    26 +-
 .../net/wireless/realtek/rtlwifi/rtl8723ae/trx.c   |     8 +-
 .../net/wireless/realtek/rtlwifi/rtl8723be/hw.c    |    12 +-
 .../net/wireless/realtek/rtlwifi/rtl8723be/trx.c   |     8 +-
 .../net/wireless/realtek/rtlwifi/rtl8821ae/hw.c    |    30 +-
 .../net/wireless/realtek/rtlwifi/rtl8821ae/trx.c   |     6 +-
 drivers/net/wireless/realtek/rtlwifi/usb.c         |     2 +-
 drivers/net/wireless/realtek/rtw88/bf.c            |     2 +-
 drivers/net/wireless/realtek/rtw88/fw.c            |    31 +-
 drivers/net/wireless/realtek/rtw88/fw.h            |     4 +-
 drivers/net/wireless/realtek/rtw88/mac.c           |     2 +-
 drivers/net/wireless/realtek/rtw88/mac80211.c      |    44 +-
 drivers/net/wireless/realtek/rtw88/main.c          |    73 +-
 drivers/net/wireless/realtek/rtw88/main.h          |     8 +-
 drivers/net/wireless/realtek/rtw88/pci.c           |    19 +-
 drivers/net/wireless/realtek/rtw88/phy.c           |     2 +-
 drivers/net/wireless/realtek/rtw88/reg.h           |     2 +
 drivers/net/wireless/realtek/rtw88/rtw8723d.c      |     1 +
 drivers/net/wireless/realtek/rtw88/rtw8821c.c      |     5 +
 .../net/wireless/realtek/rtw88/rtw8821c_table.c    |     2 +-
 drivers/net/wireless/realtek/rtw88/rtw8821ce.c     |     4 +
 drivers/net/wireless/realtek/rtw88/rtw8822b.c      |     1 +
 drivers/net/wireless/realtek/rtw88/rtw8822c.c      |     1 +
 drivers/net/wireless/realtek/rtw88/rx.c            |     3 +-
 drivers/net/wireless/realtek/rtw88/tx.c            |    31 +-
 drivers/net/wireless/realtek/rtw88/tx.h            |     4 +
 drivers/net/wireless/realtek/rtw89/Kconfig         |    18 +-
 drivers/net/wireless/realtek/rtw89/Makefile        |     9 +
 drivers/net/wireless/realtek/rtw89/cam.c           |    57 +-
 drivers/net/wireless/realtek/rtw89/cam.h           |     4 +
 drivers/net/wireless/realtek/rtw89/coex.c          |    24 +-
 drivers/net/wireless/realtek/rtw89/core.c          |   193 +-
 drivers/net/wireless/realtek/rtw89/core.h          |   295 +-
 drivers/net/wireless/realtek/rtw89/debug.c         |    75 +-
 drivers/net/wireless/realtek/rtw89/debug.h         |     1 +
 drivers/net/wireless/realtek/rtw89/fw.c            |   301 +-
 drivers/net/wireless/realtek/rtw89/fw.h            |   388 +-
 drivers/net/wireless/realtek/rtw89/mac.c           |   736 +-
 drivers/net/wireless/realtek/rtw89/mac.h           |    82 +-
 drivers/net/wireless/realtek/rtw89/mac80211.c      |    16 +-
 drivers/net/wireless/realtek/rtw89/pci.c           |   954 +-
 drivers/net/wireless/realtek/rtw89/pci.h           |   389 +
 drivers/net/wireless/realtek/rtw89/phy.c           |   481 +-
 drivers/net/wireless/realtek/rtw89/phy.h           |    76 +-
 drivers/net/wireless/realtek/rtw89/ps.c            |    34 +-
 drivers/net/wireless/realtek/rtw89/reg.h           |  1907 +-
 drivers/net/wireless/realtek/rtw89/regd.c          |   513 +-
 drivers/net/wireless/realtek/rtw89/rtw8852a.c      |    81 +-
 drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c  |    16 +-
 .../net/wireless/realtek/rtw89/rtw8852a_table.c    |   605 +-
 drivers/net/wireless/realtek/rtw89/rtw8852ae.c     |    40 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c      |  2561 ++-
 drivers/net/wireless/realtek/rtw89/rtw8852c.h      |    20 +-
 drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c  |  4041 ++++
 drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h  |    28 +
 .../wireless/realtek/rtw89/rtw8852c_rfk_table.c    |   781 +
 .../wireless/realtek/rtw89/rtw8852c_rfk_table.h    |    67 +
 .../net/wireless/realtek/rtw89/rtw8852c_table.c    | 19470 +++++++++++++++++++
 .../net/wireless/realtek/rtw89/rtw8852c_table.h    |    36 +
 drivers/net/wireless/realtek/rtw89/rtw8852ce.c     |    48 +
 drivers/net/wireless/realtek/rtw89/ser.c           |   250 +-
 drivers/net/wireless/realtek/rtw89/txrx.h          |   107 +
 drivers/net/wireless/realtek/rtw89/util.h          |    30 +
 drivers/net/wireless/rsi/rsi_91x_mac80211.c        |    12 +-
 drivers/net/wireless/rsi/rsi_91x_mgmt.c            |     8 +-
 drivers/net/wireless/silabs/Kconfig                |    18 +
 drivers/net/wireless/silabs/Makefile               |     3 +
 .../{staging => net/wireless/silabs}/wfx/Kconfig   |     0
 .../{staging => net/wireless/silabs}/wfx/Makefile  |     0
 drivers/{staging => net/wireless/silabs}/wfx/bh.c  |     6 +-
 drivers/{staging => net/wireless/silabs}/wfx/bh.h  |     0
 drivers/{staging => net/wireless/silabs}/wfx/bus.h |     0
 .../wireless/silabs}/wfx/bus_sdio.c                |     0
 .../{staging => net/wireless/silabs}/wfx/bus_spi.c |     0
 .../{staging => net/wireless/silabs}/wfx/data_rx.c |     5 +-
 .../{staging => net/wireless/silabs}/wfx/data_rx.h |     0
 .../{staging => net/wireless/silabs}/wfx/data_tx.c |     3 +-
 .../{staging => net/wireless/silabs}/wfx/data_tx.h |     0
 .../{staging => net/wireless/silabs}/wfx/debug.c   |     0
 .../{staging => net/wireless/silabs}/wfx/debug.h   |     0
 .../{staging => net/wireless/silabs}/wfx/fwio.c    |     0
 .../{staging => net/wireless/silabs}/wfx/fwio.h    |     0
 .../wireless/silabs}/wfx/hif_api_cmd.h             |     0
 .../wireless/silabs}/wfx/hif_api_general.h         |     0
 .../wireless/silabs}/wfx/hif_api_mib.h             |     0
 .../{staging => net/wireless/silabs}/wfx/hif_rx.c  |     0
 .../{staging => net/wireless/silabs}/wfx/hif_rx.h  |     0
 .../{staging => net/wireless/silabs}/wfx/hif_tx.c  |     2 +-
 .../{staging => net/wireless/silabs}/wfx/hif_tx.h  |     0
 .../wireless/silabs}/wfx/hif_tx_mib.c              |     0
 .../wireless/silabs}/wfx/hif_tx_mib.h              |     0
 .../{staging => net/wireless/silabs}/wfx/hwio.c    |     0
 .../{staging => net/wireless/silabs}/wfx/hwio.h    |     0
 drivers/{staging => net/wireless/silabs}/wfx/key.c |     4 +-
 drivers/{staging => net/wireless/silabs}/wfx/key.h |     0
 .../{staging => net/wireless/silabs}/wfx/main.c    |     6 +
 .../{staging => net/wireless/silabs}/wfx/main.h    |     0
 .../{staging => net/wireless/silabs}/wfx/queue.c   |     3 +-
 .../{staging => net/wireless/silabs}/wfx/queue.h   |     0
 .../{staging => net/wireless/silabs}/wfx/scan.c    |    11 +-
 .../{staging => net/wireless/silabs}/wfx/scan.h    |     0
 drivers/{staging => net/wireless/silabs}/wfx/sta.c |    84 +-
 drivers/{staging => net/wireless/silabs}/wfx/sta.h |     0
 .../{staging => net/wireless/silabs}/wfx/traces.h  |     0
 drivers/{staging => net/wireless/silabs}/wfx/wfx.h |     7 +-
 drivers/net/wireless/st/cw1200/sta.c               |     4 +-
 drivers/net/wireless/ti/wl1251/event.c             |    22 +-
 drivers/net/wireless/ti/wl1251/io.c                |    20 +-
 drivers/net/wireless/ti/wl1251/tx.c                |    15 +-
 drivers/net/wireless/ti/wl18xx/debugfs.c           |    18 +-
 drivers/net/wireless/ti/wlcore/cmd.c               |    14 +-
 drivers/net/wireless/ti/wlcore/debugfs.c           |    52 +-
 drivers/net/wireless/ti/wlcore/main.c              |   241 +-
 drivers/net/wireless/ti/wlcore/scan.c              |     6 +-
 drivers/net/wireless/ti/wlcore/sdio.c              |     3 +-
 drivers/net/wireless/ti/wlcore/sysfs.c             |     6 +-
 drivers/net/wireless/ti/wlcore/testmode.c          |    12 +-
 drivers/net/wireless/ti/wlcore/tx.c                |     6 +-
 drivers/net/wireless/ti/wlcore/vendor_cmd.c        |    18 +-
 drivers/net/wwan/Kconfig                           |    14 +
 drivers/net/wwan/Makefile                          |     1 +
 drivers/net/wwan/iosm/iosm_ipc_coredump.h          |     5 +-
 drivers/net/wwan/iosm/iosm_ipc_protocol_ops.c      |    10 -
 drivers/net/wwan/t7xx/Makefile                     |    20 +
 drivers/net/wwan/t7xx/t7xx_cldma.c                 |   281 +
 drivers/net/wwan/t7xx/t7xx_cldma.h                 |   180 +
 drivers/net/wwan/t7xx/t7xx_dpmaif.c                |  1281 ++
 drivers/net/wwan/t7xx/t7xx_dpmaif.h                |   179 +
 drivers/net/wwan/t7xx/t7xx_hif_cldma.c             |  1339 ++
 drivers/net/wwan/t7xx/t7xx_hif_cldma.h             |   127 +
 drivers/net/wwan/t7xx/t7xx_hif_dpmaif.c            |   574 +
 drivers/net/wwan/t7xx/t7xx_hif_dpmaif.h            |   206 +
 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c         |  1243 ++
 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.h         |   116 +
 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c         |   683 +
 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.h         |    78 +
 drivers/net/wwan/t7xx/t7xx_mhccif.c                |   122 +
 drivers/net/wwan/t7xx/t7xx_mhccif.h                |    37 +
 drivers/net/wwan/t7xx/t7xx_modem_ops.c             |   727 +
 drivers/net/wwan/t7xx/t7xx_modem_ops.h             |    88 +
 drivers/net/wwan/t7xx/t7xx_netdev.c                |   423 +
 drivers/net/wwan/t7xx/t7xx_netdev.h                |    55 +
 drivers/net/wwan/t7xx/t7xx_pci.c                   |   761 +
 drivers/net/wwan/t7xx/t7xx_pci.h                   |   120 +
 drivers/net/wwan/t7xx/t7xx_pcie_mac.c              |   262 +
 drivers/net/wwan/t7xx/t7xx_pcie_mac.h              |    31 +
 drivers/net/wwan/t7xx/t7xx_port.h                  |   135 +
 drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c         |   273 +
 drivers/net/wwan/t7xx/t7xx_port_proxy.c            |   509 +
 drivers/net/wwan/t7xx/t7xx_port_proxy.h            |    98 +
 drivers/net/wwan/t7xx/t7xx_port_wwan.c             |   176 +
 drivers/net/wwan/t7xx/t7xx_reg.h                   |   350 +
 drivers/net/wwan/t7xx/t7xx_state_monitor.c         |   550 +
 drivers/net/wwan/t7xx/t7xx_state_monitor.h         |   135 +
 drivers/net/wwan/wwan_hwsim.c                      |    22 +-
 drivers/net/xen-netback/interface.c                |     3 +-
 drivers/nfc/st21nfca/se.c                          |    17 +-
 drivers/nfc/st21nfca/st21nfca.h                    |     1 +
 drivers/ptp/ptp_clock.c                            |    31 +-
 drivers/ptp/ptp_clockmatrix.c                      |   321 +-
 drivers/ptp/ptp_clockmatrix.h                      |     7 +-
 drivers/ptp/ptp_ocp.c                              |   559 +-
 drivers/ptp/ptp_private.h                          |    11 +
 drivers/ptp/ptp_sysfs.c                            |    11 +-
 drivers/ptp/ptp_vclock.c                           |    82 +-
 drivers/s390/net/qeth_core.h                       |     2 -
 drivers/s390/net/qeth_core_main.c                  |     3 +-
 drivers/s390/net/qeth_l2_main.c                    |     4 +-
 drivers/s390/net/qeth_l3_main.c                    |     4 +-
 drivers/scsi/fcoe/fcoe.c                           |     2 +-
 drivers/ssb/pci.c                                  |     1 -
 drivers/staging/Kconfig                            |     1 -
 drivers/staging/Makefile                           |     1 -
 drivers/staging/wfx/TODO                           |     6 -
 fs/afs/misc.c                                      |     5 +-
 fs/afs/rotate.c                                    |     4 +
 fs/afs/rxrpc.c                                     |     8 +-
 fs/afs/write.c                                     |     1 +
 fs/proc/proc_sysctl.c                              |     4 +-
 fs/seq_file.c                                      |    32 +
 include/linux/bpf-cgroup.h                         |     8 +-
 include/linux/bpf.h                                |   351 +-
 include/linux/bpf_local_storage.h                  |     4 +-
 include/linux/bpf_types.h                          |     1 +
 include/linux/bpf_verifier.h                       |    23 +-
 include/linux/btf.h                                |    23 +
 include/linux/btf_ids.h                            |     3 +-
 include/linux/can/dev.h                            |    10 -
 include/linux/can/led.h                            |    51 -
 include/linux/can/rx-offload.h                     |     4 +-
 include/linux/ethtool.h                            |     4 +
 include/linux/fortify-string.h                     |    16 +
 include/linux/ftrace.h                             |     6 +
 include/linux/icmpv6.h                             |    11 +-
 include/linux/ieee802154.h                         |    81 +-
 include/linux/ipv6.h                               |     6 +-
 include/linux/kallsyms.h                           |     7 +-
 include/linux/list.h                               |    36 +
 include/linux/mdio.h                               |    70 +
 include/linux/mfd/idt8a340_reg.h                   |    12 +-
 include/linux/mlx5/accel.h                         |   156 -
 include/linux/mlx5/driver.h                        |    17 +-
 include/linux/mlx5/fs.h                            |    12 +
 include/linux/mlx5/mlx5_ifc.h                      |    23 +-
 include/linux/mlx5/mlx5_ifc_fpga.h                 |   211 -
 include/linux/mlx5/port.h                          |     2 +-
 include/linux/netdevice.h                          |   378 +-
 include/linux/phy.h                                |     8 +-
 include/linux/phylink.h                            |     6 -
 include/linux/ptp_classify.h                       |     3 +
 include/linux/ptp_clock_kernel.h                   |    42 +-
 include/linux/qed/qed_fcoe_if.h                    |     4 +-
 include/linux/qed/qed_iscsi_if.h                   |     4 +-
 include/linux/qed/qed_nvmetcp_if.h                 |     2 +-
 include/linux/qed/qed_nvmetcp_ip_services_if.h     |    29 -
 include/linux/rtnetlink.h                          |     1 +
 include/linux/seq_file.h                           |     4 +
 include/linux/skbuff.h                             |   419 +-
 include/linux/soc/mediatek/mtk_wed.h               |   131 +
 include/linux/socket.h                             |     6 +-
 include/linux/string.h                             |     4 +
 include/linux/sysctl.h                             |     9 +-
 include/linux/usb/rndis_host.h                     |     1 +
 include/linux/usb/usbnet.h                         |     1 +
 include/net/act_api.h                              |     3 +-
 include/net/bluetooth/hci.h                        |    10 +
 include/net/bluetooth/hci_core.h                   |     8 +-
 include/net/cfg80211.h                             |    16 +-
 include/net/cfg802154.h                            |     8 +-
 include/net/devlink.h                              |    48 +
 include/net/dsa.h                                  |    25 +-
 include/net/flow_dissector.h                       |     9 +
 include/net/if_inet6.h                             |     8 +
 include/net/inet6_hashtables.h                     |    28 +-
 include/net/inet_connection_sock.h                 |     5 +-
 include/net/inet_hashtables.h                      |   145 +-
 include/net/inet_sock.h                            |     5 +-
 include/net/ip.h                                   |     2 +-
 include/net/ip_fib.h                               |     4 +-
 include/net/ipv6.h                                 |    44 +
 include/net/mac80211.h                             |   126 +-
 include/net/mac802154.h                            |    19 +
 include/net/mptcp.h                                |    11 +-
 include/net/net_debug.h                            |   157 +
 include/net/netfilter/nf_conntrack.h               |    23 +-
 include/net/netfilter/nf_conntrack_core.h          |     2 +-
 include/net/netfilter/nf_conntrack_count.h         |     1 +
 include/net/netfilter/nf_conntrack_ecache.h        |    53 +-
 include/net/netfilter/nf_conntrack_extend.h        |    31 +-
 include/net/netfilter/nf_conntrack_labels.h        |    10 +-
 include/net/netfilter/nf_conntrack_timeout.h       |     8 -
 include/net/netfilter/nf_reject.h                  |    21 +-
 include/net/netns/conntrack.h                      |     8 +-
 include/net/page_pool.h                            |    21 +
 include/net/ping.h                                 |     4 +-
 include/net/pkt_cls.h                              |     6 +-
 include/net/route.h                                |    36 +-
 include/net/rtnetlink.h                            |    16 +-
 include/net/sctp/sctp.h                            |     2 +-
 include/net/sock.h                                 |    64 +-
 include/net/strparser.h                            |     4 +
 include/net/tc_act/tc_gact.h                       |    15 +
 include/net/tc_act/tc_skbedit.h                    |    13 +
 include/net/tcp.h                                  |    45 +-
 include/net/tls.h                                  |    16 +-
 include/net/udp.h                                  |     8 +-
 include/net/xfrm.h                                 |    20 +-
 include/rdma/ib_verbs.h                            |     8 -
 include/soc/mscc/ocelot.h                          |    42 +-
 include/soc/mscc/ocelot_vcap.h                     |     2 +-
 include/trace/events/mptcp.h                       |     6 +-
 include/trace/events/rxrpc.h                       |   265 +-
 include/trace/events/skb.h                         |    21 +-
 include/trace/events/tcp.h                         |    47 +-
 include/uapi/asm-generic/socket.h                  |     2 +
 include/uapi/linux/atm_zatm.h                      |    47 -
 include/uapi/linux/bpf.h                           |   125 +
 include/uapi/linux/btf.h                           |     4 +-
 include/uapi/linux/can/isotp.h                     |    25 +-
 include/uapi/linux/devlink.h                       |    23 +
 include/uapi/linux/ethtool.h                       |     1 +
 include/uapi/linux/ethtool_netlink.h               |     1 +
 include/uapi/linux/if_link.h                       |     7 +
 include/uapi/linux/ipv6.h                          |     1 +
 include/uapi/linux/mdio.h                          |    75 +
 include/uapi/linux/mptcp.h                         |     8 +
 include/uapi/linux/neighbour.h                     |     2 +
 include/uapi/linux/netlink.h                       |     1 +
 include/uapi/linux/nl80211.h                       |     2 +
 include/uapi/linux/pkt_cls.h                       |     2 +
 include/uapi/linux/tc_act/tc_skbedit.h             |     2 +
 include/uapi/linux/tipc_config.h                   |    28 +-
 include/uapi/linux/tls.h                           |     2 +
 kernel/bpf/Makefile                                |     2 +-
 kernel/bpf/arraymap.c                              |    61 +-
 kernel/bpf/bloom_filter.c                          |     6 +-
 kernel/bpf/bpf_inode_storage.c                     |    10 +-
 kernel/bpf/bpf_iter.c                              |    32 +-
 kernel/bpf/bpf_local_storage.c                     |    29 +-
 kernel/bpf/bpf_lsm.c                               |    17 +
 kernel/bpf/bpf_struct_ops.c                        |    81 +-
 kernel/bpf/bpf_task_storage.c                      |     9 +-
 kernel/bpf/btf.c                                   |   640 +-
 kernel/bpf/cgroup.c                                |   106 +-
 kernel/bpf/core.c                                  |    29 +-
 kernel/bpf/cpumap.c                                |     6 +-
 kernel/bpf/devmap.c                                |    10 +-
 kernel/bpf/hashtab.c                               |   133 +-
 kernel/bpf/helpers.c                               |   223 +-
 kernel/bpf/link_iter.c                             |   107 +
 kernel/bpf/local_storage.c                         |     7 +-
 kernel/bpf/lpm_trie.c                              |     6 +-
 kernel/bpf/map_in_map.c                            |     5 +-
 kernel/bpf/queue_stack_maps.c                      |    10 +-
 kernel/bpf/reuseport_array.c                       |     6 +-
 kernel/bpf/ringbuf.c                               |    88 +-
 kernel/bpf/stackmap.c                              |     7 +-
 kernel/bpf/syscall.c                               |   500 +-
 kernel/bpf/task_iter.c                             |     1 -
 kernel/bpf/trampoline.c                            |   118 +-
 kernel/bpf/verifier.c                              |   819 +-
 kernel/kallsyms.c                                  |     3 +-
 kernel/sysctl.c                                    |    79 -
 kernel/trace/bpf_trace.c                           |   144 +-
 kernel/trace/fprobe.c                              |    32 +-
 kernel/trace/ftrace.c                              |    62 +
 lib/test_bpf.c                                     |   315 +-
 lib/test_sysctl.c                                  |    32 +
 net/8021q/vlan.c                                   |     3 +-
 net/8021q/vlan_dev.c                               |     3 +-
 net/Kconfig.debug                                  |     7 +
 net/appletalk/ddp.c                                |     3 +-
 net/atm/common.c                                   |     4 +-
 net/ax25/af_ax25.c                                 |     3 +-
 net/ax25/ax25_dev.c                                |    22 +-
 net/batman-adv/bridge_loop_avoidance.c             |     4 +-
 net/batman-adv/hard-interface.c                    |     2 +
 net/batman-adv/main.h                              |     2 +-
 net/batman-adv/translation-table.c                 |    12 +-
 net/bluetooth/af_bluetooth.c                       |     7 +-
 net/bluetooth/eir.c                                |    31 +
 net/bluetooth/eir.h                                |     4 +
 net/bluetooth/hci_conn.c                           |     7 +-
 net/bluetooth/hci_core.c                           |     2 -
 net/bluetooth/hci_event.c                          |    35 +-
 net/bluetooth/hci_request.c                        |     4 +-
 net/bluetooth/hci_sock.c                           |     3 +-
 net/bluetooth/hci_sync.c                           |    90 +-
 net/bluetooth/mgmt.c                               |    18 +
 net/bluetooth/mgmt_util.c                          |     2 +-
 net/bluetooth/sco.c                                |    23 +-
 net/bpf/bpf_dummy_struct_ops.c                     |    24 +-
 net/bpf/test_run.c                                 |    86 +-
 net/bridge/br_device.c                             |     1 +
 net/bridge/br_fdb.c                                |   160 +-
 net/bridge/br_if.c                                 |    12 +-
 net/bridge/br_mdb.c                                |    12 +-
 net/bridge/br_netlink.c                            |     9 +-
 net/bridge/br_private.h                            |    21 +-
 net/bridge/br_switchdev.c                          |     3 +-
 net/bridge/br_sysfs_br.c                           |     6 +-
 net/caif/caif_socket.c                             |     2 +-
 net/can/bcm.c                                      |     7 +-
 net/can/isotp.c                                    |   130 +-
 net/can/j1939/socket.c                             |     4 +-
 net/can/raw.c                                      |    20 +-
 net/core/bpf_sk_storage.c                          |    11 +-
 net/core/datagram.c                                |     7 +-
 net/core/datagram.h                                |    15 -
 net/core/dev.c                                     |   232 +-
 net/core/dev.h                                     |   112 +
 net/core/dev_addr_lists.c                          |     2 +
 net/core/dev_ioctl.c                               |     2 +
 net/core/devlink.c                                 |   653 +-
 net/core/drop_monitor.c                            |     2 +-
 net/core/filter.c                                  |    37 +-
 net/core/flow_dissector.c                          |    20 +
 net/core/gro.c                                     |     8 +
 net/core/link_watch.c                              |     1 +
 net/core/neighbour.c                               |     2 +-
 net/core/net-procfs.c                              |     2 +
 net/core/net-sysfs.c                               |    22 +-
 net/core/page_pool.c                               |    83 +-
 net/core/rtnetlink.c                               |   449 +-
 net/core/skbuff.c                                  |    67 +-
 net/core/skmsg.c                                   |    22 +-
 net/core/sock.c                                    |   126 +-
 net/core/sock_map.c                                |    10 +-
 net/core/sysctl_net_core.c                         |    29 +-
 net/dccp/dccp.h                                    |     4 +-
 net/dccp/ipv4.c                                    |     7 +-
 net/dccp/ipv6.c                                    |     6 +-
 net/dccp/proto.c                                   |    40 +-
 net/decnet/dn_route.c                              |     2 +-
 net/dsa/dsa.c                                      |    49 -
 net/dsa/dsa2.c                                     |    25 +-
 net/dsa/dsa_priv.h                                 |    29 +-
 net/dsa/port.c                                     |   136 +-
 net/dsa/slave.c                                    |    67 +-
 net/dsa/switch.c                                   |   198 +-
 net/dsa/tag_8021q.c                                |    10 +-
 net/ethernet/eth.c                                 |     2 +-
 net/ethtool/common.c                               |     3 +
 net/ethtool/netlink.h                              |     2 +-
 net/ethtool/rings.c                                |    54 +-
 net/ieee802154/socket.c                            |    12 +-
 net/ipv4/Kconfig                                   |     1 -
 net/ipv4/af_inet.c                                 |    11 +-
 net/ipv4/arp.c                                     |     7 +-
 net/ipv4/datagram.c                                |     7 +-
 net/ipv4/devinet.c                                 |     2 +-
 net/ipv4/esp4.c                                    |     6 -
 net/ipv4/fib_frontend.c                            |     4 +-
 net/ipv4/fib_rules.c                               |     2 +-
 net/ipv4/fib_semantics.c                           |     4 +-
 net/ipv4/fib_trie.c                                |    12 +-
 net/ipv4/fou.c                                     |     1 -
 net/ipv4/icmp.c                                    |    77 +-
 net/ipv4/igmp.c                                    |     4 +-
 net/ipv4/inet_connection_sock.c                    |   245 +-
 net/ipv4/inet_diag.c                               |     5 +-
 net/ipv4/inet_fragment.c                           |     2 +-
 net/ipv4/inet_hashtables.c                         |   329 +-
 net/ipv4/ip_forward.c                              |    13 +-
 net/ipv4/ip_gre.c                                  |    50 +-
 net/ipv4/ip_input.c                                |     1 +
 net/ipv4/ipmr.c                                    |     2 +-
 net/ipv4/netfilter.c                               |     3 +-
 net/ipv4/netfilter/nf_reject_ipv4.c                |    10 +-
 net/ipv4/netfilter/nft_fib_ipv4.c                  |     4 +
 net/ipv4/ping.c                                    |    40 +-
 net/ipv4/raw.c                                     |     6 +-
 net/ipv4/route.c                                   |    51 +-
 net/ipv4/sysctl_net_ipv4.c                         |    16 +-
 net/ipv4/tcp.c                                     |    83 +-
 net/ipv4/tcp_bbr.c                                 |    22 +-
 net/ipv4/tcp_bic.c                                 |    14 +-
 net/ipv4/tcp_bpf.c                                 |    15 +-
 net/ipv4/tcp_cdg.c                                 |    30 +-
 net/ipv4/tcp_cong.c                                |    30 +-
 net/ipv4/tcp_cubic.c                               |    26 +-
 net/ipv4/tcp_dctcp.c                               |    11 +-
 net/ipv4/tcp_highspeed.c                           |    18 +-
 net/ipv4/tcp_htcp.c                                |    10 +-
 net/ipv4/tcp_hybla.c                               |    18 +-
 net/ipv4/tcp_illinois.c                            |    12 +-
 net/ipv4/tcp_input.c                               |   177 +-
 net/ipv4/tcp_ipv4.c                                |    30 +-
 net/ipv4/tcp_lp.c                                  |     6 +-
 net/ipv4/tcp_metrics.c                             |    12 +-
 net/ipv4/tcp_nv.c                                  |    24 +-
 net/ipv4/tcp_output.c                              |    46 +-
 net/ipv4/tcp_rate.c                                |     2 +-
 net/ipv4/tcp_recovery.c                            |    15 +-
 net/ipv4/tcp_scalable.c                            |     4 +-
 net/ipv4/tcp_vegas.c                               |    21 +-
 net/ipv4/tcp_veno.c                                |    24 +-
 net/ipv4/tcp_westwood.c                            |     3 +-
 net/ipv4/tcp_yeah.c                                |    30 +-
 net/ipv4/udp.c                                     |    16 +-
 net/ipv4/udp_bpf.c                                 |    17 +-
 net/ipv4/udp_impl.h                                |     4 +-
 net/ipv6/addrconf.c                                |    51 +-
 net/ipv6/af_inet6.c                                |     7 +-
 net/ipv6/datagram.c                                |    10 +-
 net/ipv6/esp6.c                                    |     6 -
 net/ipv6/exthdrs.c                                 |    44 +-
 net/ipv6/icmp.c                                    |    31 +-
 net/ipv6/inet6_hashtables.c                        |    11 +-
 net/ipv6/ip6_gre.c                                 |    34 +-
 net/ipv6/ip6_input.c                               |    41 +-
 net/ipv6/ip6_offload.c                             |    56 +-
 net/ipv6/ip6_output.c                              |    56 +-
 net/ipv6/ip6_tunnel.c                              |     2 -
 net/ipv6/ndisc.c                                   |    20 +-
 net/ipv6/netfilter.c                               |     3 +-
 net/ipv6/netfilter/nf_reject_ipv6.c                |     4 +-
 net/ipv6/netfilter/nft_fib_ipv6.c                  |     4 +
 net/ipv6/raw.c                                     |     6 +-
 net/ipv6/route.c                                   |     6 +-
 net/ipv6/sysctl_net_ipv6.c                         |     6 +-
 net/ipv6/tcp_ipv6.c                                |     6 +-
 net/ipv6/udp.c                                     |    23 +-
 net/ipv6/udp_impl.h                                |     4 +-
 net/iucv/af_iucv.c                                 |     3 +-
 net/key/af_key.c                                   |     4 +-
 net/l2tp/l2tp_ip.c                                 |     8 +-
 net/l2tp/l2tp_ip6.c                                |    12 +-
 net/l2tp/l2tp_ppp.c                                |     3 +-
 net/mac80211/agg-rx.c                              |    12 +-
 net/mac80211/agg-tx.c                              |     6 +-
 net/mac80211/airtime.c                             |     4 +-
 net/mac80211/cfg.c                                 |    81 +-
 net/mac80211/chan.c                                |     8 +-
 net/mac80211/debugfs.c                             |     1 +
 net/mac80211/debugfs_netdev.c                      |     2 +-
 net/mac80211/debugfs_sta.c                         |    12 +-
 net/mac80211/eht.c                                 |     6 +-
 net/mac80211/ethtool.c                             |     4 +-
 net/mac80211/he.c                                  |     8 +-
 net/mac80211/ht.c                                  |     8 +-
 net/mac80211/ibss.c                                |    26 +-
 net/mac80211/ieee80211_i.h                         |    12 +-
 net/mac80211/key.c                                 |     9 +-
 net/mac80211/main.c                                |     4 +-
 net/mac80211/mesh_hwmp.c                           |     2 +-
 net/mac80211/mesh_plink.c                          |    24 +-
 net/mac80211/mlme.c                                |   135 +-
 net/mac80211/ocb.c                                 |     2 +-
 net/mac80211/offchannel.c                          |     2 +-
 net/mac80211/rate.c                                |     8 +-
 net/mac80211/rc80211_minstrel_ht.c                 |   177 +-
 net/mac80211/rc80211_minstrel_ht.h                 |     2 +-
 net/mac80211/rx.c                                  |   131 +-
 net/mac80211/s1g.c                                 |     4 +-
 net/mac80211/scan.c                                |    20 +
 net/mac80211/sta_info.c                            |   110 +-
 net/mac80211/sta_info.h                            |   155 +-
 net/mac80211/status.c                              |   130 +-
 net/mac80211/tdls.c                                |    26 +-
 net/mac80211/trace.h                               |     4 +-
 net/mac80211/tx.c                                  |    28 +-
 net/mac80211/util.c                                |    40 -
 net/mac80211/vht.c                                 |    78 +-
 net/mac80211/wpa.c                                 |   103 +-
 net/mac802154/cfg.c                                |     1 +
 net/mac802154/ieee802154_i.h                       |     2 +
 net/mac802154/main.c                               |    54 +-
 net/mac802154/util.c                               |    22 +-
 net/mctp/af_mctp.c                                 |     4 +-
 net/mctp/test/route-test.c                         |     8 +-
 net/mpls/af_mpls.c                                 |     3 +-
 net/mptcp/Makefile                                 |     4 +-
 net/mptcp/bpf.c                                    |    21 +
 net/mptcp/ctrl.c                                   |    21 +
 net/mptcp/mib.c                                    |     5 +
 net/mptcp/mib.h                                    |     7 +
 net/mptcp/mptcp_diag.c                             |   105 +-
 net/mptcp/options.c                                |    69 +-
 net/mptcp/pm.c                                     |   108 +-
 net/mptcp/pm_netlink.c                             |   266 +-
 net/mptcp/pm_userspace.c                           |   429 +
 net/mptcp/protocol.c                               |   123 +-
 net/mptcp/protocol.h                               |   101 +-
 net/mptcp/sockopt.c                                |    21 +-
 net/mptcp/subflow.c                                |    72 +-
 net/netfilter/ipvs/ip_vs_ctl.c                     |     4 +-
 net/netfilter/nf_conncount.c                       |    11 +
 net/netfilter/nf_conntrack_bpf.c                   |    22 +-
 net/netfilter/nf_conntrack_core.c                  |   304 +-
 net/netfilter/nf_conntrack_ecache.c                |   178 +-
 net/netfilter/nf_conntrack_extend.c                |    32 +-
 net/netfilter/nf_conntrack_helper.c                |     5 -
 net/netfilter/nf_conntrack_netlink.c               |   152 +-
 net/netfilter/nf_conntrack_proto.c                 |    10 +-
 net/netfilter/nf_conntrack_proto_tcp.c             |    52 +-
 net/netfilter/nf_conntrack_standalone.c            |     2 +-
 net/netfilter/nf_conntrack_timeout.c               |     7 +-
 net/netfilter/nf_log_syslog.c                      |   136 +-
 net/netfilter/nf_nat_masquerade.c                  |     5 +-
 net/netfilter/nf_tables_api.c                      |     6 +-
 net/netfilter/nfnetlink.c                          |    40 +-
 net/netfilter/nfnetlink_cttimeout.c                |    61 +-
 net/netfilter/nft_bitwise.c                        |    13 +-
 net/netfilter/nft_fib.c                            |     4 +
 net/netfilter/nft_flow_offload.c                   |     8 +
 net/netlink/af_netlink.c                           |     3 +-
 net/netrom/af_netrom.c                             |     3 +-
 net/nfc/core.c                                     |     1 +
 net/nfc/llcp_sock.c                                |     3 +-
 net/nfc/rawsock.c                                  |     3 +-
 net/packet/af_packet.c                             |    22 +-
 net/phonet/datagram.c                              |     4 +-
 net/phonet/pep.c                                   |     7 +-
 net/qrtr/af_qrtr.c                                 |     3 +-
 net/rose/af_rose.c                                 |     3 +-
 net/rose/rose_route.c                              |    25 +-
 net/rxrpc/af_rxrpc.c                               |     2 +-
 net/rxrpc/ar-internal.h                            |    38 +-
 net/rxrpc/call_accept.c                            |    10 +-
 net/rxrpc/call_event.c                             |     7 +-
 net/rxrpc/call_object.c                            |    62 +-
 net/rxrpc/conn_client.c                            |    30 +-
 net/rxrpc/conn_object.c                            |    51 +-
 net/rxrpc/conn_service.c                           |     8 +-
 net/rxrpc/input.c                                  |    62 +-
 net/rxrpc/local_object.c                           |    68 +-
 net/rxrpc/net_ns.c                                 |     7 +-
 net/rxrpc/output.c                                 |    20 +-
 net/rxrpc/peer_object.c                            |    40 +-
 net/rxrpc/proc.c                                   |    85 +-
 net/rxrpc/recvmsg.c                                |     8 +-
 net/rxrpc/sendmsg.c                                |     6 +
 net/rxrpc/skbuff.c                                 |     1 -
 net/rxrpc/sysctl.c                                 |     4 +-
 net/sched/act_api.c                                |     4 +-
 net/sched/act_csum.c                               |     3 +-
 net/sched/act_ct.c                                 |     3 +-
 net/sched/act_gact.c                               |    13 +-
 net/sched/act_gate.c                               |     3 +-
 net/sched/act_mirred.c                             |     4 +-
 net/sched/act_mpls.c                               |    10 +-
 net/sched/act_pedit.c                              |     4 +-
 net/sched/act_police.c                             |    20 +-
 net/sched/act_sample.c                             |     3 +-
 net/sched/act_skbedit.c                            |    65 +-
 net/sched/act_tunnel_key.c                         |     4 +-
 net/sched/act_vlan.c                               |     4 +-
 net/sched/cls_api.c                                |    22 +-
 net/sched/cls_flower.c                             |   104 +-
 net/sched/cls_matchall.c                           |    19 +-
 net/sched/em_meta.c                                |     7 +-
 net/sched/sch_generic.c                            |    12 +-
 net/sctp/input.c                                   |     4 +-
 net/sctp/ipv6.c                                    |     4 +-
 net/sctp/output.c                                  |     3 +-
 net/sctp/socket.c                                  |    18 +-
 net/sctp/stream_sched.c                            |     9 +-
 net/sctp/ulpevent.c                                |     2 +-
 net/smc/af_smc.c                                   |    52 +-
 net/smc/smc_ib.c                                   |     1 +
 net/smc/smc_tx.c                                   |    17 +-
 net/smc/smc_wr.c                                   |     5 +-
 net/socket.c                                       |    75 +-
 net/sunrpc/svcsock.c                               |     2 +-
 net/sunrpc/xprtsock.c                              |     2 +-
 net/tls/tls_device.c                               |    59 +-
 net/tls/tls_main.c                                 |    55 +
 net/tls/tls_sw.c                                   |   491 +-
 net/unix/af_unix.c                                 |    11 +-
 net/unix/unix_bpf.c                                |     5 +-
 net/vmw_vsock/virtio_transport.c                   |   197 +-
 net/vmw_vsock/vmci_transport.c                     |     5 +-
 net/wireless/chan.c                                |    93 +-
 net/wireless/core.h                                |    14 +-
 net/wireless/ibss.c                                |     4 +-
 net/wireless/nl80211.c                             |   417 +-
 net/wireless/reg.c                                 |     4 +
 net/x25/af_x25.c                                   |     3 +-
 net/x25/x25_proc.c                                 |     3 +-
 net/xdp/xsk.c                                      |     4 +-
 net/xdp/xsk_queue.h                                |     4 +-
 net/xdp/xskmap.c                                   |     6 +-
 net/xfrm/espintcp.c                                |     4 +-
 net/xfrm/xfrm_device.c                             |    15 +-
 net/xfrm/xfrm_state.c                              |     4 +-
 net/xfrm/xfrm_user.c                               |     5 +-
 samples/bpf/Makefile                               |    19 +-
 samples/bpf/cpustat_user.c                         |     1 -
 samples/bpf/hbm.c                                  |     5 +-
 samples/bpf/ibumad_user.c                          |     1 -
 samples/bpf/map_perf_test_user.c                   |     1 -
 samples/bpf/offwaketime_user.c                     |     1 -
 samples/bpf/sockex2_user.c                         |     1 -
 samples/bpf/sockex3_user.c                         |     1 -
 samples/bpf/spintest_user.c                        |     1 -
 samples/bpf/syscall_tp_user.c                      |     4 +-
 samples/bpf/task_fd_query_user.c                   |     1 -
 samples/bpf/test_lru_dist.c                        |     1 -
 samples/bpf/test_map_in_map_user.c                 |     1 -
 samples/bpf/test_overhead_user.c                   |     1 -
 samples/bpf/tracex2_user.c                         |     1 -
 samples/bpf/tracex3_user.c                         |     1 -
 samples/bpf/tracex4_user.c                         |     1 -
 samples/bpf/tracex5_user.c                         |     1 -
 samples/bpf/tracex6_user.c                         |     1 -
 samples/bpf/xdp1_user.c                            |     3 +-
 samples/bpf/xdp_adjust_tail_user.c                 |     1 -
 samples/bpf/xdp_monitor_user.c                     |     1 -
 samples/bpf/xdp_redirect_cpu_user.c                |     1 -
 samples/bpf/xdp_redirect_map_multi_user.c          |     1 -
 samples/bpf/xdp_redirect_user.c                    |     1 -
 samples/bpf/xdp_router_ipv4.bpf.c                  |   180 +
 samples/bpf/xdp_router_ipv4_kern.c                 |   186 -
 samples/bpf/xdp_router_ipv4_user.c                 |   456 +-
 samples/bpf/xdp_rxq_info_user.c                    |    23 +-
 samples/bpf/xdp_sample_pkts_user.c                 |     1 -
 samples/bpf/xdp_sample_user.c                      |     1 -
 samples/bpf/xdp_tx_iptunnel_user.c                 |     1 -
 samples/bpf/xdpsock_user.c                         |     9 +-
 samples/bpf/xsk_fwd.c                              |     7 +-
 scripts/bpf_doc.py                                 |     4 +
 tools/bpf/bpftool/btf.c                            |    62 +-
 tools/bpf/bpftool/common.c                         |     8 -
 tools/bpf/bpftool/feature.c                        |    26 +-
 tools/bpf/bpftool/gen.c                            |     5 +-
 tools/bpf/bpftool/link.c                           |     4 +
 tools/bpf/bpftool/main.c                           |     6 +-
 tools/bpf/bpftool/main.h                           |     2 -
 tools/bpf/bpftool/map.c                            |     2 -
 tools/bpf/bpftool/perf.c                           |   112 +-
 tools/bpf/bpftool/pids.c                           |     1 -
 tools/bpf/bpftool/prog.c                           |     4 +-
 tools/bpf/bpftool/struct_ops.c                     |     2 -
 tools/bpf/bpftool/tracelog.c                       |     2 +-
 tools/bpf/runqslower/runqslower.c                  |    18 +-
 tools/include/uapi/asm-generic/socket.h            |     2 +
 tools/include/uapi/asm/bpf_perf_event.h            |     2 +
 tools/include/uapi/linux/bpf.h                     |   125 +
 tools/include/uapi/linux/btf.h                     |     4 +-
 tools/include/uapi/linux/if_link.h                 |     2 +
 tools/lib/bpf/Build                                |     3 +-
 tools/lib/bpf/Makefile                             |     4 +-
 tools/lib/bpf/bpf.c                                |   136 +-
 tools/lib/bpf/bpf.h                                |    46 +-
 tools/lib/bpf/bpf_core_read.h                      |    37 +-
 tools/lib/bpf/bpf_helpers.h                        |    26 +
 tools/lib/bpf/bpf_tracing.h                        |    23 +
 tools/lib/bpf/btf.c                                |    15 +-
 tools/lib/bpf/libbpf.c                             |  1273 +-
 tools/lib/bpf/libbpf.h                             |   279 +-
 tools/lib/bpf/libbpf.map                           |    17 +-
 tools/lib/bpf/libbpf_internal.h                    |    37 +
 tools/lib/bpf/libbpf_version.h                     |     4 +-
 tools/lib/bpf/relo_core.c                          |   104 +-
 tools/lib/bpf/relo_core.h                          |     6 +
 tools/lib/bpf/usdt.bpf.h                           |   259 +
 tools/lib/bpf/usdt.c                               |  1518 ++
 tools/testing/selftests/bpf/Makefile               |    39 +-
 tools/testing/selftests/bpf/bench.c                |     1 -
 tools/testing/selftests/bpf/bpf_rlimit.h           |    28 -
 tools/testing/selftests/bpf/bpf_tcp_helpers.h      |    13 +
 tools/testing/selftests/bpf/config                 |     4 +
 tools/testing/selftests/bpf/flow_dissector_load.c  |     6 +-
 tools/testing/selftests/bpf/get_cgroup_id_user.c   |     4 +-
 .../selftests/bpf/map_tests/map_in_map_batch_ops.c |   252 +
 tools/testing/selftests/bpf/network_helpers.c      |    40 +-
 tools/testing/selftests/bpf/network_helpers.h      |     2 +
 .../testing/selftests/bpf/prog_tests/arg_parsing.c |   107 +
 .../selftests/bpf/prog_tests/attach_probe.c        |    95 +-
 .../testing/selftests/bpf/prog_tests/bpf_cookie.c  |    89 +
 tools/testing/selftests/bpf/prog_tests/bpf_iter.c  |   265 +-
 .../selftests/bpf/prog_tests/bpf_mod_race.c        |     4 +-
 .../testing/selftests/bpf/prog_tests/bpf_tcp_ca.c  |     6 +-
 tools/testing/selftests/bpf/prog_tests/btf.c       |   100 +-
 .../selftests/bpf/prog_tests/core_autosize.c       |     2 +-
 .../testing/selftests/bpf/prog_tests/core_reloc.c  |    13 +-
 .../testing/selftests/bpf/prog_tests/core_retro.c  |    17 +-
 tools/testing/selftests/bpf/prog_tests/dynptr.c    |   137 +
 .../selftests/bpf/prog_tests/fexit_stress.c        |     4 +-
 tools/testing/selftests/bpf/prog_tests/for_each.c  |    42 +-
 .../selftests/bpf/prog_tests/helper_restricted.c   |    10 +-
 .../selftests/bpf/prog_tests/kprobe_multi_test.c   |   159 +-
 tools/testing/selftests/bpf/prog_tests/ksyms_btf.c |    17 +-
 .../selftests/bpf/prog_tests/linked_funcs.c        |     6 +
 tools/testing/selftests/bpf/prog_tests/log_fixup.c |   149 +
 .../selftests/bpf/prog_tests/lookup_and_delete.c   |    15 +-
 tools/testing/selftests/bpf/prog_tests/map_kptr.c  |   148 +
 .../bpf/prog_tests/map_lookup_percpu_elem.c        |    58 +
 tools/testing/selftests/bpf/prog_tests/mptcp.c     |   174 +
 tools/testing/selftests/bpf/prog_tests/netcnt.c    |     2 +-
 .../bpf/prog_tests/prog_tests_framework.c          |    56 +
 .../selftests/bpf/prog_tests/reference_tracking.c  |    23 +-
 .../selftests/bpf/prog_tests/ringbuf_multi.c       |    12 -
 .../selftests/bpf/prog_tests/skb_load_bytes.c      |    45 +
 tools/testing/selftests/bpf/prog_tests/snprintf.c  |     4 +-
 .../selftests/bpf/prog_tests/stacktrace_build_id.c |     8 +-
 .../bpf/prog_tests/stacktrace_build_id_nmi.c       |    11 +-
 .../testing/selftests/bpf/prog_tests/tc_redirect.c |     1 -
 .../selftests/bpf/prog_tests/test_global_funcs.c   |     1 +
 .../selftests/bpf/prog_tests/test_strncmp.c        |    25 +-
 .../testing/selftests/bpf/prog_tests/test_tunnel.c |   423 +
 tools/testing/selftests/bpf/prog_tests/timer_mim.c |     2 +-
 .../selftests/bpf/prog_tests/trampoline_count.c    |   134 +-
 .../selftests/bpf/prog_tests/unpriv_bpf_disabled.c |   312 +
 .../selftests/bpf/prog_tests/uprobe_autoattach.c   |    50 +
 tools/testing/selftests/bpf/prog_tests/usdt.c      |   419 +
 tools/testing/selftests/bpf/progs/bpf_iter.h       |     7 +
 .../selftests/bpf/progs/bpf_iter_bpf_link.c        |    21 +
 .../bpf/progs/btf__core_reloc_size___diff_offs.c   |     3 +
 .../bpf/progs/btf_dump_test_case_syntax.c          |     2 +-
 .../testing/selftests/bpf/progs/core_reloc_types.h |    18 +
 tools/testing/selftests/bpf/progs/dynptr_fail.c    |   588 +
 tools/testing/selftests/bpf/progs/dynptr_success.c |   164 +
 tools/testing/selftests/bpf/progs/exhandler_kern.c |    13 +-
 .../bpf/progs/for_each_map_elem_write_key.c        |    27 +
 tools/testing/selftests/bpf/progs/kprobe_multi.c   |    14 +
 .../selftests/bpf/progs/kprobe_multi_empty.c       |    12 +
 tools/testing/selftests/bpf/progs/linked_funcs1.c  |    15 +-
 tools/testing/selftests/bpf/progs/linked_funcs2.c  |    15 +-
 tools/testing/selftests/bpf/progs/loop5.c          |     1 -
 tools/testing/selftests/bpf/progs/map_kptr.c       |   292 +
 tools/testing/selftests/bpf/progs/map_kptr_fail.c  |   418 +
 tools/testing/selftests/bpf/progs/mptcp_sock.c     |    88 +
 .../selftests/bpf/progs/perf_event_stackmap.c      |     4 +-
 tools/testing/selftests/bpf/progs/profiler.inc.h   |     5 +-
 tools/testing/selftests/bpf/progs/profiler1.c      |     1 -
 tools/testing/selftests/bpf/progs/pyperf.h         |     6 +-
 tools/testing/selftests/bpf/progs/pyperf600.c      |    11 +-
 tools/testing/selftests/bpf/progs/skb_load_bytes.c |    19 +
 tools/testing/selftests/bpf/progs/strncmp_test.c   |     8 +-
 .../selftests/bpf/progs/test_attach_probe.c        |    64 +-
 .../testing/selftests/bpf/progs/test_bpf_cookie.c  |    56 +-
 .../bpf/progs/test_core_reloc_existence.c          |    11 +-
 .../selftests/bpf/progs/test_core_reloc_size.c     |    31 +-
 .../selftests/bpf/progs/test_global_func17.c       |    16 +
 .../selftests/bpf/progs/test_helper_restricted.c   |    16 +-
 .../bpf/progs/test_ksyms_btf_write_check.c         |    18 +-
 .../selftests/bpf/progs/test_l4lb_noinline.c       |     2 +-
 tools/testing/selftests/bpf/progs/test_log_fixup.c |    64 +
 .../bpf/progs/test_map_lookup_percpu_elem.c        |    76 +
 .../selftests/bpf/progs/test_module_attach.c       |     2 +-
 .../testing/selftests/bpf/progs/test_pkt_access.c  |     2 -
 .../selftests/bpf/progs/test_ringbuf_multi.c       |     2 +
 tools/testing/selftests/bpf/progs/test_sk_assign.c |     4 +-
 .../selftests/bpf/progs/test_sk_lookup_kern.c      |    18 +-
 tools/testing/selftests/bpf/progs/test_subprogs.c  |     8 +
 .../selftests/bpf/progs/test_task_pt_regs.c        |     2 +-
 .../selftests/bpf/progs/test_trampoline_count.c    |    16 +-
 .../testing/selftests/bpf/progs/test_tunnel_kern.c |   371 +-
 .../selftests/bpf/progs/test_unpriv_bpf_disabled.c |    83 +
 .../selftests/bpf/progs/test_uprobe_autoattach.c   |    73 +
 .../selftests/bpf/progs/test_urandom_usdt.c        |    70 +
 tools/testing/selftests/bpf/progs/test_usdt.c      |    96 +
 .../selftests/bpf/progs/test_usdt_multispec.c      |    32 +
 .../selftests/bpf/progs/test_xdp_noinline.c        |    12 +-
 tools/testing/selftests/bpf/progs/trigger_bench.c  |     2 +-
 tools/testing/selftests/bpf/sdt-config.h           |     6 +
 tools/testing/selftests/bpf/sdt.h                  |   513 +
 .../selftests/bpf/test_bpftool_synctypes.py        |     2 +-
 tools/testing/selftests/bpf/test_cgroup_storage.c  |     7 +-
 tools/testing/selftests/bpf/test_dev_cgroup.c      |     4 +-
 tools/testing/selftests/bpf/test_lpm_map.c         |    43 +-
 tools/testing/selftests/bpf/test_lru_map.c         |    70 +-
 tools/testing/selftests/bpf/test_offload.py        |     2 +-
 tools/testing/selftests/bpf/test_progs.c           |  1006 +-
 tools/testing/selftests/bpf/test_progs.h           |    89 +-
 .../selftests/bpf/test_skb_cgroup_id_user.c        |     4 +-
 tools/testing/selftests/bpf/test_sock.c            |     6 +-
 tools/testing/selftests/bpf/test_sock_addr.c       |     4 +-
 tools/testing/selftests/bpf/test_sockmap.c         |     5 +-
 tools/testing/selftests/bpf/test_sysctl.c          |     6 +-
 tools/testing/selftests/bpf/test_tag.c             |     4 +-
 .../selftests/bpf/test_tcp_check_syncookie_user.c  |     4 +-
 tools/testing/selftests/bpf/test_tcpnotify_user.c  |     1 -
 tools/testing/selftests/bpf/test_tunnel.sh         |   124 +-
 tools/testing/selftests/bpf/test_verifier.c        |    55 +-
 tools/testing/selftests/bpf/test_verifier_log.c    |     5 +-
 tools/testing/selftests/bpf/test_xsk.sh            |    53 +-
 tools/testing/selftests/bpf/testing_helpers.c      |    91 +-
 tools/testing/selftests/bpf/testing_helpers.h      |     8 +
 tools/testing/selftests/bpf/trace_helpers.c        |     9 +-
 tools/testing/selftests/bpf/urandom_read.c         |    63 +-
 tools/testing/selftests/bpf/urandom_read_aux.c     |     9 +
 tools/testing/selftests/bpf/urandom_read_lib1.c    |    13 +
 tools/testing/selftests/bpf/urandom_read_lib2.c    |     8 +
 tools/testing/selftests/bpf/verifier/calls.c       |    20 +
 tools/testing/selftests/bpf/verifier/map_kptr.c    |   469 +
 .../testing/selftests/bpf/verifier/ref_tracking.c  |     2 +-
 tools/testing/selftests/bpf/verifier/sock.c        |     6 +-
 tools/testing/selftests/bpf/xdp_redirect_multi.c   |     1 -
 tools/testing/selftests/bpf/xdping.c               |     8 +-
 tools/testing/selftests/bpf/xdpxceiver.c           |   553 +-
 tools/testing/selftests/bpf/xdpxceiver.h           |    42 +-
 tools/testing/selftests/bpf/xsk_prereqs.sh         |    47 +-
 .../drivers/net/dsa/bridge_locked_port.sh          |     1 +
 .../selftests/drivers/net/dsa/bridge_mdb.sh        |     1 +
 .../selftests/drivers/net/dsa/bridge_mld.sh        |     1 +
 .../selftests/drivers/net/dsa/bridge_vlan_aware.sh |     1 +
 .../selftests/drivers/net/dsa/bridge_vlan_mcast.sh |     1 +
 .../drivers/net/dsa/bridge_vlan_unaware.sh         |     1 +
 .../selftests/drivers/net/dsa/forwarding.config    |     2 +
 tools/testing/selftests/drivers/net/dsa/lib.sh     |     1 +
 .../selftests/drivers/net/dsa/local_termination.sh |     1 +
 .../selftests/drivers/net/dsa/no_forwarding.sh     |     1 +
 .../drivers/net/mlxsw/devlink_linecard.sh          |   280 +
 .../selftests/drivers/net/mlxsw/qos_burst.sh       |   480 +
 .../selftests/drivers/net/mlxsw/qos_headroom.sh    |     4 +-
 .../testing/selftests/drivers/net/mlxsw/qos_pfc.sh |     4 +-
 .../selftests/drivers/net/mlxsw/sch_red_ets.sh     |     5 +-
 .../selftests/drivers/net/mlxsw/sch_red_root.sh    |     5 +-
 .../selftests/drivers/net/netdevsim/hw_stats_l3.sh |     4 +-
 .../selftests/drivers/net/ocelot/basic_qos.sh      |   253 +
 tools/testing/selftests/drivers/net/ocelot/psfp.sh |   327 +
 .../drivers/net/ocelot/tc_flower_chains.sh         |   202 +-
 tools/testing/selftests/net/.gitignore             |     2 +
 tools/testing/selftests/net/Makefile               |     5 +
 tools/testing/selftests/net/bind_bhash_test.c      |   119 +
 tools/testing/selftests/net/fib_nexthops.sh        |    53 +-
 tools/testing/selftests/net/fib_rule_tests.sh      |    12 +-
 tools/testing/selftests/net/forwarding/Makefile    |     2 +
 .../testing/selftests/net/forwarding/bridge_mdb.sh |   103 +
 .../selftests/net/forwarding/hw_stats_l3.sh        |    16 +-
 .../selftests/net/forwarding/hw_stats_l3_gre.sh    |   109 +
 tools/testing/selftests/net/forwarding/lib.sh      |   144 +-
 .../selftests/net/forwarding/local_termination.sh  |   299 +
 .../selftests/net/forwarding/no_forwarding.sh      |   261 +
 tools/testing/selftests/net/forwarding/router.sh   |    18 +
 .../selftests/net/forwarding/router_vid_1.sh       |    27 +-
 .../testing/selftests/net/forwarding/tc_actions.sh |     2 +-
 tools/testing/selftests/net/forwarding/tsn_lib.sh  |   235 +
 tools/testing/selftests/net/mptcp/config           |     8 +
 tools/testing/selftests/net/mptcp/diag.sh          |    38 +
 tools/testing/selftests/net/mptcp/mptcp_join.sh    |   243 +-
 tools/testing/selftests/net/mptcp/pm_nl_ctl.c      |   645 +-
 tools/testing/selftests/net/mptcp/userspace_pm.sh  |   779 +
 .../selftests/net/ndisc_unsolicited_na_test.sh     |   255 +
 .../selftests/net/stress_reuseport_listen.c        |   105 +
 .../selftests/net/stress_reuseport_listen.sh       |    25 +
 .../testing/selftests/net/vrf_strict_mode_test.sh  |    48 +-
 tools/testing/selftests/netfilter/nft_fib.sh       |    50 +
 tools/testing/selftests/sysctl/sysctl.sh           |    23 +
 1931 files changed, 162345 insertions(+), 59902 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-pcie-mirror.yaml
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mt7622-wed.yaml
 create mode 100644 Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml
 create mode 100644 Documentation/devicetree/bindings/net/marvell,orion-mdio.yaml
 delete mode 100644 Documentation/devicetree/bindings/net/marvell-orion-mdio.txt
 create mode 100644 Documentation/devicetree/bindings/net/mediatek,net.yaml
 delete mode 100644 Documentation/devicetree/bindings/net/mediatek-net.txt
 create mode 100644 Documentation/devicetree/bindings/net/mscc,miim.yaml
 delete mode 100644 Documentation/devicetree/bindings/net/mscc-miim.txt
 create mode 100644 Documentation/devicetree/bindings/net/sunplus,sp7021-emac.yaml
 rename Documentation/devicetree/bindings/{staging => }/net/wireless/silabs,wfx.yaml (98%)
 delete mode 100644 Documentation/networking/device_drivers/appletalk/ltpc.rst
 create mode 100644 Documentation/networking/device_drivers/can/ctu/ctucanfd-driver.rst
 create mode 100644 Documentation/networking/device_drivers/can/ctu/fsm_txt_buffer_user.svg
 delete mode 100644 Documentation/networking/device_drivers/ethernet/dec/de4x5.rst
 create mode 100644 Documentation/networking/device_drivers/ethernet/marvell/octeon_ep.rst
 delete mode 100644 Documentation/networking/device_drivers/wan/index.rst
 delete mode 100644 Documentation/networking/device_drivers/wan/z8530book.rst
 create mode 100644 Documentation/networking/device_drivers/wwan/t7xx.rst
 create mode 100644 Documentation/networking/devlink/devlink-linecard.rst
 create mode 100644 Documentation/networking/skbuff.rst
 delete mode 100644 drivers/atm/ambassador.c
 delete mode 100644 drivers/atm/ambassador.h
 delete mode 100644 drivers/atm/firestream.c
 delete mode 100644 drivers/atm/firestream.h
 delete mode 100644 drivers/atm/horizon.c
 delete mode 100644 drivers/atm/horizon.h
 delete mode 100644 drivers/atm/uPD98401.h
 delete mode 100644 drivers/atm/uPD98402.c
 delete mode 100644 drivers/atm/uPD98402.h
 delete mode 100644 drivers/atm/zatm.c
 delete mode 100644 drivers/atm/zatm.h
 delete mode 100644 drivers/net/appletalk/ltpc.c
 delete mode 100644 drivers/net/appletalk/ltpc.h
 create mode 100644 drivers/net/can/ctucanfd/Kconfig
 create mode 100644 drivers/net/can/ctucanfd/Makefile
 create mode 100644 drivers/net/can/ctucanfd/ctucanfd.h
 create mode 100644 drivers/net/can/ctucanfd/ctucanfd_base.c
 create mode 100644 drivers/net/can/ctucanfd/ctucanfd_kframe.h
 create mode 100644 drivers/net/can/ctucanfd/ctucanfd_kregs.h
 create mode 100644 drivers/net/can/ctucanfd/ctucanfd_pci.c
 create mode 100644 drivers/net/can/ctucanfd/ctucanfd_platform.c
 delete mode 100644 drivers/net/can/led.c
 delete mode 100644 drivers/net/ethernet/amd/ni65.c
 delete mode 100644 drivers/net/ethernet/amd/ni65.h
 delete mode 100644 drivers/net/ethernet/dec/tulip/de4x5.c
 delete mode 100644 drivers/net/ethernet/dec/tulip/de4x5.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/Kconfig
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/Makefile
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_config.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_net.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_ethtool.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_main.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_main.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_regs_cn9k_pf.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_rx.h
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_tx.c
 create mode 100644 drivers/net/ethernet/marvell/octeon_ep/octep_tx.h
 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed.c
 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed.h
 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_debugfs.c
 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_ops.c
 create mode 100644 drivers/net/ethernet/mediatek/mtk_wed_regs.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/accel.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec_offload.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/ipsec_offload.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/tls.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
 rename drivers/net/ethernet/mellanox/mlx5/core/en_accel/{tls_stats.c => ktls_stats.c} (63%)
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.h
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.c
 delete mode 100644 drivers/net/ethernet/mellanox/mlx5/core/fpga/tls.h
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
 create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.h
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
 create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
 delete mode 100644 drivers/net/ethernet/qlogic/qed/qed_nvmetcp_ip_services.c
 create mode 100644 drivers/net/ethernet/sfc/ef100_sriov.c
 create mode 100644 drivers/net/ethernet/sfc/ef100_sriov.h
 create mode 100644 drivers/net/ethernet/sfc/siena/Kconfig
 create mode 100644 drivers/net/ethernet/sfc/siena/Makefile
 create mode 100644 drivers/net/ethernet/sfc/siena/bitfield.h
 create mode 100644 drivers/net/ethernet/sfc/siena/efx.c
 create mode 100644 drivers/net/ethernet/sfc/siena/efx.h
 create mode 100644 drivers/net/ethernet/sfc/siena/efx_channels.c
 create mode 100644 drivers/net/ethernet/sfc/siena/efx_channels.h
 create mode 100644 drivers/net/ethernet/sfc/siena/efx_common.c
 create mode 100644 drivers/net/ethernet/sfc/siena/efx_common.h
 create mode 100644 drivers/net/ethernet/sfc/siena/enum.h
 create mode 100644 drivers/net/ethernet/sfc/siena/ethtool.c
 create mode 100644 drivers/net/ethernet/sfc/siena/ethtool_common.c
 create mode 100644 drivers/net/ethernet/sfc/siena/ethtool_common.h
 rename drivers/net/ethernet/sfc/{ => siena}/farch.c (97%)
 create mode 100644 drivers/net/ethernet/sfc/siena/farch_regs.h
 create mode 100644 drivers/net/ethernet/sfc/siena/filter.h
 create mode 100644 drivers/net/ethernet/sfc/siena/io.h
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi.c
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi.h
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi_mon.c
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi_pcol.h
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi_port.c
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi_port.h
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi_port_common.c
 create mode 100644 drivers/net/ethernet/sfc/siena/mcdi_port_common.h
 create mode 100644 drivers/net/ethernet/sfc/siena/mtd.c
 create mode 100644 drivers/net/ethernet/sfc/siena/net_driver.h
 create mode 100644 drivers/net/ethernet/sfc/siena/nic.c
 create mode 100644 drivers/net/ethernet/sfc/siena/nic.h
 create mode 100644 drivers/net/ethernet/sfc/siena/nic_common.h
 create mode 100644 drivers/net/ethernet/sfc/siena/ptp.c
 create mode 100644 drivers/net/ethernet/sfc/siena/ptp.h
 create mode 100644 drivers/net/ethernet/sfc/siena/rx.c
 create mode 100644 drivers/net/ethernet/sfc/siena/rx_common.c
 create mode 100644 drivers/net/ethernet/sfc/siena/rx_common.h
 create mode 100644 drivers/net/ethernet/sfc/siena/selftest.c
 create mode 100644 drivers/net/ethernet/sfc/siena/selftest.h
 rename drivers/net/ethernet/sfc/{ => siena}/siena.c (89%)
 rename drivers/net/ethernet/sfc/{ => siena}/siena_sriov.c (98%)
 rename drivers/net/ethernet/sfc/{ => siena}/siena_sriov.h (94%)
 create mode 100644 drivers/net/ethernet/sfc/siena/sriov.h
 create mode 100644 drivers/net/ethernet/sfc/siena/tx.c
 create mode 100644 drivers/net/ethernet/sfc/siena/tx.h
 create mode 100644 drivers/net/ethernet/sfc/siena/tx_common.c
 create mode 100644 drivers/net/ethernet/sfc/siena/tx_common.h
 create mode 100644 drivers/net/ethernet/sfc/siena/vfdi.h
 create mode 100644 drivers/net/ethernet/sfc/siena/workarounds.h
 create mode 100644 drivers/net/ethernet/sunplus/Kconfig
 create mode 100644 drivers/net/ethernet/sunplus/Makefile
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_define.h
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_desc.c
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_desc.h
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_driver.c
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_int.c
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_int.h
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_mac.c
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_mac.h
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_mdio.c
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_mdio.h
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_phy.c
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_phy.h
 create mode 100644 drivers/net/ethernet/sunplus/spl2sw_register.h
 delete mode 100644 drivers/net/hamradio/dmascc.c
 create mode 100644 drivers/net/phy/adin1100.c
 create mode 100644 drivers/net/phy/dp83td510.c
 delete mode 100644 drivers/net/wan/cosa.c
 delete mode 100644 drivers/net/wan/cosa.h
 delete mode 100644 drivers/net/wan/hostess_sv11.c
 delete mode 100644 drivers/net/wan/lmc/Makefile
 delete mode 100644 drivers/net/wan/lmc/lmc.h
 delete mode 100644 drivers/net/wan/lmc/lmc_debug.c
 delete mode 100644 drivers/net/wan/lmc/lmc_debug.h
 delete mode 100644 drivers/net/wan/lmc/lmc_ioctl.h
 delete mode 100644 drivers/net/wan/lmc/lmc_main.c
 delete mode 100644 drivers/net/wan/lmc/lmc_media.c
 delete mode 100644 drivers/net/wan/lmc/lmc_proto.c
 delete mode 100644 drivers/net/wan/lmc/lmc_proto.h
 delete mode 100644 drivers/net/wan/lmc/lmc_var.h
 delete mode 100644 drivers/net/wan/sealevel.c
 delete mode 100644 drivers/net/wan/z85230.c
 delete mode 100644 drivers/net/wan/z85230.h
 create mode 100644 drivers/net/wireless/ath/ath11k/pcic.c
 create mode 100644 drivers/net/wireless/ath/ath11k/pcic.h
 create mode 100644 drivers/net/wireless/purelifi/Kconfig
 create mode 100644 drivers/net/wireless/purelifi/Makefile
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/Kconfig
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/Makefile
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/chip.c
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/chip.h
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/firmware.c
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/intf.h
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/mac.c
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/mac.h
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/usb.c
 create mode 100644 drivers/net/wireless/purelifi/plfxlc/usb.h
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8852c_rfk_table.c
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8852c_rfk_table.h
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
 create mode 100644 drivers/net/wireless/silabs/Kconfig
 create mode 100644 drivers/net/wireless/silabs/Makefile
 rename drivers/{staging => net/wireless/silabs}/wfx/Kconfig (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/Makefile (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/bh.c (98%)
 rename drivers/{staging => net/wireless/silabs}/wfx/bh.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/bus.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/bus_sdio.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/bus_spi.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/data_rx.c (93%)
 rename drivers/{staging => net/wireless/silabs}/wfx/data_rx.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/data_tx.c (99%)
 rename drivers/{staging => net/wireless/silabs}/wfx/data_tx.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/debug.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/debug.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/fwio.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/fwio.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_api_cmd.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_api_general.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_api_mib.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_rx.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_rx.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_tx.c (99%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_tx.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_tx_mib.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hif_tx_mib.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hwio.c (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/hwio.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/key.c (99%)
 rename drivers/{staging => net/wireless/silabs}/wfx/key.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/main.c (98%)
 rename drivers/{staging => net/wireless/silabs}/wfx/main.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/queue.c (98%)
 rename drivers/{staging => net/wireless/silabs}/wfx/queue.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/scan.c (92%)
 rename drivers/{staging => net/wireless/silabs}/wfx/scan.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/sta.c (90%)
 rename drivers/{staging => net/wireless/silabs}/wfx/sta.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/traces.h (100%)
 rename drivers/{staging => net/wireless/silabs}/wfx/wfx.h (95%)
 create mode 100644 drivers/net/wwan/t7xx/Makefile
 create mode 100644 drivers/net/wwan/t7xx/t7xx_cldma.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_cldma.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_dpmaif.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_dpmaif.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_cldma.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_cldma.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_dpmaif.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_dpmaif.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_mhccif.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_mhccif.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_modem_ops.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_modem_ops.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_netdev.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_netdev.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pci.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pcie_mac.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_pcie_mac.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port_proxy.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port_proxy.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_port_wwan.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_reg.h
 create mode 100644 drivers/net/wwan/t7xx/t7xx_state_monitor.c
 create mode 100644 drivers/net/wwan/t7xx/t7xx_state_monitor.h
 delete mode 100644 drivers/staging/wfx/TODO
 delete mode 100644 include/linux/can/led.h
 delete mode 100644 include/linux/mlx5/accel.h
 delete mode 100644 include/linux/qed/qed_nvmetcp_ip_services_if.h
 create mode 100644 include/linux/soc/mediatek/mtk_wed.h
 create mode 100644 include/net/net_debug.h
 delete mode 100644 include/uapi/linux/atm_zatm.h
 create mode 100644 kernel/bpf/link_iter.c
 delete mode 100644 net/core/datagram.h
 create mode 100644 net/core/dev.h
 create mode 100644 net/mptcp/bpf.c
 create mode 100644 net/mptcp/pm_userspace.c
 create mode 100644 samples/bpf/xdp_router_ipv4.bpf.c
 delete mode 100644 samples/bpf/xdp_router_ipv4_kern.c
 create mode 100644 tools/lib/bpf/usdt.bpf.h
 create mode 100644 tools/lib/bpf/usdt.c
 delete mode 100644 tools/testing/selftests/bpf/bpf_rlimit.h
 create mode 100644 tools/testing/selftests/bpf/map_tests/map_in_map_batch_ops.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/arg_parsing.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/dynptr.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/log_fixup.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/map_kptr.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/map_lookup_percpu_elem.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/mptcp.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/prog_tests_framework.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/skb_load_bytes.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/test_tunnel.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/unpriv_bpf_disabled.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/uprobe_autoattach.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/usdt.c
 create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_bpf_link.c
 create mode 100644 tools/testing/selftests/bpf/progs/btf__core_reloc_size___diff_offs.c
 create mode 100644 tools/testing/selftests/bpf/progs/dynptr_fail.c
 create mode 100644 tools/testing/selftests/bpf/progs/dynptr_success.c
 create mode 100644 tools/testing/selftests/bpf/progs/for_each_map_elem_write_key.c
 create mode 100644 tools/testing/selftests/bpf/progs/kprobe_multi_empty.c
 create mode 100644 tools/testing/selftests/bpf/progs/map_kptr.c
 create mode 100644 tools/testing/selftests/bpf/progs/map_kptr_fail.c
 create mode 100644 tools/testing/selftests/bpf/progs/mptcp_sock.c
 create mode 100644 tools/testing/selftests/bpf/progs/skb_load_bytes.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_global_func17.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_log_fixup.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_map_lookup_percpu_elem.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_unpriv_bpf_disabled.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_uprobe_autoattach.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_urandom_usdt.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_usdt.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_usdt_multispec.c
 create mode 100644 tools/testing/selftests/bpf/sdt-config.h
 create mode 100644 tools/testing/selftests/bpf/sdt.h
 create mode 100644 tools/testing/selftests/bpf/urandom_read_aux.c
 create mode 100644 tools/testing/selftests/bpf/urandom_read_lib1.c
 create mode 100644 tools/testing/selftests/bpf/urandom_read_lib2.c
 create mode 100644 tools/testing/selftests/bpf/verifier/map_kptr.c
 create mode 120000 tools/testing/selftests/drivers/net/dsa/bridge_locked_port.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/bridge_mdb.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/bridge_mld.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/bridge_vlan_aware.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/bridge_vlan_mcast.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/bridge_vlan_unaware.sh
 create mode 100644 tools/testing/selftests/drivers/net/dsa/forwarding.config
 create mode 120000 tools/testing/selftests/drivers/net/dsa/lib.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/local_termination.sh
 create mode 120000 tools/testing/selftests/drivers/net/dsa/no_forwarding.sh
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/devlink_linecard.sh
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/qos_burst.sh
 create mode 100755 tools/testing/selftests/drivers/net/ocelot/basic_qos.sh
 create mode 100755 tools/testing/selftests/drivers/net/ocelot/psfp.sh
 create mode 100644 tools/testing/selftests/net/bind_bhash_test.c
 create mode 100755 tools/testing/selftests/net/forwarding/bridge_mdb.sh
 create mode 100755 tools/testing/selftests/net/forwarding/hw_stats_l3_gre.sh
 mode change 100644 => 100755 tools/testing/selftests/net/forwarding/lib.sh
 create mode 100755 tools/testing/selftests/net/forwarding/local_termination.sh
 create mode 100755 tools/testing/selftests/net/forwarding/no_forwarding.sh
 create mode 100644 tools/testing/selftests/net/forwarding/tsn_lib.sh
 create mode 100755 tools/testing/selftests/net/mptcp/userspace_pm.sh
 create mode 100755 tools/testing/selftests/net/ndisc_unsolicited_na_test.sh
 create mode 100644 tools/testing/selftests/net/stress_reuseport_listen.c
 create mode 100755 tools/testing/selftests/net/stress_reuseport_listen.sh

^ permalink raw reply	[relevance 1%]

* [PATCH v8 17/31] rust: add `kernel` crate
    2022-08-02  1:50  3% ` [PATCH v8 28/31] samples: add Rust examples Miguel Ojeda
@ 2022-08-02  1:50  1% ` Miguel Ojeda
  2022-08-02 13:34  0%   ` Greg Kroah-Hartman
  1 sibling, 1 reply; 77+ results
From: Miguel Ojeda @ 2022-08-02  1:50 UTC (permalink / raw)
  To: Linus Torvalds, Greg Kroah-Hartman
  Cc: rust-for-linux, linux-kernel, Jarkko Sakkinen, Miguel Ojeda,
	Wedson Almeida Filho, Alex Gaynor, Geoffrey Thomas, Finn Behrens,
	Adam Bratschi-Kaye, Michael Ellerman, Sumera Priyadarsini,
	Sven Van Asbroeck, Gary Guo, Boris-Chengbiao Zhou, Boqun Feng,
	Fox Chen, Dan Robertson, Viktor Garske, Dariusz Sosnowski,
	Léo Lanteri Thauvin, Niklas Mohrin, Gioh Kim, Daniel Xu,
	Milan Landaverde, Morgan Bartlett, Maciej Falkowski,
	Jiapeng Chong, Nándor István Krácser, David Gow,
	John Baublitz, Björn Roy Baron

From: Wedson Almeida Filho <wedsonaf@google.com>

The `kernel` crate currently includes all the abstractions that wrap
kernel features written in C.

These abstractions call the C side of the kernel via the generated
bindings with the `bindgen` tool. Modules developed in Rust should
never call the bindings themselves.

In the future, as the abstractions grow in number, we may need
to split this crate into several, possibly following a similar
subdivision in subsystems as the kernel itself and/or moving
the code to the actual subsystems.

Co-developed-by: Alex Gaynor <alex.gaynor@gmail.com>
Signed-off-by: Alex Gaynor <alex.gaynor@gmail.com>
Co-developed-by: Geoffrey Thomas <geofft@ldpreload.com>
Signed-off-by: Geoffrey Thomas <geofft@ldpreload.com>
Co-developed-by: Finn Behrens <me@kloenk.de>
Signed-off-by: Finn Behrens <me@kloenk.de>
Co-developed-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Signed-off-by: Adam Bratschi-Kaye <ark.email@gmail.com>
Co-developed-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Co-developed-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
Co-developed-by: Sven Van Asbroeck <thesven73@gmail.com>
Signed-off-by: Sven Van Asbroeck <thesven73@gmail.com>
Co-developed-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Gary Guo <gary@garyguo.net>
Co-developed-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Co-developed-by: Fox Chen <foxhlchen@gmail.com>
Signed-off-by: Fox Chen <foxhlchen@gmail.com>
Co-developed-by: Dan Robertson <daniel.robertson@starlab.io>
Signed-off-by: Dan Robertson <daniel.robertson@starlab.io>
Co-developed-by: Viktor Garske <viktor@v-gar.de>
Signed-off-by: Viktor Garske <viktor@v-gar.de>
Co-developed-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl>
Signed-off-by: Dariusz Sosnowski <dsosnowski@dsosnowski.pl>
Co-developed-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
Signed-off-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>
Co-developed-by: Niklas Mohrin <dev@niklasmohrin.de>
Signed-off-by: Niklas Mohrin <dev@niklasmohrin.de>
Co-developed-by: Gioh Kim <gurugio@gmail.com>
Signed-off-by: Gioh Kim <gurugio@gmail.com>
Co-developed-by: Daniel Xu <dxu@dxuuu.xyz>
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
Co-developed-by: Milan Landaverde <milan@mdaverde.com>
Signed-off-by: Milan Landaverde <milan@mdaverde.com>
Co-developed-by: Morgan Bartlett <mjmouse9999@gmail.com>
Signed-off-by: Morgan Bartlett <mjmouse9999@gmail.com>
Co-developed-by: Maciej Falkowski <m.falkowski@samsung.com>
Signed-off-by: Maciej Falkowski <m.falkowski@samsung.com>
Co-developed-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
Signed-off-by: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
Co-developed-by: Nándor István Krácser <bonifaido@gmail.com>
Signed-off-by: Nándor István Krácser <bonifaido@gmail.com>
Co-developed-by: David Gow <davidgow@google.com>
Signed-off-by: David Gow <davidgow@google.com>
Co-developed-by: John Baublitz <john.m.baublitz@gmail.com>
Signed-off-by: John Baublitz <john.m.baublitz@gmail.com>
Co-developed-by: Björn Roy Baron <bjorn3_gh@protonmail.com>
Signed-off-by: Björn Roy Baron <bjorn3_gh@protonmail.com>
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
Co-developed-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
 rust/kernel/allocator.rs                 |  64 ++
 rust/kernel/amba.rs                      | 261 +++++++
 rust/kernel/build_assert.rs              |  83 +++
 rust/kernel/chrdev.rs                    | 206 ++++++
 rust/kernel/clk.rs                       |  79 ++
 rust/kernel/cred.rs                      |  46 ++
 rust/kernel/delay.rs                     | 104 +++
 rust/kernel/device.rs                    | 527 ++++++++++++++
 rust/kernel/driver.rs                    | 442 +++++++++++
 rust/kernel/error.rs                     | 564 ++++++++++++++
 rust/kernel/file.rs                      | 887 +++++++++++++++++++++++
 rust/kernel/fs.rs                        | 846 +++++++++++++++++++++
 rust/kernel/fs/param.rs                  | 553 ++++++++++++++
 rust/kernel/gpio.rs                      | 505 +++++++++++++
 rust/kernel/hwrng.rs                     | 210 ++++++
 rust/kernel/io_buffer.rs                 | 153 ++++
 rust/kernel/io_mem.rs                    | 278 +++++++
 rust/kernel/iov_iter.rs                  |  81 +++
 rust/kernel/irq.rs                       | 681 +++++++++++++++++
 rust/kernel/kasync.rs                    |  50 ++
 rust/kernel/kasync/executor.rs           | 154 ++++
 rust/kernel/kasync/executor/workqueue.rs | 291 ++++++++
 rust/kernel/kasync/net.rs                | 322 ++++++++
 rust/kernel/kunit.rs                     |  91 +++
 rust/kernel/lib.rs                       | 267 +++++++
 rust/kernel/linked_list.rs               | 247 +++++++
 rust/kernel/miscdev.rs                   | 290 ++++++++
 rust/kernel/mm.rs                        | 149 ++++
 rust/kernel/module_param.rs              | 499 +++++++++++++
 rust/kernel/net.rs                       | 392 ++++++++++
 rust/kernel/net/filter.rs                | 447 ++++++++++++
 rust/kernel/of.rs                        |  63 ++
 rust/kernel/pages.rs                     | 144 ++++
 rust/kernel/platform.rs                  | 223 ++++++
 rust/kernel/power.rs                     | 118 +++
 rust/kernel/prelude.rs                   |  36 +
 rust/kernel/print.rs                     | 406 +++++++++++
 rust/kernel/random.rs                    |  42 ++
 rust/kernel/raw_list.rs                  | 361 +++++++++
 rust/kernel/rbtree.rs                    | 563 ++++++++++++++
 rust/kernel/revocable.rs                 | 425 +++++++++++
 rust/kernel/security.rs                  |  38 +
 rust/kernel/static_assert.rs             |  34 +
 rust/kernel/std_vendor.rs                | 161 ++++
 rust/kernel/str.rs                       | 597 +++++++++++++++
 rust/kernel/sync.rs                      |  48 +-
 rust/kernel/sysctl.rs                    | 199 +++++
 rust/kernel/task.rs                      | 239 ++++++
 rust/kernel/types.rs                     | 705 ++++++++++++++++++
 rust/kernel/unsafe_list.rs               | 680 +++++++++++++++++
 rust/kernel/user_ptr.rs                  | 175 +++++
 rust/kernel/workqueue.rs                 | 512 +++++++++++++
 52 files changed, 15518 insertions(+), 20 deletions(-)
 create mode 100644 rust/kernel/allocator.rs
 create mode 100644 rust/kernel/amba.rs
 create mode 100644 rust/kernel/build_assert.rs
 create mode 100644 rust/kernel/chrdev.rs
 create mode 100644 rust/kernel/clk.rs
 create mode 100644 rust/kernel/cred.rs
 create mode 100644 rust/kernel/delay.rs
 create mode 100644 rust/kernel/device.rs
 create mode 100644 rust/kernel/driver.rs
 create mode 100644 rust/kernel/error.rs
 create mode 100644 rust/kernel/file.rs
 create mode 100644 rust/kernel/fs.rs
 create mode 100644 rust/kernel/fs/param.rs
 create mode 100644 rust/kernel/gpio.rs
 create mode 100644 rust/kernel/hwrng.rs
 create mode 100644 rust/kernel/io_buffer.rs
 create mode 100644 rust/kernel/io_mem.rs
 create mode 100644 rust/kernel/iov_iter.rs
 create mode 100644 rust/kernel/irq.rs
 create mode 100644 rust/kernel/kasync.rs
 create mode 100644 rust/kernel/kasync/executor.rs
 create mode 100644 rust/kernel/kasync/executor/workqueue.rs
 create mode 100644 rust/kernel/kasync/net.rs
 create mode 100644 rust/kernel/kunit.rs
 create mode 100644 rust/kernel/lib.rs
 create mode 100644 rust/kernel/linked_list.rs
 create mode 100644 rust/kernel/miscdev.rs
 create mode 100644 rust/kernel/mm.rs
 create mode 100644 rust/kernel/module_param.rs
 create mode 100644 rust/kernel/net.rs
 create mode 100644 rust/kernel/net/filter.rs
 create mode 100644 rust/kernel/of.rs
 create mode 100644 rust/kernel/pages.rs
 create mode 100644 rust/kernel/platform.rs
 create mode 100644 rust/kernel/power.rs
 create mode 100644 rust/kernel/prelude.rs
 create mode 100644 rust/kernel/print.rs
 create mode 100644 rust/kernel/random.rs
 create mode 100644 rust/kernel/raw_list.rs
 create mode 100644 rust/kernel/rbtree.rs
 create mode 100644 rust/kernel/revocable.rs
 create mode 100644 rust/kernel/security.rs
 create mode 100644 rust/kernel/static_assert.rs
 create mode 100644 rust/kernel/std_vendor.rs
 create mode 100644 rust/kernel/str.rs
 create mode 100644 rust/kernel/sysctl.rs
 create mode 100644 rust/kernel/task.rs
 create mode 100644 rust/kernel/types.rs
 create mode 100644 rust/kernel/unsafe_list.rs
 create mode 100644 rust/kernel/user_ptr.rs
 create mode 100644 rust/kernel/workqueue.rs

diff --git a/rust/kernel/allocator.rs b/rust/kernel/allocator.rs
new file mode 100644
index 000000000000..397a3dd57a9b
--- /dev/null
+++ b/rust/kernel/allocator.rs
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Allocator support.
+
+use core::alloc::{GlobalAlloc, Layout};
+use core::ptr;
+
+use crate::bindings;
+
+struct KernelAllocator;
+
+unsafe impl GlobalAlloc for KernelAllocator {
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        // `krealloc()` is used instead of `kmalloc()` because the latter is
+        // an inline function and cannot be bound to as a result.
+        unsafe { bindings::krealloc(ptr::null(), layout.size(), bindings::GFP_KERNEL) as *mut u8 }
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
+        unsafe {
+            bindings::kfree(ptr as *const core::ffi::c_void);
+        }
+    }
+}
+
+#[global_allocator]
+static ALLOCATOR: KernelAllocator = KernelAllocator;
+
+// `rustc` only generates these for some crate types. Even then, we would need
+// to extract the object file that has them from the archive. For the moment,
+// let's generate them ourselves instead.
+//
+// Note that `#[no_mangle]` implies exported too, nowadays.
+#[no_mangle]
+fn __rust_alloc(size: usize, _align: usize) -> *mut u8 {
+    unsafe { bindings::krealloc(core::ptr::null(), size, bindings::GFP_KERNEL) as *mut u8 }
+}
+
+#[no_mangle]
+fn __rust_dealloc(ptr: *mut u8, _size: usize, _align: usize) {
+    unsafe { bindings::kfree(ptr as *const core::ffi::c_void) };
+}
+
+#[no_mangle]
+fn __rust_realloc(ptr: *mut u8, _old_size: usize, _align: usize, new_size: usize) -> *mut u8 {
+    unsafe {
+        bindings::krealloc(
+            ptr as *const core::ffi::c_void,
+            new_size,
+            bindings::GFP_KERNEL,
+        ) as *mut u8
+    }
+}
+
+#[no_mangle]
+fn __rust_alloc_zeroed(size: usize, _align: usize) -> *mut u8 {
+    unsafe {
+        bindings::krealloc(
+            core::ptr::null(),
+            size,
+            bindings::GFP_KERNEL | bindings::__GFP_ZERO,
+        ) as *mut u8
+    }
+}
diff --git a/rust/kernel/amba.rs b/rust/kernel/amba.rs
new file mode 100644
index 000000000000..ec8808124a29
--- /dev/null
+++ b/rust/kernel/amba.rs
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Amba devices and drivers.
+//!
+//! C header: [`include/linux/amba/bus.h`](../../../../include/linux/amba/bus.h)
+
+use crate::{
+    bindings, device, driver, error::from_kernel_result, io_mem::Resource, power, str::CStr,
+    to_result, types::PointerWrapper, Result, ThisModule,
+};
+
+/// A registration of an amba driver.
+pub type Registration<T> = driver::Registration<Adapter<T>>;
+
+/// Id of an Amba device.
+#[derive(Clone, Copy)]
+pub struct DeviceId {
+    /// Device id.
+    pub id: u32,
+
+    /// Mask that identifies which bits are valid in the device id.
+    pub mask: u32,
+}
+
+// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `amba_id::data`.
+unsafe impl const driver::RawDeviceId for DeviceId {
+    type RawType = bindings::amba_id;
+    const ZERO: Self::RawType = bindings::amba_id {
+        id: 0,
+        mask: 0,
+        data: core::ptr::null_mut(),
+    };
+
+    fn to_rawid(&self, offset: isize) -> Self::RawType {
+        bindings::amba_id {
+            id: self.id,
+            mask: self.mask,
+            data: offset as _,
+        }
+    }
+}
+
+/// An amba driver.
+pub trait Driver {
+    /// Data stored on device by driver.
+    type Data: PointerWrapper + Send + Sync + driver::DeviceRemoval = ();
+
+    /// The type that implements the power-management operations.
+    ///
+    /// The default is a type that implements no power-management operations. Drivers that do
+    /// implement them need to specify the type (commonly [`Self`]).
+    type PowerOps: power::Operations<Data = Self::Data> = power::NoOperations<Self::Data>;
+
+    /// The type holding information about each device id supported by the driver.
+    type IdInfo: 'static = ();
+
+    /// The table of device ids supported by the driver.
+    const ID_TABLE: Option<driver::IdTable<'static, DeviceId, Self::IdInfo>> = None;
+
+    /// Probes for the device with the given id.
+    fn probe(dev: &mut Device, id_info: Option<&Self::IdInfo>) -> Result<Self::Data>;
+
+    /// Cleans any resources up that are associated with the device.
+    ///
+    /// This is called when the driver is detached from the device.
+    fn remove(_data: &Self::Data) {}
+}
+
+/// An adapter for the registration of Amba drivers.
+pub struct Adapter<T: Driver>(T);
+
+impl<T: Driver> driver::DriverOps for Adapter<T> {
+    type RegType = bindings::amba_driver;
+
+    unsafe fn register(
+        reg: *mut bindings::amba_driver,
+        name: &'static CStr,
+        module: &'static ThisModule,
+    ) -> Result {
+        // SAFETY: By the safety requirements of this function (defined in the trait definition),
+        // `reg` is non-null and valid.
+        let amba = unsafe { &mut *reg };
+        amba.drv.name = name.as_char_ptr();
+        amba.drv.owner = module.0;
+        amba.probe = Some(probe_callback::<T>);
+        amba.remove = Some(remove_callback::<T>);
+        if let Some(t) = T::ID_TABLE {
+            amba.id_table = t.as_ref();
+        }
+        if cfg!(CONFIG_PM) {
+            // SAFETY: `probe_callback` sets the driver data after calling `T::Data::into_pointer`,
+            // and we guarantee that `T::Data` is the same as `T::PowerOps::Data` by a constraint
+            // in the type declaration.
+            amba.drv.pm = unsafe { power::OpsTable::<T::PowerOps>::build() };
+        }
+        // SAFETY: By the safety requirements of this function, `reg` is valid and fully
+        // initialised.
+        to_result(unsafe { bindings::amba_driver_register(reg) })
+    }
+
+    unsafe fn unregister(reg: *mut bindings::amba_driver) {
+        // SAFETY: By the safety requirements of this function (defined in the trait definition),
+        // `reg` was passed (and updated) by a previous successful call to `amba_driver_register`.
+        unsafe { bindings::amba_driver_unregister(reg) };
+    }
+}
+
+unsafe extern "C" fn probe_callback<T: Driver>(
+    adev: *mut bindings::amba_device,
+    aid: *const bindings::amba_id,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: `adev` is valid by the contract with the C code. `dev` is alive only for the
+        // duration of this call, so it is guaranteed to remain alive for the lifetime of `dev`.
+        let mut dev = unsafe { Device::from_ptr(adev) };
+        // SAFETY: `aid` is valid by the requirements the contract with the C code.
+        let offset = unsafe { (*aid).data };
+        let info = if offset.is_null() {
+            None
+        } else {
+            // SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`,
+            // which guarantees that the resulting pointer is within the table.
+            let ptr = unsafe {
+                aid.cast::<u8>()
+                    .offset(offset as _)
+                    .cast::<Option<T::IdInfo>>()
+            };
+            // SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for
+            // read.
+            unsafe { (&*ptr).as_ref() }
+        };
+        let data = T::probe(&mut dev, info)?;
+        let ptr = T::Data::into_pointer(data);
+        // SAFETY: `adev` is valid for write by the contract with the C code.
+        unsafe { bindings::amba_set_drvdata(adev, ptr as _) };
+        Ok(0)
+    }
+}
+
+unsafe extern "C" fn remove_callback<T: Driver>(adev: *mut bindings::amba_device) {
+    // SAFETY: `adev` is valid by the contract with the C code.
+    let ptr = unsafe { bindings::amba_get_drvdata(adev) };
+    // SAFETY: The value returned by `amba_get_drvdata` was stored by a previous call to
+    // `amba_set_drvdata` in `probe_callback` above; the value comes from a call to
+    // `T::Data::into_pointer`.
+    let data = unsafe { T::Data::from_pointer(ptr) };
+    T::remove(&data);
+    <T::Data as driver::DeviceRemoval>::device_remove(&data);
+}
+
+/// An Amba device.
+///
+/// # Invariants
+///
+/// The field `ptr` is non-null and valid for the lifetime of the object.
+pub struct Device {
+    ptr: *mut bindings::amba_device,
+    res: Option<Resource>,
+}
+
+impl Device {
+    /// Creates a new device from the given pointer.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be non-null and valid. It must remain valid for the lifetime of the returned
+    /// instance.
+    unsafe fn from_ptr(ptr: *mut bindings::amba_device) -> Self {
+        // SAFETY: The safety requirements of the function ensure that `ptr` is valid.
+        let dev = unsafe { &mut *ptr };
+        // INVARIANT: The safety requirements of the function ensure the lifetime invariant.
+        Self {
+            ptr,
+            res: Resource::new(dev.res.start, dev.res.end),
+        }
+    }
+
+    /// Returns the io mem resource associated with the device, if there is one.
+    ///
+    /// Ownership of the resource is transferred to the caller, so subsequent calls to this
+    /// function will return [`None`].
+    pub fn take_resource(&mut self) -> Option<Resource> {
+        self.res.take()
+    }
+
+    /// Returns the index-th irq associated with the device, if one exists.
+    pub fn irq(&self, index: usize) -> Option<u32> {
+        // SAFETY: By the type invariants, `self.ptr` is valid for read.
+        let dev = unsafe { &*self.ptr };
+        if index >= dev.irq.len() || dev.irq[index] == 0 {
+            None
+        } else {
+            Some(dev.irq[index])
+        }
+    }
+}
+
+// SAFETY: The device returned by `raw_device` is the raw Amba device.
+unsafe impl device::RawDevice for Device {
+    fn raw_device(&self) -> *mut bindings::device {
+        // SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
+        unsafe { &mut (*self.ptr).dev }
+    }
+}
+
+/// Declares a kernel module that exposes a single amba driver.
+///
+/// # Examples
+///
+/// ```ignore
+/// # use kernel::{amba, define_amba_id_table, module_amba_driver};
+/// #
+/// struct MyDriver;
+/// impl amba::Driver for MyDriver {
+///     // [...]
+/// #   fn probe(_dev: &mut amba::Device, _id: Option<&Self::IdInfo>) -> Result {
+/// #       Ok(())
+/// #   }
+/// #   define_amba_id_table! {(), [
+/// #       ({ id: 0x00041061, mask: 0x000fffff }, None),
+/// #   ]}
+/// }
+///
+/// module_amba_driver! {
+///     type: MyDriver,
+///     name: b"module_name",
+///     author: b"Author name",
+///     license: b"GPL",
+/// }
+/// ```
+#[macro_export]
+macro_rules! module_amba_driver {
+    ($($f:tt)*) => {
+        $crate::module_driver!(<T>, $crate::amba::Adapter<T>, { $($f)* });
+    };
+}
+
+/// Defines the id table for amba devices.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::{amba, define_amba_id_table};
+/// #
+/// # struct Sample;
+/// # impl kernel::amba::Driver for Sample {
+/// #   fn probe(_dev: &mut amba::Device, _id: Option<&Self::IdInfo>) -> Result {
+/// #       Ok(())
+/// #   }
+/// define_amba_id_table! {(), [
+///     ({ id: 0x00041061, mask: 0x000fffff }, None),
+/// ]}
+/// # }
+/// ```
+#[macro_export]
+macro_rules! define_amba_id_table {
+    ($data_type:ty, $($t:tt)*) => {
+        type IdInfo = $data_type;
+        $crate::define_id_table!(ID_TABLE, $crate::amba::DeviceId, $data_type, $($t)*);
+    };
+}
diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
new file mode 100644
index 000000000000..72c533d8058d
--- /dev/null
+++ b/rust/kernel/build_assert.rs
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Build-time assert.
+
+/// Fails the build if the code path calling `build_error!` can possibly be executed.
+///
+/// If the macro is executed in const context, `build_error!` will panic.
+/// If the compiler or optimizer cannot guarantee that `build_error!` can never
+/// be called, a build error will be triggered.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::build_error;
+/// #[inline]
+/// fn foo(a: usize) -> usize {
+///     a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
+/// }
+///
+/// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
+/// // foo(usize::MAX); // Fails to compile.
+/// ```
+#[macro_export]
+macro_rules! build_error {
+    () => {{
+        $crate::build_error("")
+    }};
+    ($msg:expr) => {{
+        $crate::build_error($msg)
+    }};
+}
+
+/// Asserts that a boolean expression is `true` at compile time.
+///
+/// If the condition is evaluated to `false` in const context, `build_assert!`
+/// will panic. If the compiler or optimizer cannot guarantee the condition will
+/// be evaluated to `true`, a build error will be triggered.
+///
+/// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
+///
+/// # Examples
+///
+/// These examples show that different types of [`assert!`] will trigger errors
+/// at different stage of compilation. It is preferred to err as early as
+/// possible, so [`static_assert!`] should be used whenever possible.
+// TODO: Could be `compile_fail` when supported.
+/// ```ignore
+/// fn foo() {
+///     static_assert!(1 > 1); // Compile-time error
+///     build_assert!(1 > 1); // Build-time error
+///     assert!(1 > 1); // Run-time error
+/// }
+/// ```
+///
+/// When the condition refers to generic parameters or parameters of an inline function,
+/// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
+/// ```
+/// fn foo<const N: usize>() {
+///     // `static_assert!(N > 1);` is not allowed
+///     build_assert!(N > 1); // Build-time check
+///     assert!(N > 1); // Run-time check
+/// }
+///
+/// #[inline]
+/// fn bar(n: usize) {
+///     // `static_assert!(n > 1);` is not allowed
+///     build_assert!(n > 1); // Build-time check
+///     assert!(n > 1); // Run-time check
+/// }
+/// ```
+#[macro_export]
+macro_rules! build_assert {
+    ($cond:expr $(,)?) => {{
+        if !$cond {
+            $crate::build_error(concat!("assertion failed: ", stringify!($cond)));
+        }
+    }};
+    ($cond:expr, $msg:expr) => {{
+        if !$cond {
+            $crate::build_error($msg);
+        }
+    }};
+}
diff --git a/rust/kernel/chrdev.rs b/rust/kernel/chrdev.rs
new file mode 100644
index 000000000000..5b1e083c23b9
--- /dev/null
+++ b/rust/kernel/chrdev.rs
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Character devices.
+//!
+//! Also called "char devices", `chrdev`, `cdev`.
+//!
+//! C header: [`include/linux/cdev.h`](../../../../include/linux/cdev.h)
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#char-devices>
+
+use alloc::boxed::Box;
+use core::convert::TryInto;
+use core::marker::PhantomPinned;
+use core::pin::Pin;
+
+use crate::bindings;
+use crate::error::{code::*, Error, Result};
+use crate::file;
+use crate::str::CStr;
+
+/// Character device.
+///
+/// # Invariants
+///
+///   - [`self.0`] is valid and non-null.
+///   - [`(*self.0).ops`] is valid, non-null and has static lifetime.
+///   - [`(*self.0).owner`] is valid and, if non-null, has module lifetime.
+struct Cdev(*mut bindings::cdev);
+
+impl Cdev {
+    fn alloc(
+        fops: &'static bindings::file_operations,
+        module: &'static crate::ThisModule,
+    ) -> Result<Self> {
+        // SAFETY: FFI call.
+        let cdev = unsafe { bindings::cdev_alloc() };
+        if cdev.is_null() {
+            return Err(ENOMEM);
+        }
+        // SAFETY: `cdev` is valid and non-null since `cdev_alloc()`
+        // returned a valid pointer which was null-checked.
+        unsafe {
+            (*cdev).ops = fops;
+            (*cdev).owner = module.0;
+        }
+        // INVARIANTS:
+        //   - [`self.0`] is valid and non-null.
+        //   - [`(*self.0).ops`] is valid, non-null and has static lifetime,
+        //     because it was coerced from a reference with static lifetime.
+        //   - [`(*self.0).owner`] is valid and, if non-null, has module lifetime,
+        //     guaranteed by the [`ThisModule`] invariant.
+        Ok(Self(cdev))
+    }
+
+    fn add(&mut self, dev: bindings::dev_t, count: core::ffi::c_uint) -> Result {
+        // SAFETY: According to the type invariants:
+        //   - [`self.0`] can be safely passed to [`bindings::cdev_add`].
+        //   - [`(*self.0).ops`] will live at least as long as [`self.0`].
+        //   - [`(*self.0).owner`] will live at least as long as the
+        //     module, which is an implicit requirement.
+        let rc = unsafe { bindings::cdev_add(self.0, dev, count) };
+        if rc != 0 {
+            return Err(Error::from_kernel_errno(rc));
+        }
+        Ok(())
+    }
+}
+
+impl Drop for Cdev {
+    fn drop(&mut self) {
+        // SAFETY: [`self.0`] is valid and non-null by the type invariants.
+        unsafe {
+            bindings::cdev_del(self.0);
+        }
+    }
+}
+
+struct RegistrationInner<const N: usize> {
+    dev: bindings::dev_t,
+    used: usize,
+    cdevs: [Option<Cdev>; N],
+    _pin: PhantomPinned,
+}
+
+/// Character device registration.
+///
+/// May contain up to a fixed number (`N`) of devices. Must be pinned.
+pub struct Registration<const N: usize> {
+    name: &'static CStr,
+    minors_start: u16,
+    this_module: &'static crate::ThisModule,
+    inner: Option<RegistrationInner<N>>,
+}
+
+impl<const N: usize> Registration<{ N }> {
+    /// Creates a [`Registration`] object for a character device.
+    ///
+    /// This does *not* register the device: see [`Self::register()`].
+    ///
+    /// This associated function is intended to be used when you need to avoid
+    /// a memory allocation, e.g. when the [`Registration`] is a member of
+    /// a bigger structure inside your [`crate::Module`] instance. If you
+    /// are going to pin the registration right away, call
+    /// [`Self::new_pinned()`] instead.
+    pub fn new(
+        name: &'static CStr,
+        minors_start: u16,
+        this_module: &'static crate::ThisModule,
+    ) -> Self {
+        Registration {
+            name,
+            minors_start,
+            this_module,
+            inner: None,
+        }
+    }
+
+    /// Creates a pinned [`Registration`] object for a character device.
+    ///
+    /// This does *not* register the device: see [`Self::register()`].
+    pub fn new_pinned(
+        name: &'static CStr,
+        minors_start: u16,
+        this_module: &'static crate::ThisModule,
+    ) -> Result<Pin<Box<Self>>> {
+        Ok(Pin::from(Box::try_new(Self::new(
+            name,
+            minors_start,
+            this_module,
+        ))?))
+    }
+
+    /// Registers a character device.
+    ///
+    /// You may call this once per device type, up to `N` times.
+    pub fn register<T: file::Operations<OpenData = ()>>(self: Pin<&mut Self>) -> Result {
+        // SAFETY: We must ensure that we never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+        if this.inner.is_none() {
+            let mut dev: bindings::dev_t = 0;
+            // SAFETY: Calling unsafe function. `this.name` has `'static`
+            // lifetime.
+            let res = unsafe {
+                bindings::alloc_chrdev_region(
+                    &mut dev,
+                    this.minors_start.into(),
+                    N.try_into()?,
+                    this.name.as_char_ptr(),
+                )
+            };
+            if res != 0 {
+                return Err(Error::from_kernel_errno(res));
+            }
+            const NONE: Option<Cdev> = None;
+            this.inner = Some(RegistrationInner {
+                dev,
+                used: 0,
+                cdevs: [NONE; N],
+                _pin: PhantomPinned,
+            });
+        }
+
+        let mut inner = this.inner.as_mut().unwrap();
+        if inner.used == N {
+            return Err(EINVAL);
+        }
+
+        // SAFETY: The adapter doesn't retrieve any state yet, so it's compatible with any
+        // registration.
+        let fops = unsafe { file::OperationsVtable::<Self, T>::build() };
+        let mut cdev = Cdev::alloc(fops, this.this_module)?;
+        cdev.add(inner.dev + inner.used as bindings::dev_t, 1)?;
+        inner.cdevs[inner.used].replace(cdev);
+        inner.used += 1;
+        Ok(())
+    }
+}
+
+impl<const N: usize> file::OpenAdapter<()> for Registration<{ N }> {
+    unsafe fn convert(_inode: *mut bindings::inode, _file: *mut bindings::file) -> *const () {
+        // TODO: Update the SAFETY comment on the call to `FileOperationsVTable::build` above once
+        // this is updated to retrieve state.
+        &()
+    }
+}
+
+// SAFETY: `Registration` does not expose any of its state across threads
+// (it is fine for multiple threads to have a shared reference to it).
+unsafe impl<const N: usize> Sync for Registration<{ N }> {}
+
+impl<const N: usize> Drop for Registration<{ N }> {
+    fn drop(&mut self) {
+        if let Some(inner) = self.inner.as_mut() {
+            // Replicate kernel C behaviour: drop [`Cdev`]s before calling
+            // [`bindings::unregister_chrdev_region`].
+            for i in 0..inner.used {
+                inner.cdevs[i].take();
+            }
+            // SAFETY: [`self.inner`] is Some, so [`inner.dev`] was previously
+            // created using [`bindings::alloc_chrdev_region`].
+            unsafe {
+                bindings::unregister_chrdev_region(inner.dev, N.try_into().unwrap());
+            }
+        }
+    }
+}
diff --git a/rust/kernel/clk.rs b/rust/kernel/clk.rs
new file mode 100644
index 000000000000..1ec478d96abc
--- /dev/null
+++ b/rust/kernel/clk.rs
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Common clock framework.
+//!
+//! C header: [`include/linux/clk.h`](../../../../include/linux/clk.h)
+
+use crate::{bindings, error::Result, to_result};
+use core::mem::ManuallyDrop;
+
+/// Represents `struct clk *`.
+///
+/// # Invariants
+///
+/// The pointer is valid.
+pub struct Clk(*mut bindings::clk);
+
+impl Clk {
+    /// Creates new clock structure from a raw pointer.
+    ///
+    /// # Safety
+    ///
+    /// The pointer must be valid.
+    pub unsafe fn new(clk: *mut bindings::clk) -> Self {
+        Self(clk)
+    }
+
+    /// Returns value of the rate field of `struct clk`.
+    pub fn get_rate(&self) -> usize {
+        // SAFETY: The pointer is valid by the type invariant.
+        unsafe { bindings::clk_get_rate(self.0) as usize }
+    }
+
+    /// Prepares and enables the underlying hardware clock.
+    ///
+    /// This function should not be called in atomic context.
+    pub fn prepare_enable(self) -> Result<EnabledClk> {
+        // SAFETY: The pointer is valid by the type invariant.
+        to_result(unsafe { bindings::clk_prepare_enable(self.0) })?;
+        Ok(EnabledClk(self))
+    }
+}
+
+impl Drop for Clk {
+    fn drop(&mut self) {
+        // SAFETY: The pointer is valid by the type invariant.
+        unsafe { bindings::clk_put(self.0) };
+    }
+}
+
+// SAFETY: `Clk` is not restricted to a single thread so it is safe
+// to move it between threads.
+unsafe impl Send for Clk {}
+
+/// A clock variant that is prepared and enabled.
+pub struct EnabledClk(Clk);
+
+impl EnabledClk {
+    /// Returns value of the rate field of `struct clk`.
+    pub fn get_rate(&self) -> usize {
+        self.0.get_rate()
+    }
+
+    /// Disables and later unprepares the underlying hardware clock prematurely.
+    ///
+    /// This function should not be called in atomic context.
+    pub fn disable_unprepare(self) -> Clk {
+        let mut clk = ManuallyDrop::new(self);
+        // SAFETY: The pointer is valid by the type invariant.
+        unsafe { bindings::clk_disable_unprepare(clk.0 .0) };
+        core::mem::replace(&mut clk.0, Clk(core::ptr::null_mut()))
+    }
+}
+
+impl Drop for EnabledClk {
+    fn drop(&mut self) {
+        // SAFETY: The pointer is valid by the type invariant.
+        unsafe { bindings::clk_disable_unprepare(self.0 .0) };
+    }
+}
diff --git a/rust/kernel/cred.rs b/rust/kernel/cred.rs
new file mode 100644
index 000000000000..beacc71d92ac
--- /dev/null
+++ b/rust/kernel/cred.rs
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Credentials management.
+//!
+//! C header: [`include/linux/cred.h`](../../../../include/linux/cred.h)
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>
+
+use crate::{bindings, AlwaysRefCounted};
+use core::cell::UnsafeCell;
+
+/// Wraps the kernel's `struct cred`.
+///
+/// # Invariants
+///
+/// Instances of this type are always ref-counted, that is, a call to `get_cred` ensures that the
+/// allocation remains valid at least until the matching call to `put_cred`.
+#[repr(transparent)]
+pub struct Credential(pub(crate) UnsafeCell<bindings::cred>);
+
+impl Credential {
+    /// Creates a reference to a [`Credential`] from a valid pointer.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
+    /// returned [`Credential`] reference.
+    pub(crate) unsafe fn from_ptr<'a>(ptr: *const bindings::cred) -> &'a Self {
+        // SAFETY: The safety requirements guarantee the validity of the dereference, while the
+        // `Credential` type being transparent makes the cast ok.
+        unsafe { &*ptr.cast() }
+    }
+}
+
+// SAFETY: The type invariants guarantee that `Credential` is always ref-counted.
+unsafe impl AlwaysRefCounted for Credential {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::get_cred(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::put_cred(obj.cast().as_ptr()) };
+    }
+}
diff --git a/rust/kernel/delay.rs b/rust/kernel/delay.rs
new file mode 100644
index 000000000000..1e987fa65941
--- /dev/null
+++ b/rust/kernel/delay.rs
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Delay functions for operations like sleeping.
+//!
+//! C header: [`include/linux/delay.h`](../../../../include/linux/delay.h)
+
+use crate::bindings;
+use core::{cmp::min, time::Duration};
+
+const MILLIS_PER_SEC: u64 = 1_000;
+
+fn coarse_sleep_conversion(duration: Duration) -> core::ffi::c_uint {
+    let milli_as_nanos = Duration::MILLISECOND.subsec_nanos();
+
+    // Rounds the nanosecond component of `duration` up to the nearest millisecond.
+    let nanos_as_millis = duration.subsec_nanos().wrapping_add(milli_as_nanos - 1) / milli_as_nanos;
+
+    // Saturates the second component of `duration` to `c_uint::MAX`.
+    let seconds_as_millis = min(
+        duration.as_secs().saturating_mul(MILLIS_PER_SEC),
+        u64::from(core::ffi::c_uint::MAX),
+    ) as core::ffi::c_uint;
+
+    seconds_as_millis.saturating_add(nanos_as_millis)
+}
+
+/// Sleeps safely even with waitqueue interruptions.
+///
+/// This function forwards the call to the C side `msleep` function. As a result,
+/// `duration` will be rounded up to the nearest millisecond if granularity less
+/// than a millisecond is provided. Any [`Duration`] that exceeds
+/// [`c_uint::MAX`][core::ffi::c_uint::MAX] in milliseconds is saturated.
+///
+/// # Examples
+///
+// Keep these in sync with `test_coarse_sleep_examples`.
+/// ```
+/// # use core::time::Duration;
+/// # use kernel::delay::coarse_sleep;
+/// coarse_sleep(Duration::ZERO);                   // Equivalent to `msleep(0)`.
+/// coarse_sleep(Duration::from_nanos(1));          // Equivalent to `msleep(1)`.
+///
+/// coarse_sleep(Duration::from_nanos(1_000_000));  // Equivalent to `msleep(1)`.
+/// coarse_sleep(Duration::from_nanos(1_000_001));  // Equivalent to `msleep(2)`.
+/// coarse_sleep(Duration::from_nanos(1_999_999));  // Equivalent to `msleep(2)`.
+///
+/// coarse_sleep(Duration::from_millis(1));         // Equivalent to `msleep(1)`.
+/// coarse_sleep(Duration::from_millis(2));         // Equivalent to `msleep(2)`.
+///
+/// coarse_sleep(Duration::from_secs(1));           // Equivalent to `msleep(1000)`.
+/// coarse_sleep(Duration::new(1, 1));              // Equivalent to `msleep(1001)`.
+/// coarse_sleep(Duration::new(1, 2));              // Equivalent to `msleep(1001)`.
+/// ```
+pub fn coarse_sleep(duration: Duration) {
+    // SAFETY: `msleep` is safe for all values of its argument.
+    unsafe { bindings::msleep(coarse_sleep_conversion(duration)) }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{coarse_sleep_conversion, MILLIS_PER_SEC};
+    use core::time::Duration;
+
+    #[test]
+    fn test_coarse_sleep_examples() {
+        // Keep these in sync with `coarse_sleep`'s `# Examples` section.
+
+        assert_eq!(coarse_sleep_conversion(Duration::ZERO), 0);
+        assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1)), 1);
+
+        assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1_000_000)), 1);
+        assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1_000_001)), 2);
+        assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1_999_999)), 2);
+
+        assert_eq!(coarse_sleep_conversion(Duration::from_millis(1)), 1);
+        assert_eq!(coarse_sleep_conversion(Duration::from_millis(2)), 2);
+
+        assert_eq!(coarse_sleep_conversion(Duration::from_secs(1)), 1000);
+        assert_eq!(coarse_sleep_conversion(Duration::new(1, 1)), 1001);
+        assert_eq!(coarse_sleep_conversion(Duration::new(1, 2)), 1001);
+    }
+
+    #[test]
+    fn test_coarse_sleep_saturation() {
+        assert!(
+            coarse_sleep_conversion(Duration::new(
+                core::ffi::c_uint::MAX as u64 / MILLIS_PER_SEC,
+                0
+            )) < core::ffi::c_uint::MAX
+        );
+        assert_eq!(
+            coarse_sleep_conversion(Duration::new(
+                core::ffi::c_uint::MAX as u64 / MILLIS_PER_SEC,
+                999_999_999
+            )),
+            core::ffi::c_uint::MAX
+        );
+
+        assert_eq!(
+            coarse_sleep_conversion(Duration::MAX),
+            core::ffi::c_uint::MAX
+        );
+    }
+}
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
new file mode 100644
index 000000000000..c37f555c534d
--- /dev/null
+++ b/rust/kernel/device.rs
@@ -0,0 +1,527 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Generic devices that are part of the kernel's driver model.
+//!
+//! C header: [`include/linux/device.h`](../../../../include/linux/device.h)
+
+#[cfg(CONFIG_COMMON_CLK)]
+use crate::{clk::Clk, error::from_kernel_err_ptr};
+
+use crate::{
+    bindings,
+    revocable::{Revocable, RevocableGuard},
+    str::CStr,
+    sync::{LockClassKey, NeedsLockClass, RevocableMutex, RevocableMutexGuard, UniqueRef},
+    Result,
+};
+use core::{
+    fmt,
+    ops::{Deref, DerefMut},
+    pin::Pin,
+};
+
+#[cfg(CONFIG_PRINTK)]
+use crate::c_str;
+
+/// A raw device.
+///
+/// # Safety
+///
+/// Implementers must ensure that the `*mut device` returned by [`RawDevice::raw_device`] is
+/// related to `self`, that is, actions on it will affect `self`. For example, if one calls
+/// `get_device`, then the refcount on the device represented by `self` will be incremented.
+///
+/// Additionally, implementers must ensure that the device is never renamed. Commit a5462516aa99
+/// ("driver-core: document restrictions on device_rename()") has details on why `device_rename`
+/// should not be used.
+pub unsafe trait RawDevice {
+    /// Returns the raw `struct device` related to `self`.
+    fn raw_device(&self) -> *mut bindings::device;
+
+    /// Returns the name of the device.
+    fn name(&self) -> &CStr {
+        let ptr = self.raw_device();
+
+        // SAFETY: `ptr` is valid because `self` keeps it alive.
+        let name = unsafe { bindings::dev_name(ptr) };
+
+        // SAFETY: The name of the device remains valid while it is alive (because the device is
+        // never renamed, per the safety requirement of this trait). This is guaranteed to be the
+        // case because the reference to `self` outlives the one of the returned `CStr` (enforced
+        // by the compiler because of their lifetimes).
+        unsafe { CStr::from_char_ptr(name) }
+    }
+
+    /// Lookups a clock producer consumed by this device.
+    ///
+    /// Returns a managed reference to the clock producer.
+    #[cfg(CONFIG_COMMON_CLK)]
+    fn clk_get(&self, id: Option<&CStr>) -> Result<Clk> {
+        let id_ptr = match id {
+            Some(cstr) => cstr.as_char_ptr(),
+            None => core::ptr::null(),
+        };
+
+        // SAFETY: `id_ptr` is optional and may be either a valid pointer
+        // from the type invariant or NULL otherwise.
+        let clk_ptr = unsafe { from_kernel_err_ptr(bindings::clk_get(self.raw_device(), id_ptr)) }?;
+
+        // SAFETY: Clock is initialized with valid pointer returned from `bindings::clk_get` call.
+        unsafe { Ok(Clk::new(clk_ptr)) }
+    }
+
+    /// Prints an emergency-level message (level 0) prefixed with device information.
+    ///
+    /// More details are available from [`dev_emerg`].
+    fn pr_emerg(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_EMERG, args) };
+    }
+
+    /// Prints an alert-level message (level 1) prefixed with device information.
+    ///
+    /// More details are available from [`dev_alert`].
+    fn pr_alert(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_ALERT, args) };
+    }
+
+    /// Prints a critical-level message (level 2) prefixed with device information.
+    ///
+    /// More details are available from [`dev_crit`].
+    fn pr_crit(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_CRIT, args) };
+    }
+
+    /// Prints an error-level message (level 3) prefixed with device information.
+    ///
+    /// More details are available from [`dev_err`].
+    fn pr_err(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_ERR, args) };
+    }
+
+    /// Prints a warning-level message (level 4) prefixed with device information.
+    ///
+    /// More details are available from [`dev_warn`].
+    fn pr_warn(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_WARNING, args) };
+    }
+
+    /// Prints a notice-level message (level 5) prefixed with device information.
+    ///
+    /// More details are available from [`dev_notice`].
+    fn pr_notice(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_NOTICE, args) };
+    }
+
+    /// Prints an info-level message (level 6) prefixed with device information.
+    ///
+    /// More details are available from [`dev_info`].
+    fn pr_info(&self, args: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+        unsafe { self.printk(bindings::KERN_INFO, args) };
+    }
+
+    /// Prints a debug-level message (level 7) prefixed with device information.
+    ///
+    /// More details are available from [`dev_dbg`].
+    fn pr_dbg(&self, args: fmt::Arguments<'_>) {
+        if cfg!(debug_assertions) {
+            // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+            unsafe { self.printk(bindings::KERN_DEBUG, args) };
+        }
+    }
+
+    /// Prints the provided message to the console.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `klevel` is null-terminated; in particular, one of the
+    /// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
+    #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
+    unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
+        // SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.raw_device`
+        // is valid because `self` is valid. The "%pA" format string expects a pointer to
+        // `fmt::Arguments`, which is what we're passing as the last argument.
+        #[cfg(CONFIG_PRINTK)]
+        unsafe {
+            bindings::_dev_printk(
+                klevel as *const _ as *const core::ffi::c_char,
+                self.raw_device(),
+                c_str!("%pA").as_char_ptr(),
+                &msg as *const _ as *const core::ffi::c_void,
+            )
+        };
+    }
+}
+
+/// A ref-counted device.
+///
+/// # Invariants
+///
+/// `ptr` is valid, non-null, and has a non-zero reference count. One of the references is owned by
+/// `self`, and will be decremented when `self` is dropped.
+pub struct Device {
+    pub(crate) ptr: *mut bindings::device,
+}
+
+// SAFETY: `Device` only holds a pointer to a C device, which is safe to be used from any thread.
+unsafe impl Send for Device {}
+
+// SAFETY: `Device` only holds a pointer to a C device, references to which are safe to be used
+// from any thread.
+unsafe impl Sync for Device {}
+
+impl Device {
+    /// Creates a new device instance.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `ptr` is valid, non-null, and has a non-zero reference count.
+    pub unsafe fn new(ptr: *mut bindings::device) -> Self {
+        // SAFETY: By the safety requirements, ptr is valid and its refcounted will be incremented.
+        unsafe { bindings::get_device(ptr) };
+        // INVARIANT: The safety requirements satisfy all but one invariant, which is that `self`
+        // owns a reference. This is satisfied by the call to `get_device` above.
+        Self { ptr }
+    }
+
+    /// Creates a new device instance from an existing [`RawDevice`] instance.
+    pub fn from_dev(dev: &dyn RawDevice) -> Self {
+        // SAFETY: The requirements are satisfied by the existence of `RawDevice` and its safety
+        // requirements.
+        unsafe { Self::new(dev.raw_device()) }
+    }
+}
+
+// SAFETY: The device returned by `raw_device` is the one for which we hold a reference.
+unsafe impl RawDevice for Device {
+    fn raw_device(&self) -> *mut bindings::device {
+        self.ptr
+    }
+}
+
+impl Drop for Device {
+    fn drop(&mut self) {
+        // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to
+        // relinquish it now.
+        unsafe { bindings::put_device(self.ptr) };
+    }
+}
+
+/// Device data.
+///
+/// When a device is removed (for whatever reason, for example, because the device was unplugged or
+/// because the user decided to unbind the driver), the driver is given a chance to clean its state
+/// up, and all io resources should ideally not be used anymore.
+///
+/// However, the device data is reference-counted because other subsystems hold pointers to it. So
+/// some device state must be freed and not used anymore, while others must remain accessible.
+///
+/// This struct separates the device data into three categories:
+///   1. Registrations: are destroyed when the device is removed, but before the io resources
+///      become inaccessible.
+///   2. Io resources: are available until the device is removed.
+///   3. General data: remain available as long as the ref count is nonzero.
+///
+/// This struct implements the `DeviceRemoval` trait so that it can clean resources up even if not
+/// explicitly called by the device drivers.
+pub struct Data<T, U, V> {
+    registrations: RevocableMutex<T>,
+    resources: Revocable<U>,
+    general: V,
+}
+
+/// Safely creates an new reference-counted instance of [`Data`].
+#[doc(hidden)]
+#[macro_export]
+macro_rules! new_device_data {
+    ($reg:expr, $res:expr, $gen:expr, $name:literal) => {{
+        static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        let regs = $reg;
+        let res = $res;
+        let gen = $gen;
+        let name = $crate::c_str!($name);
+        $crate::device::Data::try_new(regs, res, gen, name, &CLASS1, &CLASS2)
+    }};
+}
+
+impl<T, U, V> Data<T, U, V> {
+    /// Creates a new instance of `Data`.
+    ///
+    /// It is recommended that the [`new_device_data`] macro be used as it automatically creates
+    /// the lock classes.
+    pub fn try_new(
+        registrations: T,
+        resources: U,
+        general: V,
+        name: &'static CStr,
+        key1: &'static LockClassKey,
+        key2: &'static LockClassKey,
+    ) -> Result<Pin<UniqueRef<Self>>> {
+        let mut ret = Pin::from(UniqueRef::try_new(Self {
+            // SAFETY: We call `RevocableMutex::init` below.
+            registrations: unsafe { RevocableMutex::new(registrations) },
+            resources: Revocable::new(resources),
+            general,
+        })?);
+
+        // SAFETY: `Data::registrations` is pinned when `Data` is.
+        let pinned = unsafe { ret.as_mut().map_unchecked_mut(|d| &mut d.registrations) };
+        pinned.init(name, key1, key2);
+        Ok(ret)
+    }
+
+    /// Returns the resources if they're still available.
+    pub fn resources(&self) -> Option<RevocableGuard<'_, U>> {
+        self.resources.try_access()
+    }
+
+    /// Returns the locked registrations if they're still available.
+    pub fn registrations(&self) -> Option<RevocableMutexGuard<'_, T>> {
+        self.registrations.try_write()
+    }
+}
+
+impl<T, U, V> crate::driver::DeviceRemoval for Data<T, U, V> {
+    fn device_remove(&self) {
+        // We revoke the registrations first so that resources are still available to them during
+        // unregistration.
+        self.registrations.revoke();
+
+        // Release resources now. General data remains available.
+        self.resources.revoke();
+    }
+}
+
+impl<T, U, V> Deref for Data<T, U, V> {
+    type Target = V;
+
+    fn deref(&self) -> &V {
+        &self.general
+    }
+}
+
+impl<T, U, V> DerefMut for Data<T, U, V> {
+    fn deref_mut(&mut self) -> &mut V {
+        &mut self.general
+    }
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! dev_printk {
+    ($method:ident, $dev:expr, $($f:tt)*) => {
+        {
+            // We have an explicity `use` statement here so that callers of this macro are not
+            // required to explicitly use the `RawDevice` trait to use its functions.
+            use $crate::device::RawDevice;
+            ($dev).$method(core::format_args!($($f)*));
+        }
+    }
+}
+
+/// Prints an emergency-level message (level 0) prefixed with device information.
+///
+/// This level should be used if the system is unusable.
+///
+/// Equivalent to the kernel's `dev_emerg` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_emerg!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_emerg {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_emerg, $($f)*); }
+}
+
+/// Prints an alert-level message (level 1) prefixed with device information.
+///
+/// This level should be used if action must be taken immediately.
+///
+/// Equivalent to the kernel's `dev_alert` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_alert!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_alert {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_alert, $($f)*); }
+}
+
+/// Prints a critical-level message (level 2) prefixed with device information.
+///
+/// This level should be used in critical conditions.
+///
+/// Equivalent to the kernel's `dev_crit` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_crit!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_crit {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_crit, $($f)*); }
+}
+
+/// Prints an error-level message (level 3) prefixed with device information.
+///
+/// This level should be used in error conditions.
+///
+/// Equivalent to the kernel's `dev_err` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_err!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_err {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_err, $($f)*); }
+}
+
+/// Prints a warning-level message (level 4) prefixed with device information.
+///
+/// This level should be used in warning conditions.
+///
+/// Equivalent to the kernel's `dev_warn` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_warn!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_warn {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_warn, $($f)*); }
+}
+
+/// Prints a notice-level message (level 5) prefixed with device information.
+///
+/// This level should be used in normal but significant conditions.
+///
+/// Equivalent to the kernel's `dev_notice` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_notice!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_notice {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_notice, $($f)*); }
+}
+
+/// Prints an info-level message (level 6) prefixed with device information.
+///
+/// This level should be used for informational messages.
+///
+/// Equivalent to the kernel's `dev_info` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_info!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_info {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_info, $($f)*); }
+}
+
+/// Prints a debug-level message (level 7) prefixed with device information.
+///
+/// This level should be used for debug messages.
+///
+/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and [`alloc::format!`].
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+///     dev_dbg!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_dbg {
+    ($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*); }
+}
diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
new file mode 100644
index 000000000000..82b39231e311
--- /dev/null
+++ b/rust/kernel/driver.rs
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).
+//!
+//! Each bus/subsystem is expected to implement [`DriverOps`], which allows drivers to register
+//! using the [`Registration`] class.
+
+use crate::{error::code::*, str::CStr, sync::Ref, Result, ThisModule};
+use alloc::boxed::Box;
+use core::{cell::UnsafeCell, marker::PhantomData, ops::Deref, pin::Pin};
+
+/// A subsystem (e.g., PCI, Platform, Amba, etc.) that allows drivers to be written for it.
+pub trait DriverOps {
+    /// The type that holds information about the registration. This is typically a struct defined
+    /// by the C portion of the kernel.
+    type RegType: Default;
+
+    /// Registers a driver.
+    ///
+    /// # Safety
+    ///
+    /// `reg` must point to valid, initialised, and writable memory. It may be modified by this
+    /// function to hold registration state.
+    ///
+    /// On success, `reg` must remain pinned and valid until the matching call to
+    /// [`DriverOps::unregister`].
+    unsafe fn register(
+        reg: *mut Self::RegType,
+        name: &'static CStr,
+        module: &'static ThisModule,
+    ) -> Result;
+
+    /// Unregisters a driver previously registered with [`DriverOps::register`].
+    ///
+    /// # Safety
+    ///
+    /// `reg` must point to valid writable memory, initialised by a previous successful call to
+    /// [`DriverOps::register`].
+    unsafe fn unregister(reg: *mut Self::RegType);
+}
+
+/// The registration of a driver.
+pub struct Registration<T: DriverOps> {
+    is_registered: bool,
+    concrete_reg: UnsafeCell<T::RegType>,
+}
+
+// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
+// share references to it with multiple threads as nothing can be done.
+unsafe impl<T: DriverOps> Sync for Registration<T> {}
+
+impl<T: DriverOps> Registration<T> {
+    /// Creates a new instance of the registration object.
+    pub fn new() -> Self {
+        Self {
+            is_registered: false,
+            concrete_reg: UnsafeCell::new(T::RegType::default()),
+        }
+    }
+
+    /// Allocates a pinned registration object and registers it.
+    ///
+    /// Returns a pinned heap-allocated representation of the registration.
+    pub fn new_pinned(name: &'static CStr, module: &'static ThisModule) -> Result<Pin<Box<Self>>> {
+        let mut reg = Pin::from(Box::try_new(Self::new())?);
+        reg.as_mut().register(name, module)?;
+        Ok(reg)
+    }
+
+    /// Registers a driver with its subsystem.
+    ///
+    /// It must be pinned because the memory block that represents the registration is potentially
+    /// self-referential.
+    pub fn register(
+        self: Pin<&mut Self>,
+        name: &'static CStr,
+        module: &'static ThisModule,
+    ) -> Result {
+        // SAFETY: We never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+        if this.is_registered {
+            // Already registered.
+            return Err(EINVAL);
+        }
+
+        // SAFETY: `concrete_reg` was initialised via its default constructor. It is only freed
+        // after `Self::drop` is called, which first calls `T::unregister`.
+        unsafe { T::register(this.concrete_reg.get(), name, module) }?;
+
+        this.is_registered = true;
+        Ok(())
+    }
+}
+
+impl<T: DriverOps> Default for Registration<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<T: DriverOps> Drop for Registration<T> {
+    fn drop(&mut self) {
+        if self.is_registered {
+            // SAFETY: This path only runs if a previous call to `T::register` completed
+            // successfully.
+            unsafe { T::unregister(self.concrete_reg.get()) };
+        }
+    }
+}
+
+/// Conversion from a device id to a raw device id.
+///
+/// This is meant to be implemented by buses/subsystems so that they can use [`IdTable`] to
+/// guarantee (at compile-time) zero-termination of device id tables provided by drivers.
+///
+/// # Safety
+///
+/// Implementers must ensure that:
+///   - [`RawDeviceId::ZERO`] is actually a zeroed-out version of the raw device id.
+///   - [`RawDeviceId::to_rawid`] stores `offset` in the context/data field of the raw device id so
+///     that buses can recover the pointer to the data.
+pub unsafe trait RawDeviceId {
+    /// The raw type that holds the device id.
+    ///
+    /// Id tables created from [`Self`] are going to hold this type in its zero-terminated array.
+    type RawType: Copy;
+
+    /// A zeroed-out representation of the raw device id.
+    ///
+    /// Id tables created from [`Self`] use [`Self::ZERO`] as the sentinel to indicate the end of
+    /// the table.
+    const ZERO: Self::RawType;
+
+    /// Converts an id into a raw id.
+    ///
+    /// `offset` is the offset from the memory location where the raw device id is stored to the
+    /// location where its associated context information is stored. Implementations must store
+    /// this in the appropriate context/data field of the raw type.
+    fn to_rawid(&self, offset: isize) -> Self::RawType;
+}
+
+/// A zero-terminated device id array, followed by context data.
+#[repr(C)]
+pub struct IdArray<T: RawDeviceId, U, const N: usize> {
+    ids: [T::RawType; N],
+    sentinel: T::RawType,
+    id_infos: [Option<U>; N],
+}
+
+impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
+    /// Creates a new instance of the array.
+    ///
+    /// The contents are derived from the given identifiers and context information.
+    pub const fn new(ids: [T; N], infos: [Option<U>; N]) -> Self
+    where
+        T: ~const RawDeviceId + Copy,
+    {
+        let mut array = Self {
+            ids: [T::ZERO; N],
+            sentinel: T::ZERO,
+            id_infos: infos,
+        };
+        let mut i = 0usize;
+        while i < N {
+            // SAFETY: Both pointers are within `array` (or one byte beyond), consequently they are
+            // derived from the same allocated object. We are using a `u8` pointer, whose size 1,
+            // so the pointers are necessarily 1-byte aligned.
+            let offset = unsafe {
+                (&array.id_infos[i] as *const _ as *const u8)
+                    .offset_from(&array.ids[i] as *const _ as _)
+            };
+            array.ids[i] = ids[i].to_rawid(offset);
+            i += 1;
+        }
+        array
+    }
+
+    /// Returns an `IdTable` backed by `self`.
+    ///
+    /// This is used to essentially erase the array size.
+    pub const fn as_table(&self) -> IdTable<'_, T, U> {
+        IdTable {
+            first: &self.ids[0],
+            _p: PhantomData,
+        }
+    }
+}
+
+/// A device id table.
+///
+/// The table is guaranteed to be zero-terminated and to be followed by an array of context data of
+/// type `Option<U>`.
+pub struct IdTable<'a, T: RawDeviceId, U> {
+    first: &'a T::RawType,
+    _p: PhantomData<&'a U>,
+}
+
+impl<T: RawDeviceId, U> const AsRef<T::RawType> for IdTable<'_, T, U> {
+    fn as_ref(&self) -> &T::RawType {
+        self.first
+    }
+}
+
+/// Counts the number of parenthesis-delimited, comma-separated items.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::count_paren_items;
+///
+/// assert_eq!(0, count_paren_items!());
+/// assert_eq!(1, count_paren_items!((A)));
+/// assert_eq!(1, count_paren_items!((A),));
+/// assert_eq!(2, count_paren_items!((A), (B)));
+/// assert_eq!(2, count_paren_items!((A), (B),));
+/// assert_eq!(3, count_paren_items!((A), (B), (C)));
+/// assert_eq!(3, count_paren_items!((A), (B), (C),));
+/// ```
+#[macro_export]
+macro_rules! count_paren_items {
+    (($($item:tt)*), $($remaining:tt)*) => { 1 + $crate::count_paren_items!($($remaining)*) };
+    (($($item:tt)*)) => { 1 };
+    () => { 0 };
+}
+
+/// Converts a comma-separated list of pairs into an array with the first element. That is, it
+/// discards the second element of the pair.
+///
+/// Additionally, it automatically introduces a type if the first element is warpped in curly
+/// braces, for example, if it's `{v: 10}`, it becomes `X { v: 10 }`; this is to avoid repeating
+/// the type.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::first_item;
+///
+/// #[derive(PartialEq, Debug)]
+/// struct X {
+///     v: u32,
+/// }
+///
+/// assert_eq!([] as [X; 0], first_item!(X, ));
+/// assert_eq!([X { v: 10 }], first_item!(X, ({ v: 10 }, Y)));
+/// assert_eq!([X { v: 10 }], first_item!(X, ({ v: 10 }, Y),));
+/// assert_eq!([X { v: 10 }], first_item!(X, (X { v: 10 }, Y)));
+/// assert_eq!([X { v: 10 }], first_item!(X, (X { v: 10 }, Y),));
+/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y)));
+/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y),));
+/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y)));
+/// assert_eq!([X { v: 10 }, X { v: 20 }], first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y),));
+/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
+///            first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y), ({v: 30}, Y)));
+/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
+///            first_item!(X, ({ v: 10 }, Y), ({ v: 20 }, Y), ({v: 30}, Y),));
+/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
+///            first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y), (X {v: 30}, Y)));
+/// assert_eq!([X { v: 10 }, X { v: 20 }, X { v: 30 }],
+///            first_item!(X, (X { v: 10 }, Y), (X { v: 20 }, Y), (X {v: 30}, Y),));
+/// ```
+#[macro_export]
+macro_rules! first_item {
+    ($id_type:ty, $(({$($first:tt)*}, $second:expr)),* $(,)?) => {
+        {
+            type IdType = $id_type;
+            [$(IdType{$($first)*},)*]
+        }
+    };
+    ($id_type:ty, $(($first:expr, $second:expr)),* $(,)?) => { [$($first,)*] };
+}
+
+/// Converts a comma-separated list of pairs into an array with the second element. That is, it
+/// discards the first element of the pair.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::second_item;
+///
+/// assert_eq!([] as [u32; 0], second_item!());
+/// assert_eq!([10u32], second_item!((X, 10u32)));
+/// assert_eq!([10u32], second_item!((X, 10u32),));
+/// assert_eq!([10u32], second_item!(({ X }, 10u32)));
+/// assert_eq!([10u32], second_item!(({ X }, 10u32),));
+/// assert_eq!([10u32, 20], second_item!((X, 10u32), (X, 20)));
+/// assert_eq!([10u32, 20], second_item!((X, 10u32), (X, 20),));
+/// assert_eq!([10u32, 20], second_item!(({ X }, 10u32), ({ X }, 20)));
+/// assert_eq!([10u32, 20], second_item!(({ X }, 10u32), ({ X }, 20),));
+/// assert_eq!([10u32, 20, 30], second_item!((X, 10u32), (X, 20), (X, 30)));
+/// assert_eq!([10u32, 20, 30], second_item!((X, 10u32), (X, 20), (X, 30),));
+/// assert_eq!([10u32, 20, 30], second_item!(({ X }, 10u32), ({ X }, 20), ({ X }, 30)));
+/// assert_eq!([10u32, 20, 30], second_item!(({ X }, 10u32), ({ X }, 20), ({ X }, 30),));
+/// ```
+#[macro_export]
+macro_rules! second_item {
+    ($(({$($first:tt)*}, $second:expr)),* $(,)?) => { [$($second,)*] };
+    ($(($first:expr, $second:expr)),* $(,)?) => { [$($second,)*] };
+}
+
+/// Defines a new constant [`IdArray`] with a concise syntax.
+///
+/// It is meant to be used by buses and subsystems to create a similar macro with their device id
+/// type already specified, i.e., with fewer parameters to the end user.
+///
+/// # Examples
+///
+// TODO: Exported but not usable by kernel modules (requires `const_trait_impl`).
+/// ```ignore
+/// #![feature(const_trait_impl)]
+/// # use kernel::{define_id_array, driver::RawDeviceId};
+///
+/// #[derive(Copy, Clone)]
+/// struct Id(u32);
+///
+/// // SAFETY: `ZERO` is all zeroes and `to_rawid` stores `offset` as the second element of the raw
+/// // device id pair.
+/// unsafe impl const RawDeviceId for Id {
+///     type RawType = (u64, isize);
+///     const ZERO: Self::RawType = (0, 0);
+///     fn to_rawid(&self, offset: isize) -> Self::RawType {
+///         (self.0 as u64 + 1, offset)
+///     }
+/// }
+///
+/// define_id_array!(A1, Id, (), []);
+/// define_id_array!(A2, Id, &'static [u8], [(Id(10), None)]);
+/// define_id_array!(A3, Id, &'static [u8], [(Id(10), Some(b"id1")), ]);
+/// define_id_array!(A4, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2"))]);
+/// define_id_array!(A5, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2")), ]);
+/// define_id_array!(A6, Id, &'static [u8], [(Id(10), None), (Id(20), Some(b"id2")), ]);
+/// define_id_array!(A7, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), None), ]);
+/// define_id_array!(A8, Id, &'static [u8], [(Id(10), None), (Id(20), None), ]);
+/// ```
+#[macro_export]
+macro_rules! define_id_array {
+    ($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
+        const $table_name:
+            $crate::driver::IdArray<$id_type, $data_type, { $crate::count_paren_items!($($t)*) }> =
+                $crate::driver::IdArray::new(
+                    $crate::first_item!($id_type, $($t)*), $crate::second_item!($($t)*));
+    };
+}
+
+/// Defines a new constant [`IdTable`] with a concise syntax.
+///
+/// It is meant to be used by buses and subsystems to create a similar macro with their device id
+/// type already specified, i.e., with fewer parameters to the end user.
+///
+/// # Examples
+///
+// TODO: Exported but not usable by kernel modules (requires `const_trait_impl`).
+/// ```ignore
+/// #![feature(const_trait_impl)]
+/// # use kernel::{define_id_table, driver::RawDeviceId};
+///
+/// #[derive(Copy, Clone)]
+/// struct Id(u32);
+///
+/// // SAFETY: `ZERO` is all zeroes and `to_rawid` stores `offset` as the second element of the raw
+/// // device id pair.
+/// unsafe impl const RawDeviceId for Id {
+///     type RawType = (u64, isize);
+///     const ZERO: Self::RawType = (0, 0);
+///     fn to_rawid(&self, offset: isize) -> Self::RawType {
+///         (self.0 as u64 + 1, offset)
+///     }
+/// }
+///
+/// define_id_table!(T1, Id, &'static [u8], [(Id(10), None)]);
+/// define_id_table!(T2, Id, &'static [u8], [(Id(10), Some(b"id1")), ]);
+/// define_id_table!(T3, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2"))]);
+/// define_id_table!(T4, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), Some(b"id2")), ]);
+/// define_id_table!(T5, Id, &'static [u8], [(Id(10), None), (Id(20), Some(b"id2")), ]);
+/// define_id_table!(T6, Id, &'static [u8], [(Id(10), Some(b"id1")), (Id(20), None), ]);
+/// define_id_table!(T7, Id, &'static [u8], [(Id(10), None), (Id(20), None), ]);
+/// ```
+#[macro_export]
+macro_rules! define_id_table {
+    ($table_name:ident, $id_type:ty, $data_type:ty, [ $($t:tt)* ]) => {
+        const $table_name: Option<$crate::driver::IdTable<'static, $id_type, $data_type>> = {
+            $crate::define_id_array!(ARRAY, $id_type, $data_type, [ $($t)* ]);
+            Some(ARRAY.as_table())
+        };
+    };
+}
+
+/// Custom code within device removal.
+pub trait DeviceRemoval {
+    /// Cleans resources up when the device is removed.
+    ///
+    /// This is called when a device is removed and offers implementers the chance to run some code
+    /// that cleans state up.
+    fn device_remove(&self);
+}
+
+impl DeviceRemoval for () {
+    fn device_remove(&self) {}
+}
+
+impl<T: DeviceRemoval> DeviceRemoval for Ref<T> {
+    fn device_remove(&self) {
+        self.deref().device_remove();
+    }
+}
+
+impl<T: DeviceRemoval> DeviceRemoval for Box<T> {
+    fn device_remove(&self) {
+        self.deref().device_remove();
+    }
+}
+
+/// A kernel module that only registers the given driver on init.
+///
+/// This is a helper struct to make it easier to define single-functionality modules, in this case,
+/// modules that offer a single driver.
+pub struct Module<T: DriverOps> {
+    _driver: Pin<Box<Registration<T>>>,
+}
+
+impl<T: DriverOps> crate::Module for Module<T> {
+    fn init(name: &'static CStr, module: &'static ThisModule) -> Result<Self> {
+        Ok(Self {
+            _driver: Registration::new_pinned(name, module)?,
+        })
+    }
+}
+
+/// Declares a kernel module that exposes a single driver.
+///
+/// It is meant to be used as a helper by other subsystems so they can more easily expose their own
+/// macros.
+#[macro_export]
+macro_rules! module_driver {
+    (<$gen_type:ident>, $driver_ops:ty, { type: $type:ty, $($f:tt)* }) => {
+        type Ops<$gen_type> = $driver_ops;
+        type ModuleType = $crate::driver::Module<Ops<$type>>;
+        $crate::prelude::module! {
+            type: ModuleType,
+            $($f)*
+        }
+    }
+}
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
new file mode 100644
index 000000000000..f968aa91ddf2
--- /dev/null
+++ b/rust/kernel/error.rs
@@ -0,0 +1,564 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Kernel errors.
+//!
+//! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h)
+
+use crate::bindings;
+use crate::str::CStr;
+use alloc::{
+    alloc::{AllocError, LayoutError},
+    collections::TryReserveError,
+};
+use core::convert::From;
+use core::fmt;
+use core::num::TryFromIntError;
+use core::str::{self, Utf8Error};
+
+/// Contains the C-compatible error codes.
+pub mod code {
+    macro_rules! declare_err {
+        ($err:tt $(,)? $($doc:expr),+) => {
+            $(
+            #[doc = $doc]
+            )*
+            pub const $err: super::Error = super::Error(-(crate::bindings::$err as i32));
+        };
+    }
+
+    declare_err!(EPERM, "Operation not permitted.");
+
+    declare_err!(ENOENT, "No such file or directory.");
+
+    declare_err!(ESRCH, "No such process.");
+
+    declare_err!(EINTR, "Interrupted system call.");
+
+    declare_err!(EIO, "I/O error.");
+
+    declare_err!(ENXIO, "No such device or address.");
+
+    declare_err!(E2BIG, "Argument list too long.");
+
+    declare_err!(ENOEXEC, "Exec format error.");
+
+    declare_err!(EBADF, "Bad file number.");
+
+    declare_err!(ECHILD, "Exec format error.");
+
+    declare_err!(EAGAIN, "Try again.");
+
+    declare_err!(ENOMEM, "Out of memory.");
+
+    declare_err!(EACCES, "Permission denied.");
+
+    declare_err!(EFAULT, "Bad address.");
+
+    declare_err!(ENOTBLK, "Block device required.");
+
+    declare_err!(EBUSY, "Device or resource busy.");
+
+    declare_err!(EEXIST, "File exists.");
+
+    declare_err!(EXDEV, "Cross-device link.");
+
+    declare_err!(ENODEV, "No such device.");
+
+    declare_err!(ENOTDIR, "Not a directory.");
+
+    declare_err!(EISDIR, "Is a directory.");
+
+    declare_err!(EINVAL, "Invalid argument.");
+
+    declare_err!(ENFILE, "File table overflow.");
+
+    declare_err!(EMFILE, "Too many open files.");
+
+    declare_err!(ENOTTY, "Not a typewriter.");
+
+    declare_err!(ETXTBSY, "Text file busy.");
+
+    declare_err!(EFBIG, "File too large.");
+
+    declare_err!(ENOSPC, "No space left on device.");
+
+    declare_err!(ESPIPE, "Illegal seek.");
+
+    declare_err!(EROFS, "Read-only file system.");
+
+    declare_err!(EMLINK, "Too many links.");
+
+    declare_err!(EPIPE, "Broken pipe.");
+
+    declare_err!(EDOM, "Math argument out of domain of func.");
+
+    declare_err!(ERANGE, "Math result not representable.");
+
+    declare_err!(EDEADLK, "Resource deadlock would occur");
+
+    declare_err!(ENAMETOOLONG, "File name too long");
+
+    declare_err!(ENOLCK, "No record locks available");
+
+    declare_err!(
+        ENOSYS,
+        "Invalid system call number.",
+        "",
+        "This error code is special: arch syscall entry code will return",
+        "[`ENOSYS`] if users try to call a syscall that doesn't exist.",
+        "To keep failures of syscalls that really do exist distinguishable from",
+        "failures due to attempts to use a nonexistent syscall, syscall",
+        "implementations should refrain from returning [`ENOSYS`]."
+    );
+
+    declare_err!(ENOTEMPTY, "Directory not empty.");
+
+    declare_err!(ELOOP, "Too many symbolic links encountered.");
+
+    declare_err!(EWOULDBLOCK, "Operation would block.");
+
+    declare_err!(ENOMSG, "No message of desired type.");
+
+    declare_err!(EIDRM, "Identifier removed.");
+
+    declare_err!(ECHRNG, "Channel number out of range.");
+
+    declare_err!(EL2NSYNC, "Level 2 not synchronized.");
+
+    declare_err!(EL3HLT, "Level 3 halted.");
+
+    declare_err!(EL3RST, "Level 3 reset.");
+
+    declare_err!(ELNRNG, "Link number out of range.");
+
+    declare_err!(EUNATCH, "Protocol driver not attached.");
+
+    declare_err!(ENOCSI, "No CSI structure available.");
+
+    declare_err!(EL2HLT, "Level 2 halted.");
+
+    declare_err!(EBADE, "Invalid exchange.");
+
+    declare_err!(EBADR, "Invalid request descriptor.");
+
+    declare_err!(EXFULL, "Exchange full.");
+
+    declare_err!(ENOANO, "No anode.");
+
+    declare_err!(EBADRQC, "Invalid request code.");
+
+    declare_err!(EBADSLT, "Invalid slot.");
+
+    declare_err!(EDEADLOCK, "Resource deadlock would occur.");
+
+    declare_err!(EBFONT, "Bad font file format.");
+
+    declare_err!(ENOSTR, "Device not a stream.");
+
+    declare_err!(ENODATA, "No data available.");
+
+    declare_err!(ETIME, "Timer expired.");
+
+    declare_err!(ENOSR, "Out of streams resources.");
+
+    declare_err!(ENONET, "Machine is not on the network.");
+
+    declare_err!(ENOPKG, "Package not installed.");
+
+    declare_err!(EREMOTE, "Object is remote.");
+
+    declare_err!(ENOLINK, "Link has been severed.");
+
+    declare_err!(EADV, "Advertise error.");
+
+    declare_err!(ESRMNT, "Srmount error.");
+
+    declare_err!(ECOMM, "Communication error on send.");
+
+    declare_err!(EPROTO, "Protocol error.");
+
+    declare_err!(EMULTIHOP, "Multihop attempted.");
+
+    declare_err!(EDOTDOT, "RFS specific error.");
+
+    declare_err!(EBADMSG, "Not a data message.");
+
+    declare_err!(EOVERFLOW, "Value too large for defined data type.");
+
+    declare_err!(ENOTUNIQ, "Name not unique on network.");
+
+    declare_err!(EBADFD, "File descriptor in bad state.");
+
+    declare_err!(EREMCHG, "Remote address changed.");
+
+    declare_err!(ELIBACC, "Can not access a needed shared library.");
+
+    declare_err!(ELIBBAD, "Accessing a corrupted shared library.");
+
+    declare_err!(ELIBSCN, ".lib section in a.out corrupted.");
+
+    declare_err!(ELIBMAX, "Attempting to link in too many shared libraries.");
+
+    declare_err!(ELIBEXEC, "Cannot exec a shared library directly.");
+
+    declare_err!(EILSEQ, "Illegal byte sequence.");
+
+    declare_err!(ERESTART, "Interrupted system call should be restarted.");
+
+    declare_err!(ESTRPIPE, "Streams pipe error.");
+
+    declare_err!(EUSERS, "Too many users.");
+
+    declare_err!(ENOTSOCK, "Socket operation on non-socket.");
+
+    declare_err!(EDESTADDRREQ, "Destination address required.");
+
+    declare_err!(EMSGSIZE, "Message too long.");
+
+    declare_err!(EPROTOTYPE, "Protocol wrong type for socket.");
+
+    declare_err!(ENOPROTOOPT, "Protocol not available.");
+
+    declare_err!(EPROTONOSUPPORT, "Protocol not supported.");
+
+    declare_err!(ESOCKTNOSUPPORT, "Socket type not supported.");
+
+    declare_err!(EOPNOTSUPP, "Operation not supported on transport endpoint.");
+
+    declare_err!(EPFNOSUPPORT, "Protocol family not supported.");
+
+    declare_err!(EAFNOSUPPORT, "Address family not supported by protocol.");
+
+    declare_err!(EADDRINUSE, "Address already in use.");
+
+    declare_err!(EADDRNOTAVAIL, "Cannot assign requested address.");
+
+    declare_err!(ENETDOWN, "Network is down.");
+
+    declare_err!(ENETUNREACH, "Network is unreachable.");
+
+    declare_err!(ENETRESET, "Network dropped connection because of reset.");
+
+    declare_err!(ECONNABORTED, "Software caused connection abort.");
+
+    declare_err!(ECONNRESET, "Connection reset by peer.");
+
+    declare_err!(ENOBUFS, "No buffer space available.");
+
+    declare_err!(EISCONN, "Transport endpoint is already connected.");
+
+    declare_err!(ENOTCONN, "Transport endpoint is not connected.");
+
+    declare_err!(ESHUTDOWN, "Cannot send after transport endpoint shutdown.");
+
+    declare_err!(ETOOMANYREFS, "Too many references: cannot splice.");
+
+    declare_err!(ETIMEDOUT, "Connection timed out.");
+
+    declare_err!(ECONNREFUSED, "Connection refused.");
+
+    declare_err!(EHOSTDOWN, "Host is down.");
+
+    declare_err!(EHOSTUNREACH, "No route to host.");
+
+    declare_err!(EALREADY, "Operation already in progress.");
+
+    declare_err!(EINPROGRESS, "Operation now in progress.");
+
+    declare_err!(ESTALE, "Stale file handle.");
+
+    declare_err!(EUCLEAN, "Structure needs cleaning.");
+
+    declare_err!(ENOTNAM, "Not a XENIX named type file.");
+
+    declare_err!(ENAVAIL, "No XENIX semaphores available.");
+
+    declare_err!(EISNAM, "Is a named type file.");
+
+    declare_err!(EREMOTEIO, "Remote I/O error.");
+
+    declare_err!(EDQUOT, "Quota exceeded.");
+
+    declare_err!(ENOMEDIUM, "No medium found.");
+
+    declare_err!(EMEDIUMTYPE, "Wrong medium type.");
+
+    declare_err!(ECANCELED, "Operation Canceled.");
+
+    declare_err!(ENOKEY, "Required key not available.");
+
+    declare_err!(EKEYEXPIRED, "Key has expired.");
+
+    declare_err!(EKEYREVOKED, "Key has been revoked.");
+
+    declare_err!(EKEYREJECTED, "Key was rejected by service.");
+
+    declare_err!(EOWNERDEAD, "Owner died.", "", "For robust mutexes.");
+
+    declare_err!(ENOTRECOVERABLE, "State not recoverable.");
+
+    declare_err!(ERFKILL, "Operation not possible due to RF-kill.");
+
+    declare_err!(EHWPOISON, "Memory page has hardware error.");
+
+    declare_err!(ERESTARTSYS, "Restart the system call.");
+
+    declare_err!(ENOTSUPP, "Operation is not supported.");
+
+    declare_err!(ENOPARAM, "Parameter not supported.");
+}
+
+/// Generic integer kernel error.
+///
+/// The kernel defines a set of integer generic error codes based on C and
+/// POSIX ones. These codes may have a more specific meaning in some contexts.
+///
+/// # Invariants
+///
+/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct Error(core::ffi::c_int);
+
+impl Error {
+    /// Creates an [`Error`] from a kernel error code.
+    ///
+    /// It is a bug to pass an out-of-range `errno`. `EINVAL` would
+    /// be returned in such a case.
+    pub(crate) fn from_kernel_errno(errno: core::ffi::c_int) -> Error {
+        if errno < -(bindings::MAX_ERRNO as i32) || errno >= 0 {
+            // TODO: Make it a `WARN_ONCE` once available.
+            crate::pr_warn!(
+                "attempted to create `Error` with out of range `errno`: {}",
+                errno
+            );
+            return code::EINVAL;
+        }
+
+        // INVARIANT: The check above ensures the type invariant
+        // will hold.
+        Error(errno)
+    }
+
+    /// Creates an [`Error`] from a kernel error code.
+    ///
+    /// # Safety
+    ///
+    /// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`).
+    pub(crate) unsafe fn from_kernel_errno_unchecked(errno: core::ffi::c_int) -> Error {
+        // INVARIANT: The contract ensures the type invariant
+        // will hold.
+        Error(errno)
+    }
+
+    /// Returns the kernel error code.
+    pub fn to_kernel_errno(self) -> core::ffi::c_int {
+        self.0
+    }
+
+    /// Returns a string representing the error, if one exists.
+    #[cfg(not(testlib))]
+    pub fn name(&self) -> Option<&'static CStr> {
+        // SAFETY: Just an FFI call, there are no extra safety requirements.
+        let ptr = unsafe { bindings::errname(-self.0) };
+        if ptr.is_null() {
+            None
+        } else {
+            // SAFETY: The string returned by `errname` is static and `NUL`-terminated.
+            Some(unsafe { CStr::from_char_ptr(ptr) })
+        }
+    }
+
+    /// Returns a string representing the error, if one exists.
+    ///
+    /// When `testlib` is configured, this always returns `None` to avoid the dependency on a
+    /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still
+    /// run in userspace.
+    #[cfg(testlib)]
+    pub fn name(&self) -> Option<&'static CStr> {
+        None
+    }
+}
+
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.name() {
+            // Print out number if no name can be found.
+            None => f.debug_tuple("Error").field(&-self.0).finish(),
+            // SAFETY: These strings are ASCII-only.
+            Some(name) => f
+                .debug_tuple(unsafe { str::from_utf8_unchecked(name) })
+                .finish(),
+        }
+    }
+}
+
+impl From<TryFromIntError> for Error {
+    fn from(_: TryFromIntError) -> Error {
+        code::EINVAL
+    }
+}
+
+impl From<Utf8Error> for Error {
+    fn from(_: Utf8Error) -> Error {
+        code::EINVAL
+    }
+}
+
+impl From<TryReserveError> for Error {
+    fn from(_: TryReserveError) -> Error {
+        code::ENOMEM
+    }
+}
+
+impl From<LayoutError> for Error {
+    fn from(_: LayoutError) -> Error {
+        code::ENOMEM
+    }
+}
+
+impl From<core::fmt::Error> for Error {
+    fn from(_: core::fmt::Error) -> Error {
+        code::EINVAL
+    }
+}
+
+impl From<core::convert::Infallible> for Error {
+    fn from(e: core::convert::Infallible) -> Error {
+        match e {}
+    }
+}
+
+/// A [`Result`] with an [`Error`] error type.
+///
+/// To be used as the return type for functions that may fail.
+///
+/// # Error codes in C and Rust
+///
+/// In C, it is common that functions indicate success or failure through
+/// their return value; modifying or returning extra data through non-`const`
+/// pointer parameters. In particular, in the kernel, functions that may fail
+/// typically return an `int` that represents a generic error code. We model
+/// those as [`Error`].
+///
+/// In Rust, it is idiomatic to model functions that may fail as returning
+/// a [`Result`]. Since in the kernel many functions return an error code,
+/// [`Result`] is a type alias for a [`core::result::Result`] that uses
+/// [`Error`] as its error type.
+///
+/// Note that even if a function does not return anything when it succeeds,
+/// it should still be modeled as returning a `Result` rather than
+/// just an [`Error`].
+pub type Result<T = ()> = core::result::Result<T, Error>;
+
+impl From<AllocError> for Error {
+    fn from(_: AllocError) -> Error {
+        code::ENOMEM
+    }
+}
+
+// # Invariant: `-bindings::MAX_ERRNO` fits in an `i16`.
+crate::static_assert!(bindings::MAX_ERRNO <= -(i16::MIN as i32) as u32);
+
+pub(crate) fn from_kernel_result_helper<T>(r: Result<T>) -> T
+where
+    T: From<i16>,
+{
+    match r {
+        Ok(v) => v,
+        // NO-OVERFLOW: negative `errno`s are no smaller than `-bindings::MAX_ERRNO`,
+        // `-bindings::MAX_ERRNO` fits in an `i16` as per invariant above,
+        // therefore a negative `errno` always fits in an `i16` and will not overflow.
+        Err(e) => T::from(e.to_kernel_errno() as i16),
+    }
+}
+
+/// Transforms a [`crate::error::Result<T>`] to a kernel C integer result.
+///
+/// This is useful when calling Rust functions that return [`crate::error::Result<T>`]
+/// from inside `extern "C"` functions that need to return an integer
+/// error result.
+///
+/// `T` should be convertible to an `i16` via `From<i16>`.
+///
+/// # Examples
+///
+/// ```ignore
+/// # use kernel::from_kernel_result;
+/// # use kernel::bindings;
+/// unsafe extern "C" fn probe_callback(
+///     pdev: *mut bindings::platform_device,
+/// ) -> core::ffi::c_int {
+///     from_kernel_result! {
+///         let ptr = devm_alloc(pdev)?;
+///         bindings::platform_set_drvdata(pdev, ptr);
+///         Ok(0)
+///     }
+/// }
+/// ```
+macro_rules! from_kernel_result {
+    ($($tt:tt)*) => {{
+        $crate::error::from_kernel_result_helper((|| {
+            $($tt)*
+        })())
+    }};
+}
+
+pub(crate) use from_kernel_result;
+
+/// Transform a kernel "error pointer" to a normal pointer.
+///
+/// Some kernel C API functions return an "error pointer" which optionally
+/// embeds an `errno`. Callers are supposed to check the returned pointer
+/// for errors. This function performs the check and converts the "error pointer"
+/// to a normal pointer in an idiomatic fashion.
+///
+/// # Examples
+///
+/// ```ignore
+/// # use kernel::from_kernel_err_ptr;
+/// # use kernel::bindings;
+/// fn devm_platform_ioremap_resource(
+///     pdev: &mut PlatformDevice,
+///     index: u32,
+/// ) -> Result<*mut core::ffi::c_void> {
+///     // SAFETY: FFI call.
+///     unsafe {
+///         from_kernel_err_ptr(bindings::devm_platform_ioremap_resource(
+///             pdev.to_ptr(),
+///             index,
+///         ))
+///     }
+/// }
+/// ```
+// TODO: Remove `dead_code` marker once an in-kernel client is available.
+#[allow(dead_code)]
+pub(crate) fn from_kernel_err_ptr<T>(ptr: *mut T) -> Result<*mut T> {
+    // CAST: Casting a pointer to `*const core::ffi::c_void` is always valid.
+    let const_ptr: *const core::ffi::c_void = ptr.cast();
+    // SAFETY: The FFI function does not deref the pointer.
+    if unsafe { bindings::IS_ERR(const_ptr) } {
+        // SAFETY: The FFI function does not deref the pointer.
+        let err = unsafe { bindings::PTR_ERR(const_ptr) };
+        // CAST: If `IS_ERR()` returns `true`,
+        // then `PTR_ERR()` is guaranteed to return a
+        // negative value greater-or-equal to `-bindings::MAX_ERRNO`,
+        // which always fits in an `i16`, as per the invariant above.
+        // And an `i16` always fits in an `i32`. So casting `err` to
+        // an `i32` can never overflow, and is always valid.
+        //
+        // SAFETY: `IS_ERR()` ensures `err` is a
+        // negative value greater-or-equal to `-bindings::MAX_ERRNO`.
+        return Err(unsafe { Error::from_kernel_errno_unchecked(err as i32) });
+    }
+    Ok(ptr)
+}
+
+/// Converts an integer as returned by a C kernel function to an error if it's negative, and
+/// `Ok(())` otherwise.
+pub fn to_result(err: core::ffi::c_int) -> Result {
+    if err < 0 {
+        Err(Error::from_kernel_errno(err))
+    } else {
+        Ok(())
+    }
+}
diff --git a/rust/kernel/file.rs b/rust/kernel/file.rs
new file mode 100644
index 000000000000..62538e6b3eea
--- /dev/null
+++ b/rust/kernel/file.rs
@@ -0,0 +1,887 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Files and file descriptors.
+//!
+//! C headers: [`include/linux/fs.h`](../../../../include/linux/fs.h) and
+//! [`include/linux/file.h`](../../../../include/linux/file.h)
+
+use crate::{
+    bindings,
+    cred::Credential,
+    error::{code::*, from_kernel_result, Error, Result},
+    io_buffer::{IoBufferReader, IoBufferWriter},
+    iov_iter::IovIter,
+    mm,
+    sync::CondVar,
+    types::PointerWrapper,
+    user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter},
+    ARef, AlwaysRefCounted,
+};
+use core::convert::{TryFrom, TryInto};
+use core::{cell::UnsafeCell, marker, mem, ptr};
+use macros::vtable;
+
+/// Flags associated with a [`File`].
+pub mod flags {
+    /// File is opened in append mode.
+    pub const O_APPEND: u32 = bindings::O_APPEND;
+
+    /// Signal-driven I/O is enabled.
+    pub const O_ASYNC: u32 = bindings::FASYNC;
+
+    /// Close-on-exec flag is set.
+    pub const O_CLOEXEC: u32 = bindings::O_CLOEXEC;
+
+    /// File was created if it didn't already exist.
+    pub const O_CREAT: u32 = bindings::O_CREAT;
+
+    /// Direct I/O is enabled for this file.
+    pub const O_DIRECT: u32 = bindings::O_DIRECT;
+
+    /// File must be a directory.
+    pub const O_DIRECTORY: u32 = bindings::O_DIRECTORY;
+
+    /// Like [`O_SYNC`] except metadata is not synced.
+    pub const O_DSYNC: u32 = bindings::O_DSYNC;
+
+    /// Ensure that this file is created with the `open(2)` call.
+    pub const O_EXCL: u32 = bindings::O_EXCL;
+
+    /// Large file size enabled (`off64_t` over `off_t`).
+    pub const O_LARGEFILE: u32 = bindings::O_LARGEFILE;
+
+    /// Do not update the file last access time.
+    pub const O_NOATIME: u32 = bindings::O_NOATIME;
+
+    /// File should not be used as process's controlling terminal.
+    pub const O_NOCTTY: u32 = bindings::O_NOCTTY;
+
+    /// If basename of path is a symbolic link, fail open.
+    pub const O_NOFOLLOW: u32 = bindings::O_NOFOLLOW;
+
+    /// File is using nonblocking I/O.
+    pub const O_NONBLOCK: u32 = bindings::O_NONBLOCK;
+
+    /// Also known as `O_NDELAY`.
+    ///
+    /// This is effectively the same flag as [`O_NONBLOCK`] on all architectures
+    /// except SPARC64.
+    pub const O_NDELAY: u32 = bindings::O_NDELAY;
+
+    /// Used to obtain a path file descriptor.
+    pub const O_PATH: u32 = bindings::O_PATH;
+
+    /// Write operations on this file will flush data and metadata.
+    pub const O_SYNC: u32 = bindings::O_SYNC;
+
+    /// This file is an unnamed temporary regular file.
+    pub const O_TMPFILE: u32 = bindings::O_TMPFILE;
+
+    /// File should be truncated to length 0.
+    pub const O_TRUNC: u32 = bindings::O_TRUNC;
+
+    /// Bitmask for access mode flags.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use kernel::file;
+    /// # fn do_something() {}
+    /// # let flags = 0;
+    /// if (flags & file::flags::O_ACCMODE) == file::flags::O_RDONLY {
+    ///     do_something();
+    /// }
+    /// ```
+    pub const O_ACCMODE: u32 = bindings::O_ACCMODE;
+
+    /// File is read only.
+    pub const O_RDONLY: u32 = bindings::O_RDONLY;
+
+    /// File is write only.
+    pub const O_WRONLY: u32 = bindings::O_WRONLY;
+
+    /// File can be both read and written.
+    pub const O_RDWR: u32 = bindings::O_RDWR;
+}
+
+/// Wraps the kernel's `struct file`.
+///
+/// # Invariants
+///
+/// Instances of this type are always ref-counted, that is, a call to `get_file` ensures that the
+/// allocation remains valid at least until the matching call to `fput`.
+#[repr(transparent)]
+pub struct File(pub(crate) UnsafeCell<bindings::file>);
+
+// TODO: Accessing fields of `struct file` through the pointer is UB because other threads may be
+// writing to them. However, this is how the C code currently operates: naked reads and writes to
+// fields. Even if we used relaxed atomics on the Rust side, we can't force this on the C side.
+impl File {
+    /// Constructs a new [`struct file`] wrapper from a file descriptor.
+    ///
+    /// The file descriptor belongs to the current process.
+    pub fn from_fd(fd: u32) -> Result<ARef<Self>> {
+        // SAFETY: FFI call, there are no requirements on `fd`.
+        let ptr = ptr::NonNull::new(unsafe { bindings::fget(fd) }).ok_or(EBADF)?;
+
+        // SAFETY: `fget` increments the refcount before returning.
+        Ok(unsafe { ARef::from_raw(ptr.cast()) })
+    }
+
+    /// Creates a reference to a [`File`] from a valid pointer.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
+    /// returned [`File`] instance.
+    pub(crate) unsafe fn from_ptr<'a>(ptr: *const bindings::file) -> &'a File {
+        // SAFETY: The safety requirements guarantee the validity of the dereference, while the
+        // `File` type being transparent makes the cast ok.
+        unsafe { &*ptr.cast() }
+    }
+
+    /// Returns the current seek/cursor/pointer position (`struct file::f_pos`).
+    pub fn pos(&self) -> u64 {
+        // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount.
+        unsafe { core::ptr::addr_of!((*self.0.get()).f_pos).read() as _ }
+    }
+
+    /// Returns the credentials of the task that originally opened the file.
+    pub fn cred(&self) -> &Credential {
+        // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount.
+        let ptr = unsafe { core::ptr::addr_of!((*self.0.get()).f_cred).read() };
+        // SAFETY: The lifetimes of `self` and `Credential` are tied, so it is guaranteed that
+        // the credential pointer remains valid (because the file is still alive, and it doesn't
+        // change over the lifetime of a file).
+        unsafe { Credential::from_ptr(ptr) }
+    }
+
+    /// Returns the flags associated with the file.
+    ///
+    /// The flags are a combination of the constants in [`flags`].
+    pub fn flags(&self) -> u32 {
+        // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount.
+        unsafe { core::ptr::addr_of!((*self.0.get()).f_flags).read() }
+    }
+}
+
+// SAFETY: The type invariants guarantee that `File` is always ref-counted.
+unsafe impl AlwaysRefCounted for File {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::get_file(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::fput(obj.cast().as_ptr()) }
+    }
+}
+
+/// A file descriptor reservation.
+///
+/// This allows the creation of a file descriptor in two steps: first, we reserve a slot for it,
+/// then we commit or drop the reservation. The first step may fail (e.g., the current process ran
+/// out of available slots), but commit and drop never fail (and are mutually exclusive).
+pub struct FileDescriptorReservation {
+    fd: u32,
+}
+
+impl FileDescriptorReservation {
+    /// Creates a new file descriptor reservation.
+    pub fn new(flags: u32) -> Result<Self> {
+        // SAFETY: FFI call, there are no safety requirements on `flags`.
+        let fd = unsafe { bindings::get_unused_fd_flags(flags) };
+        if fd < 0 {
+            return Err(Error::from_kernel_errno(fd));
+        }
+        Ok(Self { fd: fd as _ })
+    }
+
+    /// Returns the file descriptor number that was reserved.
+    pub fn reserved_fd(&self) -> u32 {
+        self.fd
+    }
+
+    /// Commits the reservation.
+    ///
+    /// The previously reserved file descriptor is bound to `file`.
+    pub fn commit(self, file: ARef<File>) {
+        // SAFETY: `self.fd` was previously returned by `get_unused_fd_flags`, and `file.ptr` is
+        // guaranteed to have an owned ref count by its type invariants.
+        unsafe { bindings::fd_install(self.fd, file.0.get()) };
+
+        // `fd_install` consumes both the file descriptor and the file reference, so we cannot run
+        // the destructors.
+        core::mem::forget(self);
+        core::mem::forget(file);
+    }
+}
+
+impl Drop for FileDescriptorReservation {
+    fn drop(&mut self) {
+        // SAFETY: `self.fd` was returned by a previous call to `get_unused_fd_flags`.
+        unsafe { bindings::put_unused_fd(self.fd) };
+    }
+}
+
+/// Wraps the kernel's `struct poll_table_struct`.
+///
+/// # Invariants
+///
+/// The pointer `PollTable::ptr` is null or valid.
+pub struct PollTable {
+    ptr: *mut bindings::poll_table_struct,
+}
+
+impl PollTable {
+    /// Constructors a new `struct poll_table_struct` wrapper.
+    ///
+    /// # Safety
+    ///
+    /// The pointer `ptr` must be either null or a valid pointer for the lifetime of the object.
+    unsafe fn from_ptr(ptr: *mut bindings::poll_table_struct) -> Self {
+        Self { ptr }
+    }
+
+    /// Associates the given file and condition variable to this poll table. It means notifying the
+    /// condition variable will notify the poll table as well; additionally, the association
+    /// between the condition variable and the file will automatically be undone by the kernel when
+    /// the file is destructed. To unilaterally remove the association before then, one can call
+    /// [`CondVar::free_waiters`].
+    ///
+    /// # Safety
+    ///
+    /// If the condition variable is destroyed before the file, then [`CondVar::free_waiters`] must
+    /// be called to ensure that all waiters are flushed out.
+    pub unsafe fn register_wait<'a>(&self, file: &'a File, cv: &'a CondVar) {
+        if self.ptr.is_null() {
+            return;
+        }
+
+        // SAFETY: `PollTable::ptr` is guaranteed to be valid by the type invariants and the null
+        // check above.
+        let table = unsafe { &*self.ptr };
+        if let Some(proc) = table._qproc {
+            // SAFETY: All pointers are known to be valid.
+            unsafe { proc(file.0.get() as _, cv.wait_list.get(), self.ptr) }
+        }
+    }
+}
+
+/// Equivalent to [`std::io::SeekFrom`].
+///
+/// [`std::io::SeekFrom`]: https://doc.rust-lang.org/std/io/enum.SeekFrom.html
+pub enum SeekFrom {
+    /// Equivalent to C's `SEEK_SET`.
+    Start(u64),
+
+    /// Equivalent to C's `SEEK_END`.
+    End(i64),
+
+    /// Equivalent to C's `SEEK_CUR`.
+    Current(i64),
+}
+
+pub(crate) struct OperationsVtable<A, T>(marker::PhantomData<A>, marker::PhantomData<T>);
+
+impl<A: OpenAdapter<T::OpenData>, T: Operations> OperationsVtable<A, T> {
+    /// Called by the VFS when an inode should be opened.
+    ///
+    /// Calls `T::open` on the returned value of `A::convert`.
+    ///
+    /// # Safety
+    ///
+    /// The returned value of `A::convert` must be a valid non-null pointer and
+    /// `T:open` must return a valid non-null pointer on an `Ok` result.
+    unsafe extern "C" fn open_callback(
+        inode: *mut bindings::inode,
+        file: *mut bindings::file,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: `A::convert` must return a valid non-null pointer that
+            // should point to data in the inode or file that lives longer
+            // than the following use of `T::open`.
+            let arg = unsafe { A::convert(inode, file) };
+            // SAFETY: The C contract guarantees that `file` is valid. Additionally,
+            // `fileref` never outlives this function, so it is guaranteed to be
+            // valid.
+            let fileref = unsafe { File::from_ptr(file) };
+            // SAFETY: `arg` was previously returned by `A::convert` and must
+            // be a valid non-null pointer.
+            let ptr = T::open(unsafe { &*arg }, fileref)?.into_pointer();
+            // SAFETY: The C contract guarantees that `private_data` is available
+            // for implementers of the file operations (no other C code accesses
+            // it), so we know that there are no concurrent threads/CPUs accessing
+            // it (it's not visible to any other Rust code).
+            unsafe { (*file).private_data = ptr as *mut core::ffi::c_void };
+            Ok(0)
+        }
+    }
+
+    unsafe extern "C" fn read_callback(
+        file: *mut bindings::file,
+        buf: *mut core::ffi::c_char,
+        len: core::ffi::c_size_t,
+        offset: *mut bindings::loff_t,
+    ) -> core::ffi::c_ssize_t {
+        from_kernel_result! {
+            let mut data =
+                unsafe { UserSlicePtr::new(buf as *mut core::ffi::c_void, len).writer() };
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            // No `FMODE_UNSIGNED_OFFSET` support, so `offset` must be in [0, 2^63).
+            // See <https://github.com/fishinabarrel/linux-kernel-module-rust/pull/113>.
+            let read = T::read(
+                f,
+                unsafe { File::from_ptr(file) },
+                &mut data,
+                unsafe { *offset }.try_into()?,
+            )?;
+            unsafe { (*offset) += bindings::loff_t::try_from(read).unwrap() };
+            Ok(read as _)
+        }
+    }
+
+    unsafe extern "C" fn read_iter_callback(
+        iocb: *mut bindings::kiocb,
+        raw_iter: *mut bindings::iov_iter,
+    ) -> isize {
+        from_kernel_result! {
+            let mut iter = unsafe { IovIter::from_ptr(raw_iter) };
+            let file = unsafe { (*iocb).ki_filp };
+            let offset = unsafe { (*iocb).ki_pos };
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            let read = T::read(
+                f,
+                unsafe { File::from_ptr(file) },
+                &mut iter,
+                offset.try_into()?,
+            )?;
+            unsafe { (*iocb).ki_pos += bindings::loff_t::try_from(read).unwrap() };
+            Ok(read as _)
+        }
+    }
+
+    unsafe extern "C" fn write_callback(
+        file: *mut bindings::file,
+        buf: *const core::ffi::c_char,
+        len: core::ffi::c_size_t,
+        offset: *mut bindings::loff_t,
+    ) -> core::ffi::c_ssize_t {
+        from_kernel_result! {
+            let mut data =
+                unsafe { UserSlicePtr::new(buf as *mut core::ffi::c_void, len).reader() };
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            // No `FMODE_UNSIGNED_OFFSET` support, so `offset` must be in [0, 2^63).
+            // See <https://github.com/fishinabarrel/linux-kernel-module-rust/pull/113>.
+            let written = T::write(
+                f,
+                unsafe { File::from_ptr(file) },
+                &mut data,
+                unsafe { *offset }.try_into()?,
+            )?;
+            unsafe { (*offset) += bindings::loff_t::try_from(written).unwrap() };
+            Ok(written as _)
+        }
+    }
+
+    unsafe extern "C" fn write_iter_callback(
+        iocb: *mut bindings::kiocb,
+        raw_iter: *mut bindings::iov_iter,
+    ) -> isize {
+        from_kernel_result! {
+            let mut iter = unsafe { IovIter::from_ptr(raw_iter) };
+            let file = unsafe { (*iocb).ki_filp };
+            let offset = unsafe { (*iocb).ki_pos };
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            let written = T::write(
+                f,
+                unsafe { File::from_ptr(file) },
+                &mut iter,
+                offset.try_into()?,
+            )?;
+            unsafe { (*iocb).ki_pos += bindings::loff_t::try_from(written).unwrap() };
+            Ok(written as _)
+        }
+    }
+
+    unsafe extern "C" fn release_callback(
+        _inode: *mut bindings::inode,
+        file: *mut bindings::file,
+    ) -> core::ffi::c_int {
+        let ptr = mem::replace(unsafe { &mut (*file).private_data }, ptr::null_mut());
+        T::release(unsafe { T::Data::from_pointer(ptr as _) }, unsafe {
+            File::from_ptr(file)
+        });
+        0
+    }
+
+    unsafe extern "C" fn llseek_callback(
+        file: *mut bindings::file,
+        offset: bindings::loff_t,
+        whence: core::ffi::c_int,
+    ) -> bindings::loff_t {
+        from_kernel_result! {
+            let off = match whence as u32 {
+                bindings::SEEK_SET => SeekFrom::Start(offset.try_into()?),
+                bindings::SEEK_CUR => SeekFrom::Current(offset),
+                bindings::SEEK_END => SeekFrom::End(offset),
+                _ => return Err(EINVAL),
+            };
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            let off = T::seek(f, unsafe { File::from_ptr(file) }, off)?;
+            Ok(off as bindings::loff_t)
+        }
+    }
+
+    unsafe extern "C" fn unlocked_ioctl_callback(
+        file: *mut bindings::file,
+        cmd: core::ffi::c_uint,
+        arg: core::ffi::c_ulong,
+    ) -> core::ffi::c_long {
+        from_kernel_result! {
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            let mut cmd = IoctlCommand::new(cmd as _, arg as _);
+            let ret = T::ioctl(f, unsafe { File::from_ptr(file) }, &mut cmd)?;
+            Ok(ret as _)
+        }
+    }
+
+    unsafe extern "C" fn compat_ioctl_callback(
+        file: *mut bindings::file,
+        cmd: core::ffi::c_uint,
+        arg: core::ffi::c_ulong,
+    ) -> core::ffi::c_long {
+        from_kernel_result! {
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            let mut cmd = IoctlCommand::new(cmd as _, arg as _);
+            let ret = T::compat_ioctl(f, unsafe { File::from_ptr(file) }, &mut cmd)?;
+            Ok(ret as _)
+        }
+    }
+
+    unsafe extern "C" fn mmap_callback(
+        file: *mut bindings::file,
+        vma: *mut bindings::vm_area_struct,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+
+            // SAFETY: The C API guarantees that `vma` is valid for the duration of this call.
+            // `area` only lives within this call, so it is guaranteed to be valid.
+            let mut area = unsafe { mm::virt::Area::from_ptr(vma) };
+
+            // SAFETY: The C API guarantees that `file` is valid for the duration of this call,
+            // which is longer than the lifetime of the file reference.
+            T::mmap(f, unsafe { File::from_ptr(file) }, &mut area)?;
+            Ok(0)
+        }
+    }
+
+    unsafe extern "C" fn fsync_callback(
+        file: *mut bindings::file,
+        start: bindings::loff_t,
+        end: bindings::loff_t,
+        datasync: core::ffi::c_int,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            let start = start.try_into()?;
+            let end = end.try_into()?;
+            let datasync = datasync != 0;
+            // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+            // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the
+            // `release` callback, which the C API guarantees that will be called only when all
+            // references to `file` have been released, so we know it can't be called while this
+            // function is running.
+            let f = unsafe { T::Data::borrow((*file).private_data) };
+            let res = T::fsync(f, unsafe { File::from_ptr(file) }, start, end, datasync)?;
+            Ok(res.try_into().unwrap())
+        }
+    }
+
+    unsafe extern "C" fn poll_callback(
+        file: *mut bindings::file,
+        wait: *mut bindings::poll_table_struct,
+    ) -> bindings::__poll_t {
+        // SAFETY: `private_data` was initialised by `open_callback` with a value returned by
+        // `T::Data::into_pointer`. `T::Data::from_pointer` is only called by the `release`
+        // callback, which the C API guarantees that will be called only when all references to
+        // `file` have been released, so we know it can't be called while this function is running.
+        let f = unsafe { T::Data::borrow((*file).private_data) };
+        match T::poll(f, unsafe { File::from_ptr(file) }, unsafe {
+            &PollTable::from_ptr(wait)
+        }) {
+            Ok(v) => v,
+            Err(_) => bindings::POLLERR,
+        }
+    }
+
+    const VTABLE: bindings::file_operations = bindings::file_operations {
+        open: Some(Self::open_callback),
+        release: Some(Self::release_callback),
+        read: if T::HAS_READ {
+            Some(Self::read_callback)
+        } else {
+            None
+        },
+        write: if T::HAS_WRITE {
+            Some(Self::write_callback)
+        } else {
+            None
+        },
+        llseek: if T::HAS_SEEK {
+            Some(Self::llseek_callback)
+        } else {
+            None
+        },
+
+        check_flags: None,
+        compat_ioctl: if T::HAS_COMPAT_IOCTL {
+            Some(Self::compat_ioctl_callback)
+        } else {
+            None
+        },
+        copy_file_range: None,
+        fallocate: None,
+        fadvise: None,
+        fasync: None,
+        flock: None,
+        flush: None,
+        fsync: if T::HAS_FSYNC {
+            Some(Self::fsync_callback)
+        } else {
+            None
+        },
+        get_unmapped_area: None,
+        iterate: None,
+        iterate_shared: None,
+        iopoll: None,
+        lock: None,
+        mmap: if T::HAS_MMAP {
+            Some(Self::mmap_callback)
+        } else {
+            None
+        },
+        mmap_supported_flags: 0,
+        owner: ptr::null_mut(),
+        poll: if T::HAS_POLL {
+            Some(Self::poll_callback)
+        } else {
+            None
+        },
+        read_iter: if T::HAS_READ {
+            Some(Self::read_iter_callback)
+        } else {
+            None
+        },
+        remap_file_range: None,
+        sendpage: None,
+        setlease: None,
+        show_fdinfo: None,
+        splice_read: None,
+        splice_write: None,
+        unlocked_ioctl: if T::HAS_IOCTL {
+            Some(Self::unlocked_ioctl_callback)
+        } else {
+            None
+        },
+        uring_cmd: None,
+        write_iter: if T::HAS_WRITE {
+            Some(Self::write_iter_callback)
+        } else {
+            None
+        },
+    };
+
+    /// Builds an instance of [`struct file_operations`].
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that the adapter is compatible with the way the device is registered.
+    pub(crate) const unsafe fn build() -> &'static bindings::file_operations {
+        &Self::VTABLE
+    }
+}
+
+/// Allows the handling of ioctls defined with the `_IO`, `_IOR`, `_IOW`, and `_IOWR` macros.
+///
+/// For each macro, there is a handler function that takes the appropriate types as arguments.
+pub trait IoctlHandler: Sync {
+    /// The type of the first argument to each associated function.
+    type Target<'a>;
+
+    /// Handles ioctls defined with the `_IO` macro, that is, with no buffer as argument.
+    fn pure(_this: Self::Target<'_>, _file: &File, _cmd: u32, _arg: usize) -> Result<i32> {
+        Err(EINVAL)
+    }
+
+    /// Handles ioctls defined with the `_IOR` macro, that is, with an output buffer provided as
+    /// argument.
+    fn read(
+        _this: Self::Target<'_>,
+        _file: &File,
+        _cmd: u32,
+        _writer: &mut UserSlicePtrWriter,
+    ) -> Result<i32> {
+        Err(EINVAL)
+    }
+
+    /// Handles ioctls defined with the `_IOW` macro, that is, with an input buffer provided as
+    /// argument.
+    fn write(
+        _this: Self::Target<'_>,
+        _file: &File,
+        _cmd: u32,
+        _reader: &mut UserSlicePtrReader,
+    ) -> Result<i32> {
+        Err(EINVAL)
+    }
+
+    /// Handles ioctls defined with the `_IOWR` macro, that is, with a buffer for both input and
+    /// output provided as argument.
+    fn read_write(
+        _this: Self::Target<'_>,
+        _file: &File,
+        _cmd: u32,
+        _data: UserSlicePtr,
+    ) -> Result<i32> {
+        Err(EINVAL)
+    }
+}
+
+/// Represents an ioctl command.
+///
+/// It can use the components of an ioctl command to dispatch ioctls using
+/// [`IoctlCommand::dispatch`].
+pub struct IoctlCommand {
+    cmd: u32,
+    arg: usize,
+    user_slice: Option<UserSlicePtr>,
+}
+
+impl IoctlCommand {
+    /// Constructs a new [`IoctlCommand`].
+    fn new(cmd: u32, arg: usize) -> Self {
+        let size = (cmd >> bindings::_IOC_SIZESHIFT) & bindings::_IOC_SIZEMASK;
+
+        // SAFETY: We only create one instance of the user slice per ioctl call, so TOCTOU issues
+        // are not possible.
+        let user_slice = Some(unsafe { UserSlicePtr::new(arg as _, size as _) });
+        Self {
+            cmd,
+            arg,
+            user_slice,
+        }
+    }
+
+    /// Dispatches the given ioctl to the appropriate handler based on the value of the command. It
+    /// also creates a [`UserSlicePtr`], [`UserSlicePtrReader`], or [`UserSlicePtrWriter`]
+    /// depending on the direction of the buffer of the command.
+    ///
+    /// It is meant to be used in implementations of [`Operations::ioctl`] and
+    /// [`Operations::compat_ioctl`].
+    pub fn dispatch<T: IoctlHandler>(
+        &mut self,
+        handler: T::Target<'_>,
+        file: &File,
+    ) -> Result<i32> {
+        let dir = (self.cmd >> bindings::_IOC_DIRSHIFT) & bindings::_IOC_DIRMASK;
+        if dir == bindings::_IOC_NONE {
+            return T::pure(handler, file, self.cmd, self.arg);
+        }
+
+        let data = self.user_slice.take().ok_or(EINVAL)?;
+        const READ_WRITE: u32 = bindings::_IOC_READ | bindings::_IOC_WRITE;
+        match dir {
+            bindings::_IOC_WRITE => T::write(handler, file, self.cmd, &mut data.reader()),
+            bindings::_IOC_READ => T::read(handler, file, self.cmd, &mut data.writer()),
+            READ_WRITE => T::read_write(handler, file, self.cmd, data),
+            _ => Err(EINVAL),
+        }
+    }
+
+    /// Returns the raw 32-bit value of the command and the ptr-sized argument.
+    pub fn raw(&self) -> (u32, usize) {
+        (self.cmd, self.arg)
+    }
+}
+
+/// Trait for extracting file open arguments from kernel data structures.
+///
+/// This is meant to be implemented by registration managers.
+pub trait OpenAdapter<T: Sync> {
+    /// Converts untyped data stored in [`struct inode`] and [`struct file`] (when [`struct
+    /// file_operations::open`] is called) into the given type. For example, for `miscdev`
+    /// devices, a pointer to the registered [`struct miscdev`] is stored in [`struct
+    /// file::private_data`].
+    ///
+    /// # Safety
+    ///
+    /// This function must be called only when [`struct file_operations::open`] is being called for
+    /// a file that was registered by the implementer. The returned pointer must be valid and
+    /// not-null.
+    unsafe fn convert(_inode: *mut bindings::inode, _file: *mut bindings::file) -> *const T;
+}
+
+/// Corresponds to the kernel's `struct file_operations`.
+///
+/// You implement this trait whenever you would create a `struct file_operations`.
+///
+/// File descriptors may be used from multiple threads/processes concurrently, so your type must be
+/// [`Sync`]. It must also be [`Send`] because [`Operations::release`] will be called from the
+/// thread that decrements that associated file's refcount to zero.
+#[vtable]
+pub trait Operations {
+    /// The type of the context data returned by [`Operations::open`] and made available to
+    /// other methods.
+    type Data: PointerWrapper + Send + Sync = ();
+
+    /// The type of the context data passed to [`Operations::open`].
+    type OpenData: Sync = ();
+
+    /// Creates a new instance of this file.
+    ///
+    /// Corresponds to the `open` function pointer in `struct file_operations`.
+    fn open(context: &Self::OpenData, file: &File) -> Result<Self::Data>;
+
+    /// Cleans up after the last reference to the file goes away.
+    ///
+    /// Note that context data is moved, so it will be freed automatically unless the
+    /// implementation moves it elsewhere.
+    ///
+    /// Corresponds to the `release` function pointer in `struct file_operations`.
+    fn release(_data: Self::Data, _file: &File) {}
+
+    /// Reads data from this file to the caller's buffer.
+    ///
+    /// Corresponds to the `read` and `read_iter` function pointers in `struct file_operations`.
+    fn read(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _writer: &mut impl IoBufferWriter,
+        _offset: u64,
+    ) -> Result<usize> {
+        Err(EINVAL)
+    }
+
+    /// Writes data from the caller's buffer to this file.
+    ///
+    /// Corresponds to the `write` and `write_iter` function pointers in `struct file_operations`.
+    fn write(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _reader: &mut impl IoBufferReader,
+        _offset: u64,
+    ) -> Result<usize> {
+        Err(EINVAL)
+    }
+
+    /// Changes the position of the file.
+    ///
+    /// Corresponds to the `llseek` function pointer in `struct file_operations`.
+    fn seek(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _offset: SeekFrom,
+    ) -> Result<u64> {
+        Err(EINVAL)
+    }
+
+    /// Performs IO control operations that are specific to the file.
+    ///
+    /// Corresponds to the `unlocked_ioctl` function pointer in `struct file_operations`.
+    fn ioctl(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _cmd: &mut IoctlCommand,
+    ) -> Result<i32> {
+        Err(ENOTTY)
+    }
+
+    /// Performs 32-bit IO control operations on that are specific to the file on 64-bit kernels.
+    ///
+    /// Corresponds to the `compat_ioctl` function pointer in `struct file_operations`.
+    fn compat_ioctl(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _cmd: &mut IoctlCommand,
+    ) -> Result<i32> {
+        Err(ENOTTY)
+    }
+
+    /// Syncs pending changes to this file.
+    ///
+    /// Corresponds to the `fsync` function pointer in `struct file_operations`.
+    fn fsync(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _start: u64,
+        _end: u64,
+        _datasync: bool,
+    ) -> Result<u32> {
+        Err(EINVAL)
+    }
+
+    /// Maps areas of the caller's virtual memory with device/file memory.
+    ///
+    /// Corresponds to the `mmap` function pointer in `struct file_operations`.
+    fn mmap(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _vma: &mut mm::virt::Area,
+    ) -> Result {
+        Err(EINVAL)
+    }
+
+    /// Checks the state of the file and optionally registers for notification when the state
+    /// changes.
+    ///
+    /// Corresponds to the `poll` function pointer in `struct file_operations`.
+    fn poll(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _file: &File,
+        _table: &PollTable,
+    ) -> Result<u32> {
+        Ok(bindings::POLLIN | bindings::POLLOUT | bindings::POLLRDNORM | bindings::POLLWRNORM)
+    }
+}
diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs
new file mode 100644
index 000000000000..46dc38aad2bc
--- /dev/null
+++ b/rust/kernel/fs.rs
@@ -0,0 +1,846 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! File systems.
+//!
+//! C headers: [`include/linux/fs.h`](../../../../include/linux/fs.h)
+
+use crate::{
+    bindings, error::code::*, error::from_kernel_result, str::CStr, to_result,
+    types::PointerWrapper, AlwaysRefCounted, Error, Result, ScopeGuard, ThisModule,
+};
+use alloc::boxed::Box;
+use core::{
+    cell::UnsafeCell,
+    marker::{PhantomData, PhantomPinned},
+    pin::Pin,
+    ptr,
+};
+use macros::vtable;
+
+pub mod param;
+
+/// Type of superblock keying.
+///
+/// It determines how C's `fs_context_operations::get_tree` is implemented.
+pub enum Super {
+    /// Only one such superblock may exist.
+    Single,
+
+    /// As [`Super::Single`], but reconfigure if it exists.
+    SingleReconf,
+
+    /// Superblocks with different data pointers may exist.
+    Keyed,
+
+    /// Multiple independent superblocks may exist.
+    Independent,
+
+    /// Uses a block device.
+    BlockDev,
+}
+
+/// A file system context.
+///
+/// It is used to gather configuration to then mount or reconfigure a file system.
+#[vtable]
+pub trait Context<T: Type + ?Sized> {
+    /// Type of the data associated with the context.
+    type Data: PointerWrapper + Send + Sync + 'static;
+
+    /// The typed file system parameters.
+    ///
+    /// Users are encouraged to define it using the [`crate::define_fs_params`] macro.
+    const PARAMS: param::SpecTable<'static, Self::Data> = param::SpecTable::empty();
+
+    /// Creates a new context.
+    fn try_new() -> Result<Self::Data>;
+
+    /// Parses a parameter that wasn't specified in [`Self::PARAMS`].
+    fn parse_unknown_param(
+        _data: &mut Self::Data,
+        _name: &CStr,
+        _value: param::Value<'_>,
+    ) -> Result {
+        Err(ENOPARAM)
+    }
+
+    /// Parses the whole parameter block, potentially skipping regular handling for parts of it.
+    ///
+    /// The return value is the portion of the input buffer for which the regular handling
+    /// (involving [`Self::PARAMS`] and [`Self::parse_unknown_param`]) will still be carried out.
+    /// If it's `None`, the regular handling is not performed at all.
+    fn parse_monolithic<'a>(
+        _data: &mut Self::Data,
+        _buf: Option<&'a mut [u8]>,
+    ) -> Result<Option<&'a mut [u8]>> {
+        Ok(None)
+    }
+
+    /// Returns the superblock data to be used by this file system context.
+    ///
+    /// This is only needed when [`Type::SUPER_TYPE`] is [`Super::Keyed`], otherwise it is never
+    /// called. In the former case, when the fs is being mounted, an existing superblock is reused
+    /// if one can be found with the same data as the returned value; otherwise a new superblock is
+    /// created.
+    fn tree_key(_data: &mut Self::Data) -> Result<T::Data> {
+        Err(ENOTSUPP)
+    }
+}
+
+struct Tables<T: Type + ?Sized>(T);
+impl<T: Type + ?Sized> Tables<T> {
+    const CONTEXT: bindings::fs_context_operations = bindings::fs_context_operations {
+        free: Some(Self::free_callback),
+        parse_param: Some(Self::parse_param_callback),
+        get_tree: Some(Self::get_tree_callback),
+        reconfigure: Some(Self::reconfigure_callback),
+        parse_monolithic: if <T::Context as Context<T>>::HAS_PARSE_MONOLITHIC {
+            Some(Self::parse_monolithic_callback)
+        } else {
+            None
+        },
+        dup: None,
+    };
+
+    unsafe extern "C" fn free_callback(fc: *mut bindings::fs_context) {
+        // SAFETY: The callback contract guarantees that `fc` is valid.
+        let fc = unsafe { &*fc };
+
+        let ptr = fc.fs_private;
+        if !ptr.is_null() {
+            // SAFETY: `fs_private` was initialised with the result of a `to_pointer` call in
+            // `init_fs_context_callback`, so it's ok to call `from_pointer` here.
+            unsafe { <T::Context as Context<T>>::Data::from_pointer(ptr) };
+        }
+
+        let ptr = fc.s_fs_info;
+        if !ptr.is_null() {
+            // SAFETY: `s_fs_info` may be initialised with the result of a `to_pointer` call in
+            // `get_tree_callback` when keyed superblocks are used (`get_tree_keyed` sets it), so
+            // it's ok to call `from_pointer` here.
+            unsafe { T::Data::from_pointer(ptr) };
+        }
+    }
+
+    unsafe extern "C" fn parse_param_callback(
+        fc: *mut bindings::fs_context,
+        param: *mut bindings::fs_parameter,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: The callback contract guarantees that `fc` is valid.
+            let ptr = unsafe { (*fc).fs_private };
+
+            // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
+            // `init_fs_context_callback` to the result of an `into_pointer` call. Since the
+            // context is valid, `from_pointer` wasn't called yet, so `ptr` is valid. Additionally,
+            // the callback contract guarantees that callbacks are serialised, so it is ok to
+            // mutably reference it.
+            let mut data =
+                unsafe { <<T::Context as Context<T>>::Data as PointerWrapper>::borrow_mut(ptr) };
+            let mut result = bindings::fs_parse_result::default();
+            // SAFETY: All parameters are valid at least for the duration of the call.
+            let opt =
+                unsafe { bindings::fs_parse(fc, T::Context::PARAMS.first, param, &mut result) };
+
+            // SAFETY: The callback contract guarantees that `param` is valid for the duration of
+            // the callback.
+            let param = unsafe { &*param };
+            if opt >= 0 {
+                let opt = opt as usize;
+                if opt >= T::Context::PARAMS.handlers.len() {
+                    return Err(EINVAL);
+                }
+                T::Context::PARAMS.handlers[opt].handle_param(&mut data, param, &result)?;
+                return Ok(0);
+            }
+
+            if opt != ENOPARAM.to_kernel_errno() {
+                return Err(Error::from_kernel_errno(opt));
+            }
+
+            if !T::Context::HAS_PARSE_UNKNOWN_PARAM {
+                return Err(ENOPARAM);
+            }
+
+            let val = param::Value::from_fs_parameter(param);
+            // SAFETY: The callback contract guarantees the parameter key to be valid and last at
+            // least the duration of the callback.
+            T::Context::parse_unknown_param(
+                &mut data,
+                unsafe { CStr::from_char_ptr(param.key) },
+                val,
+            )?;
+            Ok(0)
+        }
+    }
+
+    unsafe extern "C" fn fill_super_callback(
+        sb_ptr: *mut bindings::super_block,
+        fc: *mut bindings::fs_context,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: The callback contract guarantees that `fc` is valid. It also guarantees that
+            // the callbacks are serialised for a given `fc`, so it is safe to mutably dereference
+            // it.
+            let fc = unsafe { &mut *fc };
+            let ptr = core::mem::replace(&mut fc.fs_private, ptr::null_mut());
+
+            // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
+            // `init_fs_context_callback` to the result of an `into_pointer` call. The context is
+            // being used to initialise a superblock, so we took over `ptr` (`fs_private` is set to
+            // null now) and call `from_pointer` below.
+            let data =
+                unsafe { <<T::Context as Context<T>>::Data as PointerWrapper>::from_pointer(ptr) };
+
+            // SAFETY: The callback contract guarantees that `sb_ptr` is a unique pointer to a
+            // newly-created superblock.
+            let newsb = unsafe { NewSuperBlock::new(sb_ptr) };
+            T::fill_super(data, newsb)?;
+            Ok(0)
+        }
+    }
+
+    unsafe extern "C" fn get_tree_callback(fc: *mut bindings::fs_context) -> core::ffi::c_int {
+        // N.B. When new types are added below, we may need to update `kill_sb_callback` to ensure
+        // that we're cleaning up properly.
+        match T::SUPER_TYPE {
+            Super::Single => unsafe {
+                // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+                // the right type and is a valid callback.
+                bindings::get_tree_single(fc, Some(Self::fill_super_callback))
+            },
+            Super::SingleReconf => unsafe {
+                // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+                // the right type and is a valid callback.
+                bindings::get_tree_single_reconf(fc, Some(Self::fill_super_callback))
+            },
+            Super::Independent => unsafe {
+                // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+                // the right type and is a valid callback.
+                bindings::get_tree_nodev(fc, Some(Self::fill_super_callback))
+            },
+            Super::BlockDev => unsafe {
+                // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+                // the right type and is a valid callback.
+                bindings::get_tree_bdev(fc, Some(Self::fill_super_callback))
+            },
+            Super::Keyed => {
+                from_kernel_result! {
+                    // SAFETY: `fc` is valid per the callback contract.
+                    let ctx = unsafe { &*fc };
+                    let ptr = ctx.fs_private;
+
+                    // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
+                    // `init_fs_context_callback` to the result of an `into_pointer` call. Since
+                    // the context is valid, `from_pointer` wasn't called yet, so `ptr` is valid.
+                    // Additionally, the callback contract guarantees that callbacks are
+                    // serialised, so it is ok to mutably reference it.
+                    let mut data = unsafe {
+                        <<T::Context as Context<T>>::Data as PointerWrapper>::borrow_mut(ptr)
+                    };
+                    let fs_data = T::Context::tree_key(&mut data)?;
+                    let fs_data_ptr = fs_data.into_pointer();
+
+                    // `get_tree_keyed` reassigns `ctx.s_fs_info`, which should be ok because
+                    // nowhere else is it assigned a non-null value. However, we add the assert
+                    // below to ensure that there are no unexpected paths on the C side that may do
+                    // this.
+                    assert_eq!(ctx.s_fs_info, core::ptr::null_mut());
+
+                    // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also
+                    // has the right type and is a valid callback. Lastly, we just called
+                    // `into_pointer` above, so `fs_data_ptr` is also valid.
+                    to_result(unsafe {
+                        bindings::get_tree_keyed(
+                            fc,
+                            Some(Self::fill_super_callback),
+                            fs_data_ptr as _,
+                        )
+                    })?;
+                    Ok(0)
+                }
+            }
+        }
+    }
+
+    unsafe extern "C" fn reconfigure_callback(_fc: *mut bindings::fs_context) -> core::ffi::c_int {
+        EINVAL.to_kernel_errno()
+    }
+
+    unsafe extern "C" fn parse_monolithic_callback(
+        fc: *mut bindings::fs_context,
+        buf: *mut core::ffi::c_void,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: The callback contract guarantees that `fc` is valid.
+            let ptr = unsafe { (*fc).fs_private };
+
+            // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
+            // `init_fs_context_callback` to the result of an `into_pointer` call. Since the
+            // context is valid, `from_pointer` wasn't called yet, so `ptr` is valid. Additionally,
+            // the callback contract guarantees that callbacks are serialised, so it is ok to
+            // mutably reference it.
+            let mut data =
+                unsafe { <<T::Context as Context<T>>::Data as PointerWrapper>::borrow_mut(ptr) };
+            let page = if buf.is_null() {
+                None
+            } else {
+                // SAFETY: This callback is called to handle the `mount` syscall, which takes a
+                // page-sized buffer as data.
+                Some(unsafe { &mut *ptr::slice_from_raw_parts_mut(buf.cast(), crate::PAGE_SIZE) })
+            };
+            let regular = T::Context::parse_monolithic(&mut data, page)?;
+            if let Some(buf) = regular {
+                // SAFETY: Both `fc` and `buf` are guaranteed to be valid; the former because the
+                // callback is still ongoing and the latter because its lifefime is tied to that of
+                // `page`, which is also valid for the duration of the callback.
+                to_result(unsafe {
+                    bindings::generic_parse_monolithic(fc, buf.as_mut_ptr().cast())
+                })?;
+            }
+            Ok(0)
+        }
+    }
+
+    const SUPER_BLOCK: bindings::super_operations = bindings::super_operations {
+        alloc_inode: None,
+        destroy_inode: None,
+        free_inode: None,
+        dirty_inode: None,
+        write_inode: None,
+        drop_inode: None,
+        evict_inode: None,
+        put_super: None,
+        sync_fs: None,
+        freeze_super: None,
+        freeze_fs: None,
+        thaw_super: None,
+        unfreeze_fs: None,
+        statfs: None,
+        remount_fs: None,
+        umount_begin: None,
+        show_options: None,
+        show_devname: None,
+        show_path: None,
+        show_stats: None,
+        #[cfg(CONFIG_QUOTA)]
+        quota_read: None,
+        #[cfg(CONFIG_QUOTA)]
+        quota_write: None,
+        #[cfg(CONFIG_QUOTA)]
+        get_dquots: None,
+        nr_cached_objects: None,
+        free_cached_objects: None,
+    };
+}
+
+/// A file system type.
+pub trait Type {
+    /// The context used to build fs configuration before it is mounted or reconfigured.
+    type Context: Context<Self> + ?Sized;
+
+    /// Data associated with each file system instance.
+    type Data: PointerWrapper + Send + Sync = ();
+
+    /// Determines how superblocks for this file system type are keyed.
+    const SUPER_TYPE: Super;
+
+    /// The name of the file system type.
+    const NAME: &'static CStr;
+
+    /// The flags of this file system type.
+    ///
+    /// It is a combination of the flags in the [`flags`] module.
+    const FLAGS: i32;
+
+    /// Initialises a super block for this file system type.
+    fn fill_super(
+        data: <Self::Context as Context<Self>>::Data,
+        sb: NewSuperBlock<'_, Self>,
+    ) -> Result<&SuperBlock<Self>>;
+}
+
+/// File system flags.
+pub mod flags {
+    use crate::bindings;
+
+    /// The file system requires a device.
+    pub const REQUIRES_DEV: i32 = bindings::FS_REQUIRES_DEV as _;
+
+    /// The options provided when mounting are in binary form.
+    pub const BINARY_MOUNTDATA: i32 = bindings::FS_BINARY_MOUNTDATA as _;
+
+    /// The file system has a subtype. It is extracted from the name and passed in as a parameter.
+    pub const HAS_SUBTYPE: i32 = bindings::FS_HAS_SUBTYPE as _;
+
+    /// The file system can be mounted by userns root.
+    pub const USERNS_MOUNT: i32 = bindings::FS_USERNS_MOUNT as _;
+
+    /// Disables fanotify permission events.
+    pub const DISALLOW_NOTIFY_PERM: i32 = bindings::FS_DISALLOW_NOTIFY_PERM as _;
+
+    /// The file system has been updated to handle vfs idmappings.
+    pub const ALLOW_IDMAP: i32 = bindings::FS_ALLOW_IDMAP as _;
+
+    /// The file systen will handle `d_move` during `rename` internally.
+    pub const RENAME_DOES_D_MOVE: i32 = bindings::FS_RENAME_DOES_D_MOVE as _;
+}
+
+/// A file system registration.
+#[derive(Default)]
+pub struct Registration {
+    is_registered: bool,
+    fs: UnsafeCell<bindings::file_system_type>,
+    _pin: PhantomPinned,
+}
+
+// SAFETY: `Registration` doesn't really provide any `&self` methods, so it is safe to pass
+// references to it around.
+unsafe impl Sync for Registration {}
+
+// SAFETY: Both registration and unregistration are implemented in C and safe to be performed from
+// any thread, so `Registration` is `Send`.
+unsafe impl Send for Registration {}
+
+impl Registration {
+    /// Creates a new file system registration.
+    ///
+    /// It is not visible or accessible yet. A successful call to [`Registration::register`] needs
+    /// to be made before users can mount it.
+    pub fn new() -> Self {
+        Self {
+            is_registered: false,
+            fs: UnsafeCell::new(bindings::file_system_type::default()),
+            _pin: PhantomPinned,
+        }
+    }
+
+    /// Registers a file system so that it can be mounted by users.
+    ///
+    /// The file system is described by the [`Type`] argument.
+    ///
+    /// It is automatically unregistered when the registration is dropped.
+    pub fn register<T: Type + ?Sized>(self: Pin<&mut Self>, module: &'static ThisModule) -> Result {
+        // SAFETY: We never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+
+        if this.is_registered {
+            return Err(EINVAL);
+        }
+
+        let mut fs = this.fs.get_mut();
+        fs.owner = module.0;
+        fs.name = T::NAME.as_char_ptr();
+        fs.fs_flags = T::FLAGS;
+        fs.parameters = T::Context::PARAMS.first;
+        fs.init_fs_context = Some(Self::init_fs_context_callback::<T>);
+        fs.kill_sb = Some(Self::kill_sb_callback::<T>);
+
+        // SAFETY: This block registers all fs type keys with lockdep. We just need the memory
+        // locations to be owned by the caller, which is the case.
+        unsafe {
+            bindings::lockdep_register_key(&mut fs.s_lock_key);
+            bindings::lockdep_register_key(&mut fs.s_umount_key);
+            bindings::lockdep_register_key(&mut fs.s_vfs_rename_key);
+            bindings::lockdep_register_key(&mut fs.i_lock_key);
+            bindings::lockdep_register_key(&mut fs.i_mutex_key);
+            bindings::lockdep_register_key(&mut fs.invalidate_lock_key);
+            bindings::lockdep_register_key(&mut fs.i_mutex_dir_key);
+            for key in &mut fs.s_writers_key {
+                bindings::lockdep_register_key(key);
+            }
+        }
+
+        let ptr = this.fs.get();
+
+        // SAFETY: `ptr` as valid as it points to the `self.fs`.
+        let key_guard = ScopeGuard::new(|| unsafe { Self::unregister_keys(ptr) });
+
+        // SAFETY: Pointers stored in `fs` are either static so will live for as long as the
+        // registration is active (it is undone in `drop`).
+        to_result(unsafe { bindings::register_filesystem(ptr) })?;
+        key_guard.dismiss();
+        this.is_registered = true;
+        Ok(())
+    }
+
+    /// Unregisters the lockdep keys in the file system type.
+    ///
+    /// # Safety
+    ///
+    /// `fs` must be non-null and valid.
+    unsafe fn unregister_keys(fs: *mut bindings::file_system_type) {
+        // SAFETY: This block unregisters all fs type keys from lockdep. They must have been
+        // registered before.
+        unsafe {
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).s_lock_key));
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).s_umount_key));
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).s_vfs_rename_key));
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).i_lock_key));
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).i_mutex_key));
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).invalidate_lock_key));
+            bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).i_mutex_dir_key));
+            for i in 0..(*fs).s_writers_key.len() {
+                bindings::lockdep_unregister_key(ptr::addr_of_mut!((*fs).s_writers_key[i]));
+            }
+        }
+    }
+
+    unsafe extern "C" fn init_fs_context_callback<T: Type + ?Sized>(
+        fc_ptr: *mut bindings::fs_context,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            let data = T::Context::try_new()?;
+            // SAFETY: The callback contract guarantees that `fc_ptr` is the only pointer to a
+            // newly-allocated fs context, so it is safe to mutably reference it.
+            let fc = unsafe { &mut *fc_ptr };
+            fc.fs_private = data.into_pointer() as _;
+            fc.ops = &Tables::<T>::CONTEXT;
+            Ok(0)
+        }
+    }
+
+    unsafe extern "C" fn kill_sb_callback<T: Type + ?Sized>(sb_ptr: *mut bindings::super_block) {
+        if let Super::BlockDev = T::SUPER_TYPE {
+            // SAFETY: When the superblock type is `BlockDev`, we have a block device so it's safe
+            // to call `kill_block_super`. Additionally, the callback contract guarantees that
+            // `sb_ptr` is valid.
+            unsafe { bindings::kill_block_super(sb_ptr) }
+        } else {
+            // SAFETY: We always call a `get_tree_nodev` variant from `get_tree_callback` without a
+            // device when `T::SUPER_TYPE` is not `BlockDev`, so we never have a device in such
+            // cases, therefore it is ok to call the function below. Additionally, the callback
+            // contract guarantees that `sb_ptr` is valid.
+            unsafe { bindings::kill_anon_super(sb_ptr) }
+        }
+
+        // SAFETY: The callback contract guarantees that `sb_ptr` is valid.
+        let sb = unsafe { &*sb_ptr };
+
+        // SAFETY: The `kill_sb` callback being called implies that the `s_type` field is valid.
+        unsafe { Self::unregister_keys(sb.s_type) };
+
+        let ptr = sb.s_fs_info;
+        if !ptr.is_null() {
+            // SAFETY: The only place where `s_fs_info` is assigned is `NewSuperBlock::init`, where
+            // it's initialised with the result of a `to_pointer` call. We checked above that ptr
+            // is non-null because it would be null if we never reached the point where we init the
+            // field.
+            unsafe { T::Data::from_pointer(ptr) };
+        }
+    }
+}
+
+impl Drop for Registration {
+    fn drop(&mut self) {
+        if self.is_registered {
+            // SAFETY: When `is_registered` is `true`, a previous call to `register_filesystem` has
+            // succeeded, so it is safe to unregister here.
+            unsafe { bindings::unregister_filesystem(self.fs.get()) };
+        }
+    }
+}
+
+/// State of [`NewSuperBlock`] that indicates that [`NewSuperBlock::init`] needs to be called
+/// eventually.
+pub struct NeedsInit;
+
+/// State of [`NewSuperBlock`] that indicates that [`NewSuperBlock::init_root`] needs to be called
+/// eventually.
+pub struct NeedsRoot;
+
+/// Required superblock parameters.
+///
+/// This is used in [`NewSuperBlock::init`].
+pub struct SuperParams {
+    /// The magic number of the superblock.
+    pub magic: u32,
+
+    /// The size of a block in powers of 2 (i.e., for a value of `n`, the size is `2^n`.
+    pub blocksize_bits: u8,
+
+    /// Maximum size of a file.
+    pub maxbytes: i64,
+
+    /// Granularity of c/m/atime in ns (cannot be worse than a second).
+    pub time_gran: u32,
+}
+
+impl SuperParams {
+    /// Default value for instances of [`SuperParams`].
+    pub const DEFAULT: Self = Self {
+        magic: 0,
+        blocksize_bits: crate::PAGE_SIZE as _,
+        maxbytes: bindings::MAX_LFS_FILESIZE,
+        time_gran: 1,
+    };
+}
+
+/// A superblock that is still being initialised.
+///
+/// It uses type states to ensure that callers use the right sequence of calls.
+///
+/// # Invariants
+///
+/// The superblock is a newly-created one and this is the only active pointer to it.
+pub struct NewSuperBlock<'a, T: Type + ?Sized, S = NeedsInit> {
+    sb: *mut bindings::super_block,
+    _p: PhantomData<(&'a T, S)>,
+}
+
+impl<'a, T: Type + ?Sized> NewSuperBlock<'a, T, NeedsInit> {
+    /// Creates a new instance of [`NewSuperBlock`].
+    ///
+    /// # Safety
+    ///
+    /// `sb` must point to a newly-created superblock and it must be the only active pointer to it.
+    unsafe fn new(sb: *mut bindings::super_block) -> Self {
+        // INVARIANT: The invariants are satisfied by the safety requirements of this function.
+        Self {
+            sb,
+            _p: PhantomData,
+        }
+    }
+
+    /// Initialises the superblock so that it transitions to the [`NeedsRoot`] type state.
+    pub fn init(
+        self,
+        data: T::Data,
+        params: &SuperParams,
+    ) -> Result<NewSuperBlock<'a, T, NeedsRoot>> {
+        // SAFETY: The type invariant guarantees that `self.sb` is the only pointer to a
+        // newly-allocated superblock, so it is safe to mutably reference it.
+        let sb = unsafe { &mut *self.sb };
+
+        sb.s_magic = params.magic as _;
+        sb.s_op = &Tables::<T>::SUPER_BLOCK;
+        sb.s_maxbytes = params.maxbytes;
+        sb.s_time_gran = params.time_gran;
+        sb.s_blocksize_bits = params.blocksize_bits;
+        sb.s_blocksize = 1;
+        if sb.s_blocksize.leading_zeros() < params.blocksize_bits.into() {
+            return Err(EINVAL);
+        }
+        sb.s_blocksize = 1 << sb.s_blocksize_bits;
+
+        // Keyed file systems already have `s_fs_info` initialised.
+        let info = data.into_pointer() as *mut _;
+        if let Super::Keyed = T::SUPER_TYPE {
+            // SAFETY: We just called `into_pointer` above.
+            unsafe { T::Data::from_pointer(info) };
+
+            if sb.s_fs_info != info {
+                return Err(EINVAL);
+            }
+        } else {
+            sb.s_fs_info = info;
+        }
+
+        Ok(NewSuperBlock {
+            sb: self.sb,
+            _p: PhantomData,
+        })
+    }
+}
+
+impl<'a, T: Type + ?Sized> NewSuperBlock<'a, T, NeedsRoot> {
+    /// Initialises the root of the superblock.
+    pub fn init_root(self) -> Result<&'a SuperBlock<T>> {
+        // The following is temporary code to create the root inode and dentry. It will be replaced
+        // once we allow inodes and dentries to be created directly from Rust code.
+
+        // SAFETY: `sb` is initialised (`NeedsRoot` typestate implies it), so it is safe to pass it
+        // to `new_inode`.
+        let inode = unsafe { bindings::new_inode(self.sb) };
+        if inode.is_null() {
+            return Err(ENOMEM);
+        }
+
+        {
+            // SAFETY: This is a newly-created inode. No other references to it exist, so it is
+            // safe to mutably dereference it.
+            let inode = unsafe { &mut *inode };
+
+            // SAFETY: `current_time` requires that `inode.sb` be valid, which is the case here
+            // since we allocated the inode through the superblock.
+            let time = unsafe { bindings::current_time(inode) };
+            inode.i_ino = 1;
+            inode.i_mode = (bindings::S_IFDIR | 0o755) as _;
+            inode.i_mtime = time;
+            inode.i_atime = time;
+            inode.i_ctime = time;
+
+            // SAFETY: `simple_dir_operations` never changes, it's safe to reference it.
+            inode.__bindgen_anon_3.i_fop = unsafe { &bindings::simple_dir_operations };
+
+            // SAFETY: `simple_dir_inode_operations` never changes, it's safe to reference it.
+            inode.i_op = unsafe { &bindings::simple_dir_inode_operations };
+
+            // SAFETY: `inode` is valid for write.
+            unsafe { bindings::set_nlink(inode, 2) };
+        }
+
+        // SAFETY: `d_make_root` requires that `inode` be valid and referenced, which is the
+        // case for this call.
+        //
+        // It takes over the inode, even on failure, so we don't need to clean it up.
+        let dentry = unsafe { bindings::d_make_root(inode) };
+        if dentry.is_null() {
+            return Err(ENOMEM);
+        }
+
+        // SAFETY: The typestate guarantees that `self.sb` is valid.
+        unsafe { (*self.sb).s_root = dentry };
+
+        // SAFETY: The typestate guarantees that `self.sb` is initialised and we just finished
+        // setting its root, so it's a fully ready superblock.
+        Ok(unsafe { &mut *self.sb.cast() })
+    }
+}
+
+/// A file system super block.
+///
+/// Wraps the kernel's `struct super_block`.
+#[repr(transparent)]
+pub struct SuperBlock<T: Type + ?Sized>(
+    pub(crate) UnsafeCell<bindings::super_block>,
+    PhantomData<T>,
+);
+
+/// Wraps the kernel's `struct inode`.
+///
+/// # Invariants
+///
+/// Instances of this type are always ref-counted, that is, a call to `ihold` ensures that the
+/// allocation remains valid at least until the matching call to `iput`.
+#[repr(transparent)]
+pub struct INode(pub(crate) UnsafeCell<bindings::inode>);
+
+// SAFETY: The type invariants guarantee that `INode` is always ref-counted.
+unsafe impl AlwaysRefCounted for INode {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::ihold(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::iput(obj.cast().as_ptr()) }
+    }
+}
+
+/// Wraps the kernel's `struct dentry`.
+///
+/// # Invariants
+///
+/// Instances of this type are always ref-counted, that is, a call to `dget` ensures that the
+/// allocation remains valid at least until the matching call to `dput`.
+#[repr(transparent)]
+pub struct DEntry(pub(crate) UnsafeCell<bindings::dentry>);
+
+// SAFETY: The type invariants guarantee that `DEntry` is always ref-counted.
+unsafe impl AlwaysRefCounted for DEntry {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::dget(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::dput(obj.cast().as_ptr()) }
+    }
+}
+
+/// Wraps the kernel's `struct filename`.
+#[repr(transparent)]
+pub struct Filename(pub(crate) UnsafeCell<bindings::filename>);
+
+impl Filename {
+    /// Creates a reference to a [`Filename`] from a valid pointer.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
+    /// returned [`Filename`] instance.
+    pub(crate) unsafe fn from_ptr<'a>(ptr: *const bindings::filename) -> &'a Filename {
+        // SAFETY: The safety requirements guarantee the validity of the dereference, while the
+        // `Filename` type being transparent makes the cast ok.
+        unsafe { &*ptr.cast() }
+    }
+}
+
+/// Kernel module that exposes a single file system implemented by `T`.
+pub struct Module<T: Type> {
+    _fs: Pin<Box<Registration>>,
+    _p: PhantomData<T>,
+}
+
+impl<T: Type + Sync> crate::Module for Module<T> {
+    fn init(_name: &'static CStr, module: &'static ThisModule) -> Result<Self> {
+        let mut reg = Pin::from(Box::try_new(Registration::new())?);
+        reg.as_mut().register::<T>(module)?;
+        Ok(Self {
+            _fs: reg,
+            _p: PhantomData,
+        })
+    }
+}
+
+/// Declares a kernel module that exposes a single file system.
+///
+/// The `type` argument must be a type which implements the [`Type`] trait. Also accepts various
+/// forms of kernel metadata.
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::prelude::*;
+/// use kernel::{c_str, fs};
+///
+/// module_fs! {
+///     type: MyFs,
+///     name: b"my_fs_kernel_module",
+///     author: b"Rust for Linux Contributors",
+///     description: b"My very own file system kernel module!",
+///     license: b"GPL",
+/// }
+///
+/// struct MyFs;
+///
+/// #[vtable]
+/// impl fs::Context<Self> for MyFs {
+///     type Data = ();
+///     fn try_new() -> Result {
+///         Ok(())
+///     }
+/// }
+///
+/// impl fs::Type for MyFs {
+///     type Context = Self;
+///     const SUPER_TYPE: fs::Super = fs::Super::Independent;
+///     const NAME: &'static CStr = c_str!("example");
+///     const FLAGS: i32 = 0;
+///
+///     fn fill_super(_data: (), sb: fs::NewSuperBlock<'_, Self>) -> Result<&fs::SuperBlock<Self>> {
+///         let sb = sb.init(
+///             (),
+///             &fs::SuperParams {
+///                 magic: 0x6578616d,
+///                 ..fs::SuperParams::DEFAULT
+///             },
+///         )?;
+///         let sb = sb.init_root()?;
+///         Ok(sb)
+///     }
+/// }
+/// ```
+#[macro_export]
+macro_rules! module_fs {
+    (type: $type:ty, $($f:tt)*) => {
+        type ModuleType = $crate::fs::Module<$type>;
+        $crate::macros::module! {
+            type: ModuleType,
+            $($f)*
+        }
+    }
+}
diff --git a/rust/kernel/fs/param.rs b/rust/kernel/fs/param.rs
new file mode 100644
index 000000000000..445cea404bcd
--- /dev/null
+++ b/rust/kernel/fs/param.rs
@@ -0,0 +1,553 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! File system parameters and parsing them.
+//!
+//! C headers: [`include/linux/fs_parser.h`](../../../../../include/linux/fs_parser.h)
+
+use crate::{bindings, file, fs, str::CStr, Result};
+use core::{marker::PhantomData, ptr};
+
+/// The value of a file system parameter.
+pub enum Value<'a> {
+    /// The value is undefined.
+    Undefined,
+
+    /// There is no value, but parameter itself is a flag.
+    Flag,
+
+    /// The value is the given string.
+    String(&'a CStr),
+
+    /// The value is the given binary blob.
+    Blob(&'a mut [u8]),
+
+    /// The value is the given file.
+    File(&'a file::File),
+
+    /// The value is the given filename and the given directory file descriptor (which may be
+    /// `AT_FDCWD`, to indicate the current directory).
+    Filename(&'a fs::Filename, i32),
+}
+
+impl<'a> Value<'a> {
+    pub(super) fn from_fs_parameter(p: &'a bindings::fs_parameter) -> Self {
+        match p.type_() {
+            bindings::fs_value_type_fs_value_is_string => {
+                // SAFETY: `type_` is string, so it is ok to use the union field. Additionally, it
+                // is guaranteed to be valid while `p` is valid.
+                Self::String(unsafe { CStr::from_char_ptr(p.__bindgen_anon_1.string) })
+            }
+            bindings::fs_value_type_fs_value_is_flag => Self::Flag,
+            bindings::fs_value_type_fs_value_is_blob => {
+                // SAFETY: `type_` is blob, so it is ok to use the union field and size.
+                // Additionally, it is guaranteed to be valid while `p` is valid.
+                let slice = unsafe {
+                    &mut *ptr::slice_from_raw_parts_mut(p.__bindgen_anon_1.blob.cast(), p.size)
+                };
+                Self::Blob(slice)
+            }
+            bindings::fs_value_type_fs_value_is_file => {
+                // SAFETY: `type_` is file, so it is ok to use the union field. Additionally, it is
+                // guaranteed to be valid while `p` is valid.
+                let file_ptr = unsafe { p.__bindgen_anon_1.file };
+                if file_ptr.is_null() {
+                    Self::Undefined
+                } else {
+                    // SAFETY: `file_ptr` is non-null and guaranteed to be valid while `p` is.
+                    Self::File(unsafe { file::File::from_ptr(file_ptr) })
+                }
+            }
+            bindings::fs_value_type_fs_value_is_filename => {
+                // SAFETY: `type_` is filename, so it is ok to use the union field. Additionally,
+                // it is guaranteed to be valid while `p` is valid.
+                let filename_ptr = unsafe { p.__bindgen_anon_1.name };
+                if filename_ptr.is_null() {
+                    Self::Undefined
+                } else {
+                    // SAFETY: `filename_ptr` is non-null and guaranteed to be valid while `p` is.
+                    Self::Filename(unsafe { fs::Filename::from_ptr(filename_ptr) }, p.dirfd)
+                }
+            }
+            _ => Self::Undefined,
+        }
+    }
+}
+
+/// A specification of a file system parameter.
+pub struct Spec {
+    name: &'static CStr,
+    flags: u16,
+    type_: bindings::fs_param_type,
+    extra: *const core::ffi::c_void,
+}
+
+const DEFAULT: Spec = Spec {
+    name: crate::c_str!(""),
+    flags: 0,
+    type_: None,
+    extra: core::ptr::null(),
+};
+
+macro_rules! define_param_type {
+    ($name:ident, $fntype:ty, $spec:expr, |$param:ident, $result:ident| $value:expr) => {
+        /// Module to support `$name` parameter types.
+        pub mod $name {
+            use super::*;
+
+            #[doc(hidden)]
+            pub const fn spec(name: &'static CStr) -> Spec {
+                const GIVEN: Spec = $spec;
+                Spec { name, ..GIVEN }
+            }
+
+            #[doc(hidden)]
+            pub const fn handler<S>(setfn: fn(&mut S, $fntype) -> Result) -> impl Handler<S> {
+                let c =
+                    move |s: &mut S,
+                          $param: &bindings::fs_parameter,
+                          $result: &bindings::fs_parse_result| { setfn(s, $value) };
+                ConcreteHandler {
+                    setfn: c,
+                    _p: PhantomData,
+                }
+            }
+        }
+    };
+}
+
+// SAFETY: This is only called when the parse result is a boolean, so it is ok to access to union
+// field.
+define_param_type!(flag, bool, Spec { ..DEFAULT }, |_p, r| unsafe {
+    r.__bindgen_anon_1.boolean
+});
+
+define_param_type!(
+    flag_no,
+    bool,
+    Spec {
+        flags: bindings::fs_param_neg_with_no as _,
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a boolean, so it is ok to access to
+    // union field.
+    |_p, r| unsafe { r.__bindgen_anon_1.boolean }
+);
+
+define_param_type!(
+    bool,
+    bool,
+    Spec {
+        type_: Some(bindings::fs_param_is_bool),
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a boolean, so it is ok to access to
+    // union field.
+    |_p, r| unsafe { r.__bindgen_anon_1.boolean }
+);
+
+define_param_type!(
+    u32,
+    u32,
+    Spec {
+        type_: Some(bindings::fs_param_is_u32),
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union
+    // field.
+    |_p, r| unsafe { r.__bindgen_anon_1.uint_32 }
+);
+
+define_param_type!(
+    u32oct,
+    u32,
+    Spec {
+        type_: Some(bindings::fs_param_is_u32),
+        extra: 8 as _,
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union
+    // field.
+    |_p, r| unsafe { r.__bindgen_anon_1.uint_32 }
+);
+
+define_param_type!(
+    u32hex,
+    u32,
+    Spec {
+        type_: Some(bindings::fs_param_is_u32),
+        extra: 16 as _,
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union
+    // field.
+    |_p, r| unsafe { r.__bindgen_anon_1.uint_32 }
+);
+
+define_param_type!(
+    s32,
+    i32,
+    Spec {
+        type_: Some(bindings::fs_param_is_s32),
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is an i32, so it is ok to access to union
+    // field.
+    |_p, r| unsafe { r.__bindgen_anon_1.int_32 }
+);
+
+define_param_type!(
+    u64,
+    u64,
+    Spec {
+        type_: Some(bindings::fs_param_is_u64),
+        extra: 16 as _,
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a u32, so it is ok to access to union
+    // field.
+    |_p, r| unsafe { r.__bindgen_anon_1.uint_64 }
+);
+
+define_param_type!(
+    string,
+    &CStr,
+    Spec {
+        type_: Some(bindings::fs_param_is_string),
+        ..DEFAULT
+    },
+    // SAFETY: This is only called when the parse result is a string, so it is ok to access to
+    // union field.
+    |p, _r| unsafe { CStr::from_char_ptr(p.__bindgen_anon_1.string) }
+);
+
+/// Module to support `enum` parameter types.
+pub mod enum_ {
+    use super::*;
+
+    #[doc(hidden)]
+    pub const fn spec(name: &'static CStr, options: ConstantTable<'static>) -> Spec {
+        Spec {
+            name,
+            type_: Some(bindings::fs_param_is_enum),
+            extra: options.first as *const _ as _,
+            ..DEFAULT
+        }
+    }
+
+    #[doc(hidden)]
+    pub const fn handler<S>(setfn: fn(&mut S, u32) -> Result) -> impl Handler<S> {
+        let c = move |s: &mut S, _p: &bindings::fs_parameter, r: &bindings::fs_parse_result| {
+            // SAFETY: This is only called when the parse result is an enum, so it is ok to access
+            // to union field.
+            setfn(s, unsafe { r.__bindgen_anon_1.uint_32 })
+        };
+        ConcreteHandler {
+            setfn: c,
+            _p: PhantomData,
+        }
+    }
+}
+
+const ZERO_SPEC: bindings::fs_parameter_spec = bindings::fs_parameter_spec {
+    name: core::ptr::null(),
+    type_: None,
+    opt: 0,
+    flags: 0,
+    data: core::ptr::null(),
+};
+
+/// A zero-terminated parameter spec array, followed by handlers.
+#[repr(C)]
+pub struct SpecArray<const N: usize, S: 'static> {
+    specs: [bindings::fs_parameter_spec; N],
+    sentinel: bindings::fs_parameter_spec,
+    handlers: [&'static dyn Handler<S>; N],
+}
+
+impl<const N: usize, S: 'static> SpecArray<N, S> {
+    /// Creates a new spec array.
+    ///
+    /// Users are encouraged to use the [`define_fs_params`] macro to define the
+    /// [`super::Context::PARAMS`] constant.
+    ///
+    /// # Safety
+    ///
+    /// The type of the elements in `handlers` must be compatible with the types in specs. For
+    /// example, if `specs` declares that the i-th element is a bool then the i-th handler
+    /// should be for a bool.
+    pub const unsafe fn new(specs: [Spec; N], handlers: [&'static dyn Handler<S>; N]) -> Self {
+        let mut array = Self {
+            specs: [ZERO_SPEC; N],
+            sentinel: ZERO_SPEC,
+            handlers,
+        };
+        let mut i = 0usize;
+        while i < N {
+            array.specs[i] = bindings::fs_parameter_spec {
+                name: specs[i].name.as_char_ptr(),
+                type_: specs[i].type_,
+                opt: i as _,
+                flags: specs[i].flags,
+                data: specs[i].extra,
+            };
+            i += 1;
+        }
+        array
+    }
+
+    /// Returns a [`SpecTable`] backed by `self`.
+    ///
+    /// This is used to essentially erase the array size.
+    pub const fn as_table(&self) -> SpecTable<'_, S> {
+        SpecTable {
+            first: &self.specs[0],
+            handlers: &self.handlers,
+            _p: PhantomData,
+        }
+    }
+}
+
+/// A parameter spec table.
+///
+/// The table is guaranteed to be zero-terminated.
+///
+/// Users are encouraged to use the [`define_fs_params`] macro to define the
+/// [`super::Context::PARAMS`] constant.
+pub struct SpecTable<'a, S: 'static> {
+    pub(super) first: &'a bindings::fs_parameter_spec,
+    pub(super) handlers: &'a [&'static dyn Handler<S>],
+    _p: PhantomData<S>,
+}
+
+impl<S> SpecTable<'static, S> {
+    pub(super) const fn empty() -> Self {
+        Self {
+            first: &ZERO_SPEC,
+            handlers: &[],
+            _p: PhantomData,
+        }
+    }
+}
+
+/// A zero-terminated parameter constant array.
+#[repr(C)]
+pub struct ConstantArray<const N: usize> {
+    consts: [bindings::constant_table; N],
+    sentinel: bindings::constant_table,
+}
+
+impl<const N: usize> ConstantArray<N> {
+    /// Creates a new constant array.
+    ///
+    /// Users are encouraged to use the [`define_fs_params`] macro to define the
+    /// [`super::Context::PARAMS`] constant.
+    pub const fn new(consts: [(&'static CStr, u32); N]) -> Self {
+        const ZERO: bindings::constant_table = bindings::constant_table {
+            name: core::ptr::null(),
+            value: 0,
+        };
+        let mut array = Self {
+            consts: [ZERO; N],
+            sentinel: ZERO,
+        };
+        let mut i = 0usize;
+        while i < N {
+            array.consts[i] = bindings::constant_table {
+                name: consts[i].0.as_char_ptr(),
+                value: consts[i].1 as _,
+            };
+            i += 1;
+        }
+        array
+    }
+
+    /// Returns a [`ConstantTable`] backed by `self`.
+    ///
+    /// This is used to essentially erase the array size.
+    pub const fn as_table(&self) -> ConstantTable<'_> {
+        ConstantTable {
+            first: &self.consts[0],
+        }
+    }
+}
+
+/// A parameter constant table.
+///
+/// The table is guaranteed to be zero-terminated.
+pub struct ConstantTable<'a> {
+    pub(super) first: &'a bindings::constant_table,
+}
+
+#[doc(hidden)]
+pub trait Handler<S> {
+    fn handle_param(
+        &self,
+        state: &mut S,
+        p: &bindings::fs_parameter,
+        r: &bindings::fs_parse_result,
+    ) -> Result;
+}
+
+struct ConcreteHandler<
+    S,
+    T: Fn(&mut S, &bindings::fs_parameter, &bindings::fs_parse_result) -> Result,
+> {
+    setfn: T,
+    _p: PhantomData<S>,
+}
+
+impl<S, T: Fn(&mut S, &bindings::fs_parameter, &bindings::fs_parse_result) -> Result> Handler<S>
+    for ConcreteHandler<S, T>
+{
+    fn handle_param(
+        &self,
+        state: &mut S,
+        p: &bindings::fs_parameter,
+        r: &bindings::fs_parse_result,
+    ) -> Result {
+        (self.setfn)(state, p, r)
+    }
+}
+
+/// Counts the number of comma-separated entries surrounded by braces.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::count_brace_items;
+///
+/// assert_eq!(0, count_brace_items!());
+/// assert_eq!(1, count_brace_items!({ A }));
+/// assert_eq!(1, count_brace_items!({ A },));
+/// assert_eq!(2, count_brace_items!({ A }, { B }));
+/// assert_eq!(2, count_brace_items!({ A }, { B },));
+/// assert_eq!(3, count_brace_items!({ A }, { B }, { C }));
+/// assert_eq!(3, count_brace_items!({ A }, { B }, { C },));
+/// ```
+#[macro_export]
+macro_rules! count_brace_items {
+    ({$($item:tt)*}, $($remaining:tt)*) => { 1 + $crate::count_brace_items!($($remaining)*) };
+    ({$($item:tt)*}) => { 1 };
+    () => { 0 };
+}
+
+/// Defines the file system parameters of a given file system context.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::prelude::*;
+/// # use kernel::{c_str, fs, str::CString};
+///
+/// #[derive(Default)]
+/// struct State {
+///     flag: Option<bool>,
+///     flag_no: Option<bool>,
+///     bool_value: Option<bool>,
+///     u32_value: Option<u32>,
+///     i32_value: Option<i32>,
+///     u64_value: Option<u64>,
+///     str_value: Option<CString>,
+///     enum_value: Option<u32>,
+/// }
+///
+/// fn set_u32(s: &mut Box<State>, v: u32) -> Result {
+///     s.u32_value = Some(v);
+///     Ok(())
+/// }
+///
+/// struct Example;
+///
+/// #[vtable]
+/// impl fs::Context<Self> for Example {
+///     type Data = Box<State>;
+///
+///     kernel::define_fs_params! {Box<State>,
+///         {flag, "flag", |s, v| { s.flag = Some(v); Ok(()) } },
+///         {flag_no, "flagno", |s, v| { s.flag_no = Some(v); Ok(()) } },
+///         {bool, "bool", |s, v| { s.bool_value = Some(v); Ok(()) } },
+///         {u32, "u32", set_u32 },
+///         {u32oct, "u32oct", set_u32 },
+///         {u32hex, "u32hex", set_u32 },
+///         {s32, "s32", |s, v| { s.i32_value = Some(v); Ok(()) } },
+///         {u64, "u64", |s, v| { s.u64_value = Some(v); Ok(()) } },
+///         {string, "string", |s, v| {
+///             s.str_value = Some(CString::try_from_fmt(fmt!("{v}"))?);
+///             Ok(())
+///         }},
+///         {enum, "enum", [("first", 10), ("second", 20)], |s, v| {
+///             s.enum_value = Some(v);
+///             Ok(())
+///         }},
+///     }
+///
+///     fn try_new() -> Result<Self::Data> {
+///         Ok(Box::try_new(State::default())?)
+///     }
+/// }
+///
+/// # impl fs::Type for Example {
+/// #    type Context = Self;
+/// #    const SUPER_TYPE: fs::Super = fs::Super::Independent;
+/// #    const NAME: &'static CStr = c_str!("example");
+/// #    const FLAGS: i32 = 0;
+/// #
+/// #    fn fill_super<'a>(
+/// #        _data: Box<State>,
+/// #        sb: fs::NewSuperBlock<'_, Self>,
+/// #    ) -> Result<&fs::SuperBlock<Self>> {
+/// #        let sb = sb.init(
+/// #            (),
+/// #            &fs::SuperParams {
+/// #                magic: 0x6578616d,
+/// #                ..fs::SuperParams::DEFAULT
+/// #            },
+/// #        )?;
+/// #        let sb = sb.init_root()?;
+/// #        Ok(sb)
+/// #    }
+/// # }
+/// ```
+#[macro_export]
+macro_rules! define_fs_params {
+    ($data_type:ty, $({$($t:tt)*}),+ $(,)?) => {
+        const PARAMS: $crate::fs::param::SpecTable<'static, $data_type> =
+            {
+                use $crate::fs::param::{self, ConstantArray, Spec, SpecArray, Handler};
+                use $crate::c_str;
+                const COUNT: usize = $crate::count_brace_items!($({$($t)*},)*);
+                const SPECS: [Spec; COUNT] = $crate::define_fs_params!(@specs $({$($t)*},)*);
+                const HANDLERS: [&dyn Handler<$data_type>; COUNT] =
+                    $crate::define_fs_params!(@handlers $data_type, $({$($t)*},)*);
+                // SAFETY: We defined matching specs and handlers above.
+                const ARRAY: SpecArray<COUNT, $data_type> =
+                    unsafe { SpecArray::new(SPECS, HANDLERS) };
+                ARRAY.as_table()
+            };
+    };
+
+    (@handlers $data_type:ty, $({$($t:tt)*},)*) => {
+        [ $($crate::define_fs_params!(@handler $data_type, $($t)*),)* ]
+    };
+    (@handler $data_type:ty, enum, $name:expr, $opts:expr, $closure:expr) => {
+        &param::enum_::handler::<$data_type>($closure)
+    };
+    (@handler $data_type:ty, $type:ident, $name:expr, $closure:expr) => {
+        &param::$type::handler::<$data_type>($closure)
+    };
+
+    (@specs $({$($t:tt)*},)*) => {[ $($crate::define_fs_params!(@spec $($t)*),)* ]};
+    (@spec enum, $name:expr, [$($opts:tt)*], $closure:expr) => {
+        {
+            const COUNT: usize = $crate::count_paren_items!($($opts)*);
+            const OPTIONS: ConstantArray<COUNT> =
+                ConstantArray::new($crate::define_fs_params!(@c_str_first $($opts)*));
+            param::enum_::spec(c_str!($name), OPTIONS.as_table())
+        }
+    };
+    (@spec $type:ident, $name:expr, $closure:expr) => { param::$type::spec(c_str!($name)) };
+
+    (@c_str_first $(($first:expr, $second:expr)),+ $(,)?) => {
+        [$((c_str!($first), $second),)*]
+    };
+}
diff --git a/rust/kernel/gpio.rs b/rust/kernel/gpio.rs
new file mode 100644
index 000000000000..53c7b398d10b
--- /dev/null
+++ b/rust/kernel/gpio.rs
@@ -0,0 +1,505 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Support for gpio device drivers.
+//!
+//! C header: [`include/linux/gpio/driver.h`](../../../../include/linux/gpio/driver.h)
+
+use crate::{
+    bindings, device, error::code::*, error::from_kernel_result, sync::LockClassKey,
+    types::PointerWrapper, Error, Result,
+};
+use core::{
+    cell::UnsafeCell,
+    marker::{PhantomData, PhantomPinned},
+    pin::Pin,
+};
+use macros::vtable;
+
+#[cfg(CONFIG_GPIOLIB_IRQCHIP)]
+pub use irqchip::{ChipWithIrqChip, RegistrationWithIrqChip};
+
+/// The direction of a gpio line.
+pub enum LineDirection {
+    /// Direction is input.
+    In = bindings::GPIO_LINE_DIRECTION_IN as _,
+
+    /// Direction is output.
+    Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
+}
+
+/// A gpio chip.
+#[vtable]
+pub trait Chip {
+    /// Context data associated with the gpio chip.
+    ///
+    /// It determines the type of the context data passed to each of the methods of the trait.
+    type Data: PointerWrapper + Sync + Send;
+
+    /// Returns the direction of the given gpio line.
+    fn get_direction(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _offset: u32,
+    ) -> Result<LineDirection> {
+        Err(ENOTSUPP)
+    }
+
+    /// Configures the direction as input of the given gpio line.
+    fn direction_input(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _offset: u32,
+    ) -> Result {
+        Err(EIO)
+    }
+
+    /// Configures the direction as output of the given gpio line.
+    ///
+    /// The value that will be initially output is also specified.
+    fn direction_output(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _offset: u32,
+        _value: bool,
+    ) -> Result {
+        Err(ENOTSUPP)
+    }
+
+    /// Returns the current value of the given gpio line.
+    fn get(_data: <Self::Data as PointerWrapper>::Borrowed<'_>, _offset: u32) -> Result<bool> {
+        Err(EIO)
+    }
+
+    /// Sets the value of the given gpio line.
+    fn set(_data: <Self::Data as PointerWrapper>::Borrowed<'_>, _offset: u32, _value: bool) {}
+}
+
+/// A registration of a gpio chip.
+///
+/// # Examples
+///
+/// The following example registers an empty gpio chip.
+///
+/// ```
+/// # use kernel::prelude::*;
+/// use kernel::{
+///     device::RawDevice,
+///     gpio::{self, Registration},
+/// };
+///
+/// struct MyGpioChip;
+/// #[vtable]
+/// impl gpio::Chip for MyGpioChip {
+///     type Data = ();
+/// }
+///
+/// fn example(parent: &dyn RawDevice) -> Result<Pin<Box<Registration<MyGpioChip>>>> {
+///     let mut r = Pin::from(Box::try_new(Registration::new())?);
+///     kernel::gpio_chip_register!(r.as_mut(), 32, None, parent, ())?;
+///     Ok(r)
+/// }
+/// ```
+pub struct Registration<T: Chip> {
+    gc: UnsafeCell<bindings::gpio_chip>,
+    parent: Option<device::Device>,
+    _p: PhantomData<T>,
+    _pin: PhantomPinned,
+}
+
+impl<T: Chip> Registration<T> {
+    /// Creates a new [`Registration`] but does not register it yet.
+    ///
+    /// It is allowed to move.
+    pub fn new() -> Self {
+        Self {
+            parent: None,
+            gc: UnsafeCell::new(bindings::gpio_chip::default()),
+            _pin: PhantomPinned,
+            _p: PhantomData,
+        }
+    }
+
+    /// Registers a gpio chip with the rest of the kernel.
+    ///
+    /// Users are encouraged to use the [`gpio_chip_register`] macro because it automatically
+    /// defines the lock classes and calls the registration function.
+    pub fn register(
+        self: Pin<&mut Self>,
+        gpio_count: u16,
+        base: Option<i32>,
+        parent: &dyn device::RawDevice,
+        data: T::Data,
+        lock_keys: [&'static LockClassKey; 2],
+    ) -> Result {
+        if self.parent.is_some() {
+            // Already registered.
+            return Err(EINVAL);
+        }
+
+        // SAFETY: We never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+        {
+            let gc = this.gc.get_mut();
+
+            // Set up the callbacks.
+            gc.request = Some(bindings::gpiochip_generic_request);
+            gc.free = Some(bindings::gpiochip_generic_free);
+            if T::HAS_GET_DIRECTION {
+                gc.get_direction = Some(get_direction_callback::<T>);
+            }
+            if T::HAS_DIRECTION_INPUT {
+                gc.direction_input = Some(direction_input_callback::<T>);
+            }
+            if T::HAS_DIRECTION_OUTPUT {
+                gc.direction_output = Some(direction_output_callback::<T>);
+            }
+            if T::HAS_GET {
+                gc.get = Some(get_callback::<T>);
+            }
+            if T::HAS_SET {
+                gc.set = Some(set_callback::<T>);
+            }
+
+            // When a base is not explicitly given, use -1 for one to be picked.
+            if let Some(b) = base {
+                gc.base = b;
+            } else {
+                gc.base = -1;
+            }
+
+            gc.ngpio = gpio_count;
+            gc.parent = parent.raw_device();
+            gc.label = parent.name().as_char_ptr();
+
+            // TODO: Define `gc.owner` as well.
+        }
+
+        let data_pointer = <T::Data as PointerWrapper>::into_pointer(data);
+        // SAFETY: `gc` was initilised above, so it is valid.
+        let ret = unsafe {
+            bindings::gpiochip_add_data_with_key(
+                this.gc.get(),
+                data_pointer as _,
+                lock_keys[0].get(),
+                lock_keys[1].get(),
+            )
+        };
+        if ret < 0 {
+            // SAFETY: `data_pointer` was returned by `into_pointer` above.
+            unsafe { T::Data::from_pointer(data_pointer) };
+            return Err(Error::from_kernel_errno(ret));
+        }
+
+        this.parent = Some(device::Device::from_dev(parent));
+        Ok(())
+    }
+}
+
+// SAFETY: `Registration` doesn't offer any methods or access to fields when shared between threads
+// or CPUs, so it is safe to share it.
+unsafe impl<T: Chip> Sync for Registration<T> {}
+
+// SAFETY: Registration with and unregistration from the gpio subsystem can happen from any thread.
+// Additionally, `T::Data` (which is dropped during unregistration) is `Send`, so it is ok to move
+// `Registration` to different threads.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl<T: Chip> Send for Registration<T> {}
+
+impl<T: Chip> Default for Registration<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<T: Chip> Drop for Registration<T> {
+    /// Removes the registration from the kernel if it has completed successfully before.
+    fn drop(&mut self) {
+        if self.parent.is_some() {
+            // Get a pointer to the data stored in chip before destroying it.
+            // SAFETY: `gc` was during registration, which is guaranteed to have succeeded (because
+            // `parent` is `Some(_)`, so it remains valid.
+            let data_pointer = unsafe { bindings::gpiochip_get_data(self.gc.get()) };
+
+            // SAFETY: By the same argument above, `gc` is still valid.
+            unsafe { bindings::gpiochip_remove(self.gc.get()) };
+
+            // Free data as well.
+            // SAFETY: `data_pointer` was returned by `into_pointer` during registration.
+            unsafe { <T::Data as PointerWrapper>::from_pointer(data_pointer) };
+        }
+    }
+}
+
+/// Registers a gpio chip with the rest of the kernel.
+///
+/// It automatically defines the required lock classes.
+#[macro_export]
+macro_rules! gpio_chip_register {
+    ($reg:expr, $count:expr, $base:expr, $parent:expr, $data:expr $(,)?) => {{
+        static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        $crate::gpio::Registration::register(
+            $reg,
+            $count,
+            $base,
+            $parent,
+            $data,
+            [&CLASS1, &CLASS2],
+        )
+    }};
+}
+
+unsafe extern "C" fn get_direction_callback<T: Chip>(
+    gc: *mut bindings::gpio_chip,
+    offset: core::ffi::c_uint,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
+        let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
+        Ok(T::get_direction(data, offset)? as i32)
+    }
+}
+
+unsafe extern "C" fn direction_input_callback<T: Chip>(
+    gc: *mut bindings::gpio_chip,
+    offset: core::ffi::c_uint,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
+        let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
+        T::direction_input(data, offset)?;
+        Ok(0)
+    }
+}
+
+unsafe extern "C" fn direction_output_callback<T: Chip>(
+    gc: *mut bindings::gpio_chip,
+    offset: core::ffi::c_uint,
+    value: core::ffi::c_int,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
+        let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
+        T::direction_output(data, offset, value != 0)?;
+        Ok(0)
+    }
+}
+
+unsafe extern "C" fn get_callback<T: Chip>(
+    gc: *mut bindings::gpio_chip,
+    offset: core::ffi::c_uint,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
+        let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
+        let v = T::get(data, offset)?;
+        Ok(v as _)
+    }
+}
+
+unsafe extern "C" fn set_callback<T: Chip>(
+    gc: *mut bindings::gpio_chip,
+    offset: core::ffi::c_uint,
+    value: core::ffi::c_int,
+) {
+    // SAFETY: The value stored as chip data was returned by `into_pointer` during registration.
+    let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
+    T::set(data, offset, value != 0);
+}
+
+#[cfg(CONFIG_GPIOLIB_IRQCHIP)]
+mod irqchip {
+    use super::*;
+    use crate::irq;
+
+    /// A gpio chip that includes an irq chip.
+    pub trait ChipWithIrqChip: Chip {
+        /// Implements the irq flow for the gpio chip.
+        fn handle_irq_flow(
+            _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+            _desc: &irq::Descriptor,
+            _domain: &irq::Domain,
+        );
+    }
+
+    /// A registration of a gpio chip that includes an irq chip.
+    pub struct RegistrationWithIrqChip<T: ChipWithIrqChip> {
+        reg: Registration<T>,
+        irq_chip: UnsafeCell<bindings::irq_chip>,
+        parent_irq: u32,
+    }
+
+    impl<T: ChipWithIrqChip> RegistrationWithIrqChip<T> {
+        /// Creates a new [`RegistrationWithIrqChip`] but does not register it yet.
+        ///
+        /// It is allowed to move.
+        pub fn new() -> Self {
+            Self {
+                reg: Registration::new(),
+                irq_chip: UnsafeCell::new(bindings::irq_chip::default()),
+                parent_irq: 0,
+            }
+        }
+
+        /// Registers a gpio chip and its irq chip with the rest of the kernel.
+        ///
+        /// Users are encouraged to use the [`gpio_irq_chip_register`] macro because it
+        /// automatically defines the lock classes and calls the registration function.
+        pub fn register<U: irq::Chip<Data = T::Data>>(
+            mut self: Pin<&mut Self>,
+            gpio_count: u16,
+            base: Option<i32>,
+            parent: &dyn device::RawDevice,
+            data: T::Data,
+            parent_irq: u32,
+            lock_keys: [&'static LockClassKey; 2],
+        ) -> Result {
+            if self.reg.parent.is_some() {
+                // Already registered.
+                return Err(EINVAL);
+            }
+
+            // SAFETY: We never move out of `this`.
+            let this = unsafe { self.as_mut().get_unchecked_mut() };
+
+            // Initialise the irq_chip.
+            {
+                let irq_chip = this.irq_chip.get_mut();
+                irq_chip.name = parent.name().as_char_ptr();
+
+                // SAFETY: The gpio subsystem configures a pointer to `gpio_chip` as the irq chip
+                // data, so we use `IrqChipAdapter` to convert to the `T::Data`, which is the same
+                // as `irq::Chip::Data` per the bound above.
+                unsafe { irq::init_chip::<IrqChipAdapter<U>>(irq_chip) };
+            }
+
+            // Initialise gc irq state.
+            {
+                let girq = &mut this.reg.gc.get_mut().irq;
+                girq.chip = this.irq_chip.get();
+                // SAFETY: By leaving `parent_handler_data` set to `null`, the gpio subsystem
+                // initialises it to a pointer to the gpio chip, which is what `FlowHandler<T>`
+                // expects.
+                girq.parent_handler = unsafe { irq::new_flow_handler::<FlowHandler<T>>() };
+                girq.num_parents = 1;
+                girq.parents = &mut this.parent_irq;
+                this.parent_irq = parent_irq;
+                girq.default_type = bindings::IRQ_TYPE_NONE;
+                girq.handler = Some(bindings::handle_bad_irq);
+            }
+
+            // SAFETY: `reg` is pinned when `self` is.
+            let pinned = unsafe { self.map_unchecked_mut(|r| &mut r.reg) };
+            pinned.register(gpio_count, base, parent, data, lock_keys)
+        }
+    }
+
+    impl<T: ChipWithIrqChip> Default for RegistrationWithIrqChip<T> {
+        fn default() -> Self {
+            Self::new()
+        }
+    }
+
+    // SAFETY: `RegistrationWithIrqChip` doesn't offer any methods or access to fields when shared
+    // between threads or CPUs, so it is safe to share it.
+    unsafe impl<T: ChipWithIrqChip> Sync for RegistrationWithIrqChip<T> {}
+
+    // SAFETY: Registration with and unregistration from the gpio subsystem (including irq chips for
+    // them) can happen from any thread. Additionally, `T::Data` (which is dropped during
+    // unregistration) is `Send`, so it is ok to move `Registration` to different threads.
+    #[allow(clippy::non_send_fields_in_send_ty)]
+    unsafe impl<T: ChipWithIrqChip> Send for RegistrationWithIrqChip<T> where T::Data: Send {}
+
+    struct FlowHandler<T: ChipWithIrqChip>(PhantomData<T>);
+
+    impl<T: ChipWithIrqChip> irq::FlowHandler for FlowHandler<T> {
+        type Data = *mut bindings::gpio_chip;
+
+        fn handle_irq_flow(gc: *mut bindings::gpio_chip, desc: &irq::Descriptor) {
+            // SAFETY: `FlowHandler` is only used in gpio chips, and it is removed when the gpio is
+            // unregistered, so we know that `gc` must still be valid. We also know that the value
+            // stored as gpio data was returned by `T::Data::into_pointer` again because
+            // `FlowHandler` is a private structure only used in this way.
+            let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc)) };
+
+            // SAFETY: `gc` is valid (see comment above), so we can dereference it.
+            let domain = unsafe { irq::Domain::from_ptr((*gc).irq.domain) };
+
+            T::handle_irq_flow(data, desc, &domain);
+        }
+    }
+
+    /// Adapter from an irq chip with `gpio_chip` pointer as context to one where the gpio chip
+    /// data is passed as context.
+    struct IrqChipAdapter<T: irq::Chip>(PhantomData<T>);
+
+    #[vtable]
+    impl<T: irq::Chip> irq::Chip for IrqChipAdapter<T> {
+        type Data = *mut bindings::gpio_chip;
+
+        const HAS_SET_TYPE: bool = T::HAS_SET_TYPE;
+        const HAS_SET_WAKE: bool = T::HAS_SET_WAKE;
+
+        fn ack(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
+            // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
+            // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
+            // registered, so `gc` is valid.
+            let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
+            T::ack(data, irq_data);
+        }
+
+        fn mask(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
+            // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
+            // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
+            // registered, so `gc` is valid.
+            let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
+            T::mask(data, irq_data);
+        }
+
+        fn unmask(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData) {
+            // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
+            // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
+            // registered, so `gc` is valid.
+            let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
+            T::unmask(data, irq_data);
+        }
+
+        fn set_type(
+            gc: *mut bindings::gpio_chip,
+            irq_data: &mut irq::LockedIrqData,
+            flow_type: u32,
+        ) -> Result<irq::ExtraResult> {
+            // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
+            // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
+            // registered, so `gc` is valid.
+            let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
+            T::set_type(data, irq_data, flow_type)
+        }
+
+        fn set_wake(gc: *mut bindings::gpio_chip, irq_data: &irq::IrqData, on: bool) -> Result {
+            // SAFETY: `IrqChipAdapter` is a private struct, only used when the data stored in the
+            // gpio chip is known to come from `T::Data`, and only valid while the gpio chip is
+            // registered, so `gc` is valid.
+            let data = unsafe { T::Data::borrow(bindings::gpiochip_get_data(gc as _)) };
+            T::set_wake(data, irq_data, on)
+        }
+    }
+
+    /// Registers a gpio chip and its irq chip with the rest of the kernel.
+    ///
+    /// It automatically defines the required lock classes.
+    #[macro_export]
+    macro_rules! gpio_irq_chip_register {
+        ($reg:expr, $irqchip:ty, $count:expr, $base:expr, $parent:expr, $data:expr,
+         $parent_irq:expr $(,)?) => {{
+            static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+            static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+            $crate::gpio::RegistrationWithIrqChip::register::<$irqchip>(
+                $reg,
+                $count,
+                $base,
+                $parent,
+                $data,
+                $parent_irq,
+                [&CLASS1, &CLASS2],
+            )
+        }};
+    }
+}
diff --git a/rust/kernel/hwrng.rs b/rust/kernel/hwrng.rs
new file mode 100644
index 000000000000..5918f567c332
--- /dev/null
+++ b/rust/kernel/hwrng.rs
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Hardware Random Number Generator.
+//!
+//! C header: [`include/linux/hw_random.h`](../../../../include/linux/hw_random.h)
+
+use alloc::{boxed::Box, slice::from_raw_parts_mut};
+
+use crate::{
+    bindings, error::code::*, error::from_kernel_result, str::CString, to_result,
+    types::PointerWrapper, Result, ScopeGuard,
+};
+use macros::vtable;
+
+use core::{cell::UnsafeCell, fmt, marker::PhantomData, pin::Pin};
+
+/// This trait is implemented in order to provide callbacks to `struct hwrng`.
+#[vtable]
+pub trait Operations {
+    /// The pointer type that will be used to hold user-defined data type.
+    type Data: PointerWrapper + Send + Sync = ();
+
+    /// Initialization callback, can be left undefined.
+    fn init(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
+        Err(EINVAL)
+    }
+
+    /// Cleanup callback, can be left undefined.
+    fn cleanup(_data: Self::Data) {}
+
+    /// Read data into the provided buffer.
+    /// Drivers can fill up to max bytes of data into the buffer.
+    /// The buffer is aligned for any type and its size is a multiple of 4 and >= 32 bytes.
+    fn read(
+        data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        buffer: &mut [u8],
+        wait: bool,
+    ) -> Result<u32>;
+}
+
+/// Registration structure for Hardware Random Number Generator driver.
+pub struct Registration<T: Operations> {
+    hwrng: UnsafeCell<bindings::hwrng>,
+    name: Option<CString>,
+    registered: bool,
+    _p: PhantomData<T>,
+}
+
+impl<T: Operations> Registration<T> {
+    /// Creates new instance of registration.
+    ///
+    /// The data must be registered.
+    pub fn new() -> Self {
+        Self {
+            hwrng: UnsafeCell::new(bindings::hwrng::default()),
+            name: None,
+            registered: false,
+            _p: PhantomData,
+        }
+    }
+
+    /// Returns a registered and pinned, heap-allocated representation of the registration.
+    pub fn new_pinned(
+        name: fmt::Arguments<'_>,
+        quality: u16,
+        data: T::Data,
+    ) -> Result<Pin<Box<Self>>> {
+        let mut reg = Pin::from(Box::try_new(Self::new())?);
+        reg.as_mut().register(name, quality, data)?;
+        Ok(reg)
+    }
+
+    /// Registers a hwrng device within the rest of the kernel.
+    ///
+    /// It must be pinned because the memory block that represents
+    /// the registration may be self-referential.
+    pub fn register(
+        self: Pin<&mut Self>,
+        name: fmt::Arguments<'_>,
+        quality: u16,
+        data: T::Data,
+    ) -> Result {
+        // SAFETY: We never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+
+        if this.registered {
+            return Err(EINVAL);
+        }
+
+        let data_pointer = data.into_pointer();
+
+        // SAFETY: `data_pointer` comes from the call to `data.into_pointer()` above.
+        let guard = ScopeGuard::new(|| unsafe {
+            T::Data::from_pointer(data_pointer);
+        });
+
+        let name = CString::try_from_fmt(name)?;
+
+        // SAFETY: Registration is pinned and contains allocated and set to zero
+        // `bindings::hwrng` structure.
+        Self::init_hwrng(
+            unsafe { &mut *this.hwrng.get() },
+            &name,
+            quality,
+            data_pointer,
+        );
+
+        // SAFETY: `bindings::hwrng` is initialized above which guarantees safety.
+        to_result(unsafe { bindings::hwrng_register(this.hwrng.get()) })?;
+
+        this.registered = true;
+        this.name = Some(name);
+        guard.dismiss();
+        Ok(())
+    }
+
+    fn init_hwrng(
+        hwrng: &mut bindings::hwrng,
+        name: &CString,
+        quality: u16,
+        data: *const core::ffi::c_void,
+    ) {
+        hwrng.name = name.as_char_ptr();
+
+        hwrng.init = if T::HAS_INIT {
+            Some(Self::init_callback)
+        } else {
+            None
+        };
+        hwrng.cleanup = if T::HAS_CLEANUP {
+            Some(Self::cleanup_callback)
+        } else {
+            None
+        };
+        hwrng.data_present = None;
+        hwrng.data_read = None;
+        hwrng.read = Some(Self::read_callback);
+
+        hwrng.priv_ = data as _;
+        hwrng.quality = quality;
+
+        // SAFETY: All fields are properly initialized as
+        // remaining fields `list`, `ref` and `cleanup_done` are already
+        // zeroed by `bindings::hwrng::default()` call.
+    }
+
+    unsafe extern "C" fn init_callback(rng: *mut bindings::hwrng) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: `priv` private data field was initialized during creation of
+            // the `bindings::hwrng` in `Self::init_hwrng` method. This callback is only
+            // called once the driver is registered.
+            let data = unsafe { T::Data::borrow((*rng).priv_ as *const _) };
+            T::init(data)?;
+            Ok(0)
+        }
+    }
+
+    unsafe extern "C" fn cleanup_callback(rng: *mut bindings::hwrng) {
+        // SAFETY: `priv` private data field was initialized during creation of
+        // the `bindings::hwrng` in `Self::init_hwrng` method. This callback is only
+        // called once the driver is registered.
+        let data = unsafe { T::Data::from_pointer((*rng).priv_ as *const _) };
+        T::cleanup(data);
+    }
+
+    unsafe extern "C" fn read_callback(
+        rng: *mut bindings::hwrng,
+        data: *mut core::ffi::c_void,
+        max: usize,
+        wait: bindings::bool_,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: `priv` private data field was initialized during creation of
+            // the `bindings::hwrng` in `Self::init_hwrng` method. This callback is only
+            // called once the driver is registered.
+            let drv_data = unsafe { T::Data::borrow((*rng).priv_ as *const _) };
+
+            // SAFETY: Slice is created from `data` and `max` arguments that are C's buffer
+            // along with its size in bytes that are safe for this conversion.
+            let buffer = unsafe { from_raw_parts_mut(data as *mut u8, max) };
+            let ret = T::read(drv_data, buffer, wait)?;
+            Ok(ret as _)
+        }
+    }
+}
+
+impl<T: Operations> Default for Registration<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+// SAFETY: `Registration` does not expose any of its state across threads.
+unsafe impl<T: Operations> Sync for Registration<T> {}
+
+// SAFETY: `Registration` is not restricted to a single thread,
+// its `T::Data` is also `Send` so it may be moved to different threads.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl<T: Operations> Send for Registration<T> {}
+
+impl<T: Operations> Drop for Registration<T> {
+    /// Removes the registration from the kernel if it has completed successfully before.
+    fn drop(&mut self) {
+        // SAFETY: The instance of Registration<T> is unregistered only
+        // after being initialized and registered before.
+        if self.registered {
+            unsafe { bindings::hwrng_unregister(self.hwrng.get()) };
+        }
+    }
+}
diff --git a/rust/kernel/io_buffer.rs b/rust/kernel/io_buffer.rs
new file mode 100644
index 000000000000..ccecc4763aca
--- /dev/null
+++ b/rust/kernel/io_buffer.rs
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Buffers used in IO.
+
+use crate::Result;
+use alloc::vec::Vec;
+use core::mem::{size_of, MaybeUninit};
+
+/// Represents a buffer to be read from during IO.
+pub trait IoBufferReader {
+    /// Returns the number of bytes left to be read from the io buffer.
+    ///
+    /// Note that even reading less than this number of bytes may fail.
+    fn len(&self) -> usize;
+
+    /// Returns `true` if no data is available in the io buffer.
+    fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Reads raw data from the io buffer into a raw kernel buffer.
+    ///
+    /// # Safety
+    ///
+    /// The output buffer must be valid.
+    unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result;
+
+    /// Reads all data remaining in the io buffer.
+    ///
+    /// Returns `EFAULT` if the address does not currently point to mapped, readable memory.
+    fn read_all(&mut self) -> Result<Vec<u8>> {
+        let mut data = Vec::<u8>::new();
+        data.try_resize(self.len(), 0)?;
+
+        // SAFETY: The output buffer is valid as we just allocated it.
+        unsafe { self.read_raw(data.as_mut_ptr(), data.len())? };
+        Ok(data)
+    }
+
+    /// Reads a byte slice from the io buffer.
+    ///
+    /// Returns `EFAULT` if the byte slice is bigger than the remaining size of the user slice or
+    /// if the address does not currently point to mapped, readable memory.
+    fn read_slice(&mut self, data: &mut [u8]) -> Result {
+        // SAFETY: The output buffer is valid as it's coming from a live reference.
+        unsafe { self.read_raw(data.as_mut_ptr(), data.len()) }
+    }
+
+    /// Reads the contents of a plain old data (POD) type from the io buffer.
+    fn read<T: ReadableFromBytes>(&mut self) -> Result<T> {
+        let mut out = MaybeUninit::<T>::uninit();
+        // SAFETY: The buffer is valid as it was just allocated.
+        unsafe { self.read_raw(out.as_mut_ptr() as _, size_of::<T>()) }?;
+        // SAFETY: We just initialised the data.
+        Ok(unsafe { out.assume_init() })
+    }
+}
+
+/// Represents a buffer to be written to during IO.
+pub trait IoBufferWriter {
+    /// Returns the number of bytes left to be written into the io buffer.
+    ///
+    /// Note that even writing less than this number of bytes may fail.
+    fn len(&self) -> usize;
+
+    /// Returns `true` if the io buffer cannot hold any additional data.
+    fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Writes zeroes to the io buffer.
+    ///
+    /// Differently from the other write functions, `clear` will zero as much as it can and update
+    /// the writer internal state to reflect this. It will, however, return an error if it cannot
+    /// clear `len` bytes.
+    ///
+    /// For example, if a caller requests that 100 bytes be cleared but a segfault happens after
+    /// 20 bytes, then EFAULT is returned and the writer is advanced by 20 bytes.
+    fn clear(&mut self, len: usize) -> Result;
+
+    /// Writes a byte slice into the io buffer.
+    ///
+    /// Returns `EFAULT` if the byte slice is bigger than the remaining size of the io buffer or if
+    /// the address does not currently point to mapped, writable memory.
+    fn write_slice(&mut self, data: &[u8]) -> Result {
+        // SAFETY: The input buffer is valid as it's coming from a live reference.
+        unsafe { self.write_raw(data.as_ptr(), data.len()) }
+    }
+
+    /// Writes raw data to the io buffer from a raw kernel buffer.
+    ///
+    /// # Safety
+    ///
+    /// The input buffer must be valid.
+    unsafe fn write_raw(&mut self, data: *const u8, len: usize) -> Result;
+
+    /// Writes the contents of the given data into the io buffer.
+    fn write<T: WritableToBytes>(&mut self, data: &T) -> Result {
+        // SAFETY: The input buffer is valid as it's coming from a live
+        // reference to a type that implements `WritableToBytes`.
+        unsafe { self.write_raw(data as *const T as _, size_of::<T>()) }
+    }
+}
+
+/// Specifies that a type is safely readable from byte slices.
+///
+/// Not all types can be safely read from byte slices; examples from
+/// <https://doc.rust-lang.org/reference/behavior-considered-undefined.html> include `bool`
+/// that must be either `0` or `1`, and `char` that cannot be a surrogate or above `char::MAX`.
+///
+/// # Safety
+///
+/// Implementers must ensure that the type is made up only of types that can be safely read from
+/// arbitrary byte sequences (e.g., `u32`, `u64`, etc.).
+pub unsafe trait ReadableFromBytes {}
+
+// SAFETY: All bit patterns are acceptable values of the types below.
+unsafe impl ReadableFromBytes for u8 {}
+unsafe impl ReadableFromBytes for u16 {}
+unsafe impl ReadableFromBytes for u32 {}
+unsafe impl ReadableFromBytes for u64 {}
+unsafe impl ReadableFromBytes for usize {}
+unsafe impl ReadableFromBytes for i8 {}
+unsafe impl ReadableFromBytes for i16 {}
+unsafe impl ReadableFromBytes for i32 {}
+unsafe impl ReadableFromBytes for i64 {}
+unsafe impl ReadableFromBytes for isize {}
+
+/// Specifies that a type is safely writable to byte slices.
+///
+/// This means that we don't read undefined values (which leads to UB) in preparation for writing
+/// to the byte slice. It also ensures that no potentially sensitive information is leaked into the
+/// byte slices.
+///
+/// # Safety
+///
+/// A type must not include padding bytes and must be fully initialised to safely implement
+/// [`WritableToBytes`] (i.e., it doesn't contain [`MaybeUninit`] fields). A composition of
+/// writable types in a structure is not necessarily writable because it may result in padding
+/// bytes.
+pub unsafe trait WritableToBytes {}
+
+// SAFETY: Initialised instances of the following types have no uninitialised portions.
+unsafe impl WritableToBytes for u8 {}
+unsafe impl WritableToBytes for u16 {}
+unsafe impl WritableToBytes for u32 {}
+unsafe impl WritableToBytes for u64 {}
+unsafe impl WritableToBytes for usize {}
+unsafe impl WritableToBytes for i8 {}
+unsafe impl WritableToBytes for i16 {}
+unsafe impl WritableToBytes for i32 {}
+unsafe impl WritableToBytes for i64 {}
+unsafe impl WritableToBytes for isize {}
diff --git a/rust/kernel/io_mem.rs b/rust/kernel/io_mem.rs
new file mode 100644
index 000000000000..ff6886a9e3b7
--- /dev/null
+++ b/rust/kernel/io_mem.rs
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Memory-mapped IO.
+//!
+//! C header: [`include/asm-generic/io.h`](../../../../include/asm-generic/io.h)
+
+#![allow(dead_code)]
+
+use crate::{bindings, error::code::*, Result};
+use core::convert::TryInto;
+
+/// Represents a memory resource.
+pub struct Resource {
+    offset: bindings::resource_size_t,
+    size: bindings::resource_size_t,
+}
+
+impl Resource {
+    pub(crate) fn new(
+        start: bindings::resource_size_t,
+        end: bindings::resource_size_t,
+    ) -> Option<Self> {
+        if start == 0 {
+            return None;
+        }
+        Some(Self {
+            offset: start,
+            size: end.checked_sub(start)?.checked_add(1)?,
+        })
+    }
+}
+
+/// Represents a memory block of at least `SIZE` bytes.
+///
+/// # Invariants
+///
+/// `ptr` is a non-null and valid address of at least `SIZE` bytes and returned by an `ioremap`
+/// variant. `ptr` is also 8-byte aligned.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::prelude::*;
+/// use kernel::io_mem::{IoMem, Resource};
+///
+/// fn test(res: Resource) -> Result {
+///     // Create an io mem block of at least 100 bytes.
+///     // SAFETY: No DMA operations are initiated through `mem`.
+///     let mem = unsafe { IoMem::<100>::try_new(res) }?;
+///
+///     // Read one byte from offset 10.
+///     let v = mem.readb(10);
+///
+///     // Write value to offset 20.
+///     mem.writeb(v, 20);
+///
+///     Ok(())
+/// }
+/// ```
+pub struct IoMem<const SIZE: usize> {
+    ptr: usize,
+}
+
+macro_rules! define_read {
+    ($(#[$attr:meta])* $name:ident, $try_name:ident, $type_name:ty) => {
+        /// Reads IO data from the given offset known, at compile time.
+        ///
+        /// If the offset is not known at compile time, the build will fail.
+        $(#[$attr])*
+        #[inline]
+        pub fn $name(&self, offset: usize) -> $type_name {
+            Self::check_offset::<$type_name>(offset);
+            let ptr = self.ptr.wrapping_add(offset);
+            // SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
+            // guarantees that the code won't build if `offset` makes the read go out of bounds
+            // (including the type size).
+            unsafe { bindings::$name(ptr as _) }
+        }
+
+        /// Reads IO data from the given offset.
+        ///
+        /// It fails if/when the offset (plus the type size) is out of bounds.
+        $(#[$attr])*
+        pub fn $try_name(&self, offset: usize) -> Result<$type_name> {
+            if !Self::offset_ok::<$type_name>(offset) {
+                return Err(EINVAL);
+            }
+            let ptr = self.ptr.wrapping_add(offset);
+            // SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
+            // returns an error if `offset` would make the read go out of bounds (including the
+            // type size).
+            Ok(unsafe { bindings::$name(ptr as _) })
+        }
+    };
+}
+
+macro_rules! define_write {
+    ($(#[$attr:meta])* $name:ident, $try_name:ident, $type_name:ty) => {
+        /// Writes IO data to the given offset, known at compile time.
+        ///
+        /// If the offset is not known at compile time, the build will fail.
+        $(#[$attr])*
+        #[inline]
+        pub fn $name(&self, value: $type_name, offset: usize) {
+            Self::check_offset::<$type_name>(offset);
+            let ptr = self.ptr.wrapping_add(offset);
+            // SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
+            // guarantees that the code won't link if `offset` makes the write go out of bounds
+            // (including the type size).
+            unsafe { bindings::$name(value, ptr as _) }
+        }
+
+        /// Writes IO data to the given offset.
+        ///
+        /// It fails if/when the offset (plus the type size) is out of bounds.
+        $(#[$attr])*
+        pub fn $try_name(&self, value: $type_name, offset: usize) -> Result {
+            if !Self::offset_ok::<$type_name>(offset) {
+                return Err(EINVAL);
+            }
+            let ptr = self.ptr.wrapping_add(offset);
+            // SAFETY: The type invariants guarantee that `ptr` is a valid pointer. The check above
+            // returns an error if `offset` would make the write go out of bounds (including the
+            // type size).
+            unsafe { bindings::$name(value, ptr as _) };
+            Ok(())
+        }
+    };
+}
+
+impl<const SIZE: usize> IoMem<SIZE> {
+    /// Tries to create a new instance of a memory block.
+    ///
+    /// The resource described by `res` is mapped into the CPU's address space so that it can be
+    /// accessed directly. It is also consumed by this function so that it can't be mapped again
+    /// to a different address.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that either (a) the resulting interface cannot be used to initiate DMA
+    /// operations, or (b) that DMA operations initiated via the returned interface use DMA handles
+    /// allocated through the `dma` module.
+    pub unsafe fn try_new(res: Resource) -> Result<Self> {
+        // Check that the resource has at least `SIZE` bytes in it.
+        if res.size < SIZE.try_into()? {
+            return Err(EINVAL);
+        }
+
+        // To be able to check pointers at compile time based only on offsets, we need to guarantee
+        // that the base pointer is minimally aligned. So we conservatively expect at least 8 bytes.
+        if res.offset % 8 != 0 {
+            crate::pr_err!("Physical address is not 64-bit aligned: {:x}", res.offset);
+            return Err(EDOM);
+        }
+
+        // Try to map the resource.
+        // SAFETY: Just mapping the memory range.
+        let addr = unsafe { bindings::ioremap(res.offset, res.size as _) };
+        if addr.is_null() {
+            Err(ENOMEM)
+        } else {
+            // INVARIANT: `addr` is non-null and was returned by `ioremap`, so it is valid. It is
+            // also 8-byte aligned because we checked it above.
+            Ok(Self { ptr: addr as usize })
+        }
+    }
+
+    #[inline]
+    const fn offset_ok<T>(offset: usize) -> bool {
+        let type_size = core::mem::size_of::<T>();
+        if let Some(end) = offset.checked_add(type_size) {
+            end <= SIZE && offset % type_size == 0
+        } else {
+            false
+        }
+    }
+
+    fn offset_ok_of_val<T: ?Sized>(offset: usize, value: &T) -> bool {
+        let value_size = core::mem::size_of_val(value);
+        let value_alignment = core::mem::align_of_val(value);
+        if let Some(end) = offset.checked_add(value_size) {
+            end <= SIZE && offset % value_alignment == 0
+        } else {
+            false
+        }
+    }
+
+    #[inline]
+    const fn check_offset<T>(offset: usize) {
+        crate::build_assert!(Self::offset_ok::<T>(offset), "IoMem offset overflow");
+    }
+
+    /// Copy memory block from an i/o memory by filling the specified buffer with it.
+    ///
+    /// # Examples
+    /// ```
+    /// use kernel::io_mem::{self, IoMem, Resource};
+    ///
+    /// fn test(res: Resource) -> Result {
+    ///     // Create an i/o memory block of at least 100 bytes.
+    ///     let mem = unsafe { IoMem::<100>::try_new(res) }?;
+    ///
+    ///     let mut buffer: [u8; 32] = [0; 32];
+    ///
+    ///     // Memcpy 16 bytes from an offset 10 of i/o memory block into the buffer.
+    ///     mem.try_memcpy_fromio(&mut buffer[..16], 10)?;
+    ///
+    ///     Ok(())
+    /// }
+    /// ```
+    pub fn try_memcpy_fromio(&self, buffer: &mut [u8], offset: usize) -> Result {
+        if !Self::offset_ok_of_val(offset, buffer) {
+            return Err(EINVAL);
+        }
+
+        let ptr = self.ptr.wrapping_add(offset);
+
+        // SAFETY:
+        //   - The type invariants guarantee that `ptr` is a valid pointer.
+        //   - The bounds of `buffer` are checked with a call to `offset_ok_of_val()`.
+        unsafe {
+            bindings::memcpy_fromio(
+                buffer.as_mut_ptr() as *mut _,
+                ptr as *const _,
+                buffer.len() as _,
+            )
+        };
+        Ok(())
+    }
+
+    define_read!(readb, try_readb, u8);
+    define_read!(readw, try_readw, u16);
+    define_read!(readl, try_readl, u32);
+    define_read!(
+        #[cfg(CONFIG_64BIT)]
+        readq,
+        try_readq,
+        u64
+    );
+
+    define_read!(readb_relaxed, try_readb_relaxed, u8);
+    define_read!(readw_relaxed, try_readw_relaxed, u16);
+    define_read!(readl_relaxed, try_readl_relaxed, u32);
+    define_read!(
+        #[cfg(CONFIG_64BIT)]
+        readq_relaxed,
+        try_readq_relaxed,
+        u64
+    );
+
+    define_write!(writeb, try_writeb, u8);
+    define_write!(writew, try_writew, u16);
+    define_write!(writel, try_writel, u32);
+    define_write!(
+        #[cfg(CONFIG_64BIT)]
+        writeq,
+        try_writeq,
+        u64
+    );
+
+    define_write!(writeb_relaxed, try_writeb_relaxed, u8);
+    define_write!(writew_relaxed, try_writew_relaxed, u16);
+    define_write!(writel_relaxed, try_writel_relaxed, u32);
+    define_write!(
+        #[cfg(CONFIG_64BIT)]
+        writeq_relaxed,
+        try_writeq_relaxed,
+        u64
+    );
+}
+
+impl<const SIZE: usize> Drop for IoMem<SIZE> {
+    fn drop(&mut self) {
+        // SAFETY: By the type invariant, `self.ptr` is a value returned by a previous successful
+        // call to `ioremap`.
+        unsafe { bindings::iounmap(self.ptr as _) };
+    }
+}
diff --git a/rust/kernel/iov_iter.rs b/rust/kernel/iov_iter.rs
new file mode 100644
index 000000000000..b9b8dc882bd0
--- /dev/null
+++ b/rust/kernel/iov_iter.rs
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! IO vector iterators.
+//!
+//! C header: [`include/linux/uio.h`](../../../../include/linux/uio.h)
+
+use crate::{
+    bindings,
+    error::code::*,
+    io_buffer::{IoBufferReader, IoBufferWriter},
+    Result,
+};
+
+/// Wraps the kernel's `struct iov_iter`.
+///
+/// # Invariants
+///
+/// The pointer `IovIter::ptr` is non-null and valid.
+pub struct IovIter {
+    ptr: *mut bindings::iov_iter,
+}
+
+impl IovIter {
+    fn common_len(&self) -> usize {
+        // SAFETY: `IovIter::ptr` is guaranteed to be valid by the type invariants.
+        unsafe { (*self.ptr).count }
+    }
+
+    /// Constructs a new [`struct iov_iter`] wrapper.
+    ///
+    /// # Safety
+    ///
+    /// The pointer `ptr` must be non-null and valid for the lifetime of the object.
+    pub(crate) unsafe fn from_ptr(ptr: *mut bindings::iov_iter) -> Self {
+        // INVARIANTS: the safety contract ensures the type invariant will hold.
+        Self { ptr }
+    }
+}
+
+impl IoBufferWriter for IovIter {
+    fn len(&self) -> usize {
+        self.common_len()
+    }
+
+    fn clear(&mut self, mut len: usize) -> Result {
+        while len > 0 {
+            // SAFETY: `IovIter::ptr` is guaranteed to be valid by the type invariants.
+            let written = unsafe { bindings::iov_iter_zero(len, self.ptr) };
+            if written == 0 {
+                return Err(EFAULT);
+            }
+
+            len -= written;
+        }
+        Ok(())
+    }
+
+    unsafe fn write_raw(&mut self, data: *const u8, len: usize) -> Result {
+        let res = unsafe { bindings::copy_to_iter(data as _, len, self.ptr) };
+        if res != len {
+            Err(EFAULT)
+        } else {
+            Ok(())
+        }
+    }
+}
+
+impl IoBufferReader for IovIter {
+    fn len(&self) -> usize {
+        self.common_len()
+    }
+
+    unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result {
+        let res = unsafe { bindings::copy_from_iter(out as _, len, self.ptr) };
+        if res != len {
+            Err(EFAULT)
+        } else {
+            Ok(())
+        }
+    }
+}
diff --git a/rust/kernel/irq.rs b/rust/kernel/irq.rs
new file mode 100644
index 000000000000..f2fa270dd728
--- /dev/null
+++ b/rust/kernel/irq.rs
@@ -0,0 +1,681 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Interrupts and interrupt chips.
+//!
+//! See <https://www.kernel.org/doc/Documentation/core-api/genericirq.rst>.
+//!
+//! C headers: [`include/linux/irq.h`](../../../../include/linux/irq.h) and
+//! [`include/linux/interrupt.h`](../../../../include/linux/interrupt.h).
+
+#![allow(dead_code)]
+
+use crate::{
+    bindings,
+    error::{from_kernel_result, to_result},
+    str::CString,
+    types::PointerWrapper,
+    Error, Result, ScopeGuard,
+};
+use core::{fmt, marker::PhantomData, ops::Deref};
+use macros::vtable;
+
+/// The type of irq hardware numbers.
+pub type HwNumber = bindings::irq_hw_number_t;
+
+/// Wraps the kernel's `struct irq_data`.
+///
+/// # Invariants
+///
+/// The pointer `IrqData::ptr` is non-null and valid.
+pub struct IrqData {
+    ptr: *mut bindings::irq_data,
+}
+
+impl IrqData {
+    /// Creates a new `IrqData` instance from a raw pointer.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `ptr` is non-null and valid when the function is called, and that
+    /// it remains valid for the lifetime of the return [`IrqData`] instance.
+    unsafe fn from_ptr(ptr: *mut bindings::irq_data) -> Self {
+        // INVARIANTS: By the safety requirements, the instance we're creating satisfies the type
+        // invariants.
+        Self { ptr }
+    }
+
+    /// Returns the hardware irq number.
+    pub fn hwirq(&self) -> HwNumber {
+        // SAFETY: By the type invariants, it's ok to dereference `ptr`.
+        unsafe { (*self.ptr).hwirq }
+    }
+}
+
+/// Wraps the kernel's `struct irq_data` when it is locked.
+///
+/// Being locked allows additional operations to be performed on the data.
+pub struct LockedIrqData(IrqData);
+
+impl LockedIrqData {
+    /// Sets the high-level irq flow handler to the builtin one for level-triggered irqs.
+    pub fn set_level_handler(&mut self) {
+        // SAFETY: By the type invariants of `self.0`, we know `self.0.ptr` is valid.
+        unsafe { bindings::irq_set_handler_locked(self.0.ptr, Some(bindings::handle_level_irq)) };
+    }
+
+    /// Sets the high-level irq flow handler to the builtin one for edge-triggered irqs.
+    pub fn set_edge_handler(&mut self) {
+        // SAFETY: By the type invariants of `self.0`, we know `self.0.ptr` is valid.
+        unsafe { bindings::irq_set_handler_locked(self.0.ptr, Some(bindings::handle_edge_irq)) };
+    }
+
+    /// Sets the high-level irq flow handler to the builtin one for bad irqs.
+    pub fn set_bad_handler(&mut self) {
+        // SAFETY: By the type invariants of `self.0`, we know `self.0.ptr` is valid.
+        unsafe { bindings::irq_set_handler_locked(self.0.ptr, Some(bindings::handle_bad_irq)) };
+    }
+}
+
+impl Deref for LockedIrqData {
+    type Target = IrqData;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+/// Extra information returned by some of the [`Chip`] methods on success.
+pub enum ExtraResult {
+    /// Indicates that the caller (irq core) will update the descriptor state.
+    None = bindings::IRQ_SET_MASK_OK as _,
+
+    /// Indicates that the callee (irq chip implementation) already updated the descriptor state.
+    NoCopy = bindings::IRQ_SET_MASK_OK_NOCOPY as _,
+
+    /// Same as [`ExtraResult::None`] in terms of updating descriptor state. It is used in stacked
+    /// irq chips to indicate that descendant chips should be skipped.
+    Done = bindings::IRQ_SET_MASK_OK_DONE as _,
+}
+
+/// An irq chip.
+///
+/// It is a trait for the functions defined in [`struct irq_chip`].
+///
+/// [`struct irq_chip`]: ../../../include/linux/irq.h
+#[vtable]
+pub trait Chip: Sized {
+    /// The type of the context data stored in the irq chip and made available on each callback.
+    type Data: PointerWrapper;
+
+    /// Called at the start of a new interrupt.
+    fn ack(data: <Self::Data as PointerWrapper>::Borrowed<'_>, irq_data: &IrqData);
+
+    /// Masks an interrupt source.
+    fn mask(data: <Self::Data as PointerWrapper>::Borrowed<'_>, irq_data: &IrqData);
+
+    /// Unmasks an interrupt source.
+    fn unmask(_data: <Self::Data as PointerWrapper>::Borrowed<'_>, irq_data: &IrqData);
+
+    /// Sets the flow type of an interrupt.
+    ///
+    /// The flow type is a combination of the constants in [`Type`].
+    fn set_type(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _irq_data: &mut LockedIrqData,
+        _flow_type: u32,
+    ) -> Result<ExtraResult> {
+        Ok(ExtraResult::None)
+    }
+
+    /// Enables or disables power-management wake-on of an interrupt.
+    fn set_wake(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _irq_data: &IrqData,
+        _on: bool,
+    ) -> Result {
+        Ok(())
+    }
+}
+
+/// Initialises `chip` with the callbacks defined in `T`.
+///
+/// # Safety
+///
+/// The caller must ensure that the value stored in the irq chip data is the result of calling
+/// [`PointerWrapper::into_pointer] for the [`T::Data`] type.
+pub(crate) unsafe fn init_chip<T: Chip>(chip: &mut bindings::irq_chip) {
+    chip.irq_ack = Some(irq_ack_callback::<T>);
+    chip.irq_mask = Some(irq_mask_callback::<T>);
+    chip.irq_unmask = Some(irq_unmask_callback::<T>);
+
+    if T::HAS_SET_TYPE {
+        chip.irq_set_type = Some(irq_set_type_callback::<T>);
+    }
+
+    if T::HAS_SET_WAKE {
+        chip.irq_set_wake = Some(irq_set_wake_callback::<T>);
+    }
+}
+
+/// Enables or disables power-management wake-on for the given irq number.
+pub fn set_wake(irq: u32, on: bool) -> Result {
+    // SAFETY: Just an FFI call, there are no extra requirements for safety.
+    let ret = unsafe { bindings::irq_set_irq_wake(irq, on as _) };
+    if ret < 0 {
+        Err(Error::from_kernel_errno(ret))
+    } else {
+        Ok(())
+    }
+}
+
+unsafe extern "C" fn irq_ack_callback<T: Chip>(irq_data: *mut bindings::irq_data) {
+    // SAFETY: The safety requirements of `init_chip`, which is the only place that uses this
+    // callback, ensure that the value stored as irq chip data comes from a previous call to
+    // `PointerWrapper::into_pointer`.
+    let data = unsafe { T::Data::borrow(bindings::irq_data_get_irq_chip_data(irq_data)) };
+
+    // SAFETY: The value returned by `IrqData` is only valid until the end of this function, and
+    // `irq_data` is guaranteed to be valid until then (by the contract with C code).
+    T::ack(data, unsafe { &IrqData::from_ptr(irq_data) })
+}
+
+unsafe extern "C" fn irq_mask_callback<T: Chip>(irq_data: *mut bindings::irq_data) {
+    // SAFETY: The safety requirements of `init_chip`, which is the only place that uses this
+    // callback, ensure that the value stored as irq chip data comes from a previous call to
+    // `PointerWrapper::into_pointer`.
+    let data = unsafe { T::Data::borrow(bindings::irq_data_get_irq_chip_data(irq_data)) };
+
+    // SAFETY: The value returned by `IrqData` is only valid until the end of this function, and
+    // `irq_data` is guaranteed to be valid until then (by the contract with C code).
+    T::mask(data, unsafe { &IrqData::from_ptr(irq_data) })
+}
+
+unsafe extern "C" fn irq_unmask_callback<T: Chip>(irq_data: *mut bindings::irq_data) {
+    // SAFETY: The safety requirements of `init_chip`, which is the only place that uses this
+    // callback, ensure that the value stored as irq chip data comes from a previous call to
+    // `PointerWrapper::into_pointer`.
+    let data = unsafe { T::Data::borrow(bindings::irq_data_get_irq_chip_data(irq_data)) };
+
+    // SAFETY: The value returned by `IrqData` is only valid until the end of this function, and
+    // `irq_data` is guaranteed to be valid until then (by the contract with C code).
+    T::unmask(data, unsafe { &IrqData::from_ptr(irq_data) })
+}
+
+unsafe extern "C" fn irq_set_type_callback<T: Chip>(
+    irq_data: *mut bindings::irq_data,
+    flow_type: core::ffi::c_uint,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: The safety requirements of `init_chip`, which is the only place that uses this
+        // callback, ensure that the value stored as irq chip data comes from a previous call to
+        // `PointerWrapper::into_pointer`.
+        let data = unsafe { T::Data::borrow(bindings::irq_data_get_irq_chip_data(irq_data)) };
+
+        // SAFETY: The value returned by `IrqData` is only valid until the end of this function, and
+        // `irq_data` is guaranteed to be valid until then (by the contract with C code).
+        let ret = T::set_type(
+            data,
+            &mut LockedIrqData(unsafe { IrqData::from_ptr(irq_data) }),
+            flow_type,
+        )?;
+        Ok(ret as _)
+    }
+}
+
+unsafe extern "C" fn irq_set_wake_callback<T: Chip>(
+    irq_data: *mut bindings::irq_data,
+    on: core::ffi::c_uint,
+) -> core::ffi::c_int {
+    from_kernel_result! {
+        // SAFETY: The safety requirements of `init_chip`, which is the only place that uses this
+        // callback, ensure that the value stored as irq chip data comes from a previous call to
+        // `PointerWrapper::into_pointer`.
+        let data = unsafe { T::Data::borrow(bindings::irq_data_get_irq_chip_data(irq_data)) };
+
+        // SAFETY: The value returned by `IrqData` is only valid until the end of this function, and
+        // `irq_data` is guaranteed to be valid until then (by the contract with C code).
+        T::set_wake(data, unsafe { &IrqData::from_ptr(irq_data) }, on != 0)?;
+        Ok(0)
+    }
+}
+
+/// Contains constants that describes how an interrupt can be triggered.
+///
+/// It is tagged with `non_exhaustive` to prevent users from instantiating it.
+#[non_exhaustive]
+pub struct Type;
+
+impl Type {
+    /// The interrupt cannot be triggered.
+    pub const NONE: u32 = bindings::IRQ_TYPE_NONE;
+
+    /// The interrupt is triggered when the signal goes from low to high.
+    pub const EDGE_RISING: u32 = bindings::IRQ_TYPE_EDGE_RISING;
+
+    /// The interrupt is triggered when the signal goes from high to low.
+    pub const EDGE_FALLING: u32 = bindings::IRQ_TYPE_EDGE_FALLING;
+
+    /// The interrupt is triggered when the signal goes from low to high and when it goes to high
+    /// to low.
+    pub const EDGE_BOTH: u32 = bindings::IRQ_TYPE_EDGE_BOTH;
+
+    /// The interrupt is triggered while the signal is held high.
+    pub const LEVEL_HIGH: u32 = bindings::IRQ_TYPE_LEVEL_HIGH;
+
+    /// The interrupt is triggered while the signal is held low.
+    pub const LEVEL_LOW: u32 = bindings::IRQ_TYPE_LEVEL_LOW;
+}
+
+/// Wraps the kernel's `struct irq_desc`.
+///
+/// # Invariants
+///
+/// The pointer `Descriptor::ptr` is non-null and valid.
+pub struct Descriptor {
+    pub(crate) ptr: *mut bindings::irq_desc,
+}
+
+impl Descriptor {
+    /// Constructs a new `struct irq_desc` wrapper.
+    ///
+    /// # Safety
+    ///
+    /// The pointer `ptr` must be non-null and valid for the lifetime of the returned object.
+    unsafe fn from_ptr(ptr: *mut bindings::irq_desc) -> Self {
+        // INVARIANT: The safety requirements ensure the invariant.
+        Self { ptr }
+    }
+
+    /// Calls `chained_irq_enter` and returns a guard that calls `chained_irq_exit` once dropped.
+    ///
+    /// It is meant to be used by chained irq handlers to dispatch irqs to the next handlers.
+    pub fn enter_chained(&self) -> ChainedGuard<'_> {
+        // SAFETY: By the type invariants, `ptr` is always non-null and valid.
+        let irq_chip = unsafe { bindings::irq_desc_get_chip(self.ptr) };
+
+        // SAFETY: By the type invariants, `ptr` is always non-null and valid. `irq_chip` was just
+        // returned from `ptr`, so it is still valid too.
+        unsafe { bindings::chained_irq_enter(irq_chip, self.ptr) };
+        ChainedGuard {
+            desc: self,
+            irq_chip,
+        }
+    }
+}
+
+struct InternalRegistration<T: PointerWrapper> {
+    irq: u32,
+    data: *mut core::ffi::c_void,
+    name: CString,
+    _p: PhantomData<T>,
+}
+
+impl<T: PointerWrapper> InternalRegistration<T> {
+    /// Registers a new irq handler.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `handler` and `thread_fn` are compatible with the registration,
+    /// that is, that they only use their second argument while the call is happening and that they
+    /// only call [`T::borrow`] on it (e.g., they shouldn't call [`T::from_pointer`] and consume
+    /// it).
+    unsafe fn try_new(
+        irq: core::ffi::c_uint,
+        handler: bindings::irq_handler_t,
+        thread_fn: bindings::irq_handler_t,
+        flags: usize,
+        data: T,
+        name: fmt::Arguments<'_>,
+    ) -> Result<Self> {
+        let ptr = data.into_pointer() as *mut _;
+        let name = CString::try_from_fmt(name)?;
+        let guard = ScopeGuard::new(|| {
+            // SAFETY: `ptr` came from a previous call to `into_pointer`.
+            unsafe { T::from_pointer(ptr) };
+        });
+        // SAFETY: `name` and `ptr` remain valid as long as the registration is alive.
+        to_result(unsafe {
+            bindings::request_threaded_irq(
+                irq,
+                handler,
+                thread_fn,
+                flags as _,
+                name.as_char_ptr(),
+                ptr,
+            )
+        })?;
+        guard.dismiss();
+        Ok(Self {
+            irq,
+            name,
+            data: ptr,
+            _p: PhantomData,
+        })
+    }
+}
+
+impl<T: PointerWrapper> Drop for InternalRegistration<T> {
+    fn drop(&mut self) {
+        // Unregister irq handler.
+        //
+        // SAFETY: When `try_new` succeeds, the irq was successfully requested, so it is ok to free
+        // it here.
+        unsafe { bindings::free_irq(self.irq, self.data) };
+
+        // Free context data.
+        //
+        // SAFETY: This matches the call to `into_pointer` from `try_new` in the success case.
+        unsafe { T::from_pointer(self.data) };
+    }
+}
+
+/// An irq handler.
+pub trait Handler {
+    /// The context data associated with and made available to the handler.
+    type Data: PointerWrapper;
+
+    /// Called from interrupt context when the irq happens.
+    fn handle_irq(data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Return;
+}
+
+/// The registration of an interrupt handler.
+///
+/// # Examples
+///
+/// The following is an example of a regular handler with a boxed `u32` as data.
+///
+/// ```
+/// # use kernel::prelude::*;
+/// use kernel::irq;
+///
+/// struct Example;
+///
+/// impl irq::Handler for Example {
+///     type Data = Box<u32>;
+///
+///     fn handle_irq(_data: &u32) -> irq::Return {
+///         irq::Return::None
+///     }
+/// }
+///
+/// fn request_irq(irq: u32, data: Box<u32>) -> Result<irq::Registration<Example>> {
+///     irq::Registration::try_new(irq, data, irq::flags::SHARED, fmt!("example_{irq}"))
+/// }
+/// ```
+pub struct Registration<H: Handler>(InternalRegistration<H::Data>);
+
+impl<H: Handler> Registration<H> {
+    /// Registers a new irq handler.
+    ///
+    /// The valid values of `flags` come from the [`flags`] module.
+    pub fn try_new(
+        irq: u32,
+        data: H::Data,
+        flags: usize,
+        name: fmt::Arguments<'_>,
+    ) -> Result<Self> {
+        // SAFETY: `handler` only calls `H::Data::borrow` on `raw_data`.
+        Ok(Self(unsafe {
+            InternalRegistration::try_new(irq, Some(Self::handler), None, flags, data, name)?
+        }))
+    }
+
+    unsafe extern "C" fn handler(
+        _irq: core::ffi::c_int,
+        raw_data: *mut core::ffi::c_void,
+    ) -> bindings::irqreturn_t {
+        // SAFETY: On registration, `into_pointer` was called, so it is safe to borrow from it here
+        // because `from_pointer` is called only after the irq is unregistered.
+        let data = unsafe { H::Data::borrow(raw_data) };
+        H::handle_irq(data) as _
+    }
+}
+
+/// A threaded irq handler.
+pub trait ThreadedHandler {
+    /// The context data associated with and made available to the handlers.
+    type Data: PointerWrapper;
+
+    /// Called from interrupt context when the irq first happens.
+    fn handle_primary_irq(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Return {
+        Return::WakeThread
+    }
+
+    /// Called from the handler thread.
+    fn handle_threaded_irq(data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Return;
+}
+
+/// The registration of a threaded interrupt handler.
+///
+/// # Examples
+///
+/// The following is an example of a threaded handler with a ref-counted u32 as data:
+///
+/// ```
+/// # use kernel::prelude::*;
+/// use kernel::{
+///     irq,
+///     sync::{Ref, RefBorrow},
+/// };
+///
+/// struct Example;
+///
+/// impl irq::ThreadedHandler for Example {
+///     type Data = Ref<u32>;
+///
+///     fn handle_threaded_irq(_data: RefBorrow<'_, u32>) -> irq::Return {
+///         irq::Return::None
+///     }
+/// }
+///
+/// fn request_irq(irq: u32, data: Ref<u32>) -> Result<irq::ThreadedRegistration<Example>> {
+///     irq::ThreadedRegistration::try_new(irq, data, irq::flags::SHARED, fmt!("example_{irq}"))
+/// }
+/// ```
+pub struct ThreadedRegistration<H: ThreadedHandler>(InternalRegistration<H::Data>);
+
+impl<H: ThreadedHandler> ThreadedRegistration<H> {
+    /// Registers a new threaded irq handler.
+    ///
+    /// The valid values of `flags` come from the [`flags`] module.
+    pub fn try_new(
+        irq: u32,
+        data: H::Data,
+        flags: usize,
+        name: fmt::Arguments<'_>,
+    ) -> Result<Self> {
+        // SAFETY: both `primary_handler` and `threaded_handler` only call `H::Data::borrow` on
+        // `raw_data`.
+        Ok(Self(unsafe {
+            InternalRegistration::try_new(
+                irq,
+                Some(Self::primary_handler),
+                Some(Self::threaded_handler),
+                flags,
+                data,
+                name,
+            )?
+        }))
+    }
+
+    unsafe extern "C" fn primary_handler(
+        _irq: core::ffi::c_int,
+        raw_data: *mut core::ffi::c_void,
+    ) -> bindings::irqreturn_t {
+        // SAFETY: On registration, `into_pointer` was called, so it is safe to borrow from it here
+        // because `from_pointer` is called only after the irq is unregistered.
+        let data = unsafe { H::Data::borrow(raw_data) };
+        H::handle_primary_irq(data) as _
+    }
+
+    unsafe extern "C" fn threaded_handler(
+        _irq: core::ffi::c_int,
+        raw_data: *mut core::ffi::c_void,
+    ) -> bindings::irqreturn_t {
+        // SAFETY: On registration, `into_pointer` was called, so it is safe to borrow from it here
+        // because `from_pointer` is called only after the irq is unregistered.
+        let data = unsafe { H::Data::borrow(raw_data) };
+        H::handle_threaded_irq(data) as _
+    }
+}
+
+/// The return value from interrupt handlers.
+pub enum Return {
+    /// The interrupt was not from this device or was not handled.
+    None = bindings::irqreturn_IRQ_NONE as _,
+
+    /// The interrupt was handled by this device.
+    Handled = bindings::irqreturn_IRQ_HANDLED as _,
+
+    /// The handler wants the handler thread to wake up.
+    WakeThread = bindings::irqreturn_IRQ_WAKE_THREAD as _,
+}
+
+/// Container for interrupt flags.
+pub mod flags {
+    use crate::bindings;
+
+    /// Use the interrupt line as already configured.
+    pub const TRIGGER_NONE: usize = bindings::IRQF_TRIGGER_NONE as _;
+
+    /// The interrupt is triggered when the signal goes from low to high.
+    pub const TRIGGER_RISING: usize = bindings::IRQF_TRIGGER_RISING as _;
+
+    /// The interrupt is triggered when the signal goes from high to low.
+    pub const TRIGGER_FALLING: usize = bindings::IRQF_TRIGGER_FALLING as _;
+
+    /// The interrupt is triggered while the signal is held high.
+    pub const TRIGGER_HIGH: usize = bindings::IRQF_TRIGGER_HIGH as _;
+
+    /// The interrupt is triggered while the signal is held low.
+    pub const TRIGGER_LOW: usize = bindings::IRQF_TRIGGER_LOW as _;
+
+    /// Allow sharing the irq among several devices.
+    pub const SHARED: usize = bindings::IRQF_SHARED as _;
+
+    /// Set by callers when they expect sharing mismatches to occur.
+    pub const PROBE_SHARED: usize = bindings::IRQF_PROBE_SHARED as _;
+
+    /// Flag to mark this interrupt as timer interrupt.
+    pub const TIMER: usize = bindings::IRQF_TIMER as _;
+
+    /// Interrupt is per cpu.
+    pub const PERCPU: usize = bindings::IRQF_PERCPU as _;
+
+    /// Flag to exclude this interrupt from irq balancing.
+    pub const NOBALANCING: usize = bindings::IRQF_NOBALANCING as _;
+
+    /// Interrupt is used for polling (only the interrupt that is registered first in a shared
+    /// interrupt is considered for performance reasons).
+    pub const IRQPOLL: usize = bindings::IRQF_IRQPOLL as _;
+
+    /// Interrupt is not reenabled after the hardirq handler finished. Used by threaded interrupts
+    /// which need to keep the irq line disabled until the threaded handler has been run.
+    pub const ONESHOT: usize = bindings::IRQF_ONESHOT as _;
+
+    /// Do not disable this IRQ during suspend. Does not guarantee that this interrupt will wake
+    /// the system from a suspended state.
+    pub const NO_SUSPEND: usize = bindings::IRQF_NO_SUSPEND as _;
+
+    /// Force enable it on resume even if [`NO_SUSPEND`] is set.
+    pub const FORCE_RESUME: usize = bindings::IRQF_FORCE_RESUME as _;
+
+    /// Interrupt cannot be threaded.
+    pub const NO_THREAD: usize = bindings::IRQF_NO_THREAD as _;
+
+    /// Resume IRQ early during syscore instead of at device resume time.
+    pub const EARLY_RESUME: usize = bindings::IRQF_EARLY_RESUME as _;
+
+    /// If the IRQ is shared with a NO_SUSPEND user, execute this interrupt handler after
+    /// suspending interrupts. For system wakeup devices users need to implement wakeup detection
+    /// in their interrupt handlers.
+    pub const COND_SUSPEND: usize = bindings::IRQF_COND_SUSPEND as _;
+
+    /// Don't enable IRQ or NMI automatically when users request it. Users will enable it
+    /// explicitly by `enable_irq` or `enable_nmi` later.
+    pub const NO_AUTOEN: usize = bindings::IRQF_NO_AUTOEN as _;
+
+    /// Exclude from runnaway detection for IPI and similar handlers, depends on `PERCPU`.
+    pub const NO_DEBUG: usize = bindings::IRQF_NO_DEBUG as _;
+}
+
+/// A guard to call `chained_irq_exit` after `chained_irq_enter` was called.
+///
+/// It is also used as evidence that a previous `chained_irq_enter` was called. So there are no
+/// public constructors and it is only created after indeed calling `chained_irq_enter`.
+pub struct ChainedGuard<'a> {
+    desc: &'a Descriptor,
+    irq_chip: *mut bindings::irq_chip,
+}
+
+impl Drop for ChainedGuard<'_> {
+    fn drop(&mut self) {
+        // SAFETY: The lifetime of `ChainedGuard` guarantees that `self.desc` remains valid, so it
+        // also guarantess `irq_chip` (which was returned from it) and `self.desc.ptr` (guaranteed
+        // by the type invariants).
+        unsafe { bindings::chained_irq_exit(self.irq_chip, self.desc.ptr) };
+    }
+}
+
+/// Wraps the kernel's `struct irq_domain`.
+///
+/// # Invariants
+///
+/// The pointer `Domain::ptr` is non-null and valid.
+#[cfg(CONFIG_IRQ_DOMAIN)]
+pub struct Domain {
+    ptr: *mut bindings::irq_domain,
+}
+
+#[cfg(CONFIG_IRQ_DOMAIN)]
+impl Domain {
+    /// Constructs a new `struct irq_domain` wrapper.
+    ///
+    /// # Safety
+    ///
+    /// The pointer `ptr` must be non-null and valid for the lifetime of the returned object.
+    pub(crate) unsafe fn from_ptr(ptr: *mut bindings::irq_domain) -> Self {
+        // INVARIANT: The safety requirements ensure the invariant.
+        Self { ptr }
+    }
+
+    /// Invokes the chained handler of the given hw irq of the given domain.
+    ///
+    /// It requires evidence that `chained_irq_enter` was called, which is done by passing a
+    /// `ChainedGuard` instance.
+    pub fn generic_handle_chained(&self, hwirq: u32, _guard: &ChainedGuard<'_>) {
+        // SAFETY: `ptr` is valid by the type invariants.
+        unsafe { bindings::generic_handle_domain_irq(self.ptr, hwirq) };
+    }
+}
+
+/// A high-level irq flow handler.
+pub trait FlowHandler {
+    /// The data associated with the handler.
+    type Data: PointerWrapper;
+
+    /// Implements the irq flow for the given descriptor.
+    fn handle_irq_flow(data: <Self::Data as PointerWrapper>::Borrowed<'_>, desc: &Descriptor);
+}
+
+/// Returns the raw irq flow handler corresponding to the (high-level) one defined in `T`.
+///
+/// # Safety
+///
+/// The caller must ensure that the value stored in the irq handler data (as returned by
+/// `irq_desc_get_handler_data`) is the result of calling [`PointerWrapper::into_pointer] for the
+/// [`T::Data`] type.
+pub(crate) unsafe fn new_flow_handler<T: FlowHandler>() -> bindings::irq_flow_handler_t {
+    Some(irq_flow_handler::<T>)
+}
+
+unsafe extern "C" fn irq_flow_handler<T: FlowHandler>(desc: *mut bindings::irq_desc) {
+    // SAFETY: By the safety requirements of `new_flow_handler`, we know that the value returned by
+    // `irq_desc_get_handler_data` comes from calling `T::Data::into_pointer`. `desc` is valid by
+    // the C API contract.
+    let data = unsafe { T::Data::borrow(bindings::irq_desc_get_handler_data(desc)) };
+
+    // SAFETY: The C API guarantees that `desc` is valid for the duration of this call, which
+    // outlives the lifetime returned by `from_desc`.
+    T::handle_irq_flow(data, &unsafe { Descriptor::from_ptr(desc) });
+}
diff --git a/rust/kernel/kasync.rs b/rust/kernel/kasync.rs
new file mode 100644
index 000000000000..d48e9041e804
--- /dev/null
+++ b/rust/kernel/kasync.rs
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Kernel async functionality.
+
+use core::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+pub mod executor;
+#[cfg(CONFIG_NET)]
+pub mod net;
+
+/// Yields execution of the current task so that other tasks may execute.
+///
+/// The task continues to be in a "runnable" state though, so it will eventually run again.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::kasync::yield_now;
+///
+/// async fn example() {
+///     pr_info!("Before yield\n");
+///     yield_now().await;
+///     pr_info!("After yield\n");
+/// }
+/// ```
+pub fn yield_now() -> impl Future<Output = ()> {
+    struct Yield {
+        first_poll: bool,
+    }
+
+    impl Future for Yield {
+        type Output = ();
+
+        fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
+            if !self.first_poll {
+                Poll::Ready(())
+            } else {
+                self.first_poll = false;
+                cx.waker().wake_by_ref();
+                Poll::Pending
+            }
+        }
+    }
+
+    Yield { first_poll: true }
+}
diff --git a/rust/kernel/kasync/executor.rs b/rust/kernel/kasync/executor.rs
new file mode 100644
index 000000000000..e8e55dcfdf35
--- /dev/null
+++ b/rust/kernel/kasync/executor.rs
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Kernel support for executing futures.
+
+use crate::{
+    sync::{LockClassKey, Ref, RefBorrow},
+    types::PointerWrapper,
+    Result,
+};
+use core::{
+    future::Future,
+    task::{RawWaker, RawWakerVTable, Waker},
+};
+
+pub mod workqueue;
+
+/// Spawns a new task to run in the given executor.
+///
+/// It also automatically defines a new lockdep lock class for executors (e.g., workqueue) that
+/// require one.
+#[macro_export]
+macro_rules! spawn_task {
+    ($executor:expr, $task:expr) => {{
+        static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        $crate::kasync::executor::Executor::spawn($executor, &CLASS, $task)
+    }};
+}
+
+/// A task spawned in an executor.
+pub trait Task {
+    /// Synchronously stops the task.
+    ///
+    /// It ensures that the task won't run again and releases resources needed to run the task
+    /// (e.g., the closure is dropped). If the task is inflight, it waits for the task to block or
+    /// complete before cleaning up and returning.
+    ///
+    /// Callers must not call this from within the task itself as it will likely lead to a
+    /// deadlock.
+    fn sync_stop(self: Ref<Self>);
+}
+
+/// An environment for executing tasks.
+pub trait Executor: Sync + Send {
+    /// Starts executing a task defined by the given future.
+    ///
+    /// Callers are encouraged to use the [`spawn_task`] macro because it automatically defines a
+    /// new lock class key.
+    fn spawn(
+        self: RefBorrow<'_, Self>,
+        lock_class_key: &'static LockClassKey,
+        future: impl Future + 'static + Send,
+    ) -> Result<Ref<dyn Task>>
+    where
+        Self: Sized;
+
+    /// Stops the executor.
+    ///
+    /// After it is called, attempts to spawn new tasks will result in an error and existing ones
+    /// won't be polled anymore.
+    fn stop(&self);
+}
+
+/// A waker that is wrapped in [`Ref`] for its reference counting.
+///
+/// Types that implement this trait can get a [`Waker`] by calling [`ref_waker`].
+pub trait RefWake: Send + Sync {
+    /// Wakes a task up.
+    fn wake_by_ref(self: RefBorrow<'_, Self>);
+
+    /// Wakes a task up and consumes a reference.
+    fn wake(self: Ref<Self>) {
+        self.as_ref_borrow().wake_by_ref();
+    }
+}
+
+/// Creates a [`Waker`] from a [`Ref<T>`], where `T` implements the [`RefWake`] trait.
+pub fn ref_waker<T: 'static + RefWake>(w: Ref<T>) -> Waker {
+    fn raw_waker<T: 'static + RefWake>(w: Ref<T>) -> RawWaker {
+        let data = w.into_pointer();
+        RawWaker::new(
+            data.cast(),
+            &RawWakerVTable::new(clone::<T>, wake::<T>, wake_by_ref::<T>, drop::<T>),
+        )
+    }
+
+    unsafe fn clone<T: 'static + RefWake>(ptr: *const ()) -> RawWaker {
+        // SAFETY: The data stored in the raw waker is the result of a call to `into_pointer`.
+        let w = unsafe { Ref::<T>::borrow(ptr.cast()) };
+        raw_waker(w.into())
+    }
+
+    unsafe fn wake<T: 'static + RefWake>(ptr: *const ()) {
+        // SAFETY: The data stored in the raw waker is the result of a call to `into_pointer`.
+        let w = unsafe { Ref::<T>::from_pointer(ptr.cast()) };
+        w.wake();
+    }
+
+    unsafe fn wake_by_ref<T: 'static + RefWake>(ptr: *const ()) {
+        // SAFETY: The data stored in the raw waker is the result of a call to `into_pointer`.
+        let w = unsafe { Ref::<T>::borrow(ptr.cast()) };
+        w.wake_by_ref();
+    }
+
+    unsafe fn drop<T: 'static + RefWake>(ptr: *const ()) {
+        // SAFETY: The data stored in the raw waker is the result of a call to `into_pointer`.
+        unsafe { Ref::<T>::from_pointer(ptr.cast()) };
+    }
+
+    let raw = raw_waker(w);
+    // SAFETY: The vtable of the raw waker satisfy the behaviour requirements of a waker.
+    unsafe { Waker::from_raw(raw) }
+}
+
+/// A handle to an executor that automatically stops it on drop.
+pub struct AutoStopHandle<T: Executor + ?Sized> {
+    executor: Option<Ref<T>>,
+}
+
+impl<T: Executor + ?Sized> AutoStopHandle<T> {
+    /// Creates a new instance of an [`AutoStopHandle`].
+    pub fn new(executor: Ref<T>) -> Self {
+        Self {
+            executor: Some(executor),
+        }
+    }
+
+    /// Detaches from the auto-stop handle.
+    ///
+    /// That is, extracts the executor from the handle and doesn't stop it anymore.
+    pub fn detach(mut self) -> Ref<T> {
+        self.executor.take().unwrap()
+    }
+
+    /// Returns the executor associated with the auto-stop handle.
+    ///
+    /// This is so that callers can, for example, spawn new tasks.
+    pub fn executor(&self) -> RefBorrow<'_, T> {
+        self.executor.as_ref().unwrap().as_ref_borrow()
+    }
+}
+
+impl<T: Executor + ?Sized> Drop for AutoStopHandle<T> {
+    fn drop(&mut self) {
+        if let Some(ex) = self.executor.take() {
+            ex.stop();
+        }
+    }
+}
+
+impl<T: 'static + Executor> From<AutoStopHandle<T>> for AutoStopHandle<dyn Executor> {
+    fn from(src: AutoStopHandle<T>) -> Self {
+        Self::new(src.detach())
+    }
+}
diff --git a/rust/kernel/kasync/executor/workqueue.rs b/rust/kernel/kasync/executor/workqueue.rs
new file mode 100644
index 000000000000..81cd16880600
--- /dev/null
+++ b/rust/kernel/kasync/executor/workqueue.rs
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Kernel support for executing futures in C workqueues (`struct workqueue_struct`).
+
+use super::{AutoStopHandle, RefWake};
+use crate::{
+    error::code::*,
+    mutex_init,
+    revocable::AsyncRevocable,
+    sync::{LockClassKey, Mutex, Ref, RefBorrow, UniqueRef},
+    unsafe_list,
+    workqueue::{BoxedQueue, Queue, Work, WorkAdapter},
+    Either, Left, Result, Right,
+};
+use core::{cell::UnsafeCell, future::Future, marker::PhantomPinned, pin::Pin, task::Context};
+
+trait RevocableTask {
+    fn revoke(&self);
+    fn flush(self: Ref<Self>);
+    fn to_links(&self) -> &unsafe_list::Links<dyn RevocableTask>;
+}
+
+// SAFETY: `Task` has a single `links` field and only one adapter.
+unsafe impl unsafe_list::Adapter for dyn RevocableTask {
+    type EntryType = dyn RevocableTask;
+    fn to_links(obj: &dyn RevocableTask) -> &unsafe_list::Links<dyn RevocableTask> {
+        obj.to_links()
+    }
+}
+
+struct Task<T: 'static + Send + Future> {
+    links: unsafe_list::Links<dyn RevocableTask>,
+    executor: Ref<Executor>,
+    work: Work,
+    future: AsyncRevocable<UnsafeCell<T>>,
+}
+
+// SAFETY: The `future` field is only used by one thread at a time (in the `poll` method, which is
+// called by the work queue, who guarantees no reentrancy), so a task is `Sync` as long as the
+// future is `Send`.
+unsafe impl<T: 'static + Send + Future> Sync for Task<T> {}
+
+// SAFETY: If the future `T` is `Send`, so is the task.
+unsafe impl<T: 'static + Send + Future> Send for Task<T> {}
+
+impl<T: 'static + Send + Future> Task<T> {
+    fn try_new(
+        executor: Ref<Executor>,
+        key: &'static LockClassKey,
+        future: T,
+    ) -> Result<Ref<Self>> {
+        let task = UniqueRef::try_new(Self {
+            executor: executor.clone(),
+            links: unsafe_list::Links::new(),
+            // SAFETY: `work` is initialised below.
+            work: unsafe { Work::new() },
+            future: AsyncRevocable::new(UnsafeCell::new(future)),
+        })?;
+
+        Work::init(&task, key);
+
+        let task = Ref::from(task);
+
+        // Add task to list.
+        {
+            let mut guard = executor.inner.lock();
+            if guard.stopped {
+                return Err(EINVAL);
+            }
+
+            // Convert one reference into a pointer so that we hold on to a ref count while the
+            // task is in the list.
+            Ref::into_raw(task.clone());
+
+            // SAFETY: The task was just created, so it is not in any other lists. It remains alive
+            // because we incremented the refcount to account for it being in the list. It never
+            // moves because it's pinned behind a `Ref`.
+            unsafe { guard.tasks.push_back(&*task) };
+        }
+
+        Ok(task)
+    }
+}
+
+unsafe impl<T: 'static + Send + Future> WorkAdapter for Task<T> {
+    type Target = Self;
+    const FIELD_OFFSET: isize = crate::offset_of!(Self, work);
+    fn run(task: Ref<Task<T>>) {
+        let waker = super::ref_waker(task.clone());
+        let mut ctx = Context::from_waker(&waker);
+
+        let guard = if let Some(g) = task.future.try_access() {
+            g
+        } else {
+            return;
+        };
+
+        // SAFETY: `future` is pinned when the task is. The task is pinned because it's behind a
+        // `Ref`, which is always pinned.
+        //
+        // Work queues guarantee no reentrancy and this is the only place where the future is
+        // dereferenced, so it's ok to do it mutably.
+        let future = unsafe { Pin::new_unchecked(&mut *guard.get()) };
+        if future.poll(&mut ctx).is_ready() {
+            drop(guard);
+            task.revoke();
+        }
+    }
+}
+
+impl<T: 'static + Send + Future> super::Task for Task<T> {
+    fn sync_stop(self: Ref<Self>) {
+        self.revoke();
+        self.flush();
+    }
+}
+
+impl<T: 'static + Send + Future> RevocableTask for Task<T> {
+    fn revoke(&self) {
+        if !self.future.revoke() {
+            // Nothing to do if the task was already revoked.
+            return;
+        }
+
+        // SAFETY: The object is inserted into the list on creation and only removed when the
+        // future is first revoked. (Subsequent revocations don't result in additional attempts
+        // to remove per the check above.)
+        unsafe { self.executor.inner.lock().tasks.remove(self) };
+
+        // Decrement the refcount now that the task is no longer in the list.
+        //
+        // SAFETY: `into_raw` was called from `try_new` when the task was added to the list.
+        unsafe { Ref::from_raw(self) };
+    }
+
+    fn flush(self: Ref<Self>) {
+        self.work.cancel();
+    }
+
+    fn to_links(&self) -> &unsafe_list::Links<dyn RevocableTask> {
+        &self.links
+    }
+}
+
+impl<T: 'static + Send + Future> RefWake for Task<T> {
+    fn wake(self: Ref<Self>) {
+        if self.future.is_revoked() {
+            return;
+        }
+
+        match &self.executor.queue {
+            Left(q) => &**q,
+            Right(q) => *q,
+        }
+        .enqueue(self.clone());
+    }
+
+    fn wake_by_ref(self: RefBorrow<'_, Self>) {
+        Ref::from(self).wake();
+    }
+}
+
+struct ExecutorInner {
+    stopped: bool,
+    tasks: unsafe_list::List<dyn RevocableTask>,
+}
+
+/// An executor backed by a work queue.
+///
+/// # Examples
+///
+/// The following example runs two tasks on the shared system workqueue.
+///
+/// ```
+/// # use kernel::prelude::*;
+/// use kernel::kasync::executor::workqueue::Executor;
+/// use kernel::spawn_task;
+/// use kernel::workqueue;
+///
+/// fn example_shared_workqueue() -> Result {
+///     let mut handle = Executor::try_new(workqueue::system())?;
+///     spawn_task!(handle.executor(), async {
+///         pr_info!("First workqueue task\n");
+///     })?;
+///     spawn_task!(handle.executor(), async {
+///         pr_info!("Second workqueue task\n");
+///     })?;
+///     handle.detach();
+///     Ok(())
+/// }
+///
+/// # example_shared_workqueue().unwrap();
+/// ```
+pub struct Executor {
+    queue: Either<BoxedQueue, &'static Queue>,
+    inner: Mutex<ExecutorInner>,
+    _pin: PhantomPinned,
+}
+
+// SAFETY: The executor is backed by a kernel `struct workqueue_struct`, which works from any
+// thread.
+unsafe impl Send for Executor {}
+
+// SAFETY: The executor is backed by a kernel `struct workqueue_struct`, which can be used
+// concurrently by multiple threads.
+unsafe impl Sync for Executor {}
+
+impl Executor {
+    /// Creates a new workqueue-based executor using a static work queue.
+    pub fn try_new(wq: &'static Queue) -> Result<AutoStopHandle<Self>> {
+        Self::new_internal(Right(wq))
+    }
+
+    /// Creates a new workqueue-based executor using an owned (boxed) work queue.
+    pub fn try_new_owned(wq: BoxedQueue) -> Result<AutoStopHandle<Self>> {
+        Self::new_internal(Left(wq))
+    }
+
+    /// Creates a new workqueue-based executor.
+    ///
+    /// It uses the given work queue to run its tasks.
+    fn new_internal(queue: Either<BoxedQueue, &'static Queue>) -> Result<AutoStopHandle<Self>> {
+        let mut e = Pin::from(UniqueRef::try_new(Self {
+            queue,
+            _pin: PhantomPinned,
+            // SAFETY: `mutex_init` is called below.
+            inner: unsafe {
+                Mutex::new(ExecutorInner {
+                    stopped: false,
+                    tasks: unsafe_list::List::new(),
+                })
+            },
+        })?);
+        // SAFETY: `tasks` is pinned when the executor is.
+        let pinned = unsafe { e.as_mut().map_unchecked_mut(|e| &mut e.inner) };
+        mutex_init!(pinned, "Executor::inner");
+
+        Ok(AutoStopHandle::new(e.into()))
+    }
+}
+
+impl super::Executor for Executor {
+    fn spawn(
+        self: RefBorrow<'_, Self>,
+        key: &'static LockClassKey,
+        future: impl Future + 'static + Send,
+    ) -> Result<Ref<dyn super::Task>> {
+        let task = Task::try_new(self.into(), key, future)?;
+        task.clone().wake();
+        Ok(task)
+    }
+
+    fn stop(&self) {
+        // Set the `stopped` flag.
+        self.inner.lock().stopped = true;
+
+        // Go through all tasks and revoke & flush them.
+        //
+        // N.B. If we decide to allow "asynchronous" stops, we need to ensure that tasks that have
+        // been revoked but not flushed yet remain in the list so that we can flush them here.
+        // Otherwise we may have a race where we may have a running task (was revoked while
+        // running) that isn't the list anymore, so we think we've synchronously stopped all tasks
+        // when we haven't really -- unloading a module in this situation leads to memory safety
+        // issues (running unloaded code).
+        loop {
+            let guard = self.inner.lock();
+
+            let front = if let Some(t) = guard.tasks.front() {
+                t
+            } else {
+                break;
+            };
+
+            // Get a new reference to the task.
+            //
+            // SAFETY: We know all entries in the list are of type `Ref<dyn RevocableTask>` and
+            // that a reference exists while the entry is in the list, and since we are holding the
+            // list lock, we know it cannot go away. The `into_raw` call below ensures that we
+            // don't decrement the refcount accidentally.
+            let tasktmp = unsafe { Ref::<dyn RevocableTask>::from_raw(front.as_ptr()) };
+            let task = tasktmp.clone();
+            Ref::into_raw(tasktmp);
+
+            // Release the mutex before revoking the task.
+            drop(guard);
+
+            task.revoke();
+            task.flush();
+        }
+    }
+}
diff --git a/rust/kernel/kasync/net.rs b/rust/kernel/kasync/net.rs
new file mode 100644
index 000000000000..b4bbeffad94a
--- /dev/null
+++ b/rust/kernel/kasync/net.rs
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Async networking.
+
+use crate::{bindings, error::code::*, net, sync::NoWaitLock, types::Opaque, Result};
+use core::{
+    future::Future,
+    marker::{PhantomData, PhantomPinned},
+    ops::Deref,
+    pin::Pin,
+    task::{Context, Poll, Waker},
+};
+
+/// A socket listening on a TCP port.
+///
+/// The [`TcpListener::accept`] method is meant to be used in async contexts.
+pub struct TcpListener {
+    listener: net::TcpListener,
+}
+
+impl TcpListener {
+    /// Creates a new TCP listener.
+    ///
+    /// It is configured to listen on the given socket address for the given namespace.
+    pub fn try_new(ns: &net::Namespace, addr: &net::SocketAddr) -> Result<Self> {
+        Ok(Self {
+            listener: net::TcpListener::try_new(ns, addr)?,
+        })
+    }
+
+    /// Accepts a new connection.
+    ///
+    /// Returns a future that when ready indicates the result of the accept operation; on success,
+    /// it contains the newly-accepted tcp stream.
+    pub fn accept(&self) -> impl Future<Output = Result<TcpStream>> + '_ {
+        SocketFuture::from_listener(
+            self,
+            bindings::BINDINGS_EPOLLIN | bindings::BINDINGS_EPOLLERR,
+            || {
+                Ok(TcpStream {
+                    stream: self.listener.accept(false)?,
+                })
+            },
+        )
+    }
+}
+
+impl Deref for TcpListener {
+    type Target = net::TcpListener;
+
+    fn deref(&self) -> &Self::Target {
+        &self.listener
+    }
+}
+
+/// A connected TCP socket.
+///
+/// The potentially blocking methods (e.g., [`TcpStream::read`], [`TcpStream::write`]) are meant
+/// to be used in async contexts.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::prelude::*;
+/// # use kernel::kasync::net::TcpStream;
+/// async fn echo_server(stream: TcpStream) -> Result {
+///     let mut buf = [0u8; 1024];
+///     loop {
+///         let n = stream.read(&mut buf).await?;
+///         if n == 0 {
+///             return Ok(());
+///         }
+///         stream.write_all(&buf[..n]).await?;
+///     }
+/// }
+/// ```
+pub struct TcpStream {
+    stream: net::TcpStream,
+}
+
+impl TcpStream {
+    /// Reads data from a connected socket.
+    ///
+    /// Returns a future that when ready indicates the result of the read operation; on success, it
+    /// contains the number of bytes read, which will be zero if the connection is closed.
+    pub fn read<'a>(&'a self, buf: &'a mut [u8]) -> impl Future<Output = Result<usize>> + 'a {
+        SocketFuture::from_stream(
+            self,
+            bindings::BINDINGS_EPOLLIN | bindings::BINDINGS_EPOLLHUP | bindings::BINDINGS_EPOLLERR,
+            || self.stream.read(buf, false),
+        )
+    }
+
+    /// Writes data to the connected socket.
+    ///
+    /// Returns a future that when ready indicates the result of the write operation; on success, it
+    /// contains the number of bytes written.
+    pub fn write<'a>(&'a self, buf: &'a [u8]) -> impl Future<Output = Result<usize>> + 'a {
+        SocketFuture::from_stream(
+            self,
+            bindings::BINDINGS_EPOLLOUT | bindings::BINDINGS_EPOLLHUP | bindings::BINDINGS_EPOLLERR,
+            || self.stream.write(buf, false),
+        )
+    }
+
+    /// Writes all the data to the connected socket.
+    ///
+    /// Returns a future that when ready indicates the result of the write operation; on success, it
+    /// has written all the data.
+    pub async fn write_all<'a>(&'a self, buf: &'a [u8]) -> Result {
+        let mut rem = buf;
+
+        while !rem.is_empty() {
+            let n = self.write(rem).await?;
+            rem = &rem[n..];
+        }
+
+        Ok(())
+    }
+}
+
+impl Deref for TcpStream {
+    type Target = net::TcpStream;
+
+    fn deref(&self) -> &Self::Target {
+        &self.stream
+    }
+}
+
+/// A future for a socket operation.
+///
+/// # Invariants
+///
+/// `sock` is always non-null and valid for the duration of the lifetime of the instance.
+struct SocketFuture<'a, Out, F: FnMut() -> Result<Out> + Send + 'a> {
+    sock: *mut bindings::socket,
+    mask: u32,
+    is_queued: bool,
+    wq_entry: Opaque<bindings::wait_queue_entry>,
+    waker: NoWaitLock<Option<Waker>>,
+    _p: PhantomData<&'a ()>,
+    _pin: PhantomPinned,
+    operation: F,
+}
+
+// SAFETY: A kernel socket can be used from any thread, `wq_entry` is only used on drop and when
+// `is_queued` is initially `false`.
+unsafe impl<Out, F: FnMut() -> Result<Out> + Send> Send for SocketFuture<'_, Out, F> {}
+
+impl<'a, Out, F: FnMut() -> Result<Out> + Send + 'a> SocketFuture<'a, Out, F> {
+    /// Creates a new socket future.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `sock` is non-null, valid, and remains valid for the lifetime
+    /// (`'a`) of the returned instance.
+    unsafe fn new(sock: *mut bindings::socket, mask: u32, operation: F) -> Self {
+        Self {
+            sock,
+            mask,
+            is_queued: false,
+            wq_entry: Opaque::uninit(),
+            waker: NoWaitLock::new(None),
+            operation,
+            _p: PhantomData,
+            _pin: PhantomPinned,
+        }
+    }
+
+    /// Creates a new socket future for a tcp listener.
+    fn from_listener(listener: &'a TcpListener, mask: u32, operation: F) -> Self {
+        // SAFETY: The socket is guaranteed to remain valid because it is bound to the reference to
+        // the listener (whose existence guarantees the socket remains valid).
+        unsafe { Self::new(listener.listener.sock, mask, operation) }
+    }
+
+    /// Creates a new socket future for a tcp stream.
+    fn from_stream(stream: &'a TcpStream, mask: u32, operation: F) -> Self {
+        // SAFETY: The socket is guaranteed to remain valid because it is bound to the reference to
+        // the stream (whose existence guarantees the socket remains valid).
+        unsafe { Self::new(stream.stream.sock, mask, operation) }
+    }
+
+    /// Callback called when the socket changes state.
+    ///
+    /// If the state matches the one we're waiting on, we wake up the task so that the future can be
+    /// polled again.
+    unsafe extern "C" fn wake_callback(
+        wq_entry: *mut bindings::wait_queue_entry,
+        _mode: core::ffi::c_uint,
+        _flags: core::ffi::c_int,
+        key: *mut core::ffi::c_void,
+    ) -> core::ffi::c_int {
+        let mask = key as u32;
+
+        // SAFETY: The future is valid while this callback is called because we remove from the
+        // queue on drop.
+        //
+        // There is a potential soundness issue here because we're generating a shared reference to
+        // `Self` while `Self::poll` has a mutable (unique) reference. However, for `!Unpin` types
+        // (like `Self`), `&mut T` is treated as `*mut T` per
+        // <https://github.com/rust-lang/rust/issues/63818> -- so we avoid the unsoundness. Once a
+        // more definitive solution is available, we can change this to use it.
+        let s = unsafe { &*crate::container_of!(wq_entry, Self, wq_entry) };
+        if mask & s.mask == 0 {
+            // Nothing to do as this notification doesn't interest us.
+            return 0;
+        }
+
+        // If we can't acquire the waker lock, the waker is in the process of being modified. Our
+        // attempt to acquire the lock will be reported to the lock owner, so it will trigger the
+        // wake up.
+        if let Some(guard) = s.waker.try_lock() {
+            if let Some(ref w) = *guard {
+                let cloned = w.clone();
+                drop(guard);
+                cloned.wake();
+                return 1;
+            }
+        }
+        0
+    }
+
+    /// Poll the future once.
+    ///
+    /// It calls the operation and converts `EAGAIN` errors into a pending state.
+    fn poll_once(self: Pin<&mut Self>) -> Poll<Result<Out>> {
+        // SAFETY: We never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+        match (this.operation)() {
+            Ok(s) => Poll::Ready(Ok(s)),
+            Err(e) => {
+                if e == EAGAIN {
+                    Poll::Pending
+                } else {
+                    Poll::Ready(Err(e))
+                }
+            }
+        }
+    }
+
+    /// Updates the waker stored in the future.
+    ///
+    /// It automatically triggers a wake up on races with the reactor.
+    fn set_waker(&self, waker: &Waker) {
+        if let Some(mut guard) = self.waker.try_lock() {
+            let old = core::mem::replace(&mut *guard, Some(waker.clone()));
+            let contention = guard.unlock();
+            drop(old);
+            if !contention {
+                return;
+            }
+        }
+
+        // We either couldn't store the waker because the existing one is being awakened, or the
+        // reactor tried to acquire the lock while we held it (contention). In either case, we just
+        // wake it up to ensure we don't miss any notification.
+        waker.wake_by_ref();
+    }
+}
+
+impl<Out, F: FnMut() -> Result<Out> + Send> Future for SocketFuture<'_, Out, F> {
+    type Output = Result<Out>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.as_mut().poll_once() {
+            Poll::Ready(r) => Poll::Ready(r),
+            Poll::Pending => {
+                // Store away the latest waker every time we may `Pending`.
+                self.set_waker(cx.waker());
+                if self.is_queued {
+                    // Nothing else to do was the waiter is already queued.
+                    return Poll::Pending;
+                }
+
+                // SAFETY: We never move out of `this`.
+                let this = unsafe { self.as_mut().get_unchecked_mut() };
+
+                this.is_queued = true;
+
+                // SAFETY: `wq_entry` is valid for write.
+                unsafe {
+                    bindings::init_waitqueue_func_entry(
+                        this.wq_entry.get(),
+                        Some(Self::wake_callback),
+                    )
+                };
+
+                // SAFETY: `wq_entry` was just initialised above and is valid for read/write.
+                // By the type invariants, the socket is always valid.
+                unsafe {
+                    bindings::add_wait_queue(
+                        core::ptr::addr_of_mut!((*this.sock).wq.wait),
+                        this.wq_entry.get(),
+                    )
+                };
+
+                // If the future wasn't queued yet, we need to poll again in case it reached
+                // the desired state between the last poll and being queued (in which case we
+                // would have missed the notification).
+                self.poll_once()
+            }
+        }
+    }
+}
+
+impl<Out, F: FnMut() -> Result<Out> + Send> Drop for SocketFuture<'_, Out, F> {
+    fn drop(&mut self) {
+        if !self.is_queued {
+            return;
+        }
+
+        // SAFETY: `wq_entry` is initialised because `is_queued` is set to `true`, so it is valid
+        // for read/write. By the type invariants, the socket is always valid.
+        unsafe {
+            bindings::remove_wait_queue(
+                core::ptr::addr_of_mut!((*self.sock).wq.wait),
+                self.wq_entry.get(),
+            )
+        };
+    }
+}
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
new file mode 100644
index 000000000000..5f3e102962c3
--- /dev/null
+++ b/rust/kernel/kunit.rs
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! KUnit-based macros for Rust unit tests.
+//!
+//! C header: [`include/kunit/test.h`](../../../../../include/kunit/test.h)
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/dev-tools/kunit/index.html>
+
+/// Asserts that a boolean expression is `true` at runtime.
+///
+/// Public but hidden since it should only be used from generated tests.
+///
+/// Unlike the one in `core`, this one does not panic; instead, it is mapped to the KUnit
+/// facilities. See [`assert!`] for more details.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! kunit_assert {
+    ($test:expr, $cond:expr $(,)?) => {{
+        if !$cond {
+            #[repr(transparent)]
+            struct Location($crate::bindings::kunit_loc);
+
+            #[repr(transparent)]
+            struct UnaryAssert($crate::bindings::kunit_unary_assert);
+
+            // SAFETY: There is only a static instance and in that one the pointer field
+            // points to an immutable C string.
+            unsafe impl Sync for Location {}
+
+            // SAFETY: There is only a static instance and in that one the pointer field
+            // points to an immutable C string.
+            unsafe impl Sync for UnaryAssert {}
+
+            static FILE: &'static $crate::str::CStr = $crate::c_str!(core::file!());
+            static LOCATION: Location = Location($crate::bindings::kunit_loc {
+                file: FILE.as_char_ptr(),
+                line: core::line!() as i32,
+            });
+            static CONDITION: &'static $crate::str::CStr = $crate::c_str!(stringify!($cond));
+            static ASSERTION: UnaryAssert = UnaryAssert($crate::bindings::kunit_unary_assert {
+                assert: $crate::bindings::kunit_assert {
+                    format: Some($crate::bindings::kunit_unary_assert_format),
+                },
+                condition: CONDITION.as_char_ptr(),
+                expected_true: true,
+            });
+
+            // SAFETY:
+            //   - FFI call.
+            //   - The `test` pointer is valid because this hidden macro should only be called by
+            //     the generated documentation tests which forward the test pointer given by KUnit.
+            //   - The string pointers (`file` and `condition`) point to null-terminated ones.
+            //   - The function pointer (`format`) points to the proper function.
+            //   - The pointers passed will remain valid since they point to statics.
+            //   - The format string is allowed to be null.
+            //   - There are, however, problems with this: first of all, this will end up stopping
+            //     the thread, without running destructors. While that is problematic in itself,
+            //     it is considered UB to have what is effectively an forced foreign unwind
+            //     with `extern "C"` ABI. One could observe the stack that is now gone from
+            //     another thread. We should avoid pinning stack variables to prevent library UB,
+            //     too. For the moment, given test failures are reported immediately before the
+            //     next test runs, that test failures should be fixed and that KUnit is explicitly
+            //     documented as not suitable for production environments, we feel it is reasonable.
+            unsafe {
+                $crate::bindings::kunit_do_failed_assertion(
+                    $test,
+                    core::ptr::addr_of!(LOCATION.0),
+                    $crate::bindings::kunit_assert_type_KUNIT_ASSERTION,
+                    core::ptr::addr_of!(ASSERTION.0.assert),
+                    core::ptr::null(),
+                );
+            }
+        }
+    }};
+}
+
+/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
+///
+/// Public but hidden since it should only be used from generated tests.
+///
+/// Unlike the one in `core`, this one does not panic; instead, it is mapped to the KUnit
+/// facilities. See [`assert!`] for more details.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! kunit_assert_eq {
+    ($test:expr, $left:expr, $right:expr $(,)?) => {{
+        // For the moment, we just forward to the expression assert because,
+        // for binary asserts, KUnit supports only a few types (e.g. integers).
+        $crate::kunit_assert!($test, $left == $right);
+    }};
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
new file mode 100644
index 000000000000..b55fe00761c2
--- /dev/null
+++ b/rust/kernel/lib.rs
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! The `kernel` crate.
+//!
+//! This crate contains the kernel APIs that have been ported or wrapped for
+//! usage by Rust code in the kernel and is shared by all of them.
+//!
+//! In other words, all the rest of the Rust code in the kernel (e.g. kernel
+//! modules written in Rust) depends on [`core`], [`alloc`] and this crate.
+//!
+//! If you need a kernel C API that is not ported or wrapped yet here, then
+//! do so first instead of bypassing this crate.
+
+#![no_std]
+#![feature(allocator_api)]
+#![feature(associated_type_defaults)]
+#![feature(coerce_unsized)]
+#![feature(const_mut_refs)]
+#![feature(const_ptr_offset_from)]
+#![feature(const_refs_to_cell)]
+#![feature(const_trait_impl)]
+#![feature(core_ffi_c)]
+#![feature(c_size_t)]
+#![feature(dispatch_from_dyn)]
+#![feature(doc_cfg)]
+#![feature(duration_constants)]
+#![feature(generic_associated_types)]
+#![feature(ptr_metadata)]
+#![feature(receiver_trait)]
+#![feature(unsize)]
+
+// Ensure conditional compilation based on the kernel configuration works;
+// otherwise we may silently break things like initcall handling.
+#[cfg(not(CONFIG_RUST))]
+compile_error!("Missing kernel configuration for conditional compilation");
+
+#[cfg(not(test))]
+#[cfg(not(testlib))]
+mod allocator;
+
+#[doc(hidden)]
+pub use bindings;
+
+pub use macros;
+
+#[cfg(CONFIG_ARM_AMBA)]
+pub mod amba;
+pub mod chrdev;
+#[cfg(CONFIG_COMMON_CLK)]
+pub mod clk;
+pub mod cred;
+pub mod delay;
+pub mod device;
+pub mod driver;
+pub mod error;
+pub mod file;
+pub mod fs;
+pub mod gpio;
+pub mod hwrng;
+pub mod irq;
+pub mod kasync;
+pub mod miscdev;
+pub mod mm;
+#[cfg(CONFIG_NET)]
+pub mod net;
+pub mod pages;
+pub mod power;
+pub mod revocable;
+pub mod security;
+pub mod str;
+pub mod task;
+pub mod workqueue;
+
+pub mod linked_list;
+mod raw_list;
+pub mod rbtree;
+pub mod unsafe_list;
+
+#[doc(hidden)]
+pub mod module_param;
+
+mod build_assert;
+pub mod prelude;
+pub mod print;
+pub mod random;
+mod static_assert;
+#[doc(hidden)]
+pub mod std_vendor;
+pub mod sync;
+
+#[cfg(any(CONFIG_SYSCTL, doc))]
+#[doc(cfg(CONFIG_SYSCTL))]
+pub mod sysctl;
+
+pub mod io_buffer;
+#[cfg(CONFIG_HAS_IOMEM)]
+pub mod io_mem;
+pub mod iov_iter;
+pub mod of;
+pub mod platform;
+mod types;
+pub mod user_ptr;
+
+#[cfg(CONFIG_KUNIT)]
+pub mod kunit;
+
+#[doc(hidden)]
+pub use build_error::build_error;
+
+pub use crate::error::{to_result, Error, Result};
+pub use crate::types::{
+    bit, bits_iter, ARef, AlwaysRefCounted, Bool, Either, Either::Left, Either::Right, False, Mode,
+    Opaque, PointerWrapper, ScopeGuard, True,
+};
+
+use core::marker::PhantomData;
+
+/// Page size defined in terms of the `PAGE_SHIFT` macro from C.
+///
+/// [`PAGE_SHIFT`]: ../../../include/asm-generic/page.h
+pub const PAGE_SIZE: usize = 1 << bindings::PAGE_SHIFT;
+
+/// Prefix to appear before log messages printed from within the kernel crate.
+const __LOG_PREFIX: &[u8] = b"rust_kernel\0";
+
+/// The top level entrypoint to implementing a kernel module.
+///
+/// For any teardown or cleanup operations, your type may implement [`Drop`].
+pub trait Module: Sized + Sync {
+    /// Called at module initialization time.
+    ///
+    /// Use this method to perform whatever setup or registration your module
+    /// should do.
+    ///
+    /// Equivalent to the `module_init` macro in the C API.
+    fn init(name: &'static str::CStr, module: &'static ThisModule) -> Result<Self>;
+}
+
+/// Equivalent to `THIS_MODULE` in the C API.
+///
+/// C header: `include/linux/export.h`
+pub struct ThisModule(*mut bindings::module);
+
+// SAFETY: `THIS_MODULE` may be used from all threads within a module.
+unsafe impl Sync for ThisModule {}
+
+impl ThisModule {
+    /// Creates a [`ThisModule`] given the `THIS_MODULE` pointer.
+    ///
+    /// # Safety
+    ///
+    /// The pointer must be equal to the right `THIS_MODULE`.
+    pub const unsafe fn from_ptr(ptr: *mut bindings::module) -> ThisModule {
+        ThisModule(ptr)
+    }
+
+    /// Locks the module parameters to access them.
+    ///
+    /// Returns a [`KParamGuard`] that will release the lock when dropped.
+    pub fn kernel_param_lock(&self) -> KParamGuard<'_> {
+        // SAFETY: `kernel_param_lock` will check if the pointer is null and
+        // use the built-in mutex in that case.
+        #[cfg(CONFIG_SYSFS)]
+        unsafe {
+            bindings::kernel_param_lock(self.0)
+        }
+
+        KParamGuard {
+            #[cfg(CONFIG_SYSFS)]
+            this_module: self,
+            phantom: PhantomData,
+        }
+    }
+}
+
+/// Scoped lock on the kernel parameters of [`ThisModule`].
+///
+/// Lock will be released when this struct is dropped.
+pub struct KParamGuard<'a> {
+    #[cfg(CONFIG_SYSFS)]
+    this_module: &'a ThisModule,
+    phantom: PhantomData<&'a ()>,
+}
+
+#[cfg(CONFIG_SYSFS)]
+impl<'a> Drop for KParamGuard<'a> {
+    fn drop(&mut self) {
+        // SAFETY: `kernel_param_lock` will check if the pointer is null and
+        // use the built-in mutex in that case. The existence of `self`
+        // guarantees that the lock is held.
+        unsafe { bindings::kernel_param_unlock(self.this_module.0) }
+    }
+}
+
+/// Calculates the offset of a field from the beginning of the struct it belongs to.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::prelude::*;
+/// # use kernel::offset_of;
+/// struct Test {
+///     a: u64,
+///     b: u32,
+/// }
+///
+/// assert_eq!(offset_of!(Test, b), 8);
+/// ```
+#[macro_export]
+macro_rules! offset_of {
+    ($type:ty, $($f:tt)*) => {{
+        let tmp = core::mem::MaybeUninit::<$type>::uninit();
+        let outer = tmp.as_ptr();
+        // To avoid warnings when nesting `unsafe` blocks.
+        #[allow(unused_unsafe)]
+        // SAFETY: The pointer is valid and aligned, just not initialised; `addr_of` ensures that
+        // we don't actually read from `outer` (which would be UB) nor create an intermediate
+        // reference.
+        let inner = unsafe { core::ptr::addr_of!((*outer).$($f)*) } as *const u8;
+        // To avoid warnings when nesting `unsafe` blocks.
+        #[allow(unused_unsafe)]
+        // SAFETY: The two pointers are within the same allocation block.
+        unsafe { inner.offset_from(outer as *const u8) }
+    }}
+}
+
+/// Produces a pointer to an object from a pointer to one of its fields.
+///
+/// # Safety
+///
+/// Callers must ensure that the pointer to the field is in fact a pointer to the specified field,
+/// as opposed to a pointer to another object of the same type. If this condition is not met,
+/// any dereference of the resulting pointer is UB.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::container_of;
+/// struct Test {
+///     a: u64,
+///     b: u32,
+/// }
+///
+/// let test = Test { a: 10, b: 20 };
+/// let b_ptr = &test.b;
+/// let test_alias = container_of!(b_ptr, Test, b);
+/// assert!(core::ptr::eq(&test, test_alias));
+/// ```
+#[macro_export]
+macro_rules! container_of {
+    ($ptr:expr, $type:ty, $($f:tt)*) => {{
+        let ptr = $ptr as *const _ as *const u8;
+        let offset = $crate::offset_of!($type, $($f)*);
+        ptr.wrapping_offset(-offset) as *const $type
+    }}
+}
+
+#[cfg(not(any(testlib, test)))]
+#[panic_handler]
+fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
+    pr_emerg!("{}\n", info);
+    // SAFETY: FFI call.
+    unsafe { bindings::BUG() };
+    // Bindgen currently does not recognize `__noreturn` so `BUG` returns `()`
+    // instead of `!`. See <https://github.com/rust-lang/rust-bindgen/issues/2094>.
+    loop {}
+}
diff --git a/rust/kernel/linked_list.rs b/rust/kernel/linked_list.rs
new file mode 100644
index 000000000000..3330edcc7ca8
--- /dev/null
+++ b/rust/kernel/linked_list.rs
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Linked lists.
+//!
+//! TODO: This module is a work in progress.
+
+use alloc::boxed::Box;
+use core::ptr::NonNull;
+
+pub use crate::raw_list::{Cursor, GetLinks, Links};
+use crate::{raw_list, raw_list::RawList, sync::Ref};
+
+// TODO: Use the one from `kernel::file_operations::PointerWrapper` instead.
+/// Wraps an object to be inserted in a linked list.
+pub trait Wrapper<T: ?Sized> {
+    /// Converts the wrapped object into a pointer that represents it.
+    fn into_pointer(self) -> NonNull<T>;
+
+    /// Converts the object back from the pointer representation.
+    ///
+    /// # Safety
+    ///
+    /// The passed pointer must come from a previous call to [`Wrapper::into_pointer()`].
+    unsafe fn from_pointer(ptr: NonNull<T>) -> Self;
+
+    /// Returns a reference to the wrapped object.
+    fn as_ref(&self) -> &T;
+}
+
+impl<T: ?Sized> Wrapper<T> for Box<T> {
+    fn into_pointer(self) -> NonNull<T> {
+        NonNull::new(Box::into_raw(self)).unwrap()
+    }
+
+    unsafe fn from_pointer(ptr: NonNull<T>) -> Self {
+        unsafe { Box::from_raw(ptr.as_ptr()) }
+    }
+
+    fn as_ref(&self) -> &T {
+        AsRef::as_ref(self)
+    }
+}
+
+impl<T: ?Sized> Wrapper<T> for Ref<T> {
+    fn into_pointer(self) -> NonNull<T> {
+        NonNull::new(Ref::into_raw(self) as _).unwrap()
+    }
+
+    unsafe fn from_pointer(ptr: NonNull<T>) -> Self {
+        // SAFETY: The safety requirements of `from_pointer` satisfy the ones from `Ref::from_raw`.
+        unsafe { Ref::from_raw(ptr.as_ptr() as _) }
+    }
+
+    fn as_ref(&self) -> &T {
+        AsRef::as_ref(self)
+    }
+}
+
+impl<T: ?Sized> Wrapper<T> for &T {
+    fn into_pointer(self) -> NonNull<T> {
+        NonNull::from(self)
+    }
+
+    unsafe fn from_pointer(ptr: NonNull<T>) -> Self {
+        unsafe { &*ptr.as_ptr() }
+    }
+
+    fn as_ref(&self) -> &T {
+        self
+    }
+}
+
+/// A descriptor of wrapped list elements.
+pub trait GetLinksWrapped: GetLinks {
+    /// Specifies which wrapper (e.g., `Box` and `Arc`) wraps the list entries.
+    type Wrapped: Wrapper<Self::EntryType>;
+}
+
+impl<T: ?Sized> GetLinksWrapped for Box<T>
+where
+    Box<T>: GetLinks,
+{
+    type Wrapped = Box<<Box<T> as GetLinks>::EntryType>;
+}
+
+impl<T: GetLinks + ?Sized> GetLinks for Box<T> {
+    type EntryType = T::EntryType;
+    fn get_links(data: &Self::EntryType) -> &Links<Self::EntryType> {
+        <T as GetLinks>::get_links(data)
+    }
+}
+
+impl<T: ?Sized> GetLinksWrapped for Ref<T>
+where
+    Ref<T>: GetLinks,
+{
+    type Wrapped = Ref<<Ref<T> as GetLinks>::EntryType>;
+}
+
+impl<T: GetLinks + ?Sized> GetLinks for Ref<T> {
+    type EntryType = T::EntryType;
+
+    fn get_links(data: &Self::EntryType) -> &Links<Self::EntryType> {
+        <T as GetLinks>::get_links(data)
+    }
+}
+
+/// A linked list.
+///
+/// Elements in the list are wrapped and ownership is transferred to the list while the element is
+/// in the list.
+pub struct List<G: GetLinksWrapped> {
+    list: RawList<G>,
+}
+
+impl<G: GetLinksWrapped> List<G> {
+    /// Constructs a new empty linked list.
+    pub fn new() -> Self {
+        Self {
+            list: RawList::new(),
+        }
+    }
+
+    /// Returns whether the list is empty.
+    pub fn is_empty(&self) -> bool {
+        self.list.is_empty()
+    }
+
+    /// Adds the given object to the end (back) of the list.
+    ///
+    /// It is dropped if it's already on this (or another) list; this can happen for
+    /// reference-counted objects, so dropping means decrementing the reference count.
+    pub fn push_back(&mut self, data: G::Wrapped) {
+        let ptr = data.into_pointer();
+
+        // SAFETY: We took ownership of the entry, so it is safe to insert it.
+        if !unsafe { self.list.push_back(ptr.as_ref()) } {
+            // If insertion failed, rebuild object so that it can be freed.
+            // SAFETY: We just called `into_pointer` above.
+            unsafe { G::Wrapped::from_pointer(ptr) };
+        }
+    }
+
+    /// Inserts the given object after `existing`.
+    ///
+    /// It is dropped if it's already on this (or another) list; this can happen for
+    /// reference-counted objects, so dropping means decrementing the reference count.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `existing` points to a valid entry that is on the list.
+    pub unsafe fn insert_after(&mut self, existing: NonNull<G::EntryType>, data: G::Wrapped) {
+        let ptr = data.into_pointer();
+        let entry = unsafe { &*existing.as_ptr() };
+        if unsafe { !self.list.insert_after(entry, ptr.as_ref()) } {
+            // If insertion failed, rebuild object so that it can be freed.
+            unsafe { G::Wrapped::from_pointer(ptr) };
+        }
+    }
+
+    /// Removes the given entry.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `data` is either on this list or in no list. It being on another
+    /// list leads to memory unsafety.
+    pub unsafe fn remove(&mut self, data: &G::Wrapped) -> Option<G::Wrapped> {
+        let entry_ref = Wrapper::as_ref(data);
+        if unsafe { self.list.remove(entry_ref) } {
+            Some(unsafe { G::Wrapped::from_pointer(NonNull::from(entry_ref)) })
+        } else {
+            None
+        }
+    }
+
+    /// Removes the element currently at the front of the list and returns it.
+    ///
+    /// Returns `None` if the list is empty.
+    pub fn pop_front(&mut self) -> Option<G::Wrapped> {
+        let front = self.list.pop_front()?;
+        // SAFETY: Elements on the list were inserted after a call to `into_pointer `.
+        Some(unsafe { G::Wrapped::from_pointer(front) })
+    }
+
+    /// Returns a cursor starting on the first (front) element of the list.
+    pub fn cursor_front(&self) -> Cursor<'_, G> {
+        self.list.cursor_front()
+    }
+
+    /// Returns a mutable cursor starting on the first (front) element of the list.
+    pub fn cursor_front_mut(&mut self) -> CursorMut<'_, G> {
+        CursorMut::new(self.list.cursor_front_mut())
+    }
+}
+
+impl<G: GetLinksWrapped> Default for List<G> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<G: GetLinksWrapped> Drop for List<G> {
+    fn drop(&mut self) {
+        while self.pop_front().is_some() {}
+    }
+}
+
+/// A list cursor that allows traversing a linked list and inspecting & mutating elements.
+pub struct CursorMut<'a, G: GetLinksWrapped> {
+    cursor: raw_list::CursorMut<'a, G>,
+}
+
+impl<'a, G: GetLinksWrapped> CursorMut<'a, G> {
+    fn new(cursor: raw_list::CursorMut<'a, G>) -> Self {
+        Self { cursor }
+    }
+
+    /// Returns the element the cursor is currently positioned on.
+    pub fn current(&mut self) -> Option<&mut G::EntryType> {
+        self.cursor.current()
+    }
+
+    /// Removes the element the cursor is currently positioned on.
+    ///
+    /// After removal, it advances the cursor to the next element.
+    pub fn remove_current(&mut self) -> Option<G::Wrapped> {
+        let ptr = self.cursor.remove_current()?;
+
+        // SAFETY: Elements on the list were inserted after a call to `into_pointer `.
+        Some(unsafe { G::Wrapped::from_pointer(ptr) })
+    }
+
+    /// Returns the element immediately after the one the cursor is positioned on.
+    pub fn peek_next(&mut self) -> Option<&mut G::EntryType> {
+        self.cursor.peek_next()
+    }
+
+    /// Returns the element immediately before the one the cursor is positioned on.
+    pub fn peek_prev(&mut self) -> Option<&mut G::EntryType> {
+        self.cursor.peek_prev()
+    }
+
+    /// Moves the cursor to the next element.
+    pub fn move_next(&mut self) {
+        self.cursor.move_next();
+    }
+}
diff --git a/rust/kernel/miscdev.rs b/rust/kernel/miscdev.rs
new file mode 100644
index 000000000000..65b95d6dba90
--- /dev/null
+++ b/rust/kernel/miscdev.rs
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Miscellaneous devices.
+//!
+//! C header: [`include/linux/miscdevice.h`](../../../../include/linux/miscdevice.h)
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/driver-api/misc_devices.html>
+
+use crate::bindings;
+use crate::error::{code::*, Error, Result};
+use crate::file;
+use crate::{device, str::CStr, str::CString, ThisModule};
+use alloc::boxed::Box;
+use core::marker::PhantomPinned;
+use core::{fmt, mem::MaybeUninit, pin::Pin};
+
+/// Options which can be used to configure how a misc device is registered.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::{c_str, device::RawDevice, file, miscdev, prelude::*};
+/// fn example(
+///     reg: Pin<&mut miscdev::Registration<impl file::Operations<OpenData = ()>>>,
+///     parent: &dyn RawDevice,
+/// ) -> Result {
+///     miscdev::Options::new()
+///         .mode(0o600)
+///         .minor(10)
+///         .parent(parent)
+///         .register(reg, fmt!("sample"), ())
+/// }
+/// ```
+#[derive(Default)]
+pub struct Options<'a> {
+    minor: Option<i32>,
+    mode: Option<u16>,
+    parent: Option<&'a dyn device::RawDevice>,
+}
+
+impl<'a> Options<'a> {
+    /// Creates new [`Options`] instance with the required fields.
+    pub const fn new() -> Self {
+        Self {
+            minor: None,
+            mode: None,
+            parent: None,
+        }
+    }
+
+    /// Sets the minor device number.
+    pub const fn minor(&mut self, v: i32) -> &mut Self {
+        self.minor = Some(v);
+        self
+    }
+
+    /// Sets the device mode.
+    ///
+    /// This is usually an octal number and describes who can perform read/write/execute operations
+    /// on the device.
+    pub const fn mode(&mut self, m: u16) -> &mut Self {
+        self.mode = Some(m);
+        self
+    }
+
+    /// Sets the device parent.
+    pub const fn parent(&mut self, p: &'a dyn device::RawDevice) -> &mut Self {
+        self.parent = Some(p);
+        self
+    }
+
+    /// Registers a misc device using the configured options.
+    pub fn register<T: file::Operations>(
+        &self,
+        reg: Pin<&mut Registration<T>>,
+        name: fmt::Arguments<'_>,
+        open_data: T::OpenData,
+    ) -> Result {
+        reg.register_with_options(name, open_data, self)
+    }
+
+    /// Allocates a new registration of a misc device and completes the registration with the
+    /// configured options.
+    pub fn register_new<T: file::Operations>(
+        &self,
+        name: fmt::Arguments<'_>,
+        open_data: T::OpenData,
+    ) -> Result<Pin<Box<Registration<T>>>> {
+        let mut r = Pin::from(Box::try_new(Registration::new())?);
+        self.register(r.as_mut(), name, open_data)?;
+        Ok(r)
+    }
+}
+
+/// A registration of a miscellaneous device.
+///
+/// # Invariants
+///
+/// `Context` is always initialised when `registered` is `true`, and not initialised otherwise.
+pub struct Registration<T: file::Operations> {
+    registered: bool,
+    mdev: bindings::miscdevice,
+    name: Option<CString>,
+    _pin: PhantomPinned,
+
+    /// Context initialised on construction and made available to all file instances on
+    /// [`file::Operations::open`].
+    open_data: MaybeUninit<T::OpenData>,
+}
+
+impl<T: file::Operations> Registration<T> {
+    /// Creates a new [`Registration`] but does not register it yet.
+    ///
+    /// It is allowed to move.
+    pub fn new() -> Self {
+        // INVARIANT: `registered` is `false` and `open_data` is not initialised.
+        Self {
+            registered: false,
+            mdev: bindings::miscdevice::default(),
+            name: None,
+            _pin: PhantomPinned,
+            open_data: MaybeUninit::uninit(),
+        }
+    }
+
+    /// Registers a miscellaneous device.
+    ///
+    /// Returns a pinned heap-allocated representation of the registration.
+    pub fn new_pinned(name: fmt::Arguments<'_>, open_data: T::OpenData) -> Result<Pin<Box<Self>>> {
+        Options::new().register_new(name, open_data)
+    }
+
+    /// Registers a miscellaneous device with the rest of the kernel.
+    ///
+    /// It must be pinned because the memory block that represents the registration is
+    /// self-referential.
+    pub fn register(
+        self: Pin<&mut Self>,
+        name: fmt::Arguments<'_>,
+        open_data: T::OpenData,
+    ) -> Result {
+        Options::new().register(self, name, open_data)
+    }
+
+    /// Registers a miscellaneous device with the rest of the kernel. Additional optional settings
+    /// are provided via the `opts` parameter.
+    ///
+    /// It must be pinned because the memory block that represents the registration is
+    /// self-referential.
+    pub fn register_with_options(
+        self: Pin<&mut Self>,
+        name: fmt::Arguments<'_>,
+        open_data: T::OpenData,
+        opts: &Options<'_>,
+    ) -> Result {
+        // SAFETY: We must ensure that we never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+        if this.registered {
+            // Already registered.
+            return Err(EINVAL);
+        }
+
+        let name = CString::try_from_fmt(name)?;
+
+        // SAFETY: The adapter is compatible with `misc_register`.
+        this.mdev.fops = unsafe { file::OperationsVtable::<Self, T>::build() };
+        this.mdev.name = name.as_char_ptr();
+        this.mdev.minor = opts.minor.unwrap_or(bindings::MISC_DYNAMIC_MINOR as i32);
+        this.mdev.mode = opts.mode.unwrap_or(0);
+        this.mdev.parent = opts
+            .parent
+            .map_or(core::ptr::null_mut(), |p| p.raw_device());
+
+        // We write to `open_data` here because as soon as `misc_register` succeeds, the file can be
+        // opened, so we need `open_data` configured ahead of time.
+        //
+        // INVARIANT: `registered` is set to `true`, but `open_data` is also initialised.
+        this.registered = true;
+        this.open_data.write(open_data);
+
+        let ret = unsafe { bindings::misc_register(&mut this.mdev) };
+        if ret < 0 {
+            // INVARIANT: `registered` is set back to `false` and the `open_data` is destructued.
+            this.registered = false;
+            // SAFETY: `open_data` was initialised a few lines above.
+            unsafe { this.open_data.assume_init_drop() };
+            return Err(Error::from_kernel_errno(ret));
+        }
+
+        this.name = Some(name);
+
+        Ok(())
+    }
+}
+
+impl<T: file::Operations> Default for Registration<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<T: file::Operations> file::OpenAdapter<T::OpenData> for Registration<T> {
+    unsafe fn convert(
+        _inode: *mut bindings::inode,
+        file: *mut bindings::file,
+    ) -> *const T::OpenData {
+        // SAFETY: The caller must guarantee that `file` is valid.
+        let reg = crate::container_of!(unsafe { (*file).private_data }, Self, mdev);
+
+        // SAFETY: This function is only called while the misc device is still registered, so the
+        // registration must be valid. Additionally, the type invariants guarantee that while the
+        // miscdev is registered, `open_data` is initialised.
+        unsafe { (*reg).open_data.as_ptr() }
+    }
+}
+
+// SAFETY: The only method is `register()`, which requires a (pinned) mutable `Registration`, so it
+// is safe to pass `&Registration` to multiple threads because it offers no interior mutability.
+unsafe impl<T: file::Operations> Sync for Registration<T> {}
+
+// SAFETY: All functions work from any thread. So as long as the `Registration::open_data` is
+// `Send`, so is `Registration<T>`.
+unsafe impl<T: file::Operations> Send for Registration<T> where T::OpenData: Send {}
+
+impl<T: file::Operations> Drop for Registration<T> {
+    /// Removes the registration from the kernel if it has completed successfully before.
+    fn drop(&mut self) {
+        if self.registered {
+            // SAFETY: `registered` being `true` indicates that a previous call to  `misc_register`
+            // succeeded.
+            unsafe { bindings::misc_deregister(&mut self.mdev) };
+
+            // SAFETY: The type invariant guarantees that `open_data` is initialised when
+            // `registered` is `true`.
+            unsafe { self.open_data.assume_init_drop() };
+        }
+    }
+}
+
+/// Kernel module that exposes a single miscdev device implemented by `T`.
+pub struct Module<T: file::Operations<OpenData = ()>> {
+    _dev: Pin<Box<Registration<T>>>,
+}
+
+impl<T: file::Operations<OpenData = ()>> crate::Module for Module<T> {
+    fn init(name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
+        Ok(Self {
+            _dev: Registration::new_pinned(crate::fmt!("{name}"), ())?,
+        })
+    }
+}
+
+/// Declares a kernel module that exposes a single misc device.
+///
+/// The `type` argument should be a type which implements the [`FileOpener`] trait. Also accepts
+/// various forms of kernel metadata.
+///
+/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
+///
+/// [`FileOpener`]: ../kernel/file_operations/trait.FileOpener.html
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::prelude::*;
+///
+/// module_misc_device! {
+///     type: MyFile,
+///     name: b"my_miscdev_kernel_module",
+///     author: b"Rust for Linux Contributors",
+///     description: b"My very own misc device kernel module!",
+///     license: b"GPL",
+/// }
+///
+/// #[derive(Default)]
+/// struct MyFile;
+///
+/// #[vtable]
+/// impl kernel::file::Operations for MyFile {}
+/// ```
+#[macro_export]
+macro_rules! module_misc_device {
+    (type: $type:ty, $($f:tt)*) => {
+        type ModuleType = kernel::miscdev::Module<$type>;
+        module! {
+            type: ModuleType,
+            $($f)*
+        }
+    }
+}
diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs
new file mode 100644
index 000000000000..8a69c69dddd9
--- /dev/null
+++ b/rust/kernel/mm.rs
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Memory management.
+//!
+//! C header: [`include/linux/mm.h`](../../../../include/linux/mm.h)
+
+use crate::{bindings, pages, to_result, Result};
+
+/// Virtual memory.
+pub mod virt {
+    use super::*;
+
+    /// A wrapper for the kernel's `struct vm_area_struct`.
+    ///
+    /// It represents an area of virtual memory.
+    ///
+    /// # Invariants
+    ///
+    /// `vma` is always non-null and valid.
+    pub struct Area {
+        vma: *mut bindings::vm_area_struct,
+    }
+
+    impl Area {
+        /// Creates a new instance of a virtual memory area.
+        ///
+        /// # Safety
+        ///
+        /// Callers must ensure that `vma` is non-null and valid for the duration of the new area's
+        /// lifetime.
+        pub(crate) unsafe fn from_ptr(vma: *mut bindings::vm_area_struct) -> Self {
+            // INVARIANTS: The safety requirements guarantee the invariants.
+            Self { vma }
+        }
+
+        /// Returns the flags associated with the virtual memory area.
+        ///
+        /// The possible flags are a combination of the constants in [`flags`].
+        pub fn flags(&self) -> usize {
+            // SAFETY: `self.vma` is valid by the type invariants.
+            unsafe { (*self.vma).vm_flags as _ }
+        }
+
+        /// Sets the flags associated with the virtual memory area.
+        ///
+        /// The possible flags are a combination of the constants in [`flags`].
+        pub fn set_flags(&mut self, flags: usize) {
+            // SAFETY: `self.vma` is valid by the type invariants.
+            unsafe { (*self.vma).vm_flags = flags as _ };
+        }
+
+        /// Returns the start address of the virtual memory area.
+        pub fn start(&self) -> usize {
+            // SAFETY: `self.vma` is valid by the type invariants.
+            unsafe { (*self.vma).vm_start as _ }
+        }
+
+        /// Returns the end address of the virtual memory area.
+        pub fn end(&self) -> usize {
+            // SAFETY: `self.vma` is valid by the type invariants.
+            unsafe { (*self.vma).vm_end as _ }
+        }
+
+        /// Maps a single page at the given address within the virtual memory area.
+        pub fn insert_page(&mut self, address: usize, page: &pages::Pages<0>) -> Result {
+            // SAFETY: The page is guaranteed to be order 0 by the type system. The range of
+            // `address` is already checked by `vm_insert_page`. `self.vma` and `page.pages` are
+            // guaranteed by their repective type invariants to be valid.
+            to_result(unsafe { bindings::vm_insert_page(self.vma, address as _, page.pages) })
+        }
+    }
+
+    /// Container for [`Area`] flags.
+    pub mod flags {
+        use crate::bindings;
+
+        /// No flags are set.
+        pub const NONE: usize = bindings::VM_NONE as _;
+
+        /// Mapping allows reads.
+        pub const READ: usize = bindings::VM_READ as _;
+
+        /// Mapping allows writes.
+        pub const WRITE: usize = bindings::VM_WRITE as _;
+
+        /// Mapping allows execution.
+        pub const EXEC: usize = bindings::VM_EXEC as _;
+
+        /// Mapping is shared.
+        pub const SHARED: usize = bindings::VM_SHARED as _;
+
+        /// Mapping may be updated to allow reads.
+        pub const MAYREAD: usize = bindings::VM_MAYREAD as _;
+
+        /// Mapping may be updated to allow writes.
+        pub const MAYWRITE: usize = bindings::VM_MAYWRITE as _;
+
+        /// Mapping may be updated to allow execution.
+        pub const MAYEXEC: usize = bindings::VM_MAYEXEC as _;
+
+        /// Mapping may be updated to be shared.
+        pub const MAYSHARE: usize = bindings::VM_MAYSHARE as _;
+
+        /// Do not copy this vma on fork.
+        pub const DONTCOPY: usize = bindings::VM_DONTCOPY as _;
+
+        /// Cannot expand with mremap().
+        pub const DONTEXPAND: usize = bindings::VM_DONTEXPAND as _;
+
+        /// Lock the pages covered when they are faulted in.
+        pub const LOCKONFAULT: usize = bindings::VM_LOCKONFAULT as _;
+
+        /// Is a VM accounted object.
+        pub const ACCOUNT: usize = bindings::VM_ACCOUNT as _;
+
+        /// should the VM suppress accounting.
+        pub const NORESERVE: usize = bindings::VM_NORESERVE as _;
+
+        /// Huge TLB Page VM.
+        pub const HUGETLB: usize = bindings::VM_HUGETLB as _;
+
+        /// Synchronous page faults.
+        pub const SYNC: usize = bindings::VM_SYNC as _;
+
+        /// Architecture-specific flag.
+        pub const ARCH_1: usize = bindings::VM_ARCH_1 as _;
+
+        /// Wipe VMA contents in child..
+        pub const WIPEONFORK: usize = bindings::VM_WIPEONFORK as _;
+
+        /// Do not include in the core dump.
+        pub const DONTDUMP: usize = bindings::VM_DONTDUMP as _;
+
+        /// Not soft dirty clean area.
+        pub const SOFTDIRTY: usize = bindings::VM_SOFTDIRTY as _;
+
+        /// Can contain "struct page" and pure PFN pages.
+        pub const MIXEDMAP: usize = bindings::VM_MIXEDMAP as _;
+
+        /// MADV_HUGEPAGE marked this vma.
+        pub const HUGEPAGE: usize = bindings::VM_HUGEPAGE as _;
+
+        /// MADV_NOHUGEPAGE marked this vma.
+        pub const NOHUGEPAGE: usize = bindings::VM_NOHUGEPAGE as _;
+
+        /// KSM may merge identical pages.
+        pub const MERGEABLE: usize = bindings::VM_MERGEABLE as _;
+    }
+}
diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs
new file mode 100644
index 000000000000..6df38c78c65c
--- /dev/null
+++ b/rust/kernel/module_param.rs
@@ -0,0 +1,499 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Types for module parameters.
+//!
+//! C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
+
+use crate::error::{code::*, from_kernel_result};
+use crate::str::{CStr, Formatter};
+use core::fmt::Write;
+
+/// Types that can be used for module parameters.
+///
+/// Note that displaying the type in `sysfs` will fail if
+/// [`alloc::string::ToString::to_string`] (as implemented through the
+/// [`core::fmt::Display`] trait) writes more than [`PAGE_SIZE`]
+/// bytes (including an additional null terminator).
+///
+/// [`PAGE_SIZE`]: `crate::PAGE_SIZE`
+pub trait ModuleParam: core::fmt::Display + core::marker::Sized {
+    /// The `ModuleParam` will be used by the kernel module through this type.
+    ///
+    /// This may differ from `Self` if, for example, `Self` needs to track
+    /// ownership without exposing it or allocate extra space for other possible
+    /// parameter values. See [`StringParam`] or [`ArrayParam`] for examples.
+    type Value: ?Sized;
+
+    /// Whether the parameter is allowed to be set without an argument.
+    ///
+    /// Setting this to `true` allows the parameter to be passed without an
+    /// argument (e.g. just `module.param` instead of `module.param=foo`).
+    const NOARG_ALLOWED: bool;
+
+    /// Convert a parameter argument into the parameter value.
+    ///
+    /// `None` should be returned when parsing of the argument fails.
+    /// `arg == None` indicates that the parameter was passed without an
+    /// argument. If `NOARG_ALLOWED` is set to `false` then `arg` is guaranteed
+    /// to always be `Some(_)`.
+    ///
+    /// Parameters passed at boot time will be set before [`kmalloc`] is
+    /// available (even if the module is loaded at a later time). However, in
+    /// this case, the argument buffer will be valid for the entire lifetime of
+    /// the kernel. So implementations of this method which need to allocate
+    /// should first check that the allocator is available (with
+    /// [`crate::bindings::slab_is_available`]) and when it is not available
+    /// provide an alternative implementation which doesn't allocate. In cases
+    /// where the allocator is not available it is safe to save references to
+    /// `arg` in `Self`, but in other cases a copy should be made.
+    ///
+    /// [`kmalloc`]: ../../../include/linux/slab.h
+    fn try_from_param_arg(arg: Option<&'static [u8]>) -> Option<Self>;
+
+    /// Get the current value of the parameter for use in the kernel module.
+    ///
+    /// This function should not be used directly. Instead use the wrapper
+    /// `read` which will be generated by [`macros::module`].
+    fn value(&self) -> &Self::Value;
+
+    /// Set the module parameter from a string.
+    ///
+    /// Used to set the parameter value when loading the module or when set
+    /// through `sysfs`.
+    ///
+    /// # Safety
+    ///
+    /// If `val` is non-null then it must point to a valid null-terminated
+    /// string. The `arg` field of `param` must be an instance of `Self`.
+    unsafe extern "C" fn set_param(
+        val: *const core::ffi::c_char,
+        param: *const crate::bindings::kernel_param,
+    ) -> core::ffi::c_int {
+        let arg = if val.is_null() {
+            None
+        } else {
+            Some(unsafe { CStr::from_char_ptr(val).as_bytes() })
+        };
+        match Self::try_from_param_arg(arg) {
+            Some(new_value) => {
+                let old_value = unsafe { (*param).__bindgen_anon_1.arg as *mut Self };
+                let _ = unsafe { core::ptr::replace(old_value, new_value) };
+                0
+            }
+            None => EINVAL.to_kernel_errno(),
+        }
+    }
+
+    /// Write a string representation of the current parameter value to `buf`.
+    ///
+    /// Used for displaying the current parameter value in `sysfs`.
+    ///
+    /// # Safety
+    ///
+    /// `buf` must be a buffer of length at least `kernel::PAGE_SIZE` that is
+    /// writeable. The `arg` field of `param` must be an instance of `Self`.
+    unsafe extern "C" fn get_param(
+        buf: *mut core::ffi::c_char,
+        param: *const crate::bindings::kernel_param,
+    ) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: The C contracts guarantees that the buffer is at least `PAGE_SIZE` bytes.
+            let mut f = unsafe { Formatter::from_buffer(buf.cast(), crate::PAGE_SIZE) };
+            unsafe { write!(f, "{}\0", *((*param).__bindgen_anon_1.arg as *mut Self)) }?;
+            Ok(f.bytes_written().try_into()?)
+        }
+    }
+
+    /// Drop the parameter.
+    ///
+    /// Called when unloading a module.
+    ///
+    /// # Safety
+    ///
+    /// The `arg` field of `param` must be an instance of `Self`.
+    unsafe extern "C" fn free(arg: *mut core::ffi::c_void) {
+        unsafe { core::ptr::drop_in_place(arg as *mut Self) };
+    }
+}
+
+/// Trait for parsing integers.
+///
+/// Strings beginning with `0x`, `0o`, or `0b` are parsed as hex, octal, or
+/// binary respectively. Strings beginning with `0` otherwise are parsed as
+/// octal. Anything else is parsed as decimal. A leading `+` or `-` is also
+/// permitted. Any string parsed by [`kstrtol()`] or [`kstrtoul()`] will be
+/// successfully parsed.
+///
+/// [`kstrtol()`]: https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#c.kstrtol
+/// [`kstrtoul()`]: https://www.kernel.org/doc/html/latest/core-api/kernel-api.html#c.kstrtoul
+trait ParseInt: Sized {
+    fn from_str_radix(src: &str, radix: u32) -> Result<Self, core::num::ParseIntError>;
+    fn checked_neg(self) -> Option<Self>;
+
+    fn from_str_unsigned(src: &str) -> Result<Self, core::num::ParseIntError> {
+        let (radix, digits) = if let Some(n) = src.strip_prefix("0x") {
+            (16, n)
+        } else if let Some(n) = src.strip_prefix("0X") {
+            (16, n)
+        } else if let Some(n) = src.strip_prefix("0o") {
+            (8, n)
+        } else if let Some(n) = src.strip_prefix("0O") {
+            (8, n)
+        } else if let Some(n) = src.strip_prefix("0b") {
+            (2, n)
+        } else if let Some(n) = src.strip_prefix("0B") {
+            (2, n)
+        } else if src.starts_with('0') {
+            (8, src)
+        } else {
+            (10, src)
+        };
+        Self::from_str_radix(digits, radix)
+    }
+
+    fn from_str(src: &str) -> Option<Self> {
+        match src.bytes().next() {
+            None => None,
+            Some(b'-') => Self::from_str_unsigned(&src[1..]).ok()?.checked_neg(),
+            Some(b'+') => Some(Self::from_str_unsigned(&src[1..]).ok()?),
+            Some(_) => Some(Self::from_str_unsigned(src).ok()?),
+        }
+    }
+}
+
+macro_rules! impl_parse_int {
+    ($ty:ident) => {
+        impl ParseInt for $ty {
+            fn from_str_radix(src: &str, radix: u32) -> Result<Self, core::num::ParseIntError> {
+                $ty::from_str_radix(src, radix)
+            }
+
+            fn checked_neg(self) -> Option<Self> {
+                self.checked_neg()
+            }
+        }
+    };
+}
+
+impl_parse_int!(i8);
+impl_parse_int!(u8);
+impl_parse_int!(i16);
+impl_parse_int!(u16);
+impl_parse_int!(i32);
+impl_parse_int!(u32);
+impl_parse_int!(i64);
+impl_parse_int!(u64);
+impl_parse_int!(isize);
+impl_parse_int!(usize);
+
+macro_rules! impl_module_param {
+    ($ty:ident) => {
+        impl ModuleParam for $ty {
+            type Value = $ty;
+
+            const NOARG_ALLOWED: bool = false;
+
+            fn try_from_param_arg(arg: Option<&'static [u8]>) -> Option<Self> {
+                let bytes = arg?;
+                let utf8 = core::str::from_utf8(bytes).ok()?;
+                <$ty as crate::module_param::ParseInt>::from_str(utf8)
+            }
+
+            fn value(&self) -> &Self::Value {
+                self
+            }
+        }
+    };
+}
+
+#[doc(hidden)]
+#[macro_export]
+/// Generate a static [`kernel_param_ops`](../../../include/linux/moduleparam.h) struct.
+///
+/// # Examples
+///
+/// ```ignore
+/// make_param_ops!(
+///     /// Documentation for new param ops.
+///     PARAM_OPS_MYTYPE, // Name for the static.
+///     MyType // A type which implements [`ModuleParam`].
+/// );
+/// ```
+macro_rules! make_param_ops {
+    ($ops:ident, $ty:ty) => {
+        $crate::make_param_ops!(
+            #[doc=""]
+            $ops,
+            $ty
+        );
+    };
+    ($(#[$meta:meta])* $ops:ident, $ty:ty) => {
+        $(#[$meta])*
+        ///
+        /// Static [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+        /// struct generated by [`make_param_ops`].
+        pub static $ops: $crate::bindings::kernel_param_ops = $crate::bindings::kernel_param_ops {
+            flags: if <$ty as $crate::module_param::ModuleParam>::NOARG_ALLOWED {
+                $crate::bindings::KERNEL_PARAM_OPS_FL_NOARG
+            } else {
+                0
+            },
+            set: Some(<$ty as $crate::module_param::ModuleParam>::set_param),
+            get: Some(<$ty as $crate::module_param::ModuleParam>::get_param),
+            free: Some(<$ty as $crate::module_param::ModuleParam>::free),
+        };
+    };
+}
+
+impl_module_param!(i8);
+impl_module_param!(u8);
+impl_module_param!(i16);
+impl_module_param!(u16);
+impl_module_param!(i32);
+impl_module_param!(u32);
+impl_module_param!(i64);
+impl_module_param!(u64);
+impl_module_param!(isize);
+impl_module_param!(usize);
+
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`i8`].
+    PARAM_OPS_I8,
+    i8
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`u8`].
+    PARAM_OPS_U8,
+    u8
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`i16`].
+    PARAM_OPS_I16,
+    i16
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`u16`].
+    PARAM_OPS_U16,
+    u16
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`i32`].
+    PARAM_OPS_I32,
+    i32
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`u32`].
+    PARAM_OPS_U32,
+    u32
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`i64`].
+    PARAM_OPS_I64,
+    i64
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`u64`].
+    PARAM_OPS_U64,
+    u64
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`isize`].
+    PARAM_OPS_ISIZE,
+    isize
+);
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`usize`].
+    PARAM_OPS_USIZE,
+    usize
+);
+
+impl ModuleParam for bool {
+    type Value = bool;
+
+    const NOARG_ALLOWED: bool = true;
+
+    fn try_from_param_arg(arg: Option<&'static [u8]>) -> Option<Self> {
+        match arg {
+            None => Some(true),
+            Some(b"y") | Some(b"Y") | Some(b"1") | Some(b"true") => Some(true),
+            Some(b"n") | Some(b"N") | Some(b"0") | Some(b"false") => Some(false),
+            _ => None,
+        }
+    }
+
+    fn value(&self) -> &Self::Value {
+        self
+    }
+}
+
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`bool`].
+    PARAM_OPS_BOOL,
+    bool
+);
+
+/// An array of at __most__ `N` values.
+///
+/// # Invariant
+///
+/// The first `self.used` elements of `self.values` are initialized.
+pub struct ArrayParam<T, const N: usize> {
+    values: [core::mem::MaybeUninit<T>; N],
+    used: usize,
+}
+
+impl<T, const N: usize> ArrayParam<T, { N }> {
+    fn values(&self) -> &[T] {
+        // SAFETY: The invariant maintained by `ArrayParam` allows us to cast
+        // the first `self.used` elements to `T`.
+        unsafe {
+            &*(&self.values[0..self.used] as *const [core::mem::MaybeUninit<T>] as *const [T])
+        }
+    }
+}
+
+impl<T: Copy, const N: usize> ArrayParam<T, { N }> {
+    const fn new() -> Self {
+        // INVARIANT: The first `self.used` elements of `self.values` are
+        // initialized.
+        ArrayParam {
+            values: [core::mem::MaybeUninit::uninit(); N],
+            used: 0,
+        }
+    }
+
+    const fn push(&mut self, val: T) {
+        if self.used < N {
+            // INVARIANT: The first `self.used` elements of `self.values` are
+            // initialized.
+            self.values[self.used] = core::mem::MaybeUninit::new(val);
+            self.used += 1;
+        }
+    }
+
+    /// Create an instance of `ArrayParam` initialized with `vals`.
+    ///
+    /// This function is only meant to be used in the [`module::module`] macro.
+    pub const fn create(vals: &[T]) -> Self {
+        let mut result = ArrayParam::new();
+        let mut i = 0;
+        while i < vals.len() {
+            result.push(vals[i]);
+            i += 1;
+        }
+        result
+    }
+}
+
+impl<T: core::fmt::Display, const N: usize> core::fmt::Display for ArrayParam<T, { N }> {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        for val in self.values() {
+            write!(f, "{},", val)?;
+        }
+        Ok(())
+    }
+}
+
+impl<T: Copy + core::fmt::Display + ModuleParam, const N: usize> ModuleParam
+    for ArrayParam<T, { N }>
+{
+    type Value = [T];
+
+    const NOARG_ALLOWED: bool = false;
+
+    fn try_from_param_arg(arg: Option<&'static [u8]>) -> Option<Self> {
+        arg.and_then(|args| {
+            let mut result = Self::new();
+            for arg in args.split(|b| *b == b',') {
+                result.push(T::try_from_param_arg(Some(arg))?);
+            }
+            Some(result)
+        })
+    }
+
+    fn value(&self) -> &Self::Value {
+        self.values()
+    }
+}
+
+/// A C-style string parameter.
+///
+/// The Rust version of the [`charp`] parameter. This type is meant to be
+/// used by the [`macros::module`] macro, not handled directly. Instead use the
+/// `read` method generated by that macro.
+///
+/// [`charp`]: ../../../include/linux/moduleparam.h
+pub enum StringParam {
+    /// A borrowed parameter value.
+    ///
+    /// Either the default value (which is static in the module) or borrowed
+    /// from the original argument buffer used to set the value.
+    Ref(&'static [u8]),
+
+    /// A value that was allocated when the parameter was set.
+    ///
+    /// The value needs to be freed when the parameter is reset or the module is
+    /// unloaded.
+    Owned(alloc::vec::Vec<u8>),
+}
+
+impl StringParam {
+    fn bytes(&self) -> &[u8] {
+        match self {
+            StringParam::Ref(bytes) => *bytes,
+            StringParam::Owned(vec) => &vec[..],
+        }
+    }
+}
+
+impl core::fmt::Display for StringParam {
+    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+        let bytes = self.bytes();
+        match core::str::from_utf8(bytes) {
+            Ok(utf8) => write!(f, "{}", utf8),
+            Err(_) => write!(f, "{:?}", bytes),
+        }
+    }
+}
+
+impl ModuleParam for StringParam {
+    type Value = [u8];
+
+    const NOARG_ALLOWED: bool = false;
+
+    fn try_from_param_arg(arg: Option<&'static [u8]>) -> Option<Self> {
+        // SAFETY: It is always safe to call [`slab_is_available`](../../../include/linux/slab.h).
+        let slab_available = unsafe { crate::bindings::slab_is_available() };
+        arg.and_then(|arg| {
+            if slab_available {
+                let mut vec = alloc::vec::Vec::new();
+                vec.try_extend_from_slice(arg).ok()?;
+                Some(StringParam::Owned(vec))
+            } else {
+                Some(StringParam::Ref(arg))
+            }
+        })
+    }
+
+    fn value(&self) -> &Self::Value {
+        self.bytes()
+    }
+}
+
+make_param_ops!(
+    /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
+    /// for [`StringParam`].
+    PARAM_OPS_STR,
+    StringParam
+);
diff --git a/rust/kernel/net.rs b/rust/kernel/net.rs
new file mode 100644
index 000000000000..0115f3a35cd0
--- /dev/null
+++ b/rust/kernel/net.rs
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Networking core.
+//!
+//! C headers: [`include/net/net_namespace.h`](../../../../include/linux/net/net_namespace.h),
+//! [`include/linux/netdevice.h`](../../../../include/linux/netdevice.h),
+//! [`include/linux/skbuff.h`](../../../../include/linux/skbuff.h).
+
+use crate::{bindings, str::CStr, to_result, ARef, AlwaysRefCounted, Error, Result};
+use core::{cell::UnsafeCell, ptr::NonNull};
+
+#[cfg(CONFIG_NETFILTER)]
+pub mod filter;
+
+/// Wraps the kernel's `struct net_device`.
+#[repr(transparent)]
+pub struct Device(UnsafeCell<bindings::net_device>);
+
+// SAFETY: Instances of `Device` are created on the C side. They are always refcounted.
+unsafe impl AlwaysRefCounted for Device {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::dev_hold(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::dev_put(obj.cast().as_ptr()) };
+    }
+}
+
+/// Wraps the kernel's `struct net`.
+#[repr(transparent)]
+pub struct Namespace(UnsafeCell<bindings::net>);
+
+impl Namespace {
+    /// Finds a network device with the given name in the namespace.
+    pub fn dev_get_by_name(&self, name: &CStr) -> Option<ARef<Device>> {
+        // SAFETY: The existence of a shared reference guarantees the refcount is nonzero.
+        let ptr =
+            NonNull::new(unsafe { bindings::dev_get_by_name(self.0.get(), name.as_char_ptr()) })?;
+        Some(unsafe { ARef::from_raw(ptr.cast()) })
+    }
+}
+
+// SAFETY: Instances of `Namespace` are created on the C side. They are always refcounted.
+unsafe impl AlwaysRefCounted for Namespace {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::get_net(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::put_net(obj.cast().as_ptr()) };
+    }
+}
+
+/// Returns the network namespace for the `init` process.
+pub fn init_ns() -> &'static Namespace {
+    unsafe { &*core::ptr::addr_of!(bindings::init_net).cast() }
+}
+
+/// Wraps the kernel's `struct sk_buff`.
+#[repr(transparent)]
+pub struct SkBuff(UnsafeCell<bindings::sk_buff>);
+
+impl SkBuff {
+    /// Creates a reference to an [`SkBuff`] from a valid pointer.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the
+    /// returned [`SkBuff`] instance.
+    pub unsafe fn from_ptr<'a>(ptr: *const bindings::sk_buff) -> &'a SkBuff {
+        // SAFETY: The safety requirements guarantee the validity of the dereference, while the
+        // `SkBuff` type being transparent makes the cast ok.
+        unsafe { &*ptr.cast() }
+    }
+
+    /// Returns the remaining data in the buffer's first segment.
+    pub fn head_data(&self) -> &[u8] {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        let headlen = unsafe { bindings::skb_headlen(self.0.get()) };
+        let len = headlen.try_into().unwrap_or(usize::MAX);
+        // SAFETY: The existence of a shared reference means `self.0` is valid.
+        let data = unsafe { core::ptr::addr_of!((*self.0.get()).data).read() };
+        // SAFETY: The `struct sk_buff` conventions guarantee that at least `skb_headlen(skb)` bytes
+        // are valid from `skb->data`.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+
+    /// Returns the total length of the data (in all segments) in the skb.
+    #[allow(clippy::len_without_is_empty)]
+    pub fn len(&self) -> u32 {
+        // SAFETY: The existence of a shared reference means `self.0` is valid.
+        unsafe { core::ptr::addr_of!((*self.0.get()).len).read() }
+    }
+}
+
+// SAFETY: Instances of `SkBuff` are created on the C side. They are always refcounted.
+unsafe impl AlwaysRefCounted for SkBuff {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::skb_get(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: core::ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe {
+            bindings::kfree_skb_reason(
+                obj.cast().as_ptr(),
+                bindings::skb_drop_reason_SKB_DROP_REASON_NOT_SPECIFIED,
+            )
+        };
+    }
+}
+
+/// An IPv4 address.
+///
+/// This is equivalent to C's `in_addr`.
+#[repr(transparent)]
+pub struct Ipv4Addr(bindings::in_addr);
+
+impl Ipv4Addr {
+    /// A wildcard IPv4 address.
+    ///
+    /// Binding to this address means binding to all IPv4 addresses.
+    pub const ANY: Self = Self::new(0, 0, 0, 0);
+
+    /// The IPv4 loopback address.
+    pub const LOOPBACK: Self = Self::new(127, 0, 0, 1);
+
+    /// The IPv4 broadcast address.
+    pub const BROADCAST: Self = Self::new(255, 255, 255, 255);
+
+    /// Creates a new IPv4 address with the given components.
+    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
+        Self(bindings::in_addr {
+            s_addr: u32::from_be_bytes([a, b, c, d]).to_be(),
+        })
+    }
+}
+
+/// An IPv6 address.
+///
+/// This is equivalent to C's `in6_addr`.
+#[repr(transparent)]
+pub struct Ipv6Addr(bindings::in6_addr);
+
+impl Ipv6Addr {
+    /// A wildcard IPv6 address.
+    ///
+    /// Binding to this address means binding to all IPv6 addresses.
+    pub const ANY: Self = Self::new(0, 0, 0, 0, 0, 0, 0, 0);
+
+    /// The IPv6 loopback address.
+    pub const LOOPBACK: Self = Self::new(0, 0, 0, 0, 0, 0, 0, 1);
+
+    /// Creates a new IPv6 address with the given components.
+    #[allow(clippy::too_many_arguments)]
+    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Self {
+        Self(bindings::in6_addr {
+            in6_u: bindings::in6_addr__bindgen_ty_1 {
+                u6_addr16: [
+                    a.to_be(),
+                    b.to_be(),
+                    c.to_be(),
+                    d.to_be(),
+                    e.to_be(),
+                    f.to_be(),
+                    g.to_be(),
+                    h.to_be(),
+                ],
+            },
+        })
+    }
+}
+
+/// A socket address.
+///
+/// It's an enum with either an IPv4 or IPv6 socket address.
+pub enum SocketAddr {
+    /// An IPv4 socket address.
+    V4(SocketAddrV4),
+
+    /// An IPv6 socket address.
+    V6(SocketAddrV6),
+}
+
+/// An IPv4 socket address.
+///
+/// This is equivalent to C's `sockaddr_in`.
+#[repr(transparent)]
+pub struct SocketAddrV4(bindings::sockaddr_in);
+
+impl SocketAddrV4 {
+    /// Creates a new IPv4 socket address.
+    pub const fn new(addr: Ipv4Addr, port: u16) -> Self {
+        Self(bindings::sockaddr_in {
+            sin_family: bindings::AF_INET as _,
+            sin_port: port.to_be(),
+            sin_addr: addr.0,
+            __pad: [0; 8],
+        })
+    }
+}
+
+/// An IPv6 socket address.
+///
+/// This is equivalent to C's `sockaddr_in6`.
+#[repr(transparent)]
+pub struct SocketAddrV6(bindings::sockaddr_in6);
+
+impl SocketAddrV6 {
+    /// Creates a new IPv6 socket address.
+    pub const fn new(addr: Ipv6Addr, port: u16, flowinfo: u32, scopeid: u32) -> Self {
+        Self(bindings::sockaddr_in6 {
+            sin6_family: bindings::AF_INET6 as _,
+            sin6_port: port.to_be(),
+            sin6_addr: addr.0,
+            sin6_flowinfo: flowinfo,
+            sin6_scope_id: scopeid,
+        })
+    }
+}
+
+/// A socket listening on a TCP port.
+///
+/// # Invariants
+///
+/// The socket pointer is always non-null and valid.
+pub struct TcpListener {
+    pub(crate) sock: *mut bindings::socket,
+}
+
+// SAFETY: `TcpListener` is just a wrapper for a kernel socket, which can be used from any thread.
+unsafe impl Send for TcpListener {}
+
+// SAFETY: `TcpListener` is just a wrapper for a kernel socket, which can be used from any thread.
+unsafe impl Sync for TcpListener {}
+
+impl TcpListener {
+    /// Creates a new TCP listener.
+    ///
+    /// It is configured to listen on the given socket address for the given namespace.
+    pub fn try_new(ns: &Namespace, addr: &SocketAddr) -> Result<Self> {
+        let mut socket = core::ptr::null_mut();
+        let (pf, addr, addrlen) = match addr {
+            SocketAddr::V4(addr) => (
+                bindings::PF_INET,
+                addr as *const _ as _,
+                core::mem::size_of::<bindings::sockaddr_in>(),
+            ),
+            SocketAddr::V6(addr) => (
+                bindings::PF_INET6,
+                addr as *const _ as _,
+                core::mem::size_of::<bindings::sockaddr_in6>(),
+            ),
+        };
+
+        // SAFETY: The namespace is valid and the output socket pointer is valid for write.
+        to_result(unsafe {
+            bindings::sock_create_kern(
+                ns.0.get(),
+                pf as _,
+                bindings::sock_type_SOCK_STREAM as _,
+                bindings::IPPROTO_TCP as _,
+                &mut socket,
+            )
+        })?;
+
+        // INVARIANT: The socket was just created, so it is valid.
+        let listener = Self { sock: socket };
+
+        // SAFETY: The type invariant guarantees that the socket is valid, and `addr` and `addrlen`
+        // were initialised based on valid values provided in the address enum.
+        to_result(unsafe { bindings::kernel_bind(socket, addr, addrlen as _) })?;
+
+        // SAFETY: The socket is valid per the type invariant.
+        to_result(unsafe { bindings::kernel_listen(socket, bindings::SOMAXCONN as _) })?;
+
+        Ok(listener)
+    }
+
+    /// Accepts a new connection.
+    ///
+    /// On success, returns the newly-accepted socket stream.
+    ///
+    /// If no connection is available to be accepted, one of two behaviours will occur:
+    /// - If `block` is `false`, returns [`crate::error::code::EAGAIN`];
+    /// - If `block` is `true`, blocks until an error occurs or some connection can be accepted.
+    pub fn accept(&self, block: bool) -> Result<TcpStream> {
+        let mut new = core::ptr::null_mut();
+        let flags = if block { 0 } else { bindings::O_NONBLOCK };
+        // SAFETY: The type invariant guarantees that the socket is valid, and the output argument
+        // is also valid for write.
+        to_result(unsafe { bindings::kernel_accept(self.sock, &mut new, flags as _) })?;
+        Ok(TcpStream { sock: new })
+    }
+}
+
+impl Drop for TcpListener {
+    fn drop(&mut self) {
+        // SAFETY: The type invariant guarantees that the socket is valid.
+        unsafe { bindings::sock_release(self.sock) };
+    }
+}
+
+/// A connected TCP socket.
+///
+/// # Invariants
+///
+/// The socket pointer is always non-null and valid.
+pub struct TcpStream {
+    pub(crate) sock: *mut bindings::socket,
+}
+
+// SAFETY: `TcpStream` is just a wrapper for a kernel socket, which can be used from any thread.
+unsafe impl Send for TcpStream {}
+
+// SAFETY: `TcpStream` is just a wrapper for a kernel socket, which can be used from any thread.
+unsafe impl Sync for TcpStream {}
+
+impl TcpStream {
+    /// Reads data from a connected socket.
+    ///
+    /// On success, returns the number of bytes read, which will be zero if the connection is
+    /// closed.
+    ///
+    /// If no data is immediately available for reading, one of two behaviours will occur:
+    /// - If `block` is `false`, returns [`crate::error::code::EAGAIN`];
+    /// - If `block` is `true`, blocks until an error occurs, the connection is closed, or some
+    ///   becomes readable.
+    pub fn read(&self, buf: &mut [u8], block: bool) -> Result<usize> {
+        let mut msg = bindings::msghdr::default();
+        let mut vec = bindings::kvec {
+            iov_base: buf.as_mut_ptr().cast(),
+            iov_len: buf.len(),
+        };
+        // SAFETY: The type invariant guarantees that the socket is valid, and `vec` was
+        // initialised with the output buffer.
+        let r = unsafe {
+            bindings::kernel_recvmsg(
+                self.sock,
+                &mut msg,
+                &mut vec,
+                1,
+                vec.iov_len,
+                if block { 0 } else { bindings::MSG_DONTWAIT } as _,
+            )
+        };
+        if r < 0 {
+            Err(Error::from_kernel_errno(r))
+        } else {
+            Ok(r as _)
+        }
+    }
+
+    /// Writes data to the connected socket.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// If the send buffer of the socket is full, one of two behaviours will occur:
+    /// - If `block` is `false`, returns [`crate::error::code::EAGAIN`];
+    /// - If `block` is `true`, blocks until an error occurs or some data is written.
+    pub fn write(&self, buf: &[u8], block: bool) -> Result<usize> {
+        let mut msg = bindings::msghdr {
+            msg_flags: if block { 0 } else { bindings::MSG_DONTWAIT },
+            ..bindings::msghdr::default()
+        };
+        let mut vec = bindings::kvec {
+            iov_base: buf.as_ptr() as *mut u8 as _,
+            iov_len: buf.len(),
+        };
+        // SAFETY: The type invariant guarantees that the socket is valid, and `vec` was
+        // initialised with the input  buffer.
+        let r = unsafe { bindings::kernel_sendmsg(self.sock, &mut msg, &mut vec, 1, vec.iov_len) };
+        if r < 0 {
+            Err(Error::from_kernel_errno(r))
+        } else {
+            Ok(r as _)
+        }
+    }
+}
+
+impl Drop for TcpStream {
+    fn drop(&mut self) {
+        // SAFETY: The type invariant guarantees that the socket is valid.
+        unsafe { bindings::sock_release(self.sock) };
+    }
+}
diff --git a/rust/kernel/net/filter.rs b/rust/kernel/net/filter.rs
new file mode 100644
index 000000000000..a50422d53848
--- /dev/null
+++ b/rust/kernel/net/filter.rs
@@ -0,0 +1,447 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Networking filters.
+//!
+//! C header: [`include/linux/netfilter.h`](../../../../../include/linux/netfilter.h)
+
+use crate::{
+    bindings,
+    error::{code::*, to_result},
+    net,
+    types::PointerWrapper,
+    ARef, AlwaysRefCounted, Result, ScopeGuard,
+};
+use alloc::boxed::Box;
+use core::{
+    marker::{PhantomData, PhantomPinned},
+    pin::Pin,
+};
+
+/// A network filter.
+pub trait Filter {
+    /// The type of the context data stored on registration and made available to the
+    /// [`Filter::filter`] function.
+    type Data: PointerWrapper + Sync = ();
+
+    /// Filters the packet stored in the given buffer.
+    ///
+    /// It dictates to the netfilter core what the fate of the packet should be.
+    fn filter(
+        _data: <Self::Data as PointerWrapper>::Borrowed<'_>,
+        _skb: &net::SkBuff,
+    ) -> Disposition;
+}
+
+/// Specifies the action to be taken by the netfilter core.
+pub enum Disposition {
+    /// Drop the packet.
+    Drop,
+
+    /// Accept the packet.
+    Accept,
+
+    /// The packet was stolen by the filter and must be treated as if it didn't exist.
+    Stolen,
+
+    /// Queue the packet to the given user-space queue.
+    Queue {
+        /// The identifier of the queue to which the packet should be added.
+        queue_id: u16,
+
+        /// Specifies the behaviour if a queue with the given identifier doesn't exist: if `true`,
+        /// the packet is accepted, otherwise it is rejected.
+        accept_if_queue_non_existent: bool,
+    },
+}
+
+/// The filter hook families.
+pub enum Family {
+    ///  IPv4 and IPv6 packets.
+    INet(inet::Hook),
+
+    /// IPv4 packets.
+    Ipv4(ipv4::Hook, ipv4::PriorityBase),
+
+    /// All packets through a device.
+    ///
+    /// When this family is used, a device _must_ be specified.
+    NetDev(netdev::Hook),
+
+    /// IPv6 packets.
+    Ipv6(ipv6::Hook, ipv6::PriorityBase),
+
+    /// Address resolution protocol (ARP) packets.
+    Arp(arp::Hook),
+}
+
+/// A registration of a networking filter.
+///
+/// # Examples
+///
+/// The following is an example of a function that attaches an inbound filter (that always accepts
+/// all packets after printing their lengths) on the specified device (in the `init` ns).
+///
+/// ```
+/// use kernel::net::{self, filter as netfilter};
+///
+/// struct MyFilter;
+/// impl netfilter::Filter for MyFilter {
+///     fn filter(_data: (), skb: &net::SkBuff) -> netfilter::Disposition {
+///         pr_info!("Packet of length {}\n", skb.len());
+///         netfilter::Disposition::Accept
+///     }
+/// }
+///
+/// fn register(name: &CStr) -> Result<Pin<Box<netfilter::Registration<MyFilter>>>> {
+///     let ns = net::init_ns();
+///     let dev = ns.dev_get_by_name(name).ok_or(ENOENT)?;
+///     netfilter::Registration::new_pinned(
+///         netfilter::Family::NetDev(netfilter::netdev::Hook::Ingress),
+///         0,
+///         ns.into(),
+///         Some(dev),
+///         (),
+///     )
+/// }
+/// ```
+#[derive(Default)]
+pub struct Registration<T: Filter> {
+    hook: bindings::nf_hook_ops,
+    // When `ns` is `Some(_)`, the hook is registered.
+    ns: Option<ARef<net::Namespace>>,
+    dev: Option<ARef<net::Device>>,
+    _p: PhantomData<T>,
+    _pinned: PhantomPinned,
+}
+
+// SAFETY: `Registration` does not expose any of its state across threads.
+unsafe impl<T: Filter> Sync for Registration<T> {}
+
+impl<T: Filter> Registration<T> {
+    /// Creates a new [`Registration`] but does not register it yet.
+    ///
+    /// It is allowed to move.
+    pub fn new() -> Self {
+        Self {
+            hook: bindings::nf_hook_ops::default(),
+            dev: None,
+            ns: None,
+            _p: PhantomData,
+            _pinned: PhantomPinned,
+        }
+    }
+
+    /// Creates a new filter registration and registers it.
+    ///
+    /// Returns a pinned heap-allocated representation of the registration.
+    pub fn new_pinned(
+        family: Family,
+        priority: i32,
+        ns: ARef<net::Namespace>,
+        dev: Option<ARef<net::Device>>,
+        data: T::Data,
+    ) -> Result<Pin<Box<Self>>> {
+        let mut filter = Pin::from(Box::try_new(Self::new())?);
+        filter.as_mut().register(family, priority, ns, dev, data)?;
+        Ok(filter)
+    }
+
+    /// Registers a network filter.
+    ///
+    /// It must be pinned because the C portion of the kernel stores a pointer to it while it is
+    /// registered.
+    ///
+    /// The priority is relative to the family's base priority. For example, if the base priority
+    /// is `100` and `priority` is `-1`, the actual priority will be `99`. If a family doesn't
+    /// explicitly allow a base to be specified, `0` is assumed.
+    pub fn register(
+        self: Pin<&mut Self>,
+        family: Family,
+        priority: i32,
+        ns: ARef<net::Namespace>,
+        dev: Option<ARef<net::Device>>,
+        data: T::Data,
+    ) -> Result {
+        // SAFETY: We must ensure that we never move out of `this`.
+        let this = unsafe { self.get_unchecked_mut() };
+        if this.ns.is_some() {
+            // Already registered.
+            return Err(EINVAL);
+        }
+
+        let data_pointer = data.into_pointer();
+
+        // SAFETY: `data_pointer` comes from the call to `data.into_pointer()` above.
+        let guard = ScopeGuard::new(|| unsafe {
+            T::Data::from_pointer(data_pointer);
+        });
+
+        let mut pri_base = 0i32;
+        match family {
+            Family::INet(hook) => {
+                this.hook.pf = bindings::NFPROTO_INET as _;
+                this.hook.hooknum = hook as _;
+            }
+            Family::Ipv4(hook, pbase) => {
+                this.hook.pf = bindings::NFPROTO_IPV4 as _;
+                this.hook.hooknum = hook as _;
+                pri_base = pbase as _;
+            }
+            Family::Ipv6(hook, pbase) => {
+                this.hook.pf = bindings::NFPROTO_IPV6 as _;
+                this.hook.hooknum = hook as _;
+                pri_base = pbase as _;
+            }
+            Family::NetDev(hook) => {
+                this.hook.pf = bindings::NFPROTO_NETDEV as _;
+                this.hook.hooknum = hook as _;
+            }
+            Family::Arp(hook) => {
+                this.hook.pf = bindings::NFPROTO_ARP as _;
+                this.hook.hooknum = hook as _;
+            }
+        }
+
+        this.hook.priority = pri_base.saturating_add(priority);
+        this.hook.priv_ = data_pointer as _;
+        this.hook.hook = Some(Self::hook_callback);
+        crate::static_assert!(bindings::nf_hook_ops_type_NF_HOOK_OP_UNDEFINED == 0);
+
+        if let Some(ref device) = dev {
+            this.hook.dev = device.0.get();
+        }
+
+        // SAFETY: `ns` has a valid reference to the namespace, and `this.hook` was just
+        // initialised above, so they're both valid.
+        to_result(unsafe { bindings::nf_register_net_hook(ns.0.get(), &this.hook) })?;
+
+        this.dev = dev;
+        this.ns = Some(ns);
+        guard.dismiss();
+        Ok(())
+    }
+
+    unsafe extern "C" fn hook_callback(
+        priv_: *mut core::ffi::c_void,
+        skb: *mut bindings::sk_buff,
+        _state: *const bindings::nf_hook_state,
+    ) -> core::ffi::c_uint {
+        // SAFETY: `priv_` was initialised on registration by a value returned from
+        // `T::Data::into_pointer`, and it remains valid until the hook is unregistered.
+        let data = unsafe { T::Data::borrow(priv_) };
+
+        // SAFETY: The C contract guarantees that `skb` remains valid for the duration of this
+        // function call.
+        match T::filter(data, unsafe { net::SkBuff::from_ptr(skb) }) {
+            Disposition::Drop => bindings::NF_DROP,
+            Disposition::Accept => bindings::NF_ACCEPT,
+            Disposition::Stolen => {
+                // SAFETY: This function takes over ownership of `skb` when it returns `NF_STOLEN`,
+                // so we decrement the refcount here to avoid a leak.
+                unsafe { net::SkBuff::dec_ref(core::ptr::NonNull::new(skb).unwrap().cast()) };
+                bindings::NF_STOLEN
+            }
+            Disposition::Queue {
+                queue_id,
+                accept_if_queue_non_existent,
+            } => {
+                // SAFETY: Just an FFI call, no additional safety requirements.
+                let verdict = unsafe { bindings::NF_QUEUE_NR(queue_id as _) };
+                if accept_if_queue_non_existent {
+                    verdict | bindings::NF_VERDICT_FLAG_QUEUE_BYPASS
+                } else {
+                    verdict
+                }
+            }
+        }
+    }
+}
+
+impl<T: Filter> Drop for Registration<T> {
+    fn drop(&mut self) {
+        if let Some(ref ns) = self.ns {
+            // SAFETY: `self.ns` is `Some(_)` only when a previous call to `nf_register_net_hook`
+            // succeeded. And the arguments are the same.
+            unsafe { bindings::nf_unregister_net_hook(ns.0.get(), &self.hook) };
+
+            // `self.hook.priv_` was initialised during registration to a value returned from
+            // `T::Data::into_pointer`, so it is ok to convert back here.
+            unsafe { T::Data::from_pointer(self.hook.priv_) };
+        }
+    }
+}
+
+/// Definitions used when defining hooks for the [`Family::NetDev`] family.
+pub mod netdev {
+    use crate::bindings;
+
+    /// Hooks allowed in the [`super::Family::NetDev`] family.
+    #[repr(u32)]
+    pub enum Hook {
+        /// All inbound packets through the given device.
+        Ingress = bindings::nf_dev_hooks_NF_NETDEV_INGRESS,
+
+        /// All outbound packets through the given device.
+        Egress = bindings::nf_dev_hooks_NF_NETDEV_EGRESS,
+    }
+}
+
+/// Definitions used when defining hooks for the [`Family::Ipv4`] family.
+pub mod ipv4 {
+    use crate::bindings;
+
+    /// Hooks allowed in [`super::Family::Ipv4`] family.
+    pub type Hook = super::inet::Hook;
+
+    /// The base priority for [`super::Family::Ipv4`] hooks.
+    ///
+    /// The actual priority is the base priority plus the priority specified when registering.
+    #[repr(i32)]
+    pub enum PriorityBase {
+        /// Same as the `NF_IP_PRI_FIRST` C constant.
+        First = bindings::nf_ip_hook_priorities_NF_IP_PRI_FIRST,
+
+        /// Same as the `NF_IP_PRI_RAW_BEFORE_DEFRAG` C constant.
+        RawBeforeDefrag = bindings::nf_ip_hook_priorities_NF_IP_PRI_RAW_BEFORE_DEFRAG,
+
+        /// Same as the `NF_IP_PRI_CONNTRACK_DEFRAG` C constant.
+        ConnTrackDefrag = bindings::nf_ip_hook_priorities_NF_IP_PRI_CONNTRACK_DEFRAG,
+
+        /// Same as the `NF_IP_PRI_RAW` C constant.
+        Raw = bindings::nf_ip_hook_priorities_NF_IP_PRI_RAW,
+
+        /// Same as the `NF_IP_PRI_SELINUX_FIRST` C constant.
+        SeLinuxFirst = bindings::nf_ip_hook_priorities_NF_IP_PRI_SELINUX_FIRST,
+
+        /// Same as the `NF_IP_PRI_CONNTRACK` C constant.
+        ConnTrack = bindings::nf_ip_hook_priorities_NF_IP_PRI_CONNTRACK,
+
+        /// Same as the `NF_IP_PRI_MANGLE` C constant.
+        Mangle = bindings::nf_ip_hook_priorities_NF_IP_PRI_MANGLE,
+
+        /// Same as the `NF_IP_PRI_NAT_DST` C constant.
+        NatDst = bindings::nf_ip_hook_priorities_NF_IP_PRI_NAT_DST,
+
+        /// Same as the `NF_IP_PRI_FILTER` C constant.
+        Filter = bindings::nf_ip_hook_priorities_NF_IP_PRI_FILTER,
+
+        /// Same as the `NF_IP_PRI_SECURITY` C constant.
+        Security = bindings::nf_ip_hook_priorities_NF_IP_PRI_SECURITY,
+
+        /// Same as the `NF_IP_PRI_NAT_SRC` C constant.
+        NatSrc = bindings::nf_ip_hook_priorities_NF_IP_PRI_NAT_SRC,
+
+        /// Same as the `NF_IP_PRI_SELINUX_LAST` C constant.
+        SeLinuxLast = bindings::nf_ip_hook_priorities_NF_IP_PRI_SELINUX_LAST,
+
+        /// Same as the `NF_IP_PRI_CONNTRACK_HELPER` C constant.
+        ConnTrackHelper = bindings::nf_ip_hook_priorities_NF_IP_PRI_CONNTRACK_HELPER,
+
+        /// Same as the `NF_IP_PRI_LAST` and `NF_IP_PRI_CONNTRACK_CONFIRM` C constants.
+        Last = bindings::nf_ip_hook_priorities_NF_IP_PRI_LAST,
+    }
+}
+
+/// Definitions used when defining hooks for the [`Family::Ipv6`] family.
+pub mod ipv6 {
+    use crate::bindings;
+
+    /// Hooks allowed in [`super::Family::Ipv6`] family.
+    pub type Hook = super::inet::Hook;
+
+    /// The base priority for [`super::Family::Ipv6`] hooks.
+    ///
+    /// The actual priority is the base priority plus the priority specified when registering.
+    #[repr(i32)]
+    pub enum PriorityBase {
+        /// Same as the `NF_IP6_PRI_FIRST` C constant.
+        First = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_FIRST,
+
+        /// Same as the `NF_IP6_PRI_RAW_BEFORE_DEFRAG` C constant.
+        RawBeforeDefrag = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_RAW_BEFORE_DEFRAG,
+
+        /// Same as the `NF_IP6_PRI_CONNTRACK_DEFRAG` C constant.
+        ConnTrackDefrag = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_CONNTRACK_DEFRAG,
+
+        /// Same as the `NF_IP6_PRI_RAW` C constant.
+        Raw = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_RAW,
+
+        /// Same as the `NF_IP6_PRI_SELINUX_FIRST` C constant.
+        SeLinuxFirst = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_SELINUX_FIRST,
+
+        /// Same as the `NF_IP6_PRI_CONNTRACK` C constant.
+        ConnTrack = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_CONNTRACK,
+
+        /// Same as the `NF_IP6_PRI_MANGLE` C constant.
+        Mangle = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_MANGLE,
+
+        /// Same as the `NF_IP6_PRI_NAT_DST` C constant.
+        NatDst = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_NAT_DST,
+
+        /// Same as the `NF_IP6_PRI_FILTER` C constant.
+        Filter = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_FILTER,
+
+        /// Same as the `NF_IP6_PRI_SECURITY` C constant.
+        Security = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_SECURITY,
+
+        /// Same as the `NF_IP6_PRI_NAT_SRC` C constant.
+        NatSrc = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_NAT_SRC,
+
+        /// Same as the `NF_IP6_PRI_SELINUX_LAST` C constant.
+        SeLinuxLast = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_SELINUX_LAST,
+
+        /// Same as the `NF_IP6_PRI_CONNTRACK_HELPER` C constant.
+        ConnTrackHelper = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_CONNTRACK_HELPER,
+
+        /// Same as the `NF_IP6_PRI_LAST` C constant.
+        Last = bindings::nf_ip6_hook_priorities_NF_IP6_PRI_LAST,
+    }
+}
+
+/// Definitions used when defining hooks for the [`Family::Arp`] family.
+pub mod arp {
+    use crate::bindings;
+
+    /// Hooks allowed in the [`super::Family::Arp`] family.
+    #[repr(u32)]
+    pub enum Hook {
+        /// Inbound ARP packets.
+        In = bindings::NF_ARP_IN,
+
+        /// Outbound ARP packets.
+        Out = bindings::NF_ARP_OUT,
+
+        /// Forwarded ARP packets.
+        Forward = bindings::NF_ARP_FORWARD,
+    }
+}
+
+/// Definitions used when defining hooks for the [`Family::INet`] family.
+pub mod inet {
+    use crate::bindings;
+
+    /// Hooks allowed in the [`super::Family::INet`], [`super::Family::Ipv4`], and
+    /// [`super::Family::Ipv6`] families.
+    #[repr(u32)]
+    pub enum Hook {
+        /// Inbound packets before routing decisions are made (i.e., before it's determined if the
+        /// packet is to be delivered locally or forwarded to another host).
+        PreRouting = bindings::nf_inet_hooks_NF_INET_PRE_ROUTING as _,
+
+        /// Inbound packets that are meant to be delivered locally.
+        LocalIn = bindings::nf_inet_hooks_NF_INET_LOCAL_IN as _,
+
+        /// Inbound packets that are meant to be forwarded to another host.
+        Forward = bindings::nf_inet_hooks_NF_INET_FORWARD as _,
+
+        /// Outbound packet created by the local networking stack.
+        LocalOut = bindings::nf_inet_hooks_NF_INET_LOCAL_OUT as _,
+
+        /// All outbound packets (i.e., generated locally or being forwarded to another host).
+        PostRouting = bindings::nf_inet_hooks_NF_INET_POST_ROUTING as _,
+
+        /// Equivalent to [`super::netdev::Hook::Ingress`], so a device must be specified. Packets
+        /// of all types (not just ipv4/ipv6) will be delivered to the filter.
+        Ingress = bindings::nf_inet_hooks_NF_INET_INGRESS as _,
+    }
+}
diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs
new file mode 100644
index 000000000000..cdcd83244337
--- /dev/null
+++ b/rust/kernel/of.rs
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Devicetree and Open Firmware abstractions.
+//!
+//! C header: [`include/linux/of_*.h`](../../../../include/linux/of_*.h)
+
+use crate::{bindings, driver, str::BStr};
+
+/// An open firmware device id.
+#[derive(Clone, Copy)]
+pub enum DeviceId {
+    /// An open firmware device id where only a compatible string is specified.
+    Compatible(&'static BStr),
+}
+
+/// Defines a const open firmware device id table that also carries per-entry data/context/info.
+///
+/// The name of the const is `OF_DEVICE_ID_TABLE`, which is what buses are expected to name their
+/// open firmware tables.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::define_of_id_table;
+/// use kernel::of;
+///
+/// define_of_id_table! {u32, [
+///     (of::DeviceId::Compatible(b"test-device1,test-device2"), Some(0xff)),
+///     (of::DeviceId::Compatible(b"test-device3"), None),
+/// ]};
+/// ```
+#[macro_export]
+macro_rules! define_of_id_table {
+    ($data_type:ty, $($t:tt)*) => {
+        $crate::define_id_table!(OF_DEVICE_ID_TABLE, $crate::of::DeviceId, $data_type, $($t)*);
+    };
+}
+
+// SAFETY: `ZERO` is all zeroed-out and `to_rawid` stores `offset` in `of_device_id::data`.
+unsafe impl const driver::RawDeviceId for DeviceId {
+    type RawType = bindings::of_device_id;
+    const ZERO: Self::RawType = bindings::of_device_id {
+        name: [0; 32],
+        type_: [0; 32],
+        compatible: [0; 128],
+        data: core::ptr::null(),
+    };
+
+    fn to_rawid(&self, offset: isize) -> Self::RawType {
+        let DeviceId::Compatible(compatible) = self;
+        let mut id = Self::ZERO;
+        let mut i = 0;
+        while i < compatible.len() {
+            // If `compatible` does not fit in `id.compatible`, an "index out of bounds" build time
+            // error will be triggered.
+            id.compatible[i] = compatible[i] as _;
+            i += 1;
+        }
+        id.compatible[i] = b'\0' as _;
+        id.data = offset as _;
+        id
+    }
+}
diff --git a/rust/kernel/pages.rs b/rust/kernel/pages.rs
new file mode 100644
index 000000000000..f2bb26810cd7
--- /dev/null
+++ b/rust/kernel/pages.rs
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Kernel page allocation and management.
+//!
+//! TODO: This module is a work in progress.
+
+use crate::{
+    bindings, error::code::*, io_buffer::IoBufferReader, user_ptr::UserSlicePtrReader, Result,
+    PAGE_SIZE,
+};
+use core::{marker::PhantomData, ptr};
+
+/// A set of physical pages.
+///
+/// `Pages` holds a reference to a set of pages of order `ORDER`. Having the order as a generic
+/// const allows the struct to have the same size as a pointer.
+///
+/// # Invariants
+///
+/// The pointer `Pages::pages` is valid and points to 2^ORDER pages.
+pub struct Pages<const ORDER: u32> {
+    pub(crate) pages: *mut bindings::page,
+}
+
+impl<const ORDER: u32> Pages<ORDER> {
+    /// Allocates a new set of contiguous pages.
+    pub fn new() -> Result<Self> {
+        // TODO: Consider whether we want to allow callers to specify flags.
+        // SAFETY: This only allocates pages. We check that it succeeds in the next statement.
+        let pages = unsafe {
+            bindings::alloc_pages(
+                bindings::GFP_KERNEL | bindings::__GFP_ZERO | bindings::__GFP_HIGHMEM,
+                ORDER,
+            )
+        };
+        if pages.is_null() {
+            return Err(ENOMEM);
+        }
+        // INVARIANTS: We checked that the allocation above succeeded.
+        Ok(Self { pages })
+    }
+
+    /// Copies data from the given [`UserSlicePtrReader`] into the pages.
+    pub fn copy_into_page(
+        &self,
+        reader: &mut UserSlicePtrReader,
+        offset: usize,
+        len: usize,
+    ) -> Result {
+        // TODO: For now this only works on the first page.
+        let end = offset.checked_add(len).ok_or(EINVAL)?;
+        if end > PAGE_SIZE {
+            return Err(EINVAL);
+        }
+
+        let mapping = self.kmap(0).ok_or(EINVAL)?;
+
+        // SAFETY: We ensured that the buffer was valid with the check above.
+        unsafe { reader.read_raw((mapping.ptr as usize + offset) as _, len) }?;
+        Ok(())
+    }
+
+    /// Maps the pages and reads from them into the given buffer.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that the destination buffer is valid for the given length.
+    /// Additionally, if the raw buffer is intended to be recast, they must ensure that the data
+    /// can be safely cast; [`crate::io_buffer::ReadableFromBytes`] has more details about it.
+    pub unsafe fn read(&self, dest: *mut u8, offset: usize, len: usize) -> Result {
+        // TODO: For now this only works on the first page.
+        let end = offset.checked_add(len).ok_or(EINVAL)?;
+        if end > PAGE_SIZE {
+            return Err(EINVAL);
+        }
+
+        let mapping = self.kmap(0).ok_or(EINVAL)?;
+        unsafe { ptr::copy((mapping.ptr as *mut u8).add(offset), dest, len) };
+        Ok(())
+    }
+
+    /// Maps the pages and writes into them from the given buffer.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that the buffer is valid for the given length. Additionally, if the
+    /// page is (or will be) mapped by userspace, they must ensure that no kernel data is leaked
+    /// through padding if it was cast from another type; [`crate::io_buffer::WritableToBytes`] has
+    /// more details about it.
+    pub unsafe fn write(&self, src: *const u8, offset: usize, len: usize) -> Result {
+        // TODO: For now this only works on the first page.
+        let end = offset.checked_add(len).ok_or(EINVAL)?;
+        if end > PAGE_SIZE {
+            return Err(EINVAL);
+        }
+
+        let mapping = self.kmap(0).ok_or(EINVAL)?;
+        unsafe { ptr::copy(src, (mapping.ptr as *mut u8).add(offset), len) };
+        Ok(())
+    }
+
+    /// Maps the page at index `index`.
+    fn kmap(&self, index: usize) -> Option<PageMapping<'_>> {
+        if index >= 1usize << ORDER {
+            return None;
+        }
+
+        // SAFETY: We checked above that `index` is within range.
+        let page = unsafe { self.pages.add(index) };
+
+        // SAFETY: `page` is valid based on the checks above.
+        let ptr = unsafe { bindings::kmap(page) };
+        if ptr.is_null() {
+            return None;
+        }
+
+        Some(PageMapping {
+            page,
+            ptr,
+            _phantom: PhantomData,
+        })
+    }
+}
+
+impl<const ORDER: u32> Drop for Pages<ORDER> {
+    fn drop(&mut self) {
+        // SAFETY: By the type invariants, we know the pages are allocated with the given order.
+        unsafe { bindings::__free_pages(self.pages, ORDER) };
+    }
+}
+
+struct PageMapping<'a> {
+    page: *mut bindings::page,
+    ptr: *mut core::ffi::c_void,
+    _phantom: PhantomData<&'a i32>,
+}
+
+impl Drop for PageMapping<'_> {
+    fn drop(&mut self) {
+        // SAFETY: An instance of `PageMapping` is created only when `kmap` succeeded for the given
+        // page, so it is safe to unmap it here.
+        unsafe { bindings::kunmap(self.page) };
+    }
+}
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
new file mode 100644
index 000000000000..d8cc0e0120aa
--- /dev/null
+++ b/rust/kernel/platform.rs
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Platform devices and drivers.
+//!
+//! Also called `platdev`, `pdev`.
+//!
+//! C header: [`include/linux/platform_device.h`](../../../../include/linux/platform_device.h)
+
+use crate::{
+    bindings,
+    device::{self, RawDevice},
+    driver,
+    error::{from_kernel_result, Result},
+    of,
+    str::CStr,
+    to_result,
+    types::PointerWrapper,
+    ThisModule,
+};
+
+/// A registration of a platform driver.
+pub type Registration<T> = driver::Registration<Adapter<T>>;
+
+/// An adapter for the registration of platform drivers.
+pub struct Adapter<T: Driver>(T);
+
+impl<T: Driver> driver::DriverOps for Adapter<T> {
+    type RegType = bindings::platform_driver;
+
+    unsafe fn register(
+        reg: *mut bindings::platform_driver,
+        name: &'static CStr,
+        module: &'static ThisModule,
+    ) -> Result {
+        // SAFETY: By the safety requirements of this function (defined in the trait definition),
+        // `reg` is non-null and valid.
+        let pdrv = unsafe { &mut *reg };
+
+        pdrv.driver.name = name.as_char_ptr();
+        pdrv.probe = Some(Self::probe_callback);
+        pdrv.remove = Some(Self::remove_callback);
+        if let Some(t) = T::OF_DEVICE_ID_TABLE {
+            pdrv.driver.of_match_table = t.as_ref();
+        }
+        // SAFETY:
+        //   - `pdrv` lives at least until the call to `platform_driver_unregister()` returns.
+        //   - `name` pointer has static lifetime.
+        //   - `module.0` lives at least as long as the module.
+        //   - `probe()` and `remove()` are static functions.
+        //   - `of_match_table` is either a raw pointer with static lifetime,
+        //      as guaranteed by the [`driver::IdTable`] type, or null.
+        to_result(unsafe { bindings::__platform_driver_register(reg, module.0) })
+    }
+
+    unsafe fn unregister(reg: *mut bindings::platform_driver) {
+        // SAFETY: By the safety requirements of this function (defined in the trait definition),
+        // `reg` was passed (and updated) by a previous successful call to
+        // `platform_driver_register`.
+        unsafe { bindings::platform_driver_unregister(reg) };
+    }
+}
+
+impl<T: Driver> Adapter<T> {
+    fn get_id_info(dev: &Device) -> Option<&'static T::IdInfo> {
+        let table = T::OF_DEVICE_ID_TABLE?;
+
+        // SAFETY: `table` has static lifetime, so it is valid for read. `dev` is guaranteed to be
+        // valid while it's alive, so is the raw device returned by it.
+        let id = unsafe { bindings::of_match_device(table.as_ref(), dev.raw_device()) };
+        if id.is_null() {
+            return None;
+        }
+
+        // SAFETY: `id` is a pointer within the static table, so it's always valid.
+        let offset = unsafe { (*id).data };
+        if offset.is_null() {
+            return None;
+        }
+
+        // SAFETY: The offset comes from a previous call to `offset_from` in `IdArray::new`, which
+        // guarantees that the resulting pointer is within the table.
+        let ptr = unsafe {
+            id.cast::<u8>()
+                .offset(offset as _)
+                .cast::<Option<T::IdInfo>>()
+        };
+
+        // SAFETY: The id table has a static lifetime, so `ptr` is guaranteed to be valid for read.
+        unsafe { (&*ptr).as_ref() }
+    }
+
+    extern "C" fn probe_callback(pdev: *mut bindings::platform_device) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: `pdev` is valid by the contract with the C code. `dev` is alive only for the
+            // duration of this call, so it is guaranteed to remain alive for the lifetime of
+            // `pdev`.
+            let mut dev = unsafe { Device::from_ptr(pdev) };
+            let info = Self::get_id_info(&dev);
+            let data = T::probe(&mut dev, info)?;
+            // SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
+            unsafe { bindings::platform_set_drvdata(pdev, data.into_pointer() as _) };
+            Ok(0)
+        }
+    }
+
+    extern "C" fn remove_callback(pdev: *mut bindings::platform_device) -> core::ffi::c_int {
+        from_kernel_result! {
+            // SAFETY: `pdev` is guaranteed to be a valid, non-null pointer.
+            let ptr = unsafe { bindings::platform_get_drvdata(pdev) };
+            // SAFETY:
+            //   - we allocated this pointer using `T::Data::into_pointer`,
+            //     so it is safe to turn back into a `T::Data`.
+            //   - the allocation happened in `probe`, no-one freed the memory,
+            //     `remove` is the canonical kernel location to free driver data. so OK
+            //     to convert the pointer back to a Rust structure here.
+            let data = unsafe { T::Data::from_pointer(ptr) };
+            let ret = T::remove(&data);
+            <T::Data as driver::DeviceRemoval>::device_remove(&data);
+            ret?;
+            Ok(0)
+        }
+    }
+}
+
+/// A platform driver.
+pub trait Driver {
+    /// Data stored on device by driver.
+    ///
+    /// Corresponds to the data set or retrieved via the kernel's
+    /// `platform_{set,get}_drvdata()` functions.
+    ///
+    /// Require that `Data` implements `PointerWrapper`. We guarantee to
+    /// never move the underlying wrapped data structure. This allows
+    type Data: PointerWrapper + Send + Sync + driver::DeviceRemoval = ();
+
+    /// The type holding information about each device id supported by the driver.
+    type IdInfo: 'static = ();
+
+    /// The table of device ids supported by the driver.
+    const OF_DEVICE_ID_TABLE: Option<driver::IdTable<'static, of::DeviceId, Self::IdInfo>> = None;
+
+    /// Platform driver probe.
+    ///
+    /// Called when a new platform device is added or discovered.
+    /// Implementers should attempt to initialize the device here.
+    fn probe(dev: &mut Device, id_info: Option<&Self::IdInfo>) -> Result<Self::Data>;
+
+    /// Platform driver remove.
+    ///
+    /// Called when a platform device is removed.
+    /// Implementers should prepare the device for complete removal here.
+    fn remove(_data: &Self::Data) -> Result {
+        Ok(())
+    }
+}
+
+/// A platform device.
+///
+/// # Invariants
+///
+/// The field `ptr` is non-null and valid for the lifetime of the object.
+pub struct Device {
+    ptr: *mut bindings::platform_device,
+}
+
+impl Device {
+    /// Creates a new device from the given pointer.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be non-null and valid. It must remain valid for the lifetime of the returned
+    /// instance.
+    unsafe fn from_ptr(ptr: *mut bindings::platform_device) -> Self {
+        // INVARIANT: The safety requirements of the function ensure the lifetime invariant.
+        Self { ptr }
+    }
+
+    /// Returns id of the platform device.
+    pub fn id(&self) -> i32 {
+        // SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
+        unsafe { (*self.ptr).id }
+    }
+}
+
+// SAFETY: The device returned by `raw_device` is the raw platform device.
+unsafe impl device::RawDevice for Device {
+    fn raw_device(&self) -> *mut bindings::device {
+        // SAFETY: By the type invariants, we know that `self.ptr` is non-null and valid.
+        unsafe { &mut (*self.ptr).dev }
+    }
+}
+
+/// Declares a kernel module that exposes a single platform driver.
+///
+/// # Examples
+///
+/// ```ignore
+/// # use kernel::{platform, define_of_id_table, module_platform_driver};
+/// #
+/// struct MyDriver;
+/// impl platform::Driver for MyDriver {
+///     // [...]
+/// #   fn probe(_dev: &mut platform::Device, _id_info: Option<&Self::IdInfo>) -> Result {
+/// #       Ok(())
+/// #   }
+/// #   define_of_id_table! {(), [
+/// #       (of::DeviceId::Compatible(b"brcm,bcm2835-rng"), None),
+/// #   ]}
+/// }
+///
+/// module_platform_driver! {
+///     type: MyDriver,
+///     name: b"module_name",
+///     author: b"Author name",
+///     license: b"GPL",
+/// }
+/// ```
+#[macro_export]
+macro_rules! module_platform_driver {
+    ($($f:tt)*) => {
+        $crate::module_driver!(<T>, $crate::platform::Adapter<T>, { $($f)* });
+    };
+}
diff --git a/rust/kernel/power.rs b/rust/kernel/power.rs
new file mode 100644
index 000000000000..ef788557b269
--- /dev/null
+++ b/rust/kernel/power.rs
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Power management interfaces.
+//!
+//! C header: [`include/linux/pm.h`](../../../../include/linux/pm.h)
+
+#![allow(dead_code)]
+
+use crate::{bindings, error::from_kernel_result, types::PointerWrapper, Result};
+use core::marker::PhantomData;
+
+/// Corresponds to the kernel's `struct dev_pm_ops`.
+///
+/// It is meant to be implemented by drivers that support power-management operations.
+pub trait Operations {
+    /// The type of the context data stored by the driver on each device.
+    type Data: PointerWrapper + Sync + Send;
+
+    /// Called before the system goes into a sleep state.
+    fn suspend(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
+        Ok(())
+    }
+
+    /// Called after the system comes back from a sleep state.
+    fn resume(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
+        Ok(())
+    }
+
+    /// Called before creating a hibernation image.
+    fn freeze(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
+        Ok(())
+    }
+
+    /// Called after the system is restored from a hibernation image.
+    fn restore(_data: <Self::Data as PointerWrapper>::Borrowed<'_>) -> Result {
+        Ok(())
+    }
+}
+
+macro_rules! pm_callback {
+    ($callback:ident, $method:ident) => {
+        unsafe extern "C" fn $callback<T: Operations>(
+            dev: *mut bindings::device,
+        ) -> core::ffi::c_int {
+            from_kernel_result! {
+                // SAFETY: `dev` is valid as it was passed in by the C portion.
+                let ptr = unsafe { bindings::dev_get_drvdata(dev) };
+                // SAFETY: By the safety requirements of `OpsTable::build`, we know that `ptr` came
+                // from a previous call to `T::Data::into_pointer`.
+                let data = unsafe { T::Data::borrow(ptr) };
+                T::$method(data)?;
+                Ok(0)
+            }
+        }
+    };
+}
+
+pm_callback!(suspend_callback, suspend);
+pm_callback!(resume_callback, resume);
+pm_callback!(freeze_callback, freeze);
+pm_callback!(restore_callback, restore);
+
+pub(crate) struct OpsTable<T: Operations>(PhantomData<*const T>);
+
+impl<T: Operations> OpsTable<T> {
+    const VTABLE: bindings::dev_pm_ops = bindings::dev_pm_ops {
+        prepare: None,
+        complete: None,
+        suspend: Some(suspend_callback::<T>),
+        resume: Some(resume_callback::<T>),
+        freeze: Some(freeze_callback::<T>),
+        thaw: None,
+        poweroff: None,
+        restore: Some(restore_callback::<T>),
+        suspend_late: None,
+        resume_early: None,
+        freeze_late: None,
+        thaw_early: None,
+        poweroff_late: None,
+        restore_early: None,
+        suspend_noirq: None,
+        resume_noirq: None,
+        freeze_noirq: None,
+        thaw_noirq: None,
+        poweroff_noirq: None,
+        restore_noirq: None,
+        runtime_suspend: None,
+        runtime_resume: None,
+        runtime_idle: None,
+    };
+
+    /// Builds an instance of `struct dev_pm_ops`.
+    ///
+    /// # Safety
+    ///
+    /// The caller must ensure that `dev_get_drvdata` will result in a value returned by
+    /// [`T::Data::into_pointer`].
+    pub(crate) const unsafe fn build() -> &'static bindings::dev_pm_ops {
+        &Self::VTABLE
+    }
+}
+
+/// Implements the [`Operations`] trait as no-ops.
+///
+/// This is useful when one doesn't want to provide the implementation of any power-manager related
+/// operation.
+pub struct NoOperations<T: PointerWrapper>(PhantomData<T>);
+
+impl<T: PointerWrapper + Send + Sync> Operations for NoOperations<T> {
+    type Data = T;
+}
+
+// SAFETY: `NoOperation` provides no functionality, it is safe to send a reference to it to
+// different threads.
+unsafe impl<T: PointerWrapper> Sync for NoOperations<T> {}
+
+// SAFETY: `NoOperation` provides no functionality, it is safe to send it to different threads.
+unsafe impl<T: PointerWrapper> Send for NoOperations<T> {}
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
new file mode 100644
index 000000000000..26f8af9e16ab
--- /dev/null
+++ b/rust/kernel/prelude.rs
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! The `kernel` prelude.
+//!
+//! These are the most common items used by Rust code in the kernel,
+//! intended to be imported by all Rust code, for convenience.
+//!
+//! # Examples
+//!
+//! ```
+//! use kernel::prelude::*;
+//! ```
+
+pub use core::pin::Pin;
+
+pub use alloc::{boxed::Box, string::String, vec::Vec};
+
+pub use macros::{module, vtable};
+
+pub use super::build_assert;
+
+pub use super::{
+    dbg, dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn, fmt,
+    pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn,
+};
+
+pub use super::{module_fs, module_misc_device};
+
+#[cfg(CONFIG_ARM_AMBA)]
+pub use super::module_amba_driver;
+
+pub use super::static_assert;
+
+pub use super::{error::code::*, Error, Result};
+
+pub use super::{str::CStr, ARef, ThisModule};
diff --git a/rust/kernel/print.rs b/rust/kernel/print.rs
new file mode 100644
index 000000000000..92541efc7e22
--- /dev/null
+++ b/rust/kernel/print.rs
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Printing facilities.
+//!
+//! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h)
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/core-api/printk-basics.html>
+
+use core::{
+    ffi::{c_char, c_void},
+    fmt,
+};
+
+use crate::str::RawFormatter;
+
+#[cfg(CONFIG_PRINTK)]
+use crate::bindings;
+
+// Called from `vsprintf` with format specifier `%pA`.
+#[no_mangle]
+unsafe fn rust_fmt_argument(buf: *mut c_char, end: *mut c_char, ptr: *const c_void) -> *mut c_char {
+    use fmt::Write;
+    // SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`.
+    let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) };
+    let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) });
+    w.pos().cast()
+}
+
+/// Format strings.
+///
+/// Public but hidden since it should only be used from public macros.
+#[doc(hidden)]
+pub mod format_strings {
+    use crate::bindings;
+
+    /// The length we copy from the `KERN_*` kernel prefixes.
+    const LENGTH_PREFIX: usize = 2;
+
+    /// The length of the fixed format strings.
+    pub const LENGTH: usize = 10;
+
+    /// Generates a fixed format string for the kernel's [`_printk`].
+    ///
+    /// The format string is always the same for a given level, i.e. for a
+    /// given `prefix`, which are the kernel's `KERN_*` constants.
+    ///
+    /// [`_printk`]: ../../../../include/linux/printk.h
+    const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] {
+        // Ensure the `KERN_*` macros are what we expect.
+        assert!(prefix[0] == b'\x01');
+        if is_cont {
+            assert!(prefix[1] == b'c');
+        } else {
+            assert!(prefix[1] >= b'0' && prefix[1] <= b'7');
+        }
+        assert!(prefix[2] == b'\x00');
+
+        let suffix: &[u8; LENGTH - LENGTH_PREFIX] = if is_cont {
+            b"%pA\0\0\0\0\0"
+        } else {
+            b"%s: %pA\0"
+        };
+
+        [
+            prefix[0], prefix[1], suffix[0], suffix[1], suffix[2], suffix[3], suffix[4], suffix[5],
+            suffix[6], suffix[7],
+        ]
+    }
+
+    // Generate the format strings at compile-time.
+    //
+    // This avoids the compiler generating the contents on the fly in the stack.
+    //
+    // Furthermore, `static` instead of `const` is used to share the strings
+    // for all the kernel.
+    pub static EMERG: [u8; LENGTH] = generate(false, bindings::KERN_EMERG);
+    pub static ALERT: [u8; LENGTH] = generate(false, bindings::KERN_ALERT);
+    pub static CRIT: [u8; LENGTH] = generate(false, bindings::KERN_CRIT);
+    pub static ERR: [u8; LENGTH] = generate(false, bindings::KERN_ERR);
+    pub static WARNING: [u8; LENGTH] = generate(false, bindings::KERN_WARNING);
+    pub static NOTICE: [u8; LENGTH] = generate(false, bindings::KERN_NOTICE);
+    pub static INFO: [u8; LENGTH] = generate(false, bindings::KERN_INFO);
+    pub static DEBUG: [u8; LENGTH] = generate(false, bindings::KERN_DEBUG);
+    pub static CONT: [u8; LENGTH] = generate(true, bindings::KERN_CONT);
+}
+
+/// Prints a message via the kernel's [`_printk`].
+///
+/// Public but hidden since it should only be used from public macros.
+///
+/// # Safety
+///
+/// The format string must be one of the ones in [`format_strings`], and
+/// the module name must be null-terminated.
+///
+/// [`_printk`]: ../../../../include/linux/_printk.h
+#[doc(hidden)]
+#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
+pub unsafe fn call_printk(
+    format_string: &[u8; format_strings::LENGTH],
+    module_name: &[u8],
+    args: fmt::Arguments<'_>,
+) {
+    // `_printk` does not seem to fail in any path.
+    #[cfg(CONFIG_PRINTK)]
+    unsafe {
+        bindings::_printk(
+            format_string.as_ptr() as _,
+            module_name.as_ptr(),
+            &args as *const _ as *const c_void,
+        );
+    }
+}
+
+/// Prints a message via the kernel's [`_printk`] for the `CONT` level.
+///
+/// Public but hidden since it should only be used from public macros.
+///
+/// [`_printk`]: ../../../../include/linux/printk.h
+#[doc(hidden)]
+#[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
+pub fn call_printk_cont(args: fmt::Arguments<'_>) {
+    // `_printk` does not seem to fail in any path.
+    //
+    // SAFETY: The format string is fixed.
+    #[cfg(CONFIG_PRINTK)]
+    unsafe {
+        bindings::_printk(
+            format_strings::CONT.as_ptr() as _,
+            &args as *const _ as *const c_void,
+        );
+    }
+}
+
+/// Performs formatting and forwards the string to [`call_printk`].
+///
+/// Public but hidden since it should only be used from public macros.
+#[doc(hidden)]
+#[cfg(not(testlib))]
+#[macro_export]
+#[allow(clippy::crate_in_macro_def)]
+macro_rules! print_macro (
+    // The non-continuation cases (most of them, e.g. `INFO`).
+    ($format_string:path, false, $($arg:tt)+) => (
+        // SAFETY: This hidden macro should only be called by the documented
+        // printing macros which ensure the format string is one of the fixed
+        // ones. All `__LOG_PREFIX`s are null-terminated as they are generated
+        // by the `module!` proc macro or fixed values defined in a kernel
+        // crate.
+        unsafe {
+            $crate::print::call_printk(
+                &$format_string,
+                crate::__LOG_PREFIX,
+                format_args!($($arg)+),
+            );
+        }
+    );
+
+    // The `CONT` case.
+    ($format_string:path, true, $($arg:tt)+) => (
+        $crate::print::call_printk_cont(
+            format_args!($($arg)+),
+        );
+    );
+);
+
+/// Stub for doctests
+#[cfg(testlib)]
+#[macro_export]
+macro_rules! print_macro (
+    ($format_string:path, $e:expr, $($arg:tt)+) => (
+        ()
+    );
+);
+
+// We could use a macro to generate these macros. However, doing so ends
+// up being a bit ugly: it requires the dollar token trick to escape `$` as
+// well as playing with the `doc` attribute. Furthermore, they cannot be easily
+// imported in the prelude due to [1]. So, for the moment, we just write them
+// manually, like in the C side; while keeping most of the logic in another
+// macro, i.e. [`print_macro`].
+//
+// [1]: https://github.com/rust-lang/rust/issues/52234
+
+/// Prints an emergency-level message (level 0).
+///
+/// Use this level if the system is unusable.
+///
+/// Equivalent to the kernel's [`pr_emerg`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_emerg`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_emerg
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_emerg!("hello {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_emerg (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::EMERG, false, $($arg)*)
+    )
+);
+
+/// Prints an alert-level message (level 1).
+///
+/// Use this level if action must be taken immediately.
+///
+/// Equivalent to the kernel's [`pr_alert`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_alert`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_alert
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_alert!("hello {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_alert (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::ALERT, false, $($arg)*)
+    )
+);
+
+/// Prints a critical-level message (level 2).
+///
+/// Use this level for critical conditions.
+///
+/// Equivalent to the kernel's [`pr_crit`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_crit`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_crit
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_crit!("hello {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_crit (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::CRIT, false, $($arg)*)
+    )
+);
+
+/// Prints an error-level message (level 3).
+///
+/// Use this level for error conditions.
+///
+/// Equivalent to the kernel's [`pr_err`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_err`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_err
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_err!("hello {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_err (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::ERR, false, $($arg)*)
+    )
+);
+
+/// Prints a warning-level message (level 4).
+///
+/// Use this level for warning conditions.
+///
+/// Equivalent to the kernel's [`pr_warn`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_warn`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_warn
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_warn!("hello {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_warn (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::WARNING, false, $($arg)*)
+    )
+);
+
+/// Prints a notice-level message (level 5).
+///
+/// Use this level for normal but significant conditions.
+///
+/// Equivalent to the kernel's [`pr_notice`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_notice`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_notice
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_notice!("hello {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_notice (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::NOTICE, false, $($arg)*)
+    )
+);
+
+/// Prints an info-level message (level 6).
+///
+/// Use this level for informational messages.
+///
+/// Equivalent to the kernel's [`pr_info`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_info`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_info
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_info!("hello {}\n", "there");
+/// ```
+#[macro_export]
+#[doc(alias = "print")]
+macro_rules! pr_info (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::INFO, false, $($arg)*)
+    )
+);
+
+/// Prints a debug-level message (level 7).
+///
+/// Use this level for debug messages.
+///
+/// Equivalent to the kernel's [`pr_debug`] macro, except that it doesn't support dynamic debug
+/// yet.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_debug`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_debug
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// pr_debug!("hello {}\n", "there");
+/// ```
+#[macro_export]
+#[doc(alias = "print")]
+macro_rules! pr_debug (
+    ($($arg:tt)*) => (
+        if cfg!(debug_assertions) {
+            $crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*)
+        }
+    )
+);
+
+/// Continues a previous log message in the same line.
+///
+/// Use only when continuing a previous `pr_*!` macro (e.g. [`pr_info!`]).
+///
+/// Equivalent to the kernel's [`pr_cont`] macro.
+///
+/// Mimics the interface of [`std::print!`]. See [`core::fmt`] and
+/// [`alloc::format!`] for information about the formatting syntax.
+///
+/// [`pr_cont`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_cont
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::pr_cont;
+/// pr_info!("hello");
+/// pr_cont!(" {}\n", "there");
+/// ```
+#[macro_export]
+macro_rules! pr_cont (
+    ($($arg:tt)*) => (
+        $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*)
+    )
+);
diff --git a/rust/kernel/random.rs b/rust/kernel/random.rs
new file mode 100644
index 000000000000..c30dd675d6a0
--- /dev/null
+++ b/rust/kernel/random.rs
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Random numbers.
+//!
+//! C header: [`include/linux/random.h`](../../../../include/linux/random.h)
+
+use crate::{bindings, error::code::*, Error, Result};
+
+/// Fills a byte slice with random bytes generated from the kernel's CSPRNG.
+///
+/// Ensures that the CSPRNG has been seeded before generating any random bytes,
+/// and will block until it is ready.
+pub fn getrandom(dest: &mut [u8]) -> Result {
+    let res = unsafe { bindings::wait_for_random_bytes() };
+    if res != 0 {
+        return Err(Error::from_kernel_errno(res));
+    }
+
+    unsafe {
+        bindings::get_random_bytes(dest.as_mut_ptr() as *mut core::ffi::c_void, dest.len());
+    }
+    Ok(())
+}
+
+/// Fills a byte slice with random bytes generated from the kernel's CSPRNG.
+///
+/// If the CSPRNG is not yet seeded, returns an `Err(EAGAIN)` immediately.
+pub fn getrandom_nonblock(dest: &mut [u8]) -> Result {
+    if !unsafe { bindings::rng_is_initialized() } {
+        return Err(EAGAIN);
+    }
+    getrandom(dest)
+}
+
+/// Contributes the contents of a byte slice to the kernel's entropy pool.
+///
+/// Does *not* credit the kernel entropy counter though.
+pub fn add_randomness(data: &[u8]) {
+    unsafe {
+        bindings::add_device_randomness(data.as_ptr() as *const core::ffi::c_void, data.len());
+    }
+}
diff --git a/rust/kernel/raw_list.rs b/rust/kernel/raw_list.rs
new file mode 100644
index 000000000000..267b21709c29
--- /dev/null
+++ b/rust/kernel/raw_list.rs
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Raw lists.
+//!
+//! TODO: This module is a work in progress.
+
+use core::{
+    cell::UnsafeCell,
+    ptr,
+    ptr::NonNull,
+    sync::atomic::{AtomicBool, Ordering},
+};
+
+/// A descriptor of list elements.
+///
+/// It describes the type of list elements and provides a function to determine how to get the
+/// links to be used on a list.
+///
+/// A type that may be in multiple lists simultaneously needs to implement one of these for each
+/// simultaneous list.
+pub trait GetLinks {
+    /// The type of the entries in the list.
+    type EntryType: ?Sized;
+
+    /// Returns the links to be used when linking an entry within a list.
+    fn get_links(data: &Self::EntryType) -> &Links<Self::EntryType>;
+}
+
+/// The links used to link an object on a linked list.
+///
+/// Instances of this type are usually embedded in structures and returned in calls to
+/// [`GetLinks::get_links`].
+pub struct Links<T: ?Sized> {
+    inserted: AtomicBool,
+    entry: UnsafeCell<ListEntry<T>>,
+}
+
+impl<T: ?Sized> Links<T> {
+    /// Constructs a new [`Links`] instance that isn't inserted on any lists yet.
+    pub fn new() -> Self {
+        Self {
+            inserted: AtomicBool::new(false),
+            entry: UnsafeCell::new(ListEntry::new()),
+        }
+    }
+
+    fn acquire_for_insertion(&self) -> bool {
+        self.inserted
+            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
+            .is_ok()
+    }
+
+    fn release_after_removal(&self) {
+        self.inserted.store(false, Ordering::Release);
+    }
+}
+
+impl<T: ?Sized> Default for Links<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+struct ListEntry<T: ?Sized> {
+    next: Option<NonNull<T>>,
+    prev: Option<NonNull<T>>,
+}
+
+impl<T: ?Sized> ListEntry<T> {
+    fn new() -> Self {
+        Self {
+            next: None,
+            prev: None,
+        }
+    }
+}
+
+/// A linked list.
+///
+/// # Invariants
+///
+/// The links of objects added to a list are owned by the list.
+pub(crate) struct RawList<G: GetLinks> {
+    head: Option<NonNull<G::EntryType>>,
+}
+
+impl<G: GetLinks> RawList<G> {
+    pub(crate) fn new() -> Self {
+        Self { head: None }
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        self.head.is_none()
+    }
+
+    fn insert_after_priv(
+        &mut self,
+        existing: &G::EntryType,
+        new_entry: &mut ListEntry<G::EntryType>,
+        new_ptr: Option<NonNull<G::EntryType>>,
+    ) {
+        {
+            // SAFETY: It's safe to get the previous entry of `existing` because the list cannot
+            // change.
+            let existing_links = unsafe { &mut *G::get_links(existing).entry.get() };
+            new_entry.next = existing_links.next;
+            existing_links.next = new_ptr;
+        }
+
+        new_entry.prev = Some(NonNull::from(existing));
+
+        // SAFETY: It's safe to get the next entry of `existing` because the list cannot change.
+        let next_links =
+            unsafe { &mut *G::get_links(new_entry.next.unwrap().as_ref()).entry.get() };
+        next_links.prev = new_ptr;
+    }
+
+    /// Inserts the given object after `existing`.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `existing` points to a valid entry that is on the list.
+    pub(crate) unsafe fn insert_after(
+        &mut self,
+        existing: &G::EntryType,
+        new: &G::EntryType,
+    ) -> bool {
+        let links = G::get_links(new);
+        if !links.acquire_for_insertion() {
+            // Nothing to do if already inserted.
+            return false;
+        }
+
+        // SAFETY: The links are now owned by the list, so it is safe to get a mutable reference.
+        let new_entry = unsafe { &mut *links.entry.get() };
+        self.insert_after_priv(existing, new_entry, Some(NonNull::from(new)));
+        true
+    }
+
+    fn push_back_internal(&mut self, new: &G::EntryType) -> bool {
+        let links = G::get_links(new);
+        if !links.acquire_for_insertion() {
+            // Nothing to do if already inserted.
+            return false;
+        }
+
+        // SAFETY: The links are now owned by the list, so it is safe to get a mutable reference.
+        let new_entry = unsafe { &mut *links.entry.get() };
+        let new_ptr = Some(NonNull::from(new));
+        match self.back() {
+            // SAFETY: `back` is valid as the list cannot change.
+            Some(back) => self.insert_after_priv(unsafe { back.as_ref() }, new_entry, new_ptr),
+            None => {
+                self.head = new_ptr;
+                new_entry.next = new_ptr;
+                new_entry.prev = new_ptr;
+            }
+        }
+        true
+    }
+
+    pub(crate) unsafe fn push_back(&mut self, new: &G::EntryType) -> bool {
+        self.push_back_internal(new)
+    }
+
+    fn remove_internal(&mut self, data: &G::EntryType) -> bool {
+        let links = G::get_links(data);
+
+        // SAFETY: The links are now owned by the list, so it is safe to get a mutable reference.
+        let entry = unsafe { &mut *links.entry.get() };
+        let next = if let Some(next) = entry.next {
+            next
+        } else {
+            // Nothing to do if the entry is not on the list.
+            return false;
+        };
+
+        if ptr::eq(data, next.as_ptr()) {
+            // We're removing the only element.
+            self.head = None
+        } else {
+            // Update the head if we're removing it.
+            if let Some(raw_head) = self.head {
+                if ptr::eq(data, raw_head.as_ptr()) {
+                    self.head = Some(next);
+                }
+            }
+
+            // SAFETY: It's safe to get the previous entry because the list cannot change.
+            unsafe { &mut *G::get_links(entry.prev.unwrap().as_ref()).entry.get() }.next =
+                entry.next;
+
+            // SAFETY: It's safe to get the next entry because the list cannot change.
+            unsafe { &mut *G::get_links(next.as_ref()).entry.get() }.prev = entry.prev;
+        }
+
+        // Reset the links of the element we're removing so that we know it's not on any list.
+        entry.next = None;
+        entry.prev = None;
+        links.release_after_removal();
+        true
+    }
+
+    /// Removes the given entry.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that `data` is either on this list or in no list. It being on another
+    /// list leads to memory unsafety.
+    pub(crate) unsafe fn remove(&mut self, data: &G::EntryType) -> bool {
+        self.remove_internal(data)
+    }
+
+    fn pop_front_internal(&mut self) -> Option<NonNull<G::EntryType>> {
+        let head = self.head?;
+        // SAFETY: The head is on the list as we just got it from there and it cannot change.
+        unsafe { self.remove(head.as_ref()) };
+        Some(head)
+    }
+
+    pub(crate) fn pop_front(&mut self) -> Option<NonNull<G::EntryType>> {
+        self.pop_front_internal()
+    }
+
+    pub(crate) fn front(&self) -> Option<NonNull<G::EntryType>> {
+        self.head
+    }
+
+    pub(crate) fn back(&self) -> Option<NonNull<G::EntryType>> {
+        // SAFETY: The links of head are owned by the list, so it is safe to get a reference.
+        unsafe { &*G::get_links(self.head?.as_ref()).entry.get() }.prev
+    }
+
+    pub(crate) fn cursor_front(&self) -> Cursor<'_, G> {
+        Cursor::new(self, self.front())
+    }
+
+    pub(crate) fn cursor_front_mut(&mut self) -> CursorMut<'_, G> {
+        CursorMut::new(self, self.front())
+    }
+}
+
+struct CommonCursor<G: GetLinks> {
+    cur: Option<NonNull<G::EntryType>>,
+}
+
+impl<G: GetLinks> CommonCursor<G> {
+    fn new(cur: Option<NonNull<G::EntryType>>) -> Self {
+        Self { cur }
+    }
+
+    fn move_next(&mut self, list: &RawList<G>) {
+        match self.cur.take() {
+            None => self.cur = list.head,
+            Some(cur) => {
+                if let Some(head) = list.head {
+                    // SAFETY: We have a shared ref to the linked list, so the links can't change.
+                    let links = unsafe { &*G::get_links(cur.as_ref()).entry.get() };
+                    if links.next.unwrap() != head {
+                        self.cur = links.next;
+                    }
+                }
+            }
+        }
+    }
+
+    fn move_prev(&mut self, list: &RawList<G>) {
+        match list.head {
+            None => self.cur = None,
+            Some(head) => {
+                let next = match self.cur.take() {
+                    None => head,
+                    Some(cur) => {
+                        if cur == head {
+                            return;
+                        }
+                        cur
+                    }
+                };
+                // SAFETY: There's a shared ref to the list, so the links can't change.
+                let links = unsafe { &*G::get_links(next.as_ref()).entry.get() };
+                self.cur = links.prev;
+            }
+        }
+    }
+}
+
+/// A list cursor that allows traversing a linked list and inspecting elements.
+pub struct Cursor<'a, G: GetLinks> {
+    cursor: CommonCursor<G>,
+    list: &'a RawList<G>,
+}
+
+impl<'a, G: GetLinks> Cursor<'a, G> {
+    fn new(list: &'a RawList<G>, cur: Option<NonNull<G::EntryType>>) -> Self {
+        Self {
+            list,
+            cursor: CommonCursor::new(cur),
+        }
+    }
+
+    /// Returns the element the cursor is currently positioned on.
+    pub fn current(&self) -> Option<&'a G::EntryType> {
+        let cur = self.cursor.cur?;
+        // SAFETY: Objects must be kept alive while on the list.
+        Some(unsafe { &*cur.as_ptr() })
+    }
+
+    /// Moves the cursor to the next element.
+    pub fn move_next(&mut self) {
+        self.cursor.move_next(self.list);
+    }
+}
+
+pub(crate) struct CursorMut<'a, G: GetLinks> {
+    cursor: CommonCursor<G>,
+    list: &'a mut RawList<G>,
+}
+
+impl<'a, G: GetLinks> CursorMut<'a, G> {
+    fn new(list: &'a mut RawList<G>, cur: Option<NonNull<G::EntryType>>) -> Self {
+        Self {
+            list,
+            cursor: CommonCursor::new(cur),
+        }
+    }
+
+    pub(crate) fn current(&mut self) -> Option<&mut G::EntryType> {
+        let cur = self.cursor.cur?;
+        // SAFETY: Objects must be kept alive while on the list.
+        Some(unsafe { &mut *cur.as_ptr() })
+    }
+
+    /// Removes the entry the cursor is pointing to and advances the cursor to the next entry. It
+    /// returns a raw pointer to the removed element (if one is removed).
+    pub(crate) fn remove_current(&mut self) -> Option<NonNull<G::EntryType>> {
+        let entry = self.cursor.cur?;
+        self.cursor.move_next(self.list);
+        // SAFETY: The entry is on the list as we just got it from there and it cannot change.
+        unsafe { self.list.remove(entry.as_ref()) };
+        Some(entry)
+    }
+
+    pub(crate) fn peek_next(&mut self) -> Option<&mut G::EntryType> {
+        let mut new = CommonCursor::new(self.cursor.cur);
+        new.move_next(self.list);
+        // SAFETY: Objects must be kept alive while on the list.
+        Some(unsafe { &mut *new.cur?.as_ptr() })
+    }
+
+    pub(crate) fn peek_prev(&mut self) -> Option<&mut G::EntryType> {
+        let mut new = CommonCursor::new(self.cursor.cur);
+        new.move_prev(self.list);
+        // SAFETY: Objects must be kept alive while on the list.
+        Some(unsafe { &mut *new.cur?.as_ptr() })
+    }
+
+    pub(crate) fn move_next(&mut self) {
+        self.cursor.move_next(self.list);
+    }
+}
diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs
new file mode 100644
index 000000000000..a30739cc6839
--- /dev/null
+++ b/rust/kernel/rbtree.rs
@@ -0,0 +1,563 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Red-black trees.
+//!
+//! C header: [`include/linux/rbtree.h`](../../../../include/linux/rbtree.h)
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/core-api/rbtree.html>
+
+use crate::{bindings, Result};
+use alloc::boxed::Box;
+use core::{
+    cmp::{Ord, Ordering},
+    iter::{IntoIterator, Iterator},
+    marker::PhantomData,
+    mem::MaybeUninit,
+    ptr::{addr_of_mut, NonNull},
+};
+
+struct Node<K, V> {
+    links: bindings::rb_node,
+    key: K,
+    value: V,
+}
+
+/// A red-black tree with owned nodes.
+///
+/// It is backed by the kernel C red-black trees.
+///
+/// # Invariants
+///
+/// Non-null parent/children pointers stored in instances of the `rb_node` C struct are always
+/// valid, and pointing to a field of our internal representation of a node.
+///
+/// # Examples
+///
+/// In the example below we do several operations on a tree. We note that insertions may fail if
+/// the system is out of memory.
+///
+/// ```
+/// use kernel::rbtree::RBTree;
+///
+/// # fn test() -> Result {
+/// // Create a new tree.
+/// let mut tree = RBTree::new();
+///
+/// // Insert three elements.
+/// tree.try_insert(20, 200)?;
+/// tree.try_insert(10, 100)?;
+/// tree.try_insert(30, 300)?;
+///
+/// // Check the nodes we just inserted.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&10, &100));
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert_eq!(iter.next().unwrap(), (&30, &300));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// // Print all elements.
+/// for (key, value) in &tree {
+///     pr_info!("{} = {}\n", key, value);
+/// }
+///
+/// // Replace one of the elements.
+/// tree.try_insert(10, 1000)?;
+///
+/// // Check that the tree reflects the replacement.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&10, &1000));
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert_eq!(iter.next().unwrap(), (&30, &300));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// // Change the value of one of the elements.
+/// *tree.get_mut(&30).unwrap() = 3000;
+///
+/// // Check that the tree reflects the update.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&10, &1000));
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert_eq!(iter.next().unwrap(), (&30, &3000));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// // Remove an element.
+/// tree.remove(&10);
+///
+/// // Check that the tree reflects the removal.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert_eq!(iter.next().unwrap(), (&30, &3000));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// // Update all values.
+/// for value in tree.values_mut() {
+///     *value *= 10;
+/// }
+///
+/// // Check that the tree reflects the changes to values.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&20, &2000));
+///     assert_eq!(iter.next().unwrap(), (&30, &30000));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// # Ok(())
+/// # }
+/// #
+/// # assert_eq!(test(), Ok(()));
+/// ```
+///
+/// In the example below, we first allocate a node, acquire a spinlock, then insert the node into
+/// the tree. This is useful when the insertion context does not allow sleeping, for example, when
+/// holding a spinlock.
+///
+/// ```
+/// use kernel::{rbtree::RBTree, sync::SpinLock};
+///
+/// fn insert_test(tree: &SpinLock<RBTree<u32, u32>>) -> Result {
+///     // Pre-allocate node. This may fail (as it allocates memory).
+///     let node = RBTree::try_allocate_node(10, 100)?;
+///
+///     // Insert node while holding the lock. It is guaranteed to succeed with no allocation
+///     // attempts.
+///     let mut guard = tree.lock();
+///     guard.insert(node);
+///     Ok(())
+/// }
+/// ```
+///
+/// In the example below, we reuse an existing node allocation from an element we removed.
+///
+/// ```
+/// use kernel::rbtree::RBTree;
+///
+/// # fn test() -> Result {
+/// // Create a new tree.
+/// let mut tree = RBTree::new();
+///
+/// // Insert three elements.
+/// tree.try_insert(20, 200)?;
+/// tree.try_insert(10, 100)?;
+/// tree.try_insert(30, 300)?;
+///
+/// // Check the nodes we just inserted.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&10, &100));
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert_eq!(iter.next().unwrap(), (&30, &300));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// // Remove a node, getting back ownership of it.
+/// let existing = tree.remove_node(&30).unwrap();
+///
+/// // Check that the tree reflects the removal.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&10, &100));
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// // Turn the node into a reservation so that we can reuse it with a different key/value.
+/// let reservation = existing.into_reservation();
+///
+/// // Insert a new node into the tree, reusing the previous allocation. This is guaranteed to
+/// // succeed (no memory allocations).
+/// tree.insert(reservation.into_node(15, 150));
+///
+/// // Check that the tree reflect the new insertion.
+/// {
+///     let mut iter = tree.iter();
+///     assert_eq!(iter.next().unwrap(), (&10, &100));
+///     assert_eq!(iter.next().unwrap(), (&15, &150));
+///     assert_eq!(iter.next().unwrap(), (&20, &200));
+///     assert!(iter.next().is_none());
+/// }
+///
+/// # Ok(())
+/// # }
+/// #
+/// # assert_eq!(test(), Ok(()));
+/// ```
+pub struct RBTree<K, V> {
+    root: bindings::rb_root,
+    _p: PhantomData<Node<K, V>>,
+}
+
+impl<K, V> RBTree<K, V> {
+    /// Creates a new and empty tree.
+    pub fn new() -> Self {
+        Self {
+            // INVARIANT: There are no nodes in the tree, so the invariant holds vacuously.
+            root: bindings::rb_root::default(),
+            _p: PhantomData,
+        }
+    }
+
+    /// Tries to insert a new value into the tree.
+    ///
+    /// It overwrites a node if one already exists with the same key and returns it (containing the
+    /// key/value pair). Returns [`None`] if a node with the same key didn't already exist.
+    ///
+    /// Returns an error if it cannot allocate memory for the new node.
+    pub fn try_insert(&mut self, key: K, value: V) -> Result<Option<RBTreeNode<K, V>>>
+    where
+        K: Ord,
+    {
+        Ok(self.insert(Self::try_allocate_node(key, value)?))
+    }
+
+    /// Allocates memory for a node to be eventually initialised and inserted into the tree via a
+    /// call to [`RBTree::insert`].
+    pub fn try_reserve_node() -> Result<RBTreeNodeReservation<K, V>> {
+        Ok(RBTreeNodeReservation {
+            node: Box::try_new(MaybeUninit::uninit())?,
+        })
+    }
+
+    /// Allocates and initialiases a node that can be inserted into the tree via
+    /// [`RBTree::insert`].
+    pub fn try_allocate_node(key: K, value: V) -> Result<RBTreeNode<K, V>> {
+        Ok(Self::try_reserve_node()?.into_node(key, value))
+    }
+
+    /// Inserts a new node into the tree.
+    ///
+    /// It overwrites a node if one already exists with the same key and returns it (containing the
+    /// key/value pair). Returns [`None`] if a node with the same key didn't already exist.
+    ///
+    /// This function always succeeds.
+    pub fn insert(&mut self, node: RBTreeNode<K, V>) -> Option<RBTreeNode<K, V>>
+    where
+        K: Ord,
+    {
+        let RBTreeNode { node } = node;
+        let node = Box::into_raw(node);
+        // SAFETY: `node` is valid at least until we call `Box::from_raw`, which only happens when
+        // the node is removed or replaced.
+        let node_links = unsafe { addr_of_mut!((*node).links) };
+        let mut new_link: &mut *mut bindings::rb_node = &mut self.root.rb_node;
+        let mut parent = core::ptr::null_mut();
+        while !new_link.is_null() {
+            let this = crate::container_of!(*new_link, Node<K, V>, links);
+
+            parent = *new_link;
+
+            // SAFETY: `this` is a non-null node so it is valid by the type invariants. `node` is
+            // valid until the node is removed.
+            match unsafe { (*node).key.cmp(&(*this).key) } {
+                // SAFETY: `parent` is a non-null node so it is valid by the type invariants.
+                Ordering::Less => new_link = unsafe { &mut (*parent).rb_left },
+                // SAFETY: `parent` is a non-null node so it is valid by the type invariants.
+                Ordering::Greater => new_link = unsafe { &mut (*parent).rb_right },
+                Ordering::Equal => {
+                    // INVARIANT: We are replacing an existing node with a new one, which is valid.
+                    // It remains valid because we "forgot" it with `Box::into_raw`.
+                    // SAFETY: All pointers are non-null and valid (parent, despite the name, really
+                    // is the node we're replacing).
+                    unsafe { bindings::rb_replace_node(parent, node_links, &mut self.root) };
+
+                    // INVARIANT: The node is being returned and the caller may free it, however,
+                    // it was removed from the tree. So the invariants still hold.
+                    return Some(RBTreeNode {
+                        // SAFETY: `this` was a node in the tree, so it is valid.
+                        node: unsafe { Box::from_raw(this as _) },
+                    });
+                }
+            }
+        }
+
+        // INVARIANT: We are linking in a new node, which is valid. It remains valid because we
+        // "forgot" it with `Box::into_raw`.
+        // SAFETY: All pointers are non-null and valid (`*new_link` is null, but `new_link` is a
+        // mutable reference).
+        unsafe { bindings::rb_link_node(node_links, parent, new_link) };
+
+        // SAFETY: All pointers are valid. `node` has just been inserted into the tree.
+        unsafe { bindings::rb_insert_color(node_links, &mut self.root) };
+        None
+    }
+
+    /// Returns a node with the given key, if one exists.
+    fn find(&self, key: &K) -> Option<NonNull<Node<K, V>>>
+    where
+        K: Ord,
+    {
+        let mut node = self.root.rb_node;
+        while !node.is_null() {
+            let this = crate::container_of!(node, Node<K, V>, links);
+            // SAFETY: `this` is a non-null node so it is valid by the type invariants.
+            node = match key.cmp(unsafe { &(*this).key }) {
+                // SAFETY: `node` is a non-null node so it is valid by the type invariants.
+                Ordering::Less => unsafe { (*node).rb_left },
+                // SAFETY: `node` is a non-null node so it is valid by the type invariants.
+                Ordering::Greater => unsafe { (*node).rb_right },
+                Ordering::Equal => return NonNull::new(this as _),
+            }
+        }
+        None
+    }
+
+    /// Returns a reference to the value corresponding to the key.
+    pub fn get(&self, key: &K) -> Option<&V>
+    where
+        K: Ord,
+    {
+        // SAFETY: The `find` return value is a node in the tree, so it is valid.
+        self.find(key).map(|node| unsafe { &node.as_ref().value })
+    }
+
+    /// Returns a mutable reference to the value corresponding to the key.
+    pub fn get_mut(&mut self, key: &K) -> Option<&mut V>
+    where
+        K: Ord,
+    {
+        // SAFETY: The `find` return value is a node in the tree, so it is valid.
+        self.find(key)
+            .map(|mut node| unsafe { &mut node.as_mut().value })
+    }
+
+    /// Removes the node with the given key from the tree.
+    ///
+    /// It returns the node that was removed if one exists, or [`None`] otherwise.
+    pub fn remove_node(&mut self, key: &K) -> Option<RBTreeNode<K, V>>
+    where
+        K: Ord,
+    {
+        let mut node = self.find(key)?;
+
+        // SAFETY: The `find` return value is a node in the tree, so it is valid.
+        unsafe { bindings::rb_erase(&mut node.as_mut().links, &mut self.root) };
+
+        // INVARIANT: The node is being returned and the caller may free it, however, it was
+        // removed from the tree. So the invariants still hold.
+        Some(RBTreeNode {
+            // SAFETY: The `find` return value was a node in the tree, so it is valid.
+            node: unsafe { Box::from_raw(node.as_ptr()) },
+        })
+    }
+
+    /// Removes the node with the given key from the tree.
+    ///
+    /// It returns the value that was removed if one exists, or [`None`] otherwise.
+    pub fn remove(&mut self, key: &K) -> Option<V>
+    where
+        K: Ord,
+    {
+        let node = self.remove_node(key)?;
+        let RBTreeNode { node } = node;
+        let Node {
+            links: _,
+            key: _,
+            value,
+        } = *node;
+        Some(value)
+    }
+
+    /// Returns an iterator over the tree nodes, sorted by key.
+    pub fn iter(&self) -> RBTreeIterator<'_, K, V> {
+        RBTreeIterator {
+            _tree: PhantomData,
+            // SAFETY: `root` is valid as it's embedded in `self` and we have a valid `self`.
+            next: unsafe { bindings::rb_first(&self.root) },
+        }
+    }
+
+    /// Returns a mutable iterator over the tree nodes, sorted by key.
+    pub fn iter_mut(&mut self) -> RBTreeIteratorMut<'_, K, V> {
+        RBTreeIteratorMut {
+            _tree: PhantomData,
+            // SAFETY: `root` is valid as it's embedded in `self` and we have a valid `self`.
+            next: unsafe { bindings::rb_first(&self.root) },
+        }
+    }
+
+    /// Returns an iterator over the keys of the nodes in the tree, in sorted order.
+    pub fn keys(&self) -> impl Iterator<Item = &'_ K> {
+        self.iter().map(|(k, _)| k)
+    }
+
+    /// Returns an iterator over the values of the nodes in the tree, sorted by key.
+    pub fn values(&self) -> impl Iterator<Item = &'_ V> {
+        self.iter().map(|(_, v)| v)
+    }
+
+    /// Returns a mutable iterator over the values of the nodes in the tree, sorted by key.
+    pub fn values_mut(&mut self) -> impl Iterator<Item = &'_ mut V> {
+        self.iter_mut().map(|(_, v)| v)
+    }
+}
+
+impl<K, V> Default for RBTree<K, V> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<K, V> Drop for RBTree<K, V> {
+    fn drop(&mut self) {
+        // SAFETY: `root` is valid as it's embedded in `self` and we have a valid `self`.
+        let mut next = unsafe { bindings::rb_first_postorder(&self.root) };
+
+        // INVARIANT: The loop invariant is that all tree nodes from `next` in postorder are valid.
+        while !next.is_null() {
+            let this = crate::container_of!(next, Node<K, V>, links);
+
+            // Find out what the next node is before disposing of the current one.
+            // SAFETY: `next` and all nodes in postorder are still valid.
+            next = unsafe { bindings::rb_next_postorder(next) };
+
+            // INVARIANT: This is the destructor, so we break the type invariant during clean-up,
+            // but it is not observable. The loop invariant is still maintained.
+            // SAFETY: `this` is valid per the loop invariant.
+            unsafe { Box::from_raw(this as *mut Node<K, V>) };
+        }
+    }
+}
+
+impl<'a, K, V> IntoIterator for &'a RBTree<K, V> {
+    type Item = (&'a K, &'a V);
+    type IntoIter = RBTreeIterator<'a, K, V>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter()
+    }
+}
+
+/// An iterator over the nodes of a [`RBTree`].
+///
+/// Instances are created by calling [`RBTree::iter`].
+pub struct RBTreeIterator<'a, K, V> {
+    _tree: PhantomData<&'a RBTree<K, V>>,
+    next: *mut bindings::rb_node,
+}
+
+impl<'a, K, V> Iterator for RBTreeIterator<'a, K, V> {
+    type Item = (&'a K, &'a V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.next.is_null() {
+            return None;
+        }
+
+        let cur = crate::container_of!(self.next, Node<K, V>, links);
+
+        // SAFETY: The reference to the tree used to create the iterator outlives the iterator, so
+        // the tree cannot change. By the tree invariant, all nodes are valid.
+        self.next = unsafe { bindings::rb_next(self.next) };
+
+        // SAFETY: By the same reasoning above, it is safe to dereference the node. Additionally,
+        // it is ok to return a reference to members because the iterator must outlive it.
+        Some(unsafe { (&(*cur).key, &(*cur).value) })
+    }
+}
+
+impl<'a, K, V> IntoIterator for &'a mut RBTree<K, V> {
+    type Item = (&'a K, &'a mut V);
+    type IntoIter = RBTreeIteratorMut<'a, K, V>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        self.iter_mut()
+    }
+}
+
+/// A mutable iterator over the nodes of a [`RBTree`].
+///
+/// Instances are created by calling [`RBTree::iter_mut`].
+pub struct RBTreeIteratorMut<'a, K, V> {
+    _tree: PhantomData<&'a RBTree<K, V>>,
+    next: *mut bindings::rb_node,
+}
+
+impl<'a, K, V> Iterator for RBTreeIteratorMut<'a, K, V> {
+    type Item = (&'a K, &'a mut V);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.next.is_null() {
+            return None;
+        }
+
+        let cur = crate::container_of!(self.next, Node<K, V>, links) as *mut Node<K, V>;
+
+        // SAFETY: The reference to the tree used to create the iterator outlives the iterator, so
+        // the tree cannot change (except for the value of previous nodes, but those don't affect
+        // the iteration process). By the tree invariant, all nodes are valid.
+        self.next = unsafe { bindings::rb_next(self.next) };
+
+        // SAFETY: By the same reasoning above, it is safe to dereference the node. Additionally,
+        // it is ok to return a reference to members because the iterator must outlive it.
+        Some(unsafe { (&(*cur).key, &mut (*cur).value) })
+    }
+}
+
+/// A memory reservation for a red-black tree node.
+///
+/// It contains the memory needed to hold a node that can be inserted into a red-black tree. One
+/// can be obtained by directly allocating it ([`RBTree::try_reserve_node`]) or by "uninitialising"
+/// ([`RBTreeNode::into_reservation`]) an actual node (usually returned by some operation like
+/// removal from a tree).
+pub struct RBTreeNodeReservation<K, V> {
+    node: Box<MaybeUninit<Node<K, V>>>,
+}
+
+impl<K, V> RBTreeNodeReservation<K, V> {
+    /// Initialises a node reservation.
+    ///
+    /// It then becomes an [`RBTreeNode`] that can be inserted into a tree.
+    pub fn into_node(mut self, key: K, value: V) -> RBTreeNode<K, V> {
+        let node_ptr = self.node.as_mut_ptr();
+        // SAFETY: `node_ptr` is valid, and so are its fields.
+        unsafe { addr_of_mut!((*node_ptr).links).write(bindings::rb_node::default()) };
+        // SAFETY: `node_ptr` is valid, and so are its fields.
+        unsafe { addr_of_mut!((*node_ptr).key).write(key) };
+        // SAFETY: `node_ptr` is valid, and so are its fields.
+        unsafe { addr_of_mut!((*node_ptr).value).write(value) };
+        let raw = Box::into_raw(self.node);
+        RBTreeNode {
+            // SAFETY: The pointer came from a `MaybeUninit<Node>` whose fields have all been
+            // initialised. Additionally, it has the same layout as `Node`.
+            node: unsafe { Box::from_raw(raw as _) },
+        }
+    }
+}
+
+/// A red-black tree node.
+///
+/// The node is fully initialised (with key and value) and can be inserted into a tree without any
+/// extra allocations or failure paths.
+pub struct RBTreeNode<K, V> {
+    node: Box<Node<K, V>>,
+}
+
+impl<K, V> RBTreeNode<K, V> {
+    /// "Uninitialises" a node.
+    ///
+    /// It then becomes a reservation that can be re-initialised into a different node (i.e., with
+    /// a different key and/or value).
+    ///
+    /// The existing key and value are dropped in-place as part of this operation, that is, memory
+    /// may be freed (but only for the key/value; memory for the node itself is kept for reuse).
+    pub fn into_reservation(self) -> RBTreeNodeReservation<K, V> {
+        let raw = Box::into_raw(self.node);
+        let mut ret = RBTreeNodeReservation {
+            // SAFETY: The pointer came from a valid `Node`, which has the same layout as
+            // `MaybeUninit<Node>`.
+            node: unsafe { Box::from_raw(raw as _) },
+        };
+        // SAFETY: Although the type is `MaybeUninit<Node>`, we know it has been initialised
+        // because it came from a `Node`. So it is safe to drop it.
+        unsafe { core::ptr::drop_in_place(ret.node.as_mut_ptr()) };
+        ret
+    }
+}
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
new file mode 100644
index 000000000000..1093c4d26026
--- /dev/null
+++ b/rust/kernel/revocable.rs
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Revocable objects.
+//!
+//! The [`Revocable`] type wraps other types and allows access to them to be revoked. The existence
+//! of a [`RevocableGuard`] ensures that objects remain valid.
+
+use crate::{bindings, sync::rcu};
+use core::{
+    cell::UnsafeCell,
+    marker::PhantomData,
+    mem::MaybeUninit,
+    ops::Deref,
+    ptr::drop_in_place,
+    sync::atomic::{fence, AtomicBool, AtomicU32, Ordering},
+};
+
+/// An object that can become inaccessible at runtime.
+///
+/// Once access is revoked and all concurrent users complete (i.e., all existing instances of
+/// [`RevocableGuard`] are dropped), the wrapped object is also dropped.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::revocable::Revocable;
+///
+/// struct Example {
+///     a: u32,
+///     b: u32,
+/// }
+///
+/// fn add_two(v: &Revocable<Example>) -> Option<u32> {
+///     let guard = v.try_access()?;
+///     Some(guard.a + guard.b)
+/// }
+///
+/// let v = Revocable::new(Example { a: 10, b: 20 });
+/// assert_eq!(add_two(&v), Some(30));
+/// v.revoke();
+/// assert_eq!(add_two(&v), None);
+/// ```
+///
+/// Sample example as above, but explicitly using the rcu read side lock.
+///
+/// ```
+/// # use kernel::revocable::Revocable;
+/// use kernel::sync::rcu;
+///
+/// struct Example {
+///     a: u32,
+///     b: u32,
+/// }
+///
+/// fn add_two(v: &Revocable<Example>) -> Option<u32> {
+///     let guard = rcu::read_lock();
+///     let e = v.try_access_with_guard(&guard)?;
+///     Some(e.a + e.b)
+/// }
+///
+/// let v = Revocable::new(Example { a: 10, b: 20 });
+/// assert_eq!(add_two(&v), Some(30));
+/// v.revoke();
+/// assert_eq!(add_two(&v), None);
+/// ```
+pub struct Revocable<T> {
+    is_available: AtomicBool,
+    data: MaybeUninit<UnsafeCell<T>>,
+}
+
+// SAFETY: `Revocable` is `Send` if the wrapped object is also `Send`. This is because while the
+// functionality exposed by `Revocable` can be accessed from any thread/CPU, it is possible that
+// this isn't supported by the wrapped object.
+unsafe impl<T: Send> Send for Revocable<T> {}
+
+// SAFETY: `Revocable` is `Sync` if the wrapped object is both `Send` and `Sync`. We require `Send`
+// from the wrapped object as well because  of `Revocable::revoke`, which can trigger the `Drop`
+// implementation of the wrapped object from an arbitrary thread.
+unsafe impl<T: Sync + Send> Sync for Revocable<T> {}
+
+impl<T> Revocable<T> {
+    /// Creates a new revocable instance of the given data.
+    pub const fn new(data: T) -> Self {
+        Self {
+            is_available: AtomicBool::new(true),
+            data: MaybeUninit::new(UnsafeCell::new(data)),
+        }
+    }
+
+    /// Tries to access the \[revocable\] wrapped object.
+    ///
+    /// Returns `None` if the object has been revoked and is therefore no longer accessible.
+    ///
+    /// Returns a guard that gives access to the object otherwise; the object is guaranteed to
+    /// remain accessible while the guard is alive. In such cases, callers are not allowed to sleep
+    /// because another CPU may be waiting to complete the revocation of this object.
+    pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
+        let guard = rcu::read_lock();
+        if self.is_available.load(Ordering::Relaxed) {
+            // SAFETY: Since `self.is_available` is true, data is initialised and has to remain
+            // valid because the RCU read side lock prevents it from being dropped.
+            Some(unsafe { RevocableGuard::new(self.data.assume_init_ref().get(), guard) })
+        } else {
+            None
+        }
+    }
+
+    /// Tries to access the \[revocable\] wrapped object.
+    ///
+    /// Returns `None` if the object has been revoked and is therefore no longer accessible.
+    ///
+    /// Returns a shared reference to the object otherwise; the object is guaranteed to
+    /// remain accessible while the rcu read side guard is alive. In such cases, callers are not
+    /// allowed to sleep because another CPU may be waiting to complete the revocation of this
+    /// object.
+    pub fn try_access_with_guard<'a>(&'a self, _guard: &'a rcu::Guard) -> Option<&'a T> {
+        if self.is_available.load(Ordering::Relaxed) {
+            // SAFETY: Since `self.is_available` is true, data is initialised and has to remain
+            // valid because the RCU read side lock prevents it from being dropped.
+            Some(unsafe { &*self.data.assume_init_ref().get() })
+        } else {
+            None
+        }
+    }
+
+    /// Revokes access to and drops the wrapped object.
+    ///
+    /// Access to the object is revoked immediately to new callers of [`Revocable::try_access`]. If
+    /// there are concurrent users of the object (i.e., ones that called [`Revocable::try_access`]
+    /// beforehand and still haven't dropped the returned guard), this function waits for the
+    /// concurrent access to complete before dropping the wrapped object.
+    pub fn revoke(&self) {
+        if self
+            .is_available
+            .compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed)
+            .is_ok()
+        {
+            // SAFETY: Just an FFI call, there are no further requirements.
+            unsafe { bindings::synchronize_rcu() };
+
+            // SAFETY: We know `self.data` is valid because only one CPU can succeed the
+            // `compare_exchange` above that takes `is_available` from `true` to `false`.
+            unsafe { drop_in_place(self.data.assume_init_ref().get()) };
+        }
+    }
+}
+
+impl<T> Drop for Revocable<T> {
+    fn drop(&mut self) {
+        // Drop only if the data hasn't been revoked yet (in which case it has already been
+        // dropped).
+        if *self.is_available.get_mut() {
+            // SAFETY: We know `self.data` is valid because no other CPU has changed
+            // `is_available` to `false` yet, and no other CPU can do it anymore because this CPU
+            // holds the only reference (mutable) to `self` now.
+            unsafe { drop_in_place(self.data.assume_init_ref().get()) };
+        }
+    }
+}
+
+/// A guard that allows access to a revocable object and keeps it alive.
+///
+/// CPUs may not sleep while holding on to [`RevocableGuard`] because it's in atomic context
+/// holding the RCU read-side lock.
+///
+/// # Invariants
+///
+/// The RCU read-side lock is held while the guard is alive.
+pub struct RevocableGuard<'a, T> {
+    data_ref: *const T,
+    _rcu_guard: rcu::Guard,
+    _p: PhantomData<&'a ()>,
+}
+
+impl<T> RevocableGuard<'_, T> {
+    fn new(data_ref: *const T, rcu_guard: rcu::Guard) -> Self {
+        Self {
+            data_ref,
+            _rcu_guard: rcu_guard,
+            _p: PhantomData,
+        }
+    }
+}
+
+impl<T> Deref for RevocableGuard<'_, T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        // SAFETY: By the type invariants, we hold the rcu read-side lock, so the object is
+        // guaranteed to remain valid.
+        unsafe { &*self.data_ref }
+    }
+}
+
+/// An object that can become inaccessible at runtime.
+///
+/// Once access is revoked and all concurrent users complete (i.e., all existing instances of
+/// [`AsyncRevocableGuard`] are dropped), the wrapped object is also dropped.
+///
+/// Unlike [`Revocable`], [`AsyncRevocable`] does not wait for concurrent users of the wrapped
+/// object to finish before [`AsyncRevocable::revoke`] completes -- thus the async qualifier. This
+/// has the advantage of not requiring RCU locks or waits of any kind.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::revocable::AsyncRevocable;
+///
+/// struct Example {
+///     a: u32,
+///     b: u32,
+/// }
+///
+/// fn add_two(v: &AsyncRevocable<Example>) -> Option<u32> {
+///     let guard = v.try_access()?;
+///     Some(guard.a + guard.b)
+/// }
+///
+/// let v = AsyncRevocable::new(Example { a: 10, b: 20 });
+/// assert_eq!(add_two(&v), Some(30));
+/// v.revoke();
+/// assert_eq!(add_two(&v), None);
+/// ```
+///
+/// Example where revocation happens while there is a user:
+///
+/// ```
+/// # use kernel::revocable::AsyncRevocable;
+/// use core::sync::atomic::{AtomicBool, Ordering};
+///
+/// struct Example {
+///     a: u32,
+///     b: u32,
+/// }
+///
+/// static DROPPED: AtomicBool = AtomicBool::new(false);
+///
+/// impl Drop for Example {
+///     fn drop(&mut self) {
+///         DROPPED.store(true, Ordering::Relaxed);
+///     }
+/// }
+///
+/// fn add_two(v: &AsyncRevocable<Example>) -> Option<u32> {
+///     let guard = v.try_access()?;
+///     Some(guard.a + guard.b)
+/// }
+///
+/// let v = AsyncRevocable::new(Example { a: 10, b: 20 });
+/// assert_eq!(add_two(&v), Some(30));
+///
+/// let guard = v.try_access().unwrap();
+/// assert!(!v.is_revoked());
+/// assert!(!DROPPED.load(Ordering::Relaxed));
+/// v.revoke();
+/// assert!(!DROPPED.load(Ordering::Relaxed));
+/// assert!(v.is_revoked());
+/// assert!(v.try_access().is_none());
+/// assert_eq!(guard.a + guard.b, 30);
+/// drop(guard);
+/// assert!(DROPPED.load(Ordering::Relaxed));
+/// ```
+pub struct AsyncRevocable<T> {
+    usage_count: AtomicU32,
+    data: MaybeUninit<UnsafeCell<T>>,
+}
+
+// SAFETY: `AsyncRevocable` is `Send` if the wrapped object is also `Send`. This is because while
+// the functionality exposed by `AsyncRevocable` can be accessed from any thread/CPU, it is
+// possible that this isn't supported by the wrapped object.
+unsafe impl<T: Send> Send for AsyncRevocable<T> {}
+
+// SAFETY: `AsyncRevocable` is `Sync` if the wrapped object is both `Send` and `Sync`. We require
+// `Send` from the wrapped object as well because  of `AsyncRevocable::revoke`, which can trigger
+// the `Drop` implementation of the wrapped object from an arbitrary thread.
+unsafe impl<T: Sync + Send> Sync for AsyncRevocable<T> {}
+
+const REVOKED: u32 = 0x80000000;
+const COUNT_MASK: u32 = !REVOKED;
+const SATURATED_COUNT: u32 = REVOKED - 1;
+
+impl<T> AsyncRevocable<T> {
+    /// Creates a new asynchronously revocable instance of the given data.
+    pub fn new(data: T) -> Self {
+        Self {
+            usage_count: AtomicU32::new(0),
+            data: MaybeUninit::new(UnsafeCell::new(data)),
+        }
+    }
+
+    /// Tries to access the \[revocable\] wrapped object.
+    ///
+    /// Returns `None` if the object has been revoked and is therefore no longer accessible.
+    ///
+    /// Returns a guard that gives access to the object otherwise; the object is guaranteed to
+    /// remain accessible while the guard is alive.
+    pub fn try_access(&self) -> Option<AsyncRevocableGuard<'_, T>> {
+        loop {
+            let count = self.usage_count.load(Ordering::Relaxed);
+
+            // Fail attempt to access if the object is already revoked.
+            if count & REVOKED != 0 {
+                return None;
+            }
+
+            // No need to increment if the count is saturated.
+            if count == SATURATED_COUNT
+                || self
+                    .usage_count
+                    .compare_exchange(count, count + 1, Ordering::Relaxed, Ordering::Relaxed)
+                    .is_ok()
+            {
+                return Some(AsyncRevocableGuard { revocable: self });
+            }
+        }
+    }
+
+    /// Revokes access to the protected object.
+    ///
+    /// Returns `true` if access has been revoked, or `false` when the object has already been
+    /// revoked by a previous call to [`AsyncRevocable::revoke`].
+    ///
+    /// This call is non-blocking, that is, no new users of the revocable object will be allowed,
+    /// but potential current users are able to continue to use it and the thread won't wait for
+    /// them to finish. In such cases, the object will be dropped when the last user completes.
+    pub fn revoke(&self) -> bool {
+        // Set the `REVOKED` bit.
+        //
+        // The acquire barrier matches up with the release when decrementing the usage count.
+        let prev = self.usage_count.fetch_or(REVOKED, Ordering::Acquire);
+        if prev & REVOKED != 0 {
+            // Another thread already revoked this object.
+            return false;
+        }
+
+        if prev == 0 {
+            // SAFETY: This thread just revoked the object and the usage count is zero, so the
+            // object is valid and there will be no future users.
+            unsafe { drop_in_place(UnsafeCell::raw_get(self.data.as_ptr())) };
+        }
+
+        true
+    }
+
+    /// Returns whether access to the object has been revoked.
+    pub fn is_revoked(&self) -> bool {
+        self.usage_count.load(Ordering::Relaxed) & REVOKED != 0
+    }
+}
+
+impl<T> Drop for AsyncRevocable<T> {
+    fn drop(&mut self) {
+        let count = *self.usage_count.get_mut();
+        if count != REVOKED {
+            // The object hasn't been dropped yet, so we do it now.
+
+            // This matches with the release when decrementing the usage count.
+            fence(Ordering::Acquire);
+
+            // SAFETY: Since `count` is does not indicate a count of 0 and the REVOKED bit set, the
+            // object is still valid.
+            unsafe { drop_in_place(UnsafeCell::raw_get(self.data.as_ptr())) };
+        }
+    }
+}
+
+/// A guard that allows access to a revocable object and keeps it alive.
+///
+/// # Invariants
+///
+/// The owner owns an increment on the usage count (which may have saturated it), which keeps the
+/// revocable object alive.
+pub struct AsyncRevocableGuard<'a, T> {
+    revocable: &'a AsyncRevocable<T>,
+}
+
+impl<T> Deref for AsyncRevocableGuard<'_, T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        // SAFETY: The type invariants guarantee that the caller owns an increment.
+        unsafe { &*self.revocable.data.assume_init_ref().get() }
+    }
+}
+
+impl<T> Drop for AsyncRevocableGuard<'_, T> {
+    fn drop(&mut self) {
+        loop {
+            let count = self.revocable.usage_count.load(Ordering::Relaxed);
+            let actual_count = count & COUNT_MASK;
+            if actual_count == SATURATED_COUNT {
+                // The count is saturated, so we won't decrement (nor do we drop the object).
+                return;
+            }
+
+            if actual_count == 0 {
+                // Trying to underflow the count.
+                panic!("actual_count is zero");
+            }
+
+            // On success, we use release ordering, which matches with the acquire in one of the
+            // places where we drop the object, namely: below, in `AsyncRevocable::revoke`, or in
+            // `AsyncRevocable::drop`.
+            if self
+                .revocable
+                .usage_count
+                .compare_exchange(count, count - 1, Ordering::Release, Ordering::Relaxed)
+                .is_ok()
+            {
+                if count == 1 | REVOKED {
+                    // `count`  is now zero and it is revoked, so free it now.
+
+                    // This matches with the release above (which may have happened in other
+                    // threads concurrently).
+                    fence(Ordering::Acquire);
+
+                    // SAFETY: Since `count` was 1, the object is still alive.
+                    unsafe { drop_in_place(UnsafeCell::raw_get(self.revocable.data.as_ptr())) };
+                }
+
+                return;
+            }
+        }
+    }
+}
diff --git a/rust/kernel/security.rs b/rust/kernel/security.rs
new file mode 100644
index 000000000000..0a33363289d3
--- /dev/null
+++ b/rust/kernel/security.rs
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Linux Security Modules (LSM).
+//!
+//! C header: [`include/linux/security.h`](../../../../include/linux/security.h).
+
+use crate::{bindings, cred::Credential, file::File, to_result, Result};
+
+/// Calls the security modules to determine if the given task can become the manager of a binder
+/// context.
+pub fn binder_set_context_mgr(mgr: &Credential) -> Result {
+    // SAFETY: `mrg.0` is valid because the shared reference guarantees a nonzero refcount.
+    to_result(unsafe { bindings::security_binder_set_context_mgr(mgr.0.get()) })
+}
+
+/// Calls the security modules to determine if binder transactions are allowed from task `from` to
+/// task `to`.
+pub fn binder_transaction(from: &Credential, to: &Credential) -> Result {
+    // SAFETY: `from` and `to` are valid because the shared references guarantee nonzero refcounts.
+    to_result(unsafe { bindings::security_binder_transaction(from.0.get(), to.0.get()) })
+}
+
+/// Calls the security modules to determine if task `from` is allowed to send binder objects
+/// (owned by itself or other processes) to task `to` through a binder transaction.
+pub fn binder_transfer_binder(from: &Credential, to: &Credential) -> Result {
+    // SAFETY: `from` and `to` are valid because the shared references guarantee nonzero refcounts.
+    to_result(unsafe { bindings::security_binder_transfer_binder(from.0.get(), to.0.get()) })
+}
+
+/// Calls the security modules to determine if task `from` is allowed to send the given file to
+/// task `to` (which would get its own file descriptor) through a binder transaction.
+pub fn binder_transfer_file(from: &Credential, to: &Credential, file: &File) -> Result {
+    // SAFETY: `from`, `to` and `file` are valid because the shared references guarantee nonzero
+    // refcounts.
+    to_result(unsafe {
+        bindings::security_binder_transfer_file(from.0.get(), to.0.get(), file.0.get())
+    })
+}
diff --git a/rust/kernel/static_assert.rs b/rust/kernel/static_assert.rs
new file mode 100644
index 000000000000..3115ee0ba8e9
--- /dev/null
+++ b/rust/kernel/static_assert.rs
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Static assert.
+
+/// Static assert (i.e. compile-time assert).
+///
+/// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
+///
+/// The feature may be added to Rust in the future: see [RFC 2790].
+///
+/// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert
+/// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert
+/// [RFC 2790]: https://github.com/rust-lang/rfcs/issues/2790
+///
+/// # Examples
+///
+/// ```
+/// static_assert!(42 > 24);
+/// static_assert!(core::mem::size_of::<u8>() == 1);
+///
+/// const X: &[u8] = b"bar";
+/// static_assert!(X[1] == b'a');
+///
+/// const fn f(x: i32) -> i32 {
+///     x + 2
+/// }
+/// static_assert!(f(40) == 42);
+/// ```
+#[macro_export]
+macro_rules! static_assert {
+    ($condition:expr) => {
+        const _: () = core::assert!($condition);
+    };
+}
diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs
new file mode 100644
index 000000000000..ffbaca0c4cb7
--- /dev/null
+++ b/rust/kernel/std_vendor.rs
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+//! The contents of this file come from the Rust standard library, hosted in
+//! the <https://github.com/rust-lang/rust> repository, licensed under
+//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details,
+//! see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>.
+
+/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`].
+///
+/// Prints and returns the value of a given expression for quick and dirty
+/// debugging.
+///
+/// An example:
+///
+/// ```rust
+/// let a = 2;
+/// # #[allow(clippy::dbg_macro)]
+/// let b = dbg!(a * 2) + 1;
+/// //      ^-- prints: [src/main.rs:2] a * 2 = 4
+/// assert_eq!(b, 5);
+/// ```
+///
+/// The macro works by using the `Debug` implementation of the type of
+/// the given expression to print the value with [`printk`] along with the
+/// source location of the macro invocation as well as the source code
+/// of the expression.
+///
+/// Invoking the macro on an expression moves and takes ownership of it
+/// before returning the evaluated expression unchanged. If the type
+/// of the expression does not implement `Copy` and you don't want
+/// to give up ownership, you can instead borrow with `dbg!(&expr)`
+/// for some expression `expr`.
+///
+/// The `dbg!` macro works exactly the same in release builds.
+/// This is useful when debugging issues that only occur in release
+/// builds or when debugging in release mode is significantly faster.
+///
+/// Note that the macro is intended as a debugging tool and therefore you
+/// should avoid having uses of it in version control for long periods
+/// (other than in tests and similar).
+///
+/// # Stability
+///
+/// The exact output printed by this macro should not be relied upon
+/// and is subject to future changes.
+///
+/// # Further examples
+///
+/// With a method call:
+///
+/// ```rust
+/// # #[allow(clippy::dbg_macro)]
+/// fn foo(n: usize) {
+///     if dbg!(n.checked_sub(4)).is_some() {
+///         // ...
+///     }
+/// }
+///
+/// foo(3)
+/// ```
+///
+/// This prints to the kernel log:
+///
+/// ```text,ignore
+/// [src/main.rs:4] n.checked_sub(4) = None
+/// ```
+///
+/// Naive factorial implementation:
+///
+/// ```rust
+/// # #[allow(clippy::dbg_macro)]
+/// # {
+/// fn factorial(n: u32) -> u32 {
+///     if dbg!(n <= 1) {
+///         dbg!(1)
+///     } else {
+///         dbg!(n * factorial(n - 1))
+///     }
+/// }
+///
+/// dbg!(factorial(4));
+/// # }
+/// ```
+///
+/// This prints to the kernel log:
+///
+/// ```text,ignore
+/// [src/main.rs:3] n <= 1 = false
+/// [src/main.rs:3] n <= 1 = false
+/// [src/main.rs:3] n <= 1 = false
+/// [src/main.rs:3] n <= 1 = true
+/// [src/main.rs:4] 1 = 1
+/// [src/main.rs:5] n * factorial(n - 1) = 2
+/// [src/main.rs:5] n * factorial(n - 1) = 6
+/// [src/main.rs:5] n * factorial(n - 1) = 24
+/// [src/main.rs:11] factorial(4) = 24
+/// ```
+///
+/// The `dbg!(..)` macro moves the input:
+///
+// TODO: Could be `compile_fail` when supported.
+/// ```ignore
+/// /// A wrapper around `usize` which importantly is not Copyable.
+/// #[derive(Debug)]
+/// struct NoCopy(usize);
+///
+/// let a = NoCopy(42);
+/// let _ = dbg!(a); // <-- `a` is moved here.
+/// let _ = dbg!(a); // <-- `a` is moved again; error!
+/// ```
+///
+/// You can also use `dbg!()` without a value to just print the
+/// file and line whenever it's reached.
+///
+/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
+/// a tuple (and return it, too):
+///
+/// ```
+/// # #[allow(clippy::dbg_macro)]
+/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
+/// ```
+///
+/// However, a single argument with a trailing comma will still not be treated
+/// as a tuple, following the convention of ignoring trailing commas in macro
+/// invocations. You can use a 1-tuple directly if you need one:
+///
+/// ```
+/// # #[allow(clippy::dbg_macro)]
+/// # {
+/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
+/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
+/// # }
+/// ```
+///
+/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html
+/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html
+/// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html
+#[macro_export]
+macro_rules! dbg {
+    // NOTE: We cannot use `concat!` to make a static string as a format argument
+    // of `pr_info!` because `file!` could contain a `{` or
+    // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!`
+    // will be malformed.
+    () => {
+        $crate::pr_info!("[{}:{}]\n", ::core::file!(), ::core::line!())
+    };
+    ($val:expr $(,)?) => {
+        // Use of `match` here is intentional because it affects the lifetimes
+        // of temporaries - https://stackoverflow.com/a/48732525/1063961
+        match $val {
+            tmp => {
+                $crate::pr_info!("[{}:{}] {} = {:#?}\n",
+                    ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp);
+                tmp
+            }
+        }
+    };
+    ($($val:expr),+ $(,)?) => {
+        ($($crate::dbg!($val)),+,)
+    };
+}
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
new file mode 100644
index 000000000000..874003e39cba
--- /dev/null
+++ b/rust/kernel/str.rs
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! String representations.
+
+use alloc::vec::Vec;
+use core::fmt::{self, Write};
+use core::ops::{self, Deref, Index};
+
+use crate::{bindings, error::code::*, Error};
+
+/// Byte string without UTF-8 validity guarantee.
+///
+/// `BStr` is simply an alias to `[u8]`, but has a more evident semantical meaning.
+pub type BStr = [u8];
+
+/// Creates a new [`BStr`] from a string literal.
+///
+/// `b_str!` converts the supplied string literal to byte string, so non-ASCII
+/// characters can be included.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::b_str;
+/// # use kernel::str::BStr;
+/// const MY_BSTR: &BStr = b_str!("My awesome BStr!");
+/// ```
+#[macro_export]
+macro_rules! b_str {
+    ($str:literal) => {{
+        const S: &'static str = $str;
+        const C: &'static $crate::str::BStr = S.as_bytes();
+        C
+    }};
+}
+
+/// Possible errors when using conversion functions in [`CStr`].
+#[derive(Debug, Clone, Copy)]
+pub enum CStrConvertError {
+    /// Supplied bytes contain an interior `NUL`.
+    InteriorNul,
+
+    /// Supplied bytes are not terminated by `NUL`.
+    NotNulTerminated,
+}
+
+impl From<CStrConvertError> for Error {
+    #[inline]
+    fn from(_: CStrConvertError) -> Error {
+        EINVAL
+    }
+}
+
+/// A string that is guaranteed to have exactly one `NUL` byte, which is at the
+/// end.
+///
+/// Used for interoperability with kernel APIs that take C strings.
+#[repr(transparent)]
+pub struct CStr([u8]);
+
+impl CStr {
+    /// Returns the length of this string excluding `NUL`.
+    #[inline]
+    pub const fn len(&self) -> usize {
+        self.len_with_nul() - 1
+    }
+
+    /// Returns the length of this string with `NUL`.
+    #[inline]
+    pub const fn len_with_nul(&self) -> usize {
+        // SAFETY: This is one of the invariant of `CStr`.
+        // We add a `unreachable_unchecked` here to hint the optimizer that
+        // the value returned from this function is non-zero.
+        if self.0.is_empty() {
+            unsafe { core::hint::unreachable_unchecked() };
+        }
+        self.0.len()
+    }
+
+    /// Returns `true` if the string only includes `NUL`.
+    #[inline]
+    pub const fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Wraps a raw C string pointer.
+    ///
+    /// # Safety
+    ///
+    /// `ptr` must be a valid pointer to a `NUL`-terminated C string, and it must
+    /// last at least `'a`. When `CStr` is alive, the memory pointed by `ptr`
+    /// must not be mutated.
+    #[inline]
+    pub unsafe fn from_char_ptr<'a>(ptr: *const core::ffi::c_char) -> &'a Self {
+        // SAFETY: The safety precondition guarantees `ptr` is a valid pointer
+        // to a `NUL`-terminated C string.
+        let len = unsafe { bindings::strlen(ptr) } + 1;
+        // SAFETY: Lifetime guaranteed by the safety precondition.
+        let bytes = unsafe { core::slice::from_raw_parts(ptr as _, len as _) };
+        // SAFETY: As `len` is returned by `strlen`, `bytes` does not contain interior `NUL`.
+        // As we have added 1 to `len`, the last byte is known to be `NUL`.
+        unsafe { Self::from_bytes_with_nul_unchecked(bytes) }
+    }
+
+    /// Creates a [`CStr`] from a `[u8]`.
+    ///
+    /// The provided slice must be `NUL`-terminated, does not contain any
+    /// interior `NUL` bytes.
+    pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, CStrConvertError> {
+        if bytes.is_empty() {
+            return Err(CStrConvertError::NotNulTerminated);
+        }
+        if bytes[bytes.len() - 1] != 0 {
+            return Err(CStrConvertError::NotNulTerminated);
+        }
+        let mut i = 0;
+        // `i + 1 < bytes.len()` allows LLVM to optimize away bounds checking,
+        // while it couldn't optimize away bounds checks for `i < bytes.len() - 1`.
+        while i + 1 < bytes.len() {
+            if bytes[i] == 0 {
+                return Err(CStrConvertError::InteriorNul);
+            }
+            i += 1;
+        }
+        // SAFETY: We just checked that all properties hold.
+        Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
+    }
+
+    /// Creates a [`CStr`] from a `[u8]`, panic if input is not valid.
+    ///
+    /// This function is only meant to be used by `c_str!` macro, so
+    /// crates using `c_str!` macro don't have to enable `const_panic` feature.
+    #[doc(hidden)]
+    pub const fn from_bytes_with_nul_unwrap(bytes: &[u8]) -> &Self {
+        match Self::from_bytes_with_nul(bytes) {
+            Ok(v) => v,
+            Err(_) => panic!("string contains interior NUL"),
+        }
+    }
+
+    /// Creates a [`CStr`] from a `[u8]` without performing any additional
+    /// checks.
+    ///
+    /// # Safety
+    ///
+    /// `bytes` *must* end with a `NUL` byte, and should only have a single
+    /// `NUL` byte (or the string will be truncated).
+    #[inline]
+    pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
+        // SAFETY: Properties of `bytes` guaranteed by the safety precondition.
+        unsafe { core::mem::transmute(bytes) }
+    }
+
+    /// Returns a C pointer to the string.
+    #[inline]
+    pub const fn as_char_ptr(&self) -> *const core::ffi::c_char {
+        self.0.as_ptr() as _
+    }
+
+    /// Convert the string to a byte slice without the trailing 0 byte.
+    #[inline]
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.0[..self.len()]
+    }
+
+    /// Convert the string to a byte slice containing the trailing 0 byte.
+    #[inline]
+    pub const fn as_bytes_with_nul(&self) -> &[u8] {
+        &self.0
+    }
+
+    /// Yields a [`&str`] slice if the [`CStr`] contains valid UTF-8.
+    ///
+    /// If the contents of the [`CStr`] are valid UTF-8 data, this
+    /// function will return the corresponding [`&str`] slice. Otherwise,
+    /// it will return an error with details of where UTF-8 validation failed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use kernel::str::CStr;
+    /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+    /// assert_eq!(cstr.to_str(), Ok("foo"));
+    /// ```
+    #[inline]
+    pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> {
+        core::str::from_utf8(self.as_bytes())
+    }
+
+    /// Unsafely convert this [`CStr`] into a [`&str`], without checking for
+    /// valid UTF-8.
+    ///
+    /// # Safety
+    ///
+    /// The contents must be valid UTF-8.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # use kernel::c_str;
+    /// # use kernel::str::CStr;
+    /// // SAFETY: String literals are guaranteed to be valid UTF-8
+    /// // by the Rust compiler.
+    /// let bar = c_str!("ツ");
+    /// assert_eq!(unsafe { bar.as_str_unchecked() }, "ツ");
+    /// ```
+    #[inline]
+    pub unsafe fn as_str_unchecked(&self) -> &str {
+        unsafe { core::str::from_utf8_unchecked(self.as_bytes()) }
+    }
+}
+
+impl fmt::Display for CStr {
+    /// Formats printable ASCII characters, escaping the rest.
+    ///
+    /// ```
+    /// # use kernel::c_str;
+    /// # use kernel::str::CStr;
+    /// # use kernel::str::CString;
+    /// let penguin = c_str!("🐧");
+    /// let s = CString::try_from_fmt(fmt!("{}", penguin)).unwrap();
+    /// assert_eq!(s.as_bytes_with_nul(), "\\xf0\\x9f\\x90\\xa7\0".as_bytes());
+    ///
+    /// let ascii = c_str!("so \"cool\"");
+    /// let s = CString::try_from_fmt(fmt!("{}", ascii)).unwrap();
+    /// assert_eq!(s.as_bytes_with_nul(), "so \"cool\"\0".as_bytes());
+    /// ```
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        for &c in self.as_bytes() {
+            if (0x20..0x7f).contains(&c) {
+                // Printable character.
+                f.write_char(c as char)?;
+            } else {
+                write!(f, "\\x{:02x}", c)?;
+            }
+        }
+        Ok(())
+    }
+}
+
+impl fmt::Debug for CStr {
+    /// Formats printable ASCII characters with a double quote on either end, escaping the rest.
+    ///
+    /// ```
+    /// # use kernel::c_str;
+    /// # use kernel::str::CStr;
+    /// # use kernel::str::CString;
+    /// let penguin = c_str!("🐧");
+    /// let s = CString::try_from_fmt(fmt!("{:?}", penguin)).unwrap();
+    /// assert_eq!(s.as_bytes_with_nul(), "\"\\xf0\\x9f\\x90\\xa7\"\0".as_bytes());
+    ///
+    /// // Embedded double quotes are escaped.
+    /// let ascii = c_str!("so \"cool\"");
+    /// let s = CString::try_from_fmt(fmt!("{:?}", ascii)).unwrap();
+    /// assert_eq!(s.as_bytes_with_nul(), "\"so \\\"cool\\\"\"\0".as_bytes());
+    /// ```
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("\"")?;
+        for &c in self.as_bytes() {
+            match c {
+                // Printable characters.
+                b'\"' => f.write_str("\\\"")?,
+                0x20..=0x7e => f.write_char(c as char)?,
+                _ => write!(f, "\\x{:02x}", c)?,
+            }
+        }
+        f.write_str("\"")
+    }
+}
+
+impl AsRef<BStr> for CStr {
+    #[inline]
+    fn as_ref(&self) -> &BStr {
+        self.as_bytes()
+    }
+}
+
+impl Deref for CStr {
+    type Target = BStr;
+
+    #[inline]
+    fn deref(&self) -> &Self::Target {
+        self.as_bytes()
+    }
+}
+
+impl Index<ops::RangeFrom<usize>> for CStr {
+    type Output = CStr;
+
+    #[inline]
+    fn index(&self, index: ops::RangeFrom<usize>) -> &Self::Output {
+        // Delegate bounds checking to slice.
+        // Assign to _ to mute clippy's unnecessary operation warning.
+        let _ = &self.as_bytes()[index.start..];
+        // SAFETY: We just checked the bounds.
+        unsafe { Self::from_bytes_with_nul_unchecked(&self.0[index.start..]) }
+    }
+}
+
+impl Index<ops::RangeFull> for CStr {
+    type Output = CStr;
+
+    #[inline]
+    fn index(&self, _index: ops::RangeFull) -> &Self::Output {
+        self
+    }
+}
+
+mod private {
+    use core::ops;
+
+    // Marker trait for index types that can be forward to `BStr`.
+    pub trait CStrIndex {}
+
+    impl CStrIndex for usize {}
+    impl CStrIndex for ops::Range<usize> {}
+    impl CStrIndex for ops::RangeInclusive<usize> {}
+    impl CStrIndex for ops::RangeToInclusive<usize> {}
+}
+
+impl<Idx> Index<Idx> for CStr
+where
+    Idx: private::CStrIndex,
+    BStr: Index<Idx>,
+{
+    type Output = <BStr as Index<Idx>>::Output;
+
+    #[inline]
+    fn index(&self, index: Idx) -> &Self::Output {
+        &self.as_bytes()[index]
+    }
+}
+
+/// Creates a new [`CStr`] from a string literal.
+///
+/// The string literal should not contain any `NUL` bytes.
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::c_str;
+/// # use kernel::str::CStr;
+/// const MY_CSTR: &CStr = c_str!("My awesome CStr!");
+/// ```
+#[macro_export]
+macro_rules! c_str {
+    ($str:expr) => {{
+        const S: &str = concat!($str, "\0");
+        const C: &$crate::str::CStr = $crate::str::CStr::from_bytes_with_nul_unwrap(S.as_bytes());
+        C
+    }};
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_cstr_to_str() {
+        let good_bytes = b"\xf0\x9f\xa6\x80\0";
+        let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
+        let checked_str = checked_cstr.to_str().unwrap();
+        assert_eq!(checked_str, "🦀");
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_cstr_to_str_panic() {
+        let bad_bytes = b"\xc3\x28\0";
+        let checked_cstr = CStr::from_bytes_with_nul(bad_bytes).unwrap();
+        checked_cstr.to_str().unwrap();
+    }
+
+    #[test]
+    fn test_cstr_as_str_unchecked() {
+        let good_bytes = b"\xf0\x9f\x90\xA7\0";
+        let checked_cstr = CStr::from_bytes_with_nul(good_bytes).unwrap();
+        let unchecked_str = unsafe { checked_cstr.as_str_unchecked() };
+        assert_eq!(unchecked_str, "🐧");
+    }
+}
+
+/// Allows formatting of [`fmt::Arguments`] into a raw buffer.
+///
+/// It does not fail if callers write past the end of the buffer so that they can calculate the
+/// size required to fit everything.
+///
+/// # Invariants
+///
+/// The memory region between `pos` (inclusive) and `end` (exclusive) is valid for writes if `pos`
+/// is less than `end`.
+pub(crate) struct RawFormatter {
+    // Use `usize` to use `saturating_*` functions.
+    beg: usize,
+    pos: usize,
+    end: usize,
+}
+
+impl RawFormatter {
+    /// Creates a new instance of [`RawFormatter`] with an empty buffer.
+    fn new() -> Self {
+        // INVARIANT: The buffer is empty, so the region that needs to be writable is empty.
+        Self {
+            beg: 0,
+            pos: 0,
+            end: 0,
+        }
+    }
+
+    /// Creates a new instance of [`RawFormatter`] with the given buffer pointers.
+    ///
+    /// # Safety
+    ///
+    /// If `pos` is less than `end`, then the region between `pos` (inclusive) and `end`
+    /// (exclusive) must be valid for writes for the lifetime of the returned [`RawFormatter`].
+    pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {
+        // INVARIANT: The safety requierments guarantee the type invariants.
+        Self {
+            beg: pos as _,
+            pos: pos as _,
+            end: end as _,
+        }
+    }
+
+    /// Creates a new instance of [`RawFormatter`] with the given buffer.
+    ///
+    /// # Safety
+    ///
+    /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes
+    /// for the lifetime of the returned [`RawFormatter`].
+    pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self {
+        let pos = buf as usize;
+        // INVARIANT: We ensure that `end` is never less then `buf`, and the safety requirements
+        // guarantees that the memory region is valid for writes.
+        Self {
+            pos,
+            beg: pos,
+            end: pos.saturating_add(len),
+        }
+    }
+
+    /// Returns the current insert position.
+    ///
+    /// N.B. It may point to invalid memory.
+    pub(crate) fn pos(&self) -> *mut u8 {
+        self.pos as _
+    }
+
+    /// Return the number of bytes written to the formatter.
+    pub(crate) fn bytes_written(&self) -> usize {
+        self.pos - self.beg
+    }
+}
+
+impl fmt::Write for RawFormatter {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        // `pos` value after writing `len` bytes. This does not have to be bounded by `end`, but we
+        // don't want it to wrap around to 0.
+        let pos_new = self.pos.saturating_add(s.len());
+
+        // Amount that we can copy. `saturating_sub` ensures we get 0 if `pos` goes past `end`.
+        let len_to_copy = core::cmp::min(pos_new, self.end).saturating_sub(self.pos);
+
+        if len_to_copy > 0 {
+            // SAFETY: If `len_to_copy` is non-zero, then we know `pos` has not gone past `end`
+            // yet, so it is valid for write per the type invariants.
+            unsafe {
+                core::ptr::copy_nonoverlapping(
+                    s.as_bytes().as_ptr(),
+                    self.pos as *mut u8,
+                    len_to_copy,
+                )
+            };
+        }
+
+        self.pos = pos_new;
+        Ok(())
+    }
+}
+
+/// Allows formatting of [`fmt::Arguments`] into a raw buffer.
+///
+/// Fails if callers attempt to write more than will fit in the buffer.
+pub(crate) struct Formatter(RawFormatter);
+
+impl Formatter {
+    /// Creates a new instance of [`Formatter`] with the given buffer.
+    ///
+    /// # Safety
+    ///
+    /// The memory region starting at `buf` and extending for `len` bytes must be valid for writes
+    /// for the lifetime of the returned [`Formatter`].
+    pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self {
+        // SAFETY: The safety requirements of this function satisfy those of the callee.
+        Self(unsafe { RawFormatter::from_buffer(buf, len) })
+    }
+}
+
+impl Deref for Formatter {
+    type Target = RawFormatter;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl fmt::Write for Formatter {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.0.write_str(s)?;
+
+        // Fail the request if we go past the end of the buffer.
+        if self.0.pos > self.0.end {
+            Err(fmt::Error)
+        } else {
+            Ok(())
+        }
+    }
+}
+
+/// An owned string that is guaranteed to have exactly one `NUL` byte, which is at the end.
+///
+/// Used for interoperability with kernel APIs that take C strings.
+///
+/// # Invariants
+///
+/// The string is always `NUL`-terminated and contains no other `NUL` bytes.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::str::CString;
+///
+/// let s = CString::try_from_fmt(fmt!("{}{}{}", "abc", 10, 20)).unwrap();
+/// assert_eq!(s.as_bytes_with_nul(), "abc1020\0".as_bytes());
+///
+/// let tmp = "testing";
+/// let s = CString::try_from_fmt(fmt!("{tmp}{}", 123)).unwrap();
+/// assert_eq!(s.as_bytes_with_nul(), "testing123\0".as_bytes());
+///
+/// // This fails because it has an embedded `NUL` byte.
+/// let s = CString::try_from_fmt(fmt!("a\0b{}", 123));
+/// assert_eq!(s.is_ok(), false);
+/// ```
+pub struct CString {
+    buf: Vec<u8>,
+}
+
+impl CString {
+    /// Creates an instance of [`CString`] from the given formatted arguments.
+    pub fn try_from_fmt(args: fmt::Arguments<'_>) -> Result<Self, Error> {
+        // Calculate the size needed (formatted string plus `NUL` terminator).
+        let mut f = RawFormatter::new();
+        f.write_fmt(args)?;
+        f.write_str("\0")?;
+        let size = f.bytes_written();
+
+        // Allocate a vector with the required number of bytes, and write to it.
+        let mut buf = Vec::try_with_capacity(size)?;
+        // SAFETY: The buffer stored in `buf` is at least of size `size` and is valid for writes.
+        let mut f = unsafe { Formatter::from_buffer(buf.as_mut_ptr(), size) };
+        f.write_fmt(args)?;
+        f.write_str("\0")?;
+
+        // SAFETY: The number of bytes that can be written to `f` is bounded by `size`, which is
+        // `buf`'s capacity. The contents of the buffer have been initialised by writes to `f`.
+        unsafe { buf.set_len(f.bytes_written()) };
+
+        // Check that there are no `NUL` bytes before the end.
+        // SAFETY: The buffer is valid for read because `f.bytes_written()` is bounded by `size`
+        // (which the minimum buffer size) and is non-zero (we wrote at least the `NUL` terminator)
+        // so `f.bytes_written() - 1` doesn't underflow.
+        let ptr = unsafe { bindings::memchr(buf.as_ptr().cast(), 0, (f.bytes_written() - 1) as _) };
+        if !ptr.is_null() {
+            return Err(EINVAL);
+        }
+
+        // INVARIANT: We wrote the `NUL` terminator and checked above that no other `NUL` bytes
+        // exist in the buffer.
+        Ok(Self { buf })
+    }
+}
+
+impl Deref for CString {
+    type Target = CStr;
+
+    fn deref(&self) -> &Self::Target {
+        // SAFETY: The type invariants guarantee that the string is `NUL`-terminated and that no
+        // other `NUL` bytes exist.
+        unsafe { CStr::from_bytes_with_nul_unchecked(self.buf.as_slice()) }
+    }
+}
+
+/// A convenience alias for [`core::format_args`].
+#[macro_export]
+macro_rules! fmt {
+    ($($f:tt)*) => ( core::format_args!($($f)*) )
+}
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index dbf705d573e6..255a4928a47a 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -22,7 +22,7 @@
 //! ```
 
 use crate::{bindings, str::CStr};
-use core::pin::Pin;
+use core::{cell::UnsafeCell, mem::MaybeUninit, pin::Pin};
 
 mod arc;
 mod condvar;
@@ -30,13 +30,14 @@ mod guard;
 mod locked_by;
 mod mutex;
 mod nowait;
+pub mod rcu;
 mod revocable;
 mod rwsem;
 mod seqlock;
 pub mod smutex;
 mod spinlock;
 
-pub use arc::{Ref, RefBorrow, UniqueRef};
+pub use arc::{new_refcount, Ref, RefBorrow, StaticRef, UniqueRef};
 pub use condvar::CondVar;
 pub use guard::{Guard, Lock, LockFactory, LockInfo, LockIniter, ReadLock, WriteLock};
 pub use locked_by::LockedBy;
@@ -47,6 +48,25 @@ pub use rwsem::{RevocableRwSemaphore, RevocableRwSemaphoreGuard, RwSemaphore};
 pub use seqlock::{SeqLock, SeqLockReadGuard};
 pub use spinlock::{RawSpinLock, SpinLock};
 
+/// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
+#[repr(transparent)]
+pub struct LockClassKey(UnsafeCell<MaybeUninit<bindings::lock_class_key>>);
+
+// SAFETY: This is a wrapper around a lock class key, so it is safe to use references to it from
+// any thread.
+unsafe impl Sync for LockClassKey {}
+
+impl LockClassKey {
+    /// Creates a new lock class key.
+    pub const fn new() -> Self {
+        Self(UnsafeCell::new(MaybeUninit::uninit()))
+    }
+
+    pub(crate) fn get(&self) -> *mut bindings::lock_class_key {
+        self.0.get().cast()
+    }
+}
+
 /// Safely initialises an object that has an `init` function that takes a name and a lock class as
 /// arguments, examples of these are [`Mutex`] and [`SpinLock`]. Each of them also provides a more
 /// specialised name that uses this macro.
@@ -54,18 +74,11 @@ pub use spinlock::{RawSpinLock, SpinLock};
 #[macro_export]
 macro_rules! init_with_lockdep {
     ($obj:expr, $name:expr) => {{
-        static mut CLASS1: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
-            core::mem::MaybeUninit::uninit();
-        static mut CLASS2: core::mem::MaybeUninit<$crate::bindings::lock_class_key> =
-            core::mem::MaybeUninit::uninit();
+        static CLASS1: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        static CLASS2: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
         let obj = $obj;
         let name = $crate::c_str!($name);
-        // SAFETY: `CLASS1` and `CLASS2` are never used by Rust code directly; the C portion of the
-        // kernel may change it though.
-        #[allow(unused_unsafe)]
-        unsafe {
-            $crate::sync::NeedsLockClass::init(obj, name, CLASS1.as_mut_ptr(), CLASS2.as_mut_ptr())
-        };
+        $crate::sync::NeedsLockClass::init(obj, name, &CLASS1, &CLASS2)
     }};
 }
 
@@ -78,16 +91,11 @@ pub trait NeedsLockClass {
     ///
     /// Callers are encouraged to use the [`init_with_lockdep`] macro as it automatically creates a
     /// new lock class on each usage.
-    ///
-    /// # Safety
-    ///
-    /// `key1` and `key2` must point to valid memory locations and remain valid until `self` is
-    /// dropped.
-    unsafe fn init(
+    fn init(
         self: Pin<&mut Self>,
         name: &'static CStr,
-        key1: *mut bindings::lock_class_key,
-        key2: *mut bindings::lock_class_key,
+        key1: &'static LockClassKey,
+        key2: &'static LockClassKey,
     );
 }
 
diff --git a/rust/kernel/sysctl.rs b/rust/kernel/sysctl.rs
new file mode 100644
index 000000000000..8f742d60037d
--- /dev/null
+++ b/rust/kernel/sysctl.rs
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! System control.
+//!
+//! C header: [`include/linux/sysctl.h`](../../../../include/linux/sysctl.h)
+//!
+//! Reference: <https://www.kernel.org/doc/Documentation/sysctl/README>
+
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::mem;
+use core::ptr;
+use core::sync::atomic;
+
+use crate::{
+    bindings,
+    error::code::*,
+    io_buffer::IoBufferWriter,
+    str::CStr,
+    types,
+    user_ptr::{UserSlicePtr, UserSlicePtrWriter},
+    Result,
+};
+
+/// Sysctl storage.
+pub trait SysctlStorage: Sync {
+    /// Writes a byte slice.
+    fn store_value(&self, data: &[u8]) -> (usize, Result);
+
+    /// Reads via a [`UserSlicePtrWriter`].
+    fn read_value(&self, data: &mut UserSlicePtrWriter) -> (usize, Result);
+}
+
+fn trim_whitespace(mut data: &[u8]) -> &[u8] {
+    while !data.is_empty() && (data[0] == b' ' || data[0] == b'\t' || data[0] == b'\n') {
+        data = &data[1..];
+    }
+    while !data.is_empty()
+        && (data[data.len() - 1] == b' '
+            || data[data.len() - 1] == b'\t'
+            || data[data.len() - 1] == b'\n')
+    {
+        data = &data[..data.len() - 1];
+    }
+    data
+}
+
+impl<T> SysctlStorage for &T
+where
+    T: SysctlStorage,
+{
+    fn store_value(&self, data: &[u8]) -> (usize, Result) {
+        (*self).store_value(data)
+    }
+
+    fn read_value(&self, data: &mut UserSlicePtrWriter) -> (usize, Result) {
+        (*self).read_value(data)
+    }
+}
+
+impl SysctlStorage for atomic::AtomicBool {
+    fn store_value(&self, data: &[u8]) -> (usize, Result) {
+        let result = match trim_whitespace(data) {
+            b"0" => {
+                self.store(false, atomic::Ordering::Relaxed);
+                Ok(())
+            }
+            b"1" => {
+                self.store(true, atomic::Ordering::Relaxed);
+                Ok(())
+            }
+            _ => Err(EINVAL),
+        };
+        (data.len(), result)
+    }
+
+    fn read_value(&self, data: &mut UserSlicePtrWriter) -> (usize, Result) {
+        let value = if self.load(atomic::Ordering::Relaxed) {
+            b"1\n"
+        } else {
+            b"0\n"
+        };
+        (value.len(), data.write_slice(value))
+    }
+}
+
+/// Holds a single `sysctl` entry (and its table).
+pub struct Sysctl<T: SysctlStorage> {
+    inner: Box<T>,
+    // Responsible for keeping the `ctl_table` alive.
+    _table: Box<[bindings::ctl_table]>,
+    header: *mut bindings::ctl_table_header,
+}
+
+// SAFETY: The only public method we have is `get()`, which returns `&T`, and
+// `T: Sync`. Any new methods must adhere to this requirement.
+unsafe impl<T: SysctlStorage> Sync for Sysctl<T> {}
+
+unsafe extern "C" fn proc_handler<T: SysctlStorage>(
+    ctl: *mut bindings::ctl_table,
+    write: core::ffi::c_int,
+    buffer: *mut core::ffi::c_void,
+    len: *mut usize,
+    ppos: *mut bindings::loff_t,
+) -> core::ffi::c_int {
+    // If we are reading from some offset other than the beginning of the file,
+    // return an empty read to signal EOF.
+    if unsafe { *ppos } != 0 && write == 0 {
+        unsafe { *len = 0 };
+        return 0;
+    }
+
+    let data = unsafe { UserSlicePtr::new(buffer, *len) };
+    let storage = unsafe { &*((*ctl).data as *const T) };
+    let (bytes_processed, result) = if write != 0 {
+        let data = match data.read_all() {
+            Ok(r) => r,
+            Err(e) => return e.to_kernel_errno(),
+        };
+        storage.store_value(&data)
+    } else {
+        let mut writer = data.writer();
+        storage.read_value(&mut writer)
+    };
+    unsafe { *len = bytes_processed };
+    unsafe { *ppos += *len as bindings::loff_t };
+    match result {
+        Ok(()) => 0,
+        Err(e) => e.to_kernel_errno(),
+    }
+}
+
+impl<T: SysctlStorage> Sysctl<T> {
+    /// Registers a single entry in `sysctl`.
+    pub fn register(
+        path: &'static CStr,
+        name: &'static CStr,
+        storage: T,
+        mode: types::Mode,
+    ) -> Result<Sysctl<T>> {
+        if name.contains(&b'/') {
+            return Err(EINVAL);
+