Merge tag 'mm-nonmm-stable-2023-04-27-16-01' of git://git.kernel.org/pub/scm/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Apr 2023 02:57:00 +0000 (19:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Apr 2023 02:57:00 +0000 (19:57 -0700)
Pull non-MM updates from Andrew Morton:
 "Mainly singleton patches all over the place.

  Series of note are:

   - updates to scripts/gdb from Glenn Washburn

   - kexec cleanups from Bjorn Helgaas"

* tag 'mm-nonmm-stable-2023-04-27-16-01' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (50 commits)
  mailmap: add entries for Paul Mackerras
  libgcc: add forward declarations for generic library routines
  mailmap: add entry for Oleksandr
  ocfs2: reduce ioctl stack usage
  fs/proc: add Kthread flag to /proc/$pid/status
  ia64: fix an addr to taddr in huge_pte_offset()
  checkpatch: introduce proper bindings license check
  epoll: rename global epmutex
  scripts/gdb: add GDB convenience functions $lx_dentry_name() and $lx_i_dentry()
  scripts/gdb: create linux/vfs.py for VFS related GDB helpers
  uapi/linux/const.h: prefer ISO-friendly __typeof__
  delayacct: track delays from IRQ/SOFTIRQ
  scripts/gdb: timerlist: convert int chunks to str
  scripts/gdb: print interrupts
  scripts/gdb: raise error with reduced debugging information
  scripts/gdb: add a Radix Tree Parser
  lib/rbtree: use '+' instead of '|' for setting color.
  proc/stat: remove arch_idle_time()
  checkpatch: check for misuse of the link tags
  checkpatch: allow Closes tags with links
  ...

15 files changed:
1  2 
.mailmap
Documentation/filesystems/proc.rst
Documentation/process/submitting-patches.rst
MAINTAINERS
arch/ia64/mm/hugetlbpage.c
fs/binfmt_elf.c
fs/eventpoll.c
fs/nfs/nfs3acl.c
fs/proc/base.c
fs/proc/proc_sysctl.c
kernel/sched/core.c
scripts/checkpatch.pl
scripts/gdb/linux/constants.py.in
tools/lib/bpf/libbpf.c
tools/lib/bpf/usdt.c

diff --combined .mailmap
+++ b/.mailmap
@@@ -232,8 -232,6 +232,8 @@@ Johan Hovold <johan@kernel.org> <johan@
  John Crispin <john@phrozen.org> <blogic@openwrt.org>
  John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
  John Stultz <johnstul@us.ibm.com>
 +<jon.toppins+linux@gmail.com> <jtoppins@cumulusnetworks.com>
 +<jon.toppins+linux@gmail.com> <jtoppins@redhat.com>
  Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>
  <josh@joshtriplett.org> <josh@freedesktop.org>
  <josh@joshtriplett.org> <josh@kernel.org>
@@@ -267,9 -265,7 +267,9 @@@ Krzysztof Kozlowski <krzk@kernel.org> <
  Krzysztof Kozlowski <krzk@kernel.org> <krzysztof.kozlowski@canonical.com>
  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org>
 +Leonard Crestez <leonard.crestez@nxp.com> Leonard Crestez <cdleonard@gmail.com>
  Leonardo Bras <leobras.c@gmail.com> <leonardo@linux.ibm.com>
 +Leonard Göhrs <l.goehrs@pengutronix.de>
  Leonid I Ananiev <leonid.i.ananiev@intel.com>
  Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
  Leon Romanovsky <leon@kernel.org> <leonro@mellanox.com>
@@@ -299,8 -295,6 +299,8 @@@ Martin Kepplinger <martink@posteo.de> <
  Martin Kepplinger <martink@posteo.de> <martin.kepplinger@theobroma-systems.com>
  Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com> <martyna.szapar-mudlaw@intel.com>
  Mathieu Othacehe <m.othacehe@gmail.com>
 +Mat Martineau <martineau@kernel.org> <mathew.j.martineau@linux.intel.com>
 +Mat Martineau <martineau@kernel.org> <mathewm@codeaurora.org>
  Matthew Wilcox <willy@infradead.org> <matthew.r.wilcox@intel.com>
  Matthew Wilcox <willy@infradead.org> <matthew@wil.cx>
  Matthew Wilcox <willy@infradead.org> <mawilcox@linuxonhyperv.com>
@@@ -360,6 -354,7 +360,7 @@@ Nicolas Pitre <nico@fluxnic.net> <nico@
  Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.de>
  Nicolas Saenz Julienne <nsaenz@kernel.org> <nsaenzjulienne@suse.com>
  Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+ Oleksandr Natalenko <oleksandr@natalenko.name> <oleksandr@redhat.com>
  Oleksij Rempel <linux@rempel-privat.de> <bug-track@fisher-privat.net>
  Oleksij Rempel <linux@rempel-privat.de> <external.Oleksij.Rempel@de.bosch.com>
  Oleksij Rempel <linux@rempel-privat.de> <fixed-term.Oleksij.Rempel@de.bosch.com>
@@@ -375,6 -370,8 +376,8 @@@ Paul E. McKenney <paulmck@kernel.org> <
  Paul E. McKenney <paulmck@kernel.org> <paulmck@linux.ibm.com>
  Paul E. McKenney <paulmck@kernel.org> <paulmck@linux.vnet.ibm.com>
  Paul E. McKenney <paulmck@kernel.org> <paulmck@us.ibm.com>
+ Paul Mackerras <paulus@ozlabs.org> <paulus@samba.org>
+ Paul Mackerras <paulus@ozlabs.org> <paulus@au1.ibm.com>
  Peter A Jonsson <pj@ludd.ltu.se>
  Peter Oruba <peter.oruba@amd.com>
  Peter Oruba <peter@oruba.de>
@@@ -85,7 -85,7 +85,7 @@@ contact Bodo  Bauer  at  bb@ricochet.ne
  document.
  
  The   latest   version    of   this   document   is    available   online   at
 -http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/proc.html
 +https://www.kernel.org/doc/html/latest/filesystems/proc.html
  
  If  the above  direction does  not works  for you,  you could  try the  kernel
  mailing  list  at  linux-kernel@vger.kernel.org  and/or try  to  reach  me  at
@@@ -179,6 -179,7 +179,7 @@@ read the file /proc/PID/status:
    Gid:    100     100     100     100
    FDSize: 256
    Groups: 100 14 16
+   Kthread:    0
    VmPeak:     5004 kB
    VmSize:     5004 kB
    VmLck:         0 kB
@@@ -232,7 -233,7 +233,7 @@@ asynchronous manner and the value may n
  snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
  It's slow but very precise.
  
 -.. table:: Table 1-2: Contents of the status files (as of 4.19)
 +.. table:: Table 1-2: Contents of the status fields (as of 4.19)
  
   ==========================  ===================================================
   Field                       Content
   NSpid                       descendant namespace process ID hierarchy
   NSpgid                      descendant namespace process group ID hierarchy
   NSsid                       descendant namespace session ID hierarchy
+  Kthread                     kernel thread flag, 1 is yes, 0 is no
   VmPeak                      peak virtual memory size
   VmSize                      total program size
   VmLck                       locked memory size
   ==========================  ===================================================
  
  
 -.. table:: Table 1-3: Contents of the statm files (as of 2.6.8-rc3)
 +.. table:: Table 1-3: Contents of the statm fields (as of 2.6.8-rc3)
  
   ======== ===============================     ==============================
   Field    Content
   ======== ===============================     ==============================
  
  
 -.. table:: Table 1-4: Contents of the stat files (as of 2.6.30-rc7)
 +.. table:: Table 1-4: Contents of the stat fields (as of 2.6.30-rc7)
  
    ============= ===============================================================
    Field         Content
@@@ -996,7 -998,6 +998,7 @@@ Example output. You may not have all o
      VmallocUsed:       40444 kB
      VmallocChunk:          0 kB
      Percpu:            29312 kB
 +    EarlyMemtestBad:       0 kB
      HardwareCorrupted:     0 kB
      AnonHugePages:   4149248 kB
      ShmemHugePages:        0 kB
@@@ -1147,13 -1148,6 +1149,13 @@@ VmallocChun
  Percpu
                Memory allocated to the percpu allocator used to back percpu
                allocations. This stat excludes the cost of metadata.
 +EarlyMemtestBad
 +              The amount of RAM/memory in kB, that was identified as corrupted
 +              by early memtest. If memtest was not run, this field will not
 +              be displayed at all. Size is never rounded down to 0 kB.
 +              That means if 0 kB is reported, you can safely assume
 +              there was at least one pass of memtest and none of the passes
 +              found a single faulty byte of RAM.
  HardwareCorrupted
                The amount of RAM/memory in KB, the kernel identifies as
                corrupted.
@@@ -1329,9 -1323,9 +1331,9 @@@ many times the slaves link has failed
  1.4 SCSI info
  -------------
  
 -If you  have  a  SCSI  host adapter in your system, you'll find a subdirectory
 -named after  the driver for this adapter in /proc/scsi. You'll also see a list
 -of all recognized SCSI devices in /proc/scsi::
 +If you have a SCSI or ATA host adapter in your system, you'll find a
 +subdirectory named after the driver for this adapter in /proc/scsi.
 +You'll also see a list of all recognized SCSI devices in /proc/scsi::
  
    >cat /proc/scsi/scsi
    Attached devices:
@@@ -1457,18 -1451,16 +1459,18 @@@ Various pieces   of  information abou
  since the system first booted.  For a quick look, simply cat the file::
  
    > cat /proc/stat
 -  cpu  2255 34 2290 22625563 6290 127 456 0 0 0
 -  cpu0 1132 34 1441 11311718 3675 127 438 0 0 0
 -  cpu1 1123 0 849 11313845 2614 0 18 0 0 0
 -  intr 114930548 113199788 3 0 5 263 0 4 [... lots more numbers ...]
 -  ctxt 1990473
 -  btime 1062191376
 -  processes 2915
 -  procs_running 1
 +  cpu  237902850 368826709 106375398 1873517540 1135548 0 14507935 0 0 0
 +  cpu0 60045249 91891769 26331539 468411416 495718 0 5739640 0 0 0
 +  cpu1 59746288 91759249 26609887 468860630 312281 0 4384817 0 0 0
 +  cpu2 59489247 92985423 26904446 467808813 171668 0 2268998 0 0 0
 +  cpu3 58622065 92190267 26529524 468436680 155879 0 2114478 0 0 0
 +  intr 8688370575 8 3373 0 0 0 0 0 0 1 40791 0 0 353317 0 0 0 0 224789828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190974333 41958554 123983334 43 0 224593 0 0 0 <more 0's deleted>
 +  ctxt 22848221062
 +  btime 1605316999
 +  processes 746787147
 +  procs_running 2
    procs_blocked 0
 -  softirq 183433 0 21755 12 39 1137 231 21459 2263
 +  softirq 12121874454 100099120 3938138295 127375644 2795979 187870761 0 173808342 3072582055 52608 224184354
  
  The very first  "cpu" line aggregates the  numbers in all  of the other "cpuN"
  lines.  These numbers identify the amount of time the CPU has spent performing
@@@ -1530,8 -1522,8 +1532,8 @@@ softirq
  Information about mounted ext4 file systems can be found in
  /proc/fs/ext4.  Each mounted filesystem will have a directory in
  /proc/fs/ext4 based on its device name (i.e., /proc/fs/ext4/hdc or
 -/proc/fs/ext4/dm-0).   The files in each per-device directory are shown
 -in Table 1-12, below.
 +/proc/fs/ext4/sda9 or /proc/fs/ext4/dm-0).   The files in each per-device
 +directory are shown in Table 1-12, below.
  
  .. table:: Table 1-12: Files in /proc/fs/ext4/<devname>
  
@@@ -1611,12 -1603,12 +1613,12 @@@ can inadvertently  disrupt  your  syste
  documentation and  source  before actually making adjustments. In any case, be
  very careful  when  writing  to  any  of these files. The entries in /proc may
  change slightly between the 2.1.* and the 2.2 kernel, so if there is any doubt
 -review the kernel documentation in the directory /usr/src/linux/Documentation.
 +review the kernel documentation in the directory linux/Documentation.
  This chapter  is  heavily  based  on the documentation included in the pre 2.2
  kernels, and became part of it in version 2.2.1 of the Linux kernel.
  
 -Please see: Documentation/admin-guide/sysctl/ directory for descriptions of these
 -entries.
 +Please see: Documentation/admin-guide/sysctl/ directory for descriptions of
 +these entries.
  
  Summary
  -------
@@@ -113,11 -113,9 +113,9 @@@ there is no collision with your six-cha
  change five years from now.
  
  If related discussions or any other background information behind the change
- can be found on the web, add 'Link:' tags pointing to it. In case your patch
- fixes a bug, for example, add a tag with a URL referencing the report in the
- mailing list archives or a bug tracker; if the patch is a result of some
- earlier mailing list discussion or something documented on the web, point to
- it.
+ can be found on the web, add 'Link:' tags pointing to it. If the patch is a
+ result of some earlier mailing list discussions or something documented on the
+ web, point to it.
  
  When linking to mailing list archives, preferably use the lore.kernel.org
  message archiver service. To create the link URL, use the contents of the
@@@ -134,6 -132,16 +132,16 @@@ resources. In addition to giving a URL 
  summarize the relevant points of the discussion that led to the
  patch as submitted.
  
+ In case your patch fixes a bug, use the 'Closes:' tag with a URL referencing
+ the report in the mailing list archives or a public bug tracker. For example::
+       Closes: https://example.com/issues/1234
+ Some bug trackers have the ability to close issues automatically when a
+ commit with such a tag is applied. Some bots monitoring mailing lists can
+ also track such tags and take certain actions. Private bug trackers and
+ invalid URLs are forbidden.
  If your patch fixes a bug in a specific commit, e.g. you found an issue using
  ``git bisect``, please use the 'Fixes:' tag with the first 12 characters of
  the SHA-1 ID, and the one line summary.  Do not split the tag across multiple
@@@ -223,17 -231,20 +231,17 @@@ patch
  Select the recipients for your patch
  ------------------------------------
  
 -You should always copy the appropriate subsystem maintainer(s) on any patch
 -to code that they maintain; look through the MAINTAINERS file and the
 -source code revision history to see who those maintainers are.  The
 -script scripts/get_maintainer.pl can be very useful at this step (pass paths to
 -your patches as arguments to scripts/get_maintainer.pl).  If you cannot find a
 +You should always copy the appropriate subsystem maintainer(s) and list(s) on
 +any patch to code that they maintain; look through the MAINTAINERS file and the
 +source code revision history to see who those maintainers are.  The script
 +scripts/get_maintainer.pl can be very useful at this step (pass paths to your
 +patches as arguments to scripts/get_maintainer.pl).  If you cannot find a
  maintainer for the subsystem you are working on, Andrew Morton
  (akpm@linux-foundation.org) serves as a maintainer of last resort.
  
 -You should also normally choose at least one mailing list to receive a copy
 -of your patch set.  linux-kernel@vger.kernel.org should be used by default
 -for all patches, but the volume on that list has caused a number of
 -developers to tune it out.  Look in the MAINTAINERS file for a
 -subsystem-specific list; your patch will probably get more attention there.
 -Please do not spam unrelated lists, though.
 +linux-kernel@vger.kernel.org should be used by default for all patches, but the
 +volume on that list has caused a number of developers to tune it out.  Please
 +do not spam unrelated lists and unrelated people, though.
  
  Many kernel-related lists are hosted on vger.kernel.org; you can find a
  list of them at http://vger.kernel.org/vger-lists.html.  There are
@@@ -495,9 -506,11 +503,11 @@@ Using Reported-by:, Tested-by:, Reviewe
  The Reported-by tag gives credit to people who find bugs and report them and it
  hopefully inspires them to help us again in the future. The tag is intended for
  bugs; please do not use it to credit feature requests. The tag should be
- followed by a Link: tag pointing to the report, unless the report is not
- available on the web. Please note that if the bug was reported in private, then
- ask for permission first before using the Reported-by tag.
+ followed by a Closes: tag pointing to the report, unless the report is not
+ available on the web. The Link: tag can be used instead of Closes: if the patch
+ fixes a part of the issue(s) being reported. Please note that if the bug was
+ reported in private, then ask for permission first before using the Reported-by
+ tag.
  
  A Tested-by: tag indicates that the patch has been successfully tested (in
  some environment) by the person named.  This tag informs maintainers that
diff --combined MAINTAINERS
@@@ -224,13 -224,13 +224,13 @@@ S:      Orphan / Obsolet
  F:    drivers/net/ethernet/8390/
  
  9P FILE SYSTEM
 -M:    Eric Van Hensbergen <ericvh@gmail.com>
 +M:    Eric Van Hensbergen <ericvh@kernel.org>
  M:    Latchesar Ionkov <lucho@ionkov.net>
  M:    Dominique Martinet <asmadeus@codewreck.org>
  R:    Christian Schoenebeck <linux_oss@crudebyte.com>
 -L:    v9fs-developer@lists.sourceforge.net
 +L:    v9fs@lists.linux.dev
  S:    Maintained
 -W:    http://swik.net/v9fs
 +W:    http://github.com/v9fs
  Q:    http://patchwork.kernel.org/project/v9fs-devel/list/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git
  T:    git git://github.com/martinetd/linux.git
@@@ -964,14 -964,6 +964,14 @@@ Q:       https://patchwork.kernel.org/project
  F:    drivers/infiniband/hw/efa/
  F:    include/uapi/rdma/efa-abi.h
  
 +AMD CDX BUS DRIVER
 +M:    Nipun Gupta <nipun.gupta@amd.com>
 +M:    Nikhil Agarwal <nikhil.agarwal@amd.com>
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/bus/xlnx,versal-net-cdx.yaml
 +F:    drivers/cdx/*
 +F:    include/linux/cdx/*
 +
  AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER
  M:    Tom Lendacky <thomas.lendacky@amd.com>
  M:    John Allen <john.allen@amd.com>
@@@ -1049,15 -1041,6 +1049,15 @@@ F:    drivers/gpu/drm/amd/include/vi_struc
  F:    include/uapi/linux/kfd_ioctl.h
  F:    include/uapi/linux/kfd_sysfs.h
  
 +AMD PDS CORE DRIVER
 +M:    Shannon Nelson <shannon.nelson@amd.com>
 +M:    Brett Creeley <brett.creeley@amd.com>
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    Documentation/networking/device_drivers/ethernet/amd/pds_core.rst
 +F:    drivers/net/ethernet/amd/pds_core/
 +F:    include/linux/pds/
 +
  AMD SPI DRIVER
  M:    Sanjay R Mehta <sanju.mehta@amd.com>
  S:    Maintained
@@@ -1088,7 -1071,7 +1088,7 @@@ M:      Naveen Krishna Chatradhi <naveenkris
  R:    Carlos Bilbao <carlos.bilbao@amd.com>
  L:    platform-driver-x86@vger.kernel.org
  S:    Maintained
 -F:    Documentation/x86/amd_hsmp.rst
 +F:    Documentation/arch/x86/amd_hsmp.rst
  F:    arch/x86/include/asm/amd_hsmp.h
  F:    arch/x86/include/uapi/asm/amd_hsmp.h
  F:    drivers/platform/x86/amd/hsmp.c
@@@ -1244,6 -1227,12 +1244,6 @@@ F:     Documentation/devicetree/bindings/ii
  F:    drivers/iio/addac/ad74413r.c
  F:    include/dt-bindings/iio/addac/adi,ad74413r.h
  
 -ANALOG DEVICES INC AD9389B DRIVER
 -M:    Hans Verkuil <hverkuil-cisco@xs4all.nl>
 -L:    linux-media@vger.kernel.org
 -S:    Maintained
 -F:    drivers/media/i2c/ad9389b*
 -
  ANALOG DEVICES INC ADA4250 DRIVER
  M:    Antoniu Miclaus <antoniu.miclaus@analog.com>
  L:    linux-iio@vger.kernel.org
@@@ -1439,6 -1428,11 +1439,6 @@@ S:     Supporte
  F:    drivers/clk/analogbits/*
  F:    include/linux/clk/analogbits*
  
 -ANDROID CONFIG FRAGMENTS
 -M:    Rob Herring <robh@kernel.org>
 -S:    Supported
 -F:    kernel/configs/android*
 -
  ANDROID DRIVERS
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  M:    Arve Hjønnevåg <arve@android.com>
@@@ -2078,7 -2072,6 +2078,7 @@@ M:      Alexander Sverdlin <alexander.sverdl
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  F:    Documentation/devicetree/bindings/iio/adc/cirrus,ep9301-adc.yaml
 +F:    Documentation/devicetree/bindings/sound/cirrus,ep9301-*
  F:    arch/arm/boot/compressed/misc-ep93xx.h
  F:    arch/arm/mach-ep93xx/
  F:    drivers/iio/adc/ep93xx_adc.c
@@@ -2098,6 -2091,7 +2098,6 @@@ F:      arch/arm/boot/dts/cx92755
  N:    digicolor
  
  ARM/CORESIGHT FRAMEWORK AND DRIVERS
 -M:    Mathieu Poirier <mathieu.poirier@linaro.org>
  M:    Suzuki K Poulose <suzuki.poulose@arm.com>
  R:    Mike Leach <mike.leach@linaro.org>
  R:    Leo Yan <leo.yan@linaro.org>
@@@ -2281,7 -2275,7 +2281,7 @@@ F:      arch/arm/boot/dts/intel-ixp
  F:    arch/arm/mach-ixp4xx/
  F:    drivers/bus/intel-ixp4xx-eb.c
  F:    drivers/clocksource/timer-ixp4xx.c
 -F:    drivers/crypto/ixp4xx_crypto.c
 +F:    drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
  F:    drivers/gpio/gpio-ixp4xx.c
  F:    drivers/irqchip/irq-ixp4xx.c
  
@@@ -2610,12 -2604,6 +2610,12 @@@ F:    include/dt-bindings/*/qcom
  F:    include/linux/*/qcom*
  F:    include/linux/soc/qcom/
  
 +ARM/QUALCOMM CHROMEBOOK SUPPORT
 +R:    cros-qcom-dts-watchers@chromium.org
 +F:    arch/arm64/boot/dts/qcom/sc7180*
 +F:    arch/arm64/boot/dts/qcom/sc7280*
 +F:    arch/arm64/boot/dts/qcom/sdm845-cheza*
 +
  ARM/RDA MICRO ARCHITECTURE
  M:    Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -2666,7 -2654,6 +2666,7 @@@ F:      arch/arm64/boot/dts/renesas
  F:    arch/riscv/boot/dts/renesas/
  F:    drivers/soc/renesas/
  F:    include/linux/soc/renesas/
 +K:    \brenesas,
  
  ARM/RISCPC ARCHITECTURE
  M:    Russell King <linux@armlinux.org.uk>
@@@ -4444,13 -4431,6 +4444,13 @@@ S:    Maintaine
  F:    drivers/scsi/BusLogic.*
  F:    drivers/scsi/FlashPoint.*
  
 +BXCAN CAN NETWORK DRIVER
 +M:    Dario Binacchi <dario.binacchi@amarulasolutions.com>
 +L:    linux-can@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/net/can/st,stm32-bxcan.yaml
 +F:    drivers/net/can/bxcan.c
 +
  C-MEDIA CMI8788 DRIVER
  M:    Clemens Ladisch <clemens@ladisch.de>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
@@@ -4481,14 -4461,14 +4481,14 @@@ F:   Documentation/devicetree/bindings/ne
  F:    drivers/net/ieee802154/ca8210.c
  
  CANAAN/KENDRYTE K210 SOC FPIOA DRIVER
 -M:    Damien Le Moal <damien.lemoal@wdc.com>
 +M:    Damien Le Moal <dlemoal@kernel.org>
  L:    linux-riscv@lists.infradead.org
  L:    linux-gpio@vger.kernel.org (pinctrl driver)
  F:    Documentation/devicetree/bindings/pinctrl/canaan,k210-fpioa.yaml
  F:    drivers/pinctrl/pinctrl-k210.c
  
  CANAAN/KENDRYTE K210 SOC RESET CONTROLLER DRIVER
 -M:    Damien Le Moal <damien.lemoal@wdc.com>
 +M:    Damien Le Moal <dlemoal@kernel.org>
  L:    linux-kernel@vger.kernel.org
  L:    linux-riscv@lists.infradead.org
  S:    Maintained
@@@ -4496,7 -4476,7 +4496,7 @@@ F:      Documentation/devicetree/bindings/re
  F:    drivers/reset/reset-k210.c
  
  CANAAN/KENDRYTE K210 SOC SYSTEM CONTROLLER DRIVER
 -M:    Damien Le Moal <damien.lemoal@wdc.com>
 +M:    Damien Le Moal <dlemoal@kernel.org>
  L:    linux-riscv@lists.infradead.org
  S:    Maintained
  F:      Documentation/devicetree/bindings/mfd/canaan,k210-sysctl.yaml
@@@ -4925,7 -4905,6 +4925,7 @@@ L:      patches@opensource.cirrus.co
  S:    Maintained
  F:    Documentation/devicetree/bindings/sound/cirrus,cs*
  F:    include/dt-bindings/sound/cs*
 +F:    include/sound/cs*
  F:    sound/pci/hda/cs*
  F:    sound/pci/hda/hda_cs_dsp_ctl.*
  F:    sound/soc/codecs/cs*
@@@ -5961,6 -5940,11 +5961,6 @@@ F:     drivers/devfreq/event
  F:    include/dt-bindings/pmu/exynos_ppmu.h
  F:    include/linux/devfreq-event.h
  
 -DEVICE NUMBER REGISTRY
 -M:    Torben Mathiasen <device@lanana.org>
 -S:    Maintained
 -W:    http://lanana.org/docs/device-list/index.html
 -
  DEVICE RESOURCE MANAGEMENT HELPERS
  M:    Hans de Goede <hdegoede@redhat.com>
  R:    Matti Vaittinen <mazziesaccount@gmail.com>
@@@ -6223,7 -6207,6 +6223,7 @@@ DOCUMENTATION REPORTING ISSUE
  M:    Thorsten Leemhuis <linux@leemhuis.info>
  L:    linux-doc@vger.kernel.org
  S:    Maintained
 +F:    Documentation/admin-guide/quickly-build-trimmed-linux.rst
  F:    Documentation/admin-guide/reporting-issues.rst
  
  DOCUMENTATION SCRIPTS
@@@ -6335,9 -6318,7 +6335,9 @@@ F:      drivers/base
  F:    fs/debugfs/
  F:    fs/sysfs/
  F:    include/linux/debugfs.h
 +F:    include/linux/fwnode.h
  F:    include/linux/kobj*
 +F:    include/linux/property.h
  F:    lib/kobj*
  
  DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
@@@ -6537,7 -6518,6 +6537,7 @@@ L:      linux-arm-msm@vger.kernel.or
  L:    dri-devel@lists.freedesktop.org
  L:    freedreno@lists.freedesktop.org
  S:    Maintained
 +B:    https://gitlab.freedesktop.org/drm/msm/-/issues
  T:    git https://gitlab.freedesktop.org/drm/msm.git
  F:    Documentation/devicetree/bindings/display/msm/
  F:    drivers/gpu/drm/msm/
@@@ -6557,13 -6537,6 +6557,13 @@@ T:    git git://anongit.freedesktop.org/dr
  F:    Documentation/devicetree/bindings/display/panel/sony,acx424akp.yaml
  F:    drivers/gpu/drm/panel/panel-novatek-nt35560.c
  
 +DRM DRIVER FOR NOVATEK NT36523 PANELS
 +M:    Jianhua Lu <lujianhua000@gmail.com>
 +S:    Maintained
 +T:    git git://anongit.freedesktop.org/drm/drm-misc
 +F:    Documentation/devicetree/bindings/display/panel/novatek,nt36523.yaml
 +F:    drivers/gpu/drm/panel/panel-novatek-nt36523.c
 +
  DRM DRIVER FOR NOVATEK NT36672A PANELS
  M:    Sumit Semwal <sumit.semwal@linaro.org>
  S:    Maintained
@@@ -6644,16 -6617,6 +6644,16 @@@ T:    git git://anongit.freedesktop.org/dr
  F:    Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
  F:    drivers/gpu/drm/panel/panel-samsung-db7430.c
  
 +DRM DRIVER FOR SAMSUNG MIPI DSIM BRIDGE
 +M:    Inki Dae <inki.dae@samsung.com>
 +M:    Jagan Teki <jagan@amarulasolutions.com>
 +M:    Marek Szyprowski <m.szyprowski@samsung.com>
 +S:    Maintained
 +T:    git git://anongit.freedesktop.org/drm/drm-misc
 +F:    Documentation/devicetree/bindings/display/bridge/samsung,mipi-dsim.yaml
 +F:    drivers/gpu/drm/bridge/samsung-dsim.c
 +F:    include/drm/bridge/samsung-dsim.h
 +
  DRM DRIVER FOR SAMSUNG S6D27A1 PANELS
  M:    Markuss Broks <markuss.broks@gmail.com>
  S:    Maintained
@@@ -6861,7 -6824,6 +6861,7 @@@ S:      Maintaine
  T:    git git://anongit.freedesktop.org/drm/drm-misc
  F:    Documentation/devicetree/bindings/display/bridge/
  F:    drivers/gpu/drm/bridge/
 +F:    include/drm/drm_bridge.h
  
  DRM DRIVERS FOR EXYNOS
  M:    Inki Dae <inki.dae@samsung.com>
@@@ -6954,7 -6916,6 +6954,7 @@@ F:      drivers/phy/mediatek/phy-mtk-mipi
  
  DRM DRIVERS FOR NVIDIA TEGRA
  M:    Thierry Reding <thierry.reding@gmail.com>
 +M:    Mikko Perttunen <mperttunen@nvidia.com>
  L:    dri-devel@lists.freedesktop.org
  L:    linux-tegra@vger.kernel.org
  S:    Supported
@@@ -7083,7 -7044,7 +7083,7 @@@ F:      Documentation/devicetree/bindings/di
  F:    drivers/gpu/drm/xlnx/
  
  DRM PANEL DRIVERS
 -M:    Thierry Reding <thierry.reding@gmail.com>
 +M:    Neil Armstrong <neil.armstrong@linaro.org>
  R:    Sam Ravnborg <sam@ravnborg.org>
  L:    dri-devel@lists.freedesktop.org
  S:    Maintained
@@@ -7564,12 -7525,6 +7564,6 @@@ T:     git git://linuxtv.org/media_tree.gi
  F:    Documentation/admin-guide/media/em28xx*
  F:    drivers/media/usb/em28xx/
  
- EMBEDDED LINUX
- M:    Olivia Mackall <olivia@selenic.com>
- M:    David Woodhouse <dwmw2@infradead.org>
- L:    linux-embedded@vger.kernel.org
- S:    Maintained
  EMMC CMDQ HOST CONTROLLER INTERFACE (CQHCI) DRIVER
  M:    Adrian Hunter <adrian.hunter@intel.com>
  M:    Ritesh Harjani <riteshh@codeaurora.org>
@@@ -7767,7 -7722,6 +7761,7 @@@ T:      git git://git.kernel.org/pub/scm/lin
  F:    Documentation/filesystems/ext4/
  F:    fs/ext4/
  F:    include/trace/events/ext4.h
 +F:    include/uapi/linux/ext4.h
  
  Extended Verification Module (EVM)
  M:    Mimi Zohar <zohar@linux.ibm.com>
@@@ -7994,11 -7948,10 +7988,11 @@@ T:   git git://git.kernel.org/pub/scm/lin
  F:    drivers/target/sbp/
  
  FIREWIRE SUBSYSTEM
 -M:    Stefan Richter <stefanr@s5r6.in-berlin.de>
 +M:    Takashi Sakamoto <o-takashi@sakamocchi.jp>
 +M:    Takashi Sakamoto <takaswie@kernel.org>
  L:    linux1394-devel@lists.sourceforge.net
  S:    Maintained
 -W:    http://ieee1394.wiki.kernel.org/
 +W:    http://ieee1394.docs.kernel.org/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git
  F:    drivers/firewire/
  F:    include/linux/firewire.h
@@@ -8141,7 -8094,7 +8135,7 @@@ M:      Pankaj Gupta <pankaj.gupta@nxp.com
  M:    Gaurav Jain <gaurav.jain@nxp.com>
  L:    linux-crypto@vger.kernel.org
  S:    Maintained
 -F:    Documentation/devicetree/bindings/crypto/fsl-sec4.txt
 +F:    Documentation/devicetree/bindings/crypto/fsl,sec-v4.0*
  F:    drivers/crypto/caam/
  
  FREESCALE COLDFIRE M5441X MMC DRIVER
@@@ -8289,23 -8242,6 +8283,23 @@@ S:    Maintaine
  F:    drivers/soc/fsl/qe/
  F:    include/soc/fsl/qe/
  
 +FREESCALE QUICC ENGINE QMC DRIVER
 +M:    Herve Codina <herve.codina@bootlin.com>
 +L:    linuxppc-dev@lists.ozlabs.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml
 +F:    drivers/soc/fsl/qe/qmc.c
 +F:    include/soc/fsl/qe/qmc.h
 +
 +FREESCALE QUICC ENGINE TSA DRIVER
 +M:    Herve Codina <herve.codina@bootlin.com>
 +L:    linuxppc-dev@lists.ozlabs.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-tsa.yaml
 +F:    drivers/soc/fsl/qe/tsa.c
 +F:    drivers/soc/fsl/qe/tsa.h
 +F:    include/dt-bindings/soc/cpm1-fsl,tsa.h
 +
  FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
  M:    Li Yang <leoyang.li@nxp.com>
  L:    netdev@vger.kernel.org
@@@ -8357,14 -8293,6 +8351,14 @@@ F:    sound/soc/fsl/fsl
  F:    sound/soc/fsl/imx*
  F:    sound/soc/fsl/mpc8610_hpcd.c
  
 +FREESCALE SOC SOUND QMC DRIVER
 +M:    Herve Codina <herve.codina@bootlin.com>
 +L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
 +L:    linuxppc-dev@lists.ozlabs.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml
 +F:    sound/soc/fsl/fsl_qmc_audio.c
 +
  FREESCALE USB PERIPHERAL DRIVERS
  M:    Li Yang <leoyang.li@nxp.com>
  L:    linux-usb@vger.kernel.org
@@@ -8484,6 -8412,14 +8478,6 @@@ L:     platform-driver-x86@vger.kernel.or
  S:    Maintained
  F:    drivers/platform/x86/fujitsu-laptop.c
  
 -FUJITSU M-5MO LS CAMERA ISP DRIVER
 -M:    Kyungmin Park <kyungmin.park@samsung.com>
 -M:    Heungjun Kim <riverful.kim@samsung.com>
 -L:    linux-media@vger.kernel.org
 -S:    Maintained
 -F:    drivers/media/i2c/m5mols/
 -F:    include/media/i2c/m5mols.h
 -
  FUJITSU TABLET EXTRAS
  M:    Robert Gerlach <khnz@gmx.de>
  L:    platform-driver-x86@vger.kernel.org
@@@ -8748,7 -8684,7 +8742,7 @@@ F:      drivers/input/touchscreen/goodix
  
  GOOGLE ETHERNET DRIVERS
  M:    Jeroen de Borst <jeroendb@google.com>
 -M:    Catherine Sullivan <csully@google.com>
 +M:    Praveen Kaligineedi <pkaligineedi@google.com>
  R:    Shailend Chand <shailend@google.com>
  L:    netdev@vger.kernel.org
  S:    Supported
@@@ -8811,6 -8747,7 +8805,6 @@@ F:      Documentation/admin-guide/gpio
  F:    Documentation/devicetree/bindings/gpio/
  F:    Documentation/driver-api/gpio/
  F:    drivers/gpio/
 -F:    include/asm-generic/gpio.h
  F:    include/dt-bindings/gpio/
  F:    include/linux/gpio.h
  F:    include/linux/gpio/
@@@ -8997,17 -8934,6 +8991,17 @@@ Q:    http://patchwork.linuxtv.org/project
  T:    git git://linuxtv.org/anttip/media_tree.git
  F:    drivers/media/usb/hackrf/
  
 +HANDSHAKE UPCALL FOR TRANSPORT LAYER SECURITY
 +M:    Chuck Lever <chuck.lever@oracle.com>
 +L:    kernel-tls-handshake@lists.linux.dev
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/netlink/specs/handshake.yaml
 +F:    Documentation/networking/tls-handshake.rst
 +F:    include/net/handshake.h
 +F:    include/trace/events/handshake.h
 +F:    net/handshake/
 +
  HANTRO VPU CODEC DRIVER
  M:    Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
  M:    Philipp Zabel <p.zabel@pengutronix.de>
@@@ -9588,7 -9514,6 +9582,7 @@@ S:      Supporte
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
  F:    Documentation/ABI/stable/sysfs-bus-vmbus
  F:    Documentation/ABI/testing/debugfs-hyperv
 +F:    Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
  F:    Documentation/virt/hyperv
  F:    Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
  F:    arch/arm64/hyperv
@@@ -9798,7 -9723,7 +9792,7 @@@ F:      include/linux/i3c
  IA64 (Itanium) PLATFORM
  L:    linux-ia64@vger.kernel.org
  S:    Orphan
 -F:    Documentation/ia64/
 +F:    Documentation/arch/ia64/
  F:    arch/ia64/
  
  IBM Operation Panel Input Driver
@@@ -10008,13 -9933,6 +10002,13 @@@ F:  Documentation/ABI/testing/sysfs-bus-
  F:    Documentation/devicetree/bindings/iio/adc/envelope-detector.yaml
  F:    drivers/iio/adc/envelope-detector.c
  
 +IIO LIGHT SENSOR GAIN-TIME-SCALE HELPERS
 +M:    Matti Vaittinen <mazziesaccount@gmail.com>
 +L:    linux-iio@vger.kernel.org
 +S:    Maintained
 +F:    drivers/iio/light/gain-time-scale-helper.c
 +F:    drivers/iio/light/gain-time-scale-helper.h
 +
  IIO MULTIPLEXER
  M:    Peter Rosin <peda@axentia.se>
  L:    linux-iio@vger.kernel.org
@@@ -10359,14 -10277,12 +10353,14 @@@ M:        Andy Shevchenko <andy@kernel.org
  L:    linux-gpio@vger.kernel.org
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
 +F:    drivers/gpio/gpio-elkhartlake.c
  F:    drivers/gpio/gpio-ich.c
  F:    drivers/gpio/gpio-merrifield.c
  F:    drivers/gpio/gpio-ml-ioh.c
  F:    drivers/gpio/gpio-pch.c
  F:    drivers/gpio/gpio-sch.c
  F:    drivers/gpio/gpio-sodaville.c
 +F:    drivers/gpio/gpio-tangier.c
  
  INTEL GVT-g DRIVERS (Intel GPU Virtualization)
  M:    Zhenyu Wang <zhenyuw@linux.intel.com>
@@@ -10459,7 -10375,7 +10453,7 @@@ INTEL IXP4XX CRYPTO SUPPOR
  M:    Corentin Labbe <clabbe@baylibre.com>
  L:    linux-crypto@vger.kernel.org
  S:    Maintained
 -F:    drivers/crypto/ixp4xx_crypto.c
 +F:    drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
  
  INTEL ISHTP ECLITE DRIVER
  M:    Sumesh K Naduvalath <sumesh.k.naduvalath@intel.com>
@@@ -10494,11 -10410,11 +10488,11 @@@ INTEL KEEM BAY OCS AES/SM4 CRYPTO DRIVE
  M:    Daniele Alessandrelli <daniele.alessandrelli@intel.com>
  S:    Maintained
  F:    Documentation/devicetree/bindings/crypto/intel,keembay-ocs-aes.yaml
 -F:    drivers/crypto/keembay/Kconfig
 -F:    drivers/crypto/keembay/Makefile
 -F:    drivers/crypto/keembay/keembay-ocs-aes-core.c
 -F:    drivers/crypto/keembay/ocs-aes.c
 -F:    drivers/crypto/keembay/ocs-aes.h
 +F:    drivers/crypto/intel/keembay/Kconfig
 +F:    drivers/crypto/intel/keembay/Makefile
 +F:    drivers/crypto/intel/keembay/keembay-ocs-aes-core.c
 +F:    drivers/crypto/intel/keembay/ocs-aes.c
 +F:    drivers/crypto/intel/keembay/ocs-aes.h
  
  INTEL KEEM BAY OCS ECC CRYPTO DRIVER
  M:    Daniele Alessandrelli <daniele.alessandrelli@intel.com>
@@@ -10506,20 -10422,20 +10500,20 @@@ M:        Prabhjot Khurana <prabhjot.khurana@i
  M:    Mark Gross <mgross@linux.intel.com>
  S:    Maintained
  F:    Documentation/devicetree/bindings/crypto/intel,keembay-ocs-ecc.yaml
 -F:    drivers/crypto/keembay/Kconfig
 -F:    drivers/crypto/keembay/Makefile
 -F:    drivers/crypto/keembay/keembay-ocs-ecc.c
 +F:    drivers/crypto/intel/keembay/Kconfig
 +F:    drivers/crypto/intel/keembay/Makefile
 +F:    drivers/crypto/intel/keembay/keembay-ocs-ecc.c
  
  INTEL KEEM BAY OCS HCU CRYPTO DRIVER
  M:    Daniele Alessandrelli <daniele.alessandrelli@intel.com>
  M:    Declan Murphy <declan.murphy@intel.com>
  S:    Maintained
  F:    Documentation/devicetree/bindings/crypto/intel,keembay-ocs-hcu.yaml
 -F:    drivers/crypto/keembay/Kconfig
 -F:    drivers/crypto/keembay/Makefile
 -F:    drivers/crypto/keembay/keembay-ocs-hcu-core.c
 -F:    drivers/crypto/keembay/ocs-hcu.c
 -F:    drivers/crypto/keembay/ocs-hcu.h
 +F:    drivers/crypto/intel/keembay/Kconfig
 +F:    drivers/crypto/intel/keembay/Makefile
 +F:    drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
 +F:    drivers/crypto/intel/keembay/ocs-hcu.c
 +F:    drivers/crypto/intel/keembay/ocs-hcu.h
  
  INTEL THUNDER BAY EMMC PHY DRIVER
  M:    Nandhini Srikandan <nandhini.srikandan@intel.com>
@@@ -10538,7 -10454,6 +10532,7 @@@ F:   drivers/watchdog/mei_wdt.
  F:    include/linux/mei_aux.h
  F:    include/linux/mei_cl_bus.h
  F:    include/uapi/linux/mei.h
 +F:    include/uapi/linux/mei_uuid.h
  F:    include/uapi/linux/uuid.h
  F:    samples/mei/*
  
@@@ -10727,7 -10642,7 +10721,7 @@@ L:   tboot-devel@lists.sourceforge.ne
  S:    Supported
  W:    http://tboot.sourceforge.net
  T:    hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
 -F:    Documentation/x86/intel_txt.rst
 +F:    Documentation/arch/x86/intel_txt.rst
  F:    arch/x86/kernel/tboot.c
  F:    include/linux/tboot.h
  
@@@ -10738,7 -10653,7 +10732,7 @@@ L:   linux-sgx@vger.kernel.or
  S:    Supported
  Q:    https://patchwork.kernel.org/project/intel-sgx/list/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/sgx
 -F:    Documentation/x86/sgx.rst
 +F:    Documentation/arch/x86/sgx.rst
  F:    arch/x86/entry/vdso/vsgx.S
  F:    arch/x86/include/asm/sgx.h
  F:    arch/x86/include/uapi/asm/sgx.h
@@@ -11602,6 -11517,16 +11596,6 @@@ F:  include/linux/kmemleak.
  F:    mm/kmemleak.c
  F:    samples/kmemleak/kmemleak-test.c
  
 -KMOD KERNEL MODULE LOADER - USERMODE HELPER
 -M:    Luis Chamberlain <mcgrof@kernel.org>
 -L:    linux-kernel@vger.kernel.org
 -L:    linux-modules@vger.kernel.org
 -S:    Maintained
 -F:    include/linux/kmod.h
 -F:    kernel/kmod.c
 -F:    lib/test_kmod.c
 -F:    tools/testing/selftests/kmod/
 -
  KMSAN
  M:    Alexander Potapenko <glider@google.com>
  R:    Marco Elver <elver@google.com>
@@@ -11827,7 -11752,7 +11821,7 @@@ T:   git git://git.kernel.org/pub/scm/lin
  F:    drivers/ata/sata_promise.*
  
  LIBATA SUBSYSTEM (Serial and Parallel ATA drivers)
 -M:    Damien Le Moal <damien.lemoal@opensource.wdc.com>
 +M:    Damien Le Moal <dlemoal@kernel.org>
  L:    linux-ide@vger.kernel.org
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata.git
@@@ -11963,7 -11888,6 +11957,7 @@@ M:   Scott Wood <oss@buserror.net
  L:    linuxppc-dev@lists.ozlabs.org
  S:    Odd fixes
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
 +F:    Documentation/devicetree/bindings/cache/freescale-l2cache.txt
  F:    Documentation/devicetree/bindings/powerpc/fsl/
  F:    arch/powerpc/platforms/83xx/
  F:    arch/powerpc/platforms/85xx/
@@@ -12187,13 -12111,6 +12181,13 @@@ S: Maintaine
  F:    Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
  F:    drivers/pinctrl/pinctrl-loongson2.c
  
 +LOONGSON GPIO DRIVER
 +M:    Yinbo Zhu <zhuyinbo@loongson.cn>
 +L:    linux-gpio@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/gpio/loongson,ls-gpio.yaml
 +F:    drivers/gpio/gpio-loongson-64bit.c
 +
  LOONGSON-2 SOC SERIES CLOCK DRIVER
  M:    Yinbo Zhu <zhuyinbo@loongson.cn>
  L:    linux-clk@vger.kernel.org
@@@ -12353,7 -12270,7 +12347,7 @@@ T:   git git://git.kernel.org/pub/scm/lin
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
  F:    Documentation/networking/mac80211-injection.rst
  F:    Documentation/networking/mac80211_hwsim/mac80211_hwsim.rst
 -F:    drivers/net/wireless/mac80211_hwsim.[ch]
 +F:    drivers/net/wireless/virtual/mac80211_hwsim.[ch]
  F:    include/net/mac80211.h
  F:    net/mac80211/
  
@@@ -13120,14 -13037,6 +13114,14 @@@ L: netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/ethernet/mediatek/
  
 +MEDIATEK ETHERNET PCS DRIVER
 +M:    Alexander Couzens <lynxis@fe80.eu>
 +M:    Daniel Golle <daniel@makrotopia.org>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/net/pcs/pcs-mtk-lynxi.c
 +F:    include/linux/pcs/pcs-mtk-lynxi.h
 +
  MEDIATEK I2C CONTROLLER DRIVER
  M:    Qii Wang <qii.wang@mediatek.com>
  L:    linux-i2c@vger.kernel.org
@@@ -13252,11 -13161,8 +13246,11 @@@ MEDIATEK SWITCH DRIVE
  M:    Sean Wang <sean.wang@mediatek.com>
  M:    Landen Chao <Landen.Chao@mediatek.com>
  M:    DENG Qingfang <dqfext@gmail.com>
 +M:    Daniel Golle <daniel@makrotopia.org>
  L:    netdev@vger.kernel.org
  S:    Maintained
 +F:    drivers/net/dsa/mt7530-mdio.c
 +F:    drivers/net/dsa/mt7530-mmio.c
  F:    drivers/net/dsa/mt7530.*
  F:    net/dsa/tag_mtk.c
  
@@@ -13457,14 -13363,13 +13451,14 @@@ F:        arch/powerpc/include/asm/membarrier.
  F:    include/uapi/linux/membarrier.h
  F:    kernel/sched/membarrier.c
  
 -MEMBLOCK
 +MEMBLOCK AND MEMORY MANAGEMENT INITIALIZATION
  M:    Mike Rapoport <rppt@kernel.org>
  L:    linux-mm@kvack.org
  S:    Maintained
  F:    Documentation/core-api/boot-time-mm.rst
  F:    include/linux/memblock.h
  F:    mm/memblock.c
 +F:    mm/mm_init.c
  F:    tools/testing/memblock/
  
  MEMORY CONTROLLER DRIVERS
@@@ -13499,7 -13404,6 +13493,7 @@@ F:   include/linux/memory_hotplug.
  F:    include/linux/mm.h
  F:    include/linux/mmzone.h
  F:    include/linux/pagewalk.h
 +F:    include/trace/events/ksm.h
  F:    mm/
  F:    tools/mm/
  F:    tools/testing/selftests/mm/
@@@ -13508,7 -13412,6 +13502,7 @@@ VMALLO
  M:    Andrew Morton <akpm@linux-foundation.org>
  R:    Uladzislau Rezki <urezki@gmail.com>
  R:    Christoph Hellwig <hch@infradead.org>
 +R:    Lorenzo Stoakes <lstoakes@gmail.com>
  L:    linux-mm@kvack.org
  S:    Maintained
  W:    http://www.linux-mm.org
@@@ -13685,13 -13588,9 +13679,13 @@@ F: Documentation/devicetree/bindings/se
  F:    drivers/spi/spi-at91-usart.c
  
  MICROCHIP AUDIO ASOC DRIVERS
 -M:    Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
 +M:    Claudiu Beznea <claudiu.beznea@microchip.com>
  L:    alsa-devel@alsa-project.org (moderated for non-subscribers)
  S:    Supported
 +F:    Documentation/devicetree/bindings/sound/atmel*
 +F:    Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
 +F:    Documentation/devicetree/bindings/sound/microchip,sama7g5-*
 +F:    Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt
  F:    sound/soc/atmel
  
  MICROCHIP CSI2DC DRIVER
@@@ -13864,10 -13763,9 +13858,10 @@@ S: Supporte
  F:    drivers/spi/spi-atmel.*
  
  MICROCHIP SSC DRIVER
 -M:    Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
 +M:    Claudiu Beznea <claudiu.beznea@microchip.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Supported
 +F:    Documentation/devicetree/bindings/misc/atmel-ssc.txt
  F:    drivers/misc/atmel-ssc.c
  F:    include/linux/atmel-ssc.h
  
@@@ -14180,11 -14078,8 +14174,11 @@@ L: linux-kernel@vger.kernel.or
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git modules-next
  F:    include/linux/module.h
 +F:    include/linux/kmod.h
  F:    kernel/module/
  F:    scripts/module*
 +F:    lib/test_kmod.c
 +F:    tools/testing/selftests/kmod/
  
  MONOLITHIC POWER SYSTEM PMIC DRIVER
  M:    Saravanan Sekar <sravanhome@gmail.com>
@@@ -14238,13 -14133,6 +14232,13 @@@ S: Odd Fixe
  F:    Documentation/devicetree/bindings/net/ieee802154/mrf24j40.txt
  F:    drivers/net/ieee802154/mrf24j40.c
  
 +MSI EC DRIVER
 +M:    Nikita Kravets <teackot@gmail.com>
 +L:    platform-driver-x86@vger.kernel.org
 +S:    Maintained
 +W:    https://github.com/BeardOverflow/msi-ec
 +F:    drivers/platform/x86/msi-ec.*
 +
  MSI LAPTOP SUPPORT
  M:    "Lee, Chun-Yi" <jlee@suse.com>
  L:    platform-driver-x86@vger.kernel.org
@@@ -14289,6 -14177,14 +14283,6 @@@ L:  linux-mtd@lists.infradead.or
  S:    Maintained
  F:    drivers/mtd/devices/docg3*
  
 -MT9M032 APTINA SENSOR DRIVER
 -M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 -L:    linux-media@vger.kernel.org
 -S:    Maintained
 -T:    git git://linuxtv.org/media_tree.git
 -F:    drivers/media/i2c/mt9m032.c
 -F:    include/media/i2c/mt9m032.h
 -
  MT9P031 APTINA CAMERA SENSOR
  M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  L:    linux-media@vger.kernel.org
@@@ -14298,6 -14194,14 +14292,6 @@@ F:  Documentation/devicetree/bindings/me
  F:    drivers/media/i2c/mt9p031.c
  F:    include/media/i2c/mt9p031.h
  
 -MT9T001 APTINA CAMERA SENSOR
 -M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 -L:    linux-media@vger.kernel.org
 -S:    Maintained
 -T:    git git://linuxtv.org/media_tree.git
 -F:    drivers/media/i2c/mt9t001.c
 -F:    include/media/i2c/mt9t001.h
 -
  MT9T112 APTINA CAMERA SENSOR
  M:    Jacopo Mondi <jacopo@jmondi.org>
  L:    linux-media@vger.kernel.org
@@@ -14684,14 -14588,11 +14678,14 @@@ F:        net/netlabel
  
  NETWORKING [MPTCP]
  M:    Matthieu Baerts <matthieu.baerts@tessares.net>
 +M:    Mat Martineau <martineau@kernel.org>
  L:    netdev@vger.kernel.org
  L:    mptcp@lists.linux.dev
  S:    Maintained
  W:    https://github.com/multipath-tcp/mptcp_net-next/wiki
  B:    https://github.com/multipath-tcp/mptcp_net-next/issues
 +T:    git https://github.com/multipath-tcp/mptcp_net-next.git export-net
 +T:    git https://github.com/multipath-tcp/mptcp_net-next.git export
  F:    Documentation/networking/mptcp-sysctl.rst
  F:    include/net/mptcp.h
  F:    include/trace/events/mptcp.h
@@@ -14754,6 -14655,7 +14748,6 @@@ L:   netdev@vger.kernel.or
  S:    Maintained
  F:    Documentation/devicetree/bindings/net/nfc/
  F:    drivers/nfc/
 -F:    include/linux/platform_data/nfcmrvl.h
  F:    include/net/nfc/
  F:    include/uapi/linux/nfc.h
  F:    net/nfc/
@@@ -14836,7 -14738,7 +14830,7 @@@ F:   include/uapi/linux/nitro_enclaves.
  F:    samples/nitro_enclaves/
  
  NOHZ, DYNTICKS SUPPORT
 -M:    Frederic Weisbecker <fweisbec@gmail.com>
 +M:    Frederic Weisbecker <frederic@kernel.org>
  M:    Thomas Gleixner <tglx@linutronix.de>
  M:    Ingo Molnar <mingo@kernel.org>
  L:    linux-kernel@vger.kernel.org
@@@ -15051,13 -14953,6 +15045,13 @@@ F: Documentation/devicetree/bindings/cl
  F:    drivers/clk/imx/
  F:    include/dt-bindings/clock/imx*
  
 +NXP i.MX 8M ISI DRIVER
 +M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 +L:    linux-media@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/media/nxp,imx8-isi.yaml
 +F:    drivers/media/platform/nxp/imx8-isi/
 +
  NXP i.MX 8MQ DCSS DRIVER
  M:    Laurentiu Palcu <laurentiu.palcu@oss.nxp.com>
  R:    Lucas Stach <l.stach@pengutronix.de>
@@@ -15418,6 -15313,18 +15412,6 @@@ S:  Maintaine
  F:    Documentation/filesystems/omfs.rst
  F:    fs/omfs/
  
 -OMNIKEY CARDMAN 4000 DRIVER
 -M:    Harald Welte <laforge@gnumonks.org>
 -S:    Maintained
 -F:    drivers/char/pcmcia/cm4000_cs.c
 -F:    include/linux/cm4000_cs.h
 -F:    include/uapi/linux/cm4000_cs.h
 -
 -OMNIKEY CARDMAN 4040 DRIVER
 -M:    Harald Welte <laforge@gnumonks.org>
 -S:    Maintained
 -F:    drivers/char/pcmcia/cm4040_cs.*
 -
  OMNIVISION OG01A1B SENSOR DRIVER
  M:    Shawn Tu <shawnx.tu@intel.com>
  L:    linux-media@vger.kernel.org
@@@ -15473,7 -15380,6 +15467,7 @@@ M:   Shunqian Zheng <zhengsq@rock-chips.c
  L:    linux-media@vger.kernel.org
  S:    Maintained
  T:    git git://linuxtv.org/media_tree.git
 +F:    Documentation/devicetree/bindings/media/i2c/ovti,ov2685.yaml
  F:    drivers/media/i2c/ov2685.c
  
  OMNIVISION OV2740 SENSOR DRIVER
@@@ -15565,7 -15471,7 +15559,7 @@@ F:   Documentation/devicetree/bindings/me
  F:    drivers/media/i2c/ov7740.c
  
  OMNIVISION OV8856 SENSOR DRIVER
 -M:    Dongchun Zhu <dongchun.zhu@mediatek.com>
 +M:    Sakari Ailus <sakari.ailus@linux.intel.com>
  L:    linux-media@vger.kernel.org
  S:    Maintained
  T:    git git://linuxtv.org/media_tree.git
@@@ -15635,12 -15541,6 +15629,12 @@@ L: linux-hwmon@vger.kernel.or
  S:    Maintained
  F:    drivers/hwmon/oxp-sensors.c
  
 +ONIE TLV NVMEM LAYOUT DRIVER
 +M:    Miquel Raynal <miquel.raynal@bootlin.com>
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml
 +F:    drivers/nvmem/layouts/onie-tlv.c
 +
  ONION OMEGA2+ BOARD
  M:    Harvey Hunt <harveyhuntnexus@gmail.com>
  L:    linux-mips@vger.kernel.org
@@@ -15714,13 -15614,6 +15708,13 @@@ L: netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/ptp/ptp_ocp.c
  
 +INTEL PTP DFL ToD DRIVER
 +M:    Tianfei Zhang <tianfei.zhang@intel.com>
 +L:    linux-fpga@vger.kernel.org
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/ptp/ptp_dfl_tod.c
 +
  OPENCORES I2C BUS DRIVER
  M:    Peter Korsgaard <peter@korsgaard.com>
  M:    Andrew Lunn <andrew@lunn.ch>
@@@ -15740,7 -15633,7 +15734,7 @@@ S:   Maintaine
  W:    http://openrisc.io
  T:    git https://github.com/openrisc/linux.git
  F:    Documentation/devicetree/bindings/openrisc/
 -F:    Documentation/openrisc/
 +F:    Documentation/arch/openrisc/
  F:    arch/openrisc/
  F:    drivers/irqchip/irq-ompic.c
  F:    drivers/irqchip/irq-or1k-*
@@@ -15936,7 -15829,7 +15930,7 @@@ W:   https://parisc.wiki.kernel.or
  Q:    http://patchwork.kernel.org/project/linux-parisc/list/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
 -F:    Documentation/parisc/
 +F:    Documentation/arch/parisc/
  F:    arch/parisc/
  F:    drivers/char/agp/parisc-agp.c
  F:    drivers/input/misc/hp_sdc_rtc.c
@@@ -16071,8 -15964,6 +16065,8 @@@ M:   Lucas Stach <l.stach@pengutronix.de
  L:    linux-pci@vger.kernel.org
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 +F:    Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml
 +F:    Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
  F:    Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
  F:    drivers/pci/controller/dwc/*imx6*
  
@@@ -16431,6 -16322,12 +16425,6 @@@ S:  Maintaine
  F:    crypto/pcrypt.c
  F:    include/crypto/pcrypt.h
  
 -PEAQ WMI HOTKEYS DRIVER
 -M:    Hans de Goede <hdegoede@redhat.com>
 -L:    platform-driver-x86@vger.kernel.org
 -S:    Maintained
 -F:    drivers/platform/x86/peaq-wmi.c
 -
  PECI HARDWARE MONITORING DRIVERS
  M:    Iwona Winiarska <iwona.winiarska@intel.com>
  L:    linux-hwmon@vger.kernel.org
@@@ -16867,8 -16764,9 +16861,8 @@@ F:   include/uapi/linux/if_pppol2tp.
  F:    net/l2tp/l2tp_ppp.c
  
  PPP PROTOCOL DRIVERS AND COMPRESSORS
 -M:    Paul Mackerras <paulus@samba.org>
  L:    linux-ppp@vger.kernel.org
 -S:    Maintained
 +S:    Orphan
  F:    drivers/net/ppp/ppp_*
  
  PPS SUPPORT
@@@ -17112,7 -17010,7 +17106,7 @@@ QAT DRIVE
  M:    Giovanni Cabiddu <giovanni.cabiddu@intel.com>
  L:    qat-linux@intel.com
  S:    Supported
 -F:    drivers/crypto/qat/
 +F:    drivers/crypto/intel/qat/
  
  QCOM AUDIO (ASoC) DRIVERS
  M:    Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
@@@ -17262,12 -17160,6 +17256,12 @@@ F: fs/qnx4
  F:    include/uapi/linux/qnx4_fs.h
  F:    include/uapi/linux/qnxtypes.h
  
 +QNX6 FILESYSTEM
 +S:    Orphan
 +F:    Documentation/filesystems/qnx6.rst
 +F:    fs/qnx6/
 +F:    include/linux/qnx6_fs.h
 +
  QORIQ DPAA2 FSL-MC BUS DRIVER
  M:    Stuart Yoder <stuyoder@gmail.com>
  M:    Laurentiu Tudor <laurentiu.tudor@nxp.com>
@@@ -17296,7 -17188,7 +17290,7 @@@ S:   Supporte
  W:    https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
  F:    drivers/net/wireless/ath/ath10k/
 -F:    Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
 +F:    Documentation/devicetree/bindings/net/wireless/qcom,ath10k.yaml
  
  QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
  M:    Kalle Valo <kvalo@kernel.org>
@@@ -17332,7 -17224,6 +17326,7 @@@ F:   drivers/net/wwan/qcom_bam_dmux.
  QUALCOMM CAMERA SUBSYSTEM DRIVER
  M:    Robert Foss <rfoss@kernel.org>
  M:    Todor Tomov <todor.too@gmail.com>
 +M:    Bryan O'Donoghue <bryan.odonoghue@linaro.org>
  L:    linux-media@vger.kernel.org
  S:    Maintained
  F:    Documentation/admin-guide/media/qcom_camss.rst
@@@ -17348,16 -17239,6 +17342,16 @@@ F: Documentation/devicetree/bindings/cl
  F:    drivers/clk/qcom/
  F:    include/dt-bindings/clock/qcom,*
  
 +QUALCOMM CLOUD AI (QAIC) DRIVER
 +M:    Jeffrey Hugo <quic_jhugo@quicinc.com>
 +L:    linux-arm-msm@vger.kernel.org
 +L:    dri-devel@lists.freedesktop.org
 +S:    Supported
 +T:    git git://anongit.freedesktop.org/drm/drm-misc
 +F:    Documentation/accel/qaic/
 +F:    drivers/accel/qaic/
 +F:    include/uapi/drm/qaic_accel.h
 +
  QUALCOMM CORE POWER REDUCTION (CPR) AVS DRIVER
  M:    Bjorn Andersson <andersson@kernel.org>
  M:    Konrad Dybcio <konrad.dybcio@linaro.org>
@@@ -17380,7 -17261,6 +17374,7 @@@ M:   Thara Gopinath <thara.gopinath@gmail
  L:    linux-crypto@vger.kernel.org
  L:    linux-arm-msm@vger.kernel.org
  S:    Maintained
 +F:    Documentation/devicetree/bindings/crypto/qcom-qce.yaml
  F:    drivers/crypto/qce/
  
  QUALCOMM EMAC GIGABIT ETHERNET DRIVER
@@@ -17394,7 -17274,7 +17388,7 @@@ M:   Vinod Koul <vkoul@kernel.org
  R:    Bhupesh Sharma <bhupesh.sharma@linaro.org>
  L:    netdev@vger.kernel.org
  S:    Maintained
 -F:    Documentation/devicetree/bindings/net/qcom,ethqos.txt
 +F:    Documentation/devicetree/bindings/net/qcom,ethqos.yaml
  F:    drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
  
  QUALCOMM FASTRPC DRIVER
@@@ -17575,8 -17455,9 +17569,8 @@@ F:   drivers/block/rbd.
  F:    drivers/block/rbd_types.h
  
  RAGE128 FRAMEBUFFER DISPLAY DRIVER
 -M:    Paul Mackerras <paulus@samba.org>
  L:    linux-fbdev@vger.kernel.org
 -S:    Maintained
 +S:    Orphan
  F:    drivers/video/fbdev/aty/aty128fb.c
  
  RAINSHADOW-CEC DRIVER
@@@ -17653,7 -17534,7 +17647,7 @@@ F:   include/ras/ras_event.
  RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
  L:    linux-wireless@vger.kernel.org
  S:    Orphan
 -F:    drivers/net/wireless/ray*
 +F:    drivers/net/wireless/legacy/ray*
  
  RC-CORE / LIRC FRAMEWORK
  M:    Sean Young <sean@mess.org>
@@@ -17739,7 -17620,7 +17733,7 @@@ M:   Fenghua Yu <fenghua.yu@intel.com
  M:    Reinette Chatre <reinette.chatre@intel.com>
  L:    linux-kernel@vger.kernel.org
  S:    Supported
 -F:    Documentation/x86/resctrl*
 +F:    Documentation/arch/x86/resctrl*
  F:    arch/x86/include/asm/resctrl.h
  F:    arch/x86/kernel/cpu/resctrl/
  F:    tools/testing/selftests/resctrl/
@@@ -17748,13 -17629,11 +17742,13 @@@ READ-COPY UPDATE (RCU
  M:    "Paul E. McKenney" <paulmck@kernel.org>
  M:    Frederic Weisbecker <frederic@kernel.org> (kernel/rcu/tree_nocb.h)
  M:    Neeraj Upadhyay <quic_neeraju@quicinc.com> (kernel/rcu/tasks.h)
 +M:    Joel Fernandes <joel@joelfernandes.org>
  M:    Josh Triplett <josh@joshtriplett.org>
 +M:    Boqun Feng <boqun.feng@gmail.com>
  R:    Steven Rostedt <rostedt@goodmis.org>
  R:    Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  R:    Lai Jiangshan <jiangshanlai@gmail.com>
 -R:    Joel Fernandes <joel@joelfernandes.org>
 +R:    Zqiang <qiang1.zhang@intel.com>
  L:    rcu@vger.kernel.org
  S:    Supported
  W:    http://www.rdrop.com/users/paulmck/RCU/
@@@ -18204,12 -18083,6 +18198,12 @@@ S: Maintaine
  F:    Documentation/devicetree/bindings/iio/light/bh1750.yaml
  F:    drivers/iio/light/bh1750.c
  
 +ROHM BU27034 AMBIENT LIGHT SENSOR DRIVER
 +M:    Matti Vaittinen <mazziesaccount@gmail.com>
 +L:    linux-iio@vger.kernel.org
 +S:    Supported
 +F:    drivers/iio/light/rohm-bu27034.c
 +
  ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS
  M:    Marek Vasut <marek.vasut+renesas@gmail.com>
  L:    linux-kernel@vger.kernel.org
@@@ -18615,7 -18488,6 +18609,7 @@@ M:   Sylwester Nawrocki <s.nawrocki@samsu
  M:    Andrzej Hajda <andrzej.hajda@intel.com>
  L:    linux-media@vger.kernel.org
  S:    Supported
 +F:    Documentation/devicetree/bindings/media/samsung,s5c73m3.yaml
  F:    drivers/media/i2c/s5c73m3/*
  
  SAMSUNG S5K5BAF CAMERA DRIVER
@@@ -18640,11 -18512,6 +18634,11 @@@ M: Sylwester Nawrocki <s.nawrocki@samsu
  L:    linux-media@vger.kernel.org
  S:    Supported
  Q:    https://patchwork.linuxtv.org/project/linux-media/list/
 +F:    Documentation/devicetree/bindings/media/samsung,exynos4210-csis.yaml
 +F:    Documentation/devicetree/bindings/media/samsung,exynos4210-fimc.yaml
 +F:    Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-is.yaml
 +F:    Documentation/devicetree/bindings/media/samsung,exynos4212-fimc-lite.yaml
 +F:    Documentation/devicetree/bindings/media/samsung,fimc.yaml
  F:    drivers/media/platform/samsung/exynos4-is/
  
  SAMSUNG SOC CLOCK DRIVERS
@@@ -18667,7 -18534,7 +18661,7 @@@ F:   include/linux/clk/samsung.
  
  SAMSUNG SPI DRIVERS
  M:    Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
 -M:    Andi Shyti <andi@etezian.org>
 +M:    Andi Shyti <andi.shyti@kernel.org>
  L:    linux-spi@vger.kernel.org
  L:    linux-samsung-soc@vger.kernel.org
  S:    Maintained
@@@ -18734,6 -18601,11 +18728,6 @@@ F:  include/linux/wait.
  F:    include/uapi/linux/sched.h
  F:    kernel/sched/
  
 -SCR24X CHIP CARD INTERFACE DRIVER
 -M:    Lubomir Rintel <lkundrak@v3.sk>
 -S:    Supported
 -F:    drivers/char/pcmcia/scr24x_cs.c
 -
  SCSI RDMA PROTOCOL (SRP) INITIATOR
  M:    Bart Van Assche <bvanassche@acm.org>
  L:    linux-rdma@vger.kernel.org
@@@ -18943,8 -18815,8 +18937,8 @@@ S:   Supporte
  W:    https://selinuxproject.org
  W:    https://github.com/SELinuxProject
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
 -F:    Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
 -F:    Documentation/ABI/obsolete/sysfs-selinux-disable
 +F:    Documentation/ABI/removed/sysfs-selinux-checkreqprot
 +F:    Documentation/ABI/removed/sysfs-selinux-disable
  F:    Documentation/admin-guide/LSM/SELinux.rst
  F:    include/trace/events/avc.h
  F:    include/uapi/linux/selinux_netlink.h
@@@ -19030,14 -18902,6 +19024,14 @@@ S: Supporte
  F:    Documentation/networking/devlink/sfc.rst
  F:    drivers/net/ethernet/sfc/
  
 +SFCTEMP HWMON DRIVER
 +M:    Emil Renner Berthing <kernel@esmil.dk>
 +L:    linux-hwmon@vger.kernel.org
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/hwmon/starfive,jh71x0-temp.yaml
 +F:    Documentation/hwmon/sfctemp.rst
 +F:    drivers/hwmon/sfctemp.c
 +
  SFF/SFP/SFP+ MODULE SUPPORT
  M:    Russell King <linux@armlinux.org.uk>
  L:    netdev@vger.kernel.org
@@@ -19126,7 -18990,6 +19120,7 @@@ L:   linux-media@vger.kernel.or
  S:    Odd Fixes
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
 +F:    Documentation/devicetree/bindings/media/silabs,si470x.yaml
  F:    drivers/media/radio/si470x/radio-si470x-i2c.c
  
  SI470X FM RADIO RECEIVER USB DRIVER
@@@ -19202,7 -19065,6 +19196,7 @@@ M:   Conor Dooley <conor@kernel.org
  L:    linux-riscv@lists.infradead.org
  S:    Maintained
  T:    git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
 +F:    Documentation/devicetree/bindings/cache/sifive,ccache0.yaml
  F:    drivers/soc/sifive/
  
  SILEAD TOUCHSCREEN DRIVER
@@@ -19312,12 -19174,6 +19306,12 @@@ F: drivers/irqchip/irq-sl28cpld.
  F:    drivers/pwm/pwm-sl28cpld.c
  F:    drivers/watchdog/sl28cpld_wdt.c
  
 +SL28 VPD NVMEM LAYOUT DRIVER
 +M:    Michael Walle <michael@walle.cc>
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
 +F:    drivers/nvmem/layouts/sl28vpd.c
 +
  SLAB ALLOCATOR
  M:    Christoph Lameter <cl@linux.com>
  M:    Pekka Enberg <penberg@kernel.org>
@@@ -20040,13 -19896,6 +20034,13 @@@ M: Emil Renner Berthing <kernel@esmil.d
  S:    Maintained
  F:    arch/riscv/boot/dts/starfive/
  
 +STARFIVE DWMAC GLUE LAYER
 +M:    Emil Renner Berthing <kernel@esmil.dk>
 +M:    Samin Guo <samin.guo@starfivetech.com>
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
 +F:    drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
 +
  STARFIVE JH7100 CLOCK DRIVERS
  M:    Emil Renner Berthing <kernel@esmil.dk>
  S:    Maintained
@@@ -20257,7 -20106,7 +20251,7 @@@ M:   John Paul Adrian Glaubitz <glaubitz@
  L:    linux-sh@vger.kernel.org
  S:    Maintained
  Q:    http://patchwork.kernel.org/project/linux-sh/list/
 -F:    Documentation/sh/
 +F:    Documentation/arch/sh/
  F:    arch/sh/
  F:    drivers/sh/
  
@@@ -20317,7 -20166,7 +20311,7 @@@ M:   Vineet Gupta <vgupta@kernel.org
  L:    linux-snps-arc@lists.infradead.org
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
 -F:    Documentation/arc/
 +F:    Documentation/arch/arc
  F:    Documentation/devicetree/bindings/arc/*
  F:    Documentation/devicetree/bindings/interrupt-controller/snps,arc*
  F:    arch/arc/
@@@ -20916,7 -20765,7 +20910,7 @@@ L:   linux-pm@vger.kernel.or
  S:    Maintained
  F:    Documentation/driver-api/thermal/power_allocator.rst
  F:    drivers/thermal/gov_power_allocator.c
 -F:    include/trace/events/thermal_power_allocator.h
 +F:    drivers/thermal/thermal_trace_ipa.h
  
  THINKPAD ACPI EXTRAS DRIVER
  M:    Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@@ -21213,6 -21062,7 +21207,6 @@@ F:   Documentation/hwmon/tmp401.rs
  F:    drivers/hwmon/tmp401.c
  
  TMP464 HARDWARE MONITOR DRIVER
 -M:    Agathe Porte <agathe.porte@nokia.com>
  M:    Guenter Roeck <linux@roeck-us.net>
  L:    linux-hwmon@vger.kernel.org
  S:    Maintained
@@@ -21375,14 -21225,6 +21369,14 @@@ S: Maintaine
  F:    Documentation/tools/rtla/
  F:    tools/tracing/rtla/
  
 +TECHNICAL ADVISORY BOARD PROCESS DOCS
 +M:    "Theodore Ts'o" <tytso@mit.edu>
 +M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 +L:    tech-board-discuss@lists.linux-foundation.org
 +S:    Maintained
 +F:    Documentation/process/researcher-guidelines.rst
 +F:    Documentation/process/contribution-maturity-model.rst
 +
  TRADITIONAL CHINESE DOCUMENTATION
  M:    Hu Haowen <src.res@email.cn>
  L:    linux-doc-tw-discuss@lists.sourceforge.net (moderated for non-subscribers)
@@@ -21937,7 -21779,7 +21931,7 @@@ USB WIRELESS RNDIS DRIVER (rndis_wlan
  M:    Jussi Kivilinna <jussi.kivilinna@iki.fi>
  L:    linux-wireless@vger.kernel.org
  S:    Maintained
 -F:    drivers/net/wireless/rndis_wlan.c
 +F:    drivers/net/wireless/legacy/rndis_wlan.c
  
  USB XHCI DRIVER
  M:    Mathias Nyman <mathias.nyman@intel.com>
@@@ -22216,7 -22058,6 +22210,7 @@@ F:   include/uapi/linux/virtio_console.
  VIRTIO CORE AND NET DRIVERS
  M:    "Michael S. Tsirkin" <mst@redhat.com>
  M:    Jason Wang <jasowang@redhat.com>
 +R:    Xuan Zhuo <xuanzhuo@linux.alibaba.com>
  L:    virtualization@lists.linux-foundation.org
  S:    Maintained
  F:    Documentation/ABI/testing/sysfs-bus-vdpa
@@@ -22230,7 -22071,6 +22224,7 @@@ F:   drivers/vdpa
  F:    drivers/virtio/
  F:    include/linux/vdpa.h
  F:    include/linux/virtio*.h
 +F:    include/linux/vringh.h
  F:    include/uapi/linux/virtio_*.h
  F:    tools/virtio/
  
@@@ -22318,9 -22158,7 +22312,9 @@@ L:   virtualization@lists.linux-foundatio
  L:    netdev@vger.kernel.org
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git
 +F:    kernel/vhost_task.c
  F:    drivers/vhost/
 +F:    include/linux/sched/vhost_task.h
  F:    include/linux/vhost_iotlb.h
  F:    include/uapi/linux/vhost.h
  
@@@ -22576,7 -22414,7 +22570,7 @@@ S:   Orpha
  F:    drivers/mmc/host/vub300.c
  
  W1 DALLAS'S 1-WIRE BUS
 -M:    Evgeniy Polyakov <zbr@ioremap.net>
 +M:    Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
  S:    Maintained
  F:    Documentation/devicetree/bindings/w1/
  F:    Documentation/w1/
@@@ -22695,7 -22533,7 +22689,7 @@@ F:   drivers/input/misc/wistron_btns.
  WL3501 WIRELESS PCMCIA CARD DRIVER
  L:    linux-wireless@vger.kernel.org
  S:    Odd fixes
 -F:    drivers/net/wireless/wl3501*
 +F:    drivers/net/wireless/legacy/wl3501*
  
  WOLFSON MICROELECTRONICS DRIVERS
  L:    patches@opensource.cirrus.com
@@@ -22794,7 -22632,7 +22788,7 @@@ L:   linux-kernel@vger.kernel.or
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
  F:    Documentation/devicetree/bindings/x86/
 -F:    Documentation/x86/
 +F:    Documentation/arch/x86/
  F:    arch/x86/
  
  X86 ENTRY CODE
@@@ -22804,24 -22642,13 +22798,24 @@@ S:        Maintaine
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/asm
  F:    arch/x86/entry/
  
 +X86 HARDWARE VULNERABILITIES
 +M:    Thomas Gleixner <tglx@linutronix.de>
 +M:    Borislav Petkov <bp@alien8.de>
 +M:    Peter Zijlstra <peterz@infradead.org>
 +M:    Josh Poimboeuf <jpoimboe@kernel.org>
 +R:    Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
 +S:    Maintained
 +F:    Documentation/admin-guide/hw-vuln/
 +F:    arch/x86/include/asm/nospec-branch.h
 +F:    arch/x86/kernel/cpu/bugs.c
 +
  X86 MCE INFRASTRUCTURE
  M:    Tony Luck <tony.luck@intel.com>
  M:    Borislav Petkov <bp@alien8.de>
  L:    linux-edac@vger.kernel.org
  S:    Maintained
  F:    Documentation/ABI/testing/sysfs-mce
 -F:    Documentation/x86/x86_64/machinecheck.rst
 +F:    Documentation/arch/x86/x86_64/machinecheck.rst
  F:    arch/x86/kernel/cpu/mce/*
  
  X86 MICROCODE UPDATE SUPPORT
@@@ -22843,7 -22670,7 +22837,7 @@@ M:   Hans de Goede <hdegoede@redhat.com
  L:    platform-driver-x86@vger.kernel.org
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git
 -F:    drivers/platform/x86/x86-android-tablets.c
 +F:    drivers/platform/x86/x86-android-tablets/
  
  X86 PLATFORM DRIVERS
  M:    Hans de Goede <hdegoede@redhat.com>
@@@ -23192,6 -23019,7 +23186,6 @@@ F:   drivers/i2c/busses/i2c-xlp9xx.
  
  XRA1403 GPIO EXPANDER
  M:    Nandor Han <nandor.han@ge.com>
 -M:    Semi Malinen <semi.malinen@ge.com>
  L:    linux-gpio@vger.kernel.org
  S:    Maintained
  F:    Documentation/devicetree/bindings/gpio/gpio-xra1403.txt
@@@ -23281,7 -23109,7 +23275,7 @@@ S:   Maintaine
  F:    arch/x86/kernel/cpu/zhaoxin.c
  
  ZONEFS FILESYSTEM
 -M:    Damien Le Moal <damien.lemoal@opensource.wdc.com>
 +M:    Damien Le Moal <dlemoal@kernel.org>
  M:    Naohiro Aota <naohiro.aota@wdc.com>
  R:    Johannes Thumshirn <jth@kernel.org>
  L:    linux-fsdevel@vger.kernel.org
@@@ -23349,13 -23177,6 +23343,13 @@@ L: linux-mm@kvack.or
  S:    Maintained
  F:    mm/zswap.c
  
 +NXP BLUETOOTH WIRELESS DRIVERS
 +M:    Amitkumar Karwar <amitkumar.karwar@nxp.com>
 +M:    Neeraj Kale <neeraj.sanjaykale@nxp.com>
 +S:    Maintained
 +F:    Documentation/devicetree/bindings/net/bluetooth/nxp,88w8987-bt.yaml
 +F:    drivers/bluetooth/btnxpuart.c
 +
  THE REST
  M:    Linus Torvalds <torvalds@linux-foundation.org>
  L:    linux-kernel@vger.kernel.org
@@@ -58,7 -58,7 +58,7 @@@ huge_pte_offset (struct mm_struct *mm, 
  
        pgd = pgd_offset(mm, taddr);
        if (pgd_present(*pgd)) {
-               p4d = p4d_offset(pgd, addr);
+               p4d = p4d_offset(pgd, taddr);
                if (p4d_present(*p4d)) {
                        pud = pud_offset(p4d, taddr);
                        if (pud_present(*pud)) {
@@@ -170,7 -170,7 +170,7 @@@ static int __init hugetlb_setup_sz(cha
        size = memparse(str, &str);
        if (*str || !is_power_of_2(size) || !(tr_pages & size) ||
                size <= PAGE_SIZE ||
 -              size >= (1UL << PAGE_SHIFT << MAX_ORDER)) {
 +              size > (1UL << PAGE_SHIFT << MAX_ORDER)) {
                printk(KERN_WARNING "Invalid huge page size specified\n");
                return 1;
        }
diff --combined fs/binfmt_elf.c
@@@ -2058,7 -2058,7 +2058,7 @@@ static int elf_core_dump(struct coredum
  
        has_dumped = 1;
  
-       offset += sizeof(elf);                          /* Elf header */
+       offset += sizeof(elf);                          /* ELF header */
        offset += segs * sizeof(struct elf_phdr);       /* Program headers */
  
        /* Write notes phdr entry */
@@@ -2174,6 -2174,7 +2174,6 @@@ static void __exit exit_elf_binfmt(void
  
  core_initcall(init_elf_binfmt);
  module_exit(exit_elf_binfmt);
 -MODULE_LICENSE("GPL");
  
  #ifdef CONFIG_BINFMT_ELF_KUNIT_TEST
  #include "binfmt_elf_test.c"
diff --combined fs/eventpoll.c
@@@ -43,7 -43,7 +43,7 @@@
   * LOCKING:
   * There are three level of locking required by epoll :
   *
-  * 1) epmutex (mutex)
+  * 1) epnested_mutex (mutex)
   * 2) ep->mtx (mutex)
   * 3) ep->lock (rwlock)
   *
   * we need a lock that will allow us to sleep. This lock is a
   * mutex (ep->mtx). It is acquired during the event transfer loop,
   * during epoll_ctl(EPOLL_CTL_DEL) and during eventpoll_release_file().
-  * Then we also need a global mutex to serialize eventpoll_release_file()
-  * and ep_free().
-  * This mutex is acquired by ep_free() during the epoll file
-  * cleanup path and it is also acquired by eventpoll_release_file()
-  * if a file has been pushed inside an epoll set and it is then
-  * close()d without a previous call to epoll_ctl(EPOLL_CTL_DEL).
-  * It is also acquired when inserting an epoll fd onto another epoll
-  * fd. We do this so that we walk the epoll tree and ensure that this
+  * The epnested_mutex is acquired when inserting an epoll fd onto another
+  * epoll fd. We do this so that we walk the epoll tree and ensure that this
   * insertion does not create a cycle of epoll file descriptors, which
   * could lead to deadlock. We need a global mutex to prevent two
   * simultaneous inserts (A into B and B into A) from racing and
@@@ -80,9 -74,9 +74,9 @@@
   * of epoll file descriptors, we use the current recursion depth as
   * the lockdep subkey.
   * It is possible to drop the "ep->mtx" and to use the global
-  * mutex "epmutex" (together with "ep->lock") to have it working,
+  * mutex "epnested_mutex" (together with "ep->lock") to have it working,
   * but having "ep->mtx" will make the interface more scalable.
-  * Events that require holding "epmutex" are very rare, while for
+  * Events that require holding "epnested_mutex" are very rare, while for
   * normal operations the epoll private "ep->mtx" will guarantee
   * a better scalability.
   */
@@@ -153,6 -147,13 +147,13 @@@ struct epitem 
        /* The file descriptor information this item refers to */
        struct epoll_filefd ffd;
  
+       /*
+        * Protected by file->f_lock, true for to-be-released epitem already
+        * removed from the "struct file" items list; together with
+        * eventpoll->refcount orchestrates "struct eventpoll" disposal
+        */
+       bool dying;
        /* List containing poll wait queues */
        struct eppoll_entry *pwqlist;
  
@@@ -217,6 -218,12 +218,12 @@@ struct eventpoll 
        u64 gen;
        struct hlist_head refs;
  
+       /*
+        * usage count, used together with epitem->dying to
+        * orchestrate the disposal of this struct
+        */
+       refcount_t refcount;
  #ifdef CONFIG_NET_RX_BUSY_POLL
        /* used to track busy poll napi_id */
        unsigned int napi_id;
@@@ -240,10 -247,8 +247,8 @@@ struct ep_pqueue 
  /* Maximum number of epoll watched descriptors, per user */
  static long max_user_watches __read_mostly;
  
- /*
-  * This mutex is used to serialize ep_free() and eventpoll_release_file().
-  */
- static DEFINE_MUTEX(epmutex);
+ /* Used for cycles detection */
+ static DEFINE_MUTEX(epnested_mutex);
  
  static u64 loop_check_gen = 0;
  
@@@ -258,7 -263,7 +263,7 @@@ static struct kmem_cache *pwq_cache __r
  
  /*
   * List of files with newly added links, where we may need to limit the number
-  * of emanating paths. Protected by the epmutex.
+  * of emanating paths. Protected by the epnested_mutex.
   */
  struct epitems_head {
        struct hlist_head epitems;
@@@ -483,8 -488,8 +488,8 @@@ static inline void ep_set_busy_poll_nap
   * (efd1) notices that it may have some event ready, so it needs to wake up
   * the waiters on its poll wait list (efd2). So it calls ep_poll_safewake()
   * that ends up in another wake_up(), after having checked about the
 - * recursion constraints. That are, no more than EP_MAX_POLLWAKE_NESTS, to
 - * avoid stack blasting.
 + * recursion constraints. That are, no more than EP_MAX_NESTS, to avoid
 + * stack blasting.
   *
   * When CONFIG_DEBUG_LOCK_ALLOC is enabled, make sure lockdep can handle
   * this special case of epoll.
@@@ -557,8 -562,7 +562,7 @@@ static void ep_remove_wait_queue(struc
  
  /*
   * This function unregisters poll callbacks from the associated file
-  * descriptor.  Must be called with "mtx" held (or "epmutex" if called from
-  * ep_free).
+  * descriptor.  Must be called with "mtx" held.
   */
  static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
  {
@@@ -681,11 -685,40 +685,40 @@@ static void epi_rcu_free(struct rcu_hea
        kmem_cache_free(epi_cache, epi);
  }
  
+ static void ep_get(struct eventpoll *ep)
+ {
+       refcount_inc(&ep->refcount);
+ }
+ /*
+  * Returns true if the event poll can be disposed
+  */
+ static bool ep_refcount_dec_and_test(struct eventpoll *ep)
+ {
+       if (!refcount_dec_and_test(&ep->refcount))
+               return false;
+       WARN_ON_ONCE(!RB_EMPTY_ROOT(&ep->rbr.rb_root));
+       return true;
+ }
+ static void ep_free(struct eventpoll *ep)
+ {
+       mutex_destroy(&ep->mtx);
+       free_uid(ep->user);
+       wakeup_source_unregister(ep->ws);
+       kfree(ep);
+ }
  /*
   * Removes a "struct epitem" from the eventpoll RB tree and deallocates
   * all the associated resources. Must be called with "mtx" held.
+  * If the dying flag is set, do the removal only if force is true.
+  * This prevents ep_clear_and_put() from dropping all the ep references
+  * while running concurrently with eventpoll_release_file().
+  * Returns true if the eventpoll can be disposed.
   */
- static int ep_remove(struct eventpoll *ep, struct epitem *epi)
+ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
  {
        struct file *file = epi->ffd.file;
        struct epitems_head *to_free;
  
        /* Remove the current item from the list of epoll hooks */
        spin_lock(&file->f_lock);
+       if (epi->dying && !force) {
+               spin_unlock(&file->f_lock);
+               return false;
+       }
        to_free = NULL;
        head = file->f_ep;
        if (head->first == &epi->fllink && !epi->fllink.next) {
        call_rcu(&epi->rcu, epi_rcu_free);
  
        percpu_counter_dec(&ep->user->epoll_watches);
+       return ep_refcount_dec_and_test(ep);
+ }
  
-       return 0;
+ /*
+  * ep_remove variant for callers owing an additional reference to the ep
+  */
+ static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi)
+ {
+       WARN_ON_ONCE(__ep_remove(ep, epi, false));
  }
  
- static void ep_free(struct eventpoll *ep)
+ static void ep_clear_and_put(struct eventpoll *ep)
  {
-       struct rb_node *rbp;
+       struct rb_node *rbp, *next;
        struct epitem *epi;
+       bool dispose;
  
        /* We need to release all tasks waiting for these file */
        if (waitqueue_active(&ep->poll_wait))
                ep_poll_safewake(ep, NULL, 0);
  
-       /*
-        * We need to lock this because we could be hit by
-        * eventpoll_release_file() while we're freeing the "struct eventpoll".
-        * We do not need to hold "ep->mtx" here because the epoll file
-        * is on the way to be removed and no one has references to it
-        * anymore. The only hit might come from eventpoll_release_file() but
-        * holding "epmutex" is sufficient here.
-        */
-       mutex_lock(&epmutex);
+       mutex_lock(&ep->mtx);
  
        /*
         * Walks through the whole tree by unregistering poll callbacks.
        }
  
        /*
-        * Walks through the whole tree by freeing each "struct epitem". At this
-        * point we are sure no poll callbacks will be lingering around, and also by
-        * holding "epmutex" we can be sure that no file cleanup code will hit
-        * us during this operation. So we can avoid the lock on "ep->lock".
-        * We do not need to lock ep->mtx, either, we only do it to prevent
-        * a lockdep warning.
+        * Walks through the whole tree and try to free each "struct epitem".
+        * Note that ep_remove_safe() will not remove the epitem in case of a
+        * racing eventpoll_release_file(); the latter will do the removal.
+        * At this point we are sure no poll callbacks will be lingering around.
+        * Since we still own a reference to the eventpoll struct, the loop can't
+        * dispose it.
         */
-       mutex_lock(&ep->mtx);
-       while ((rbp = rb_first_cached(&ep->rbr)) != NULL) {
+       for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = next) {
+               next = rb_next(rbp);
                epi = rb_entry(rbp, struct epitem, rbn);
-               ep_remove(ep, epi);
+               ep_remove_safe(ep, epi);
                cond_resched();
        }
+       dispose = ep_refcount_dec_and_test(ep);
        mutex_unlock(&ep->mtx);
  
-       mutex_unlock(&epmutex);
-       mutex_destroy(&ep->mtx);
-       free_uid(ep->user);
-       wakeup_source_unregister(ep->ws);
-       kfree(ep);
+       if (dispose)
+               ep_free(ep);
  }
  
  static int ep_eventpoll_release(struct inode *inode, struct file *file)
        struct eventpoll *ep = file->private_data;
  
        if (ep)
-               ep_free(ep);
+               ep_clear_and_put(ep);
  
        return 0;
  }
@@@ -906,33 -943,34 +943,34 @@@ void eventpoll_release_file(struct fil
  {
        struct eventpoll *ep;
        struct epitem *epi;
-       struct hlist_node *next;
+       bool dispose;
  
        /*
-        * We don't want to get "file->f_lock" because it is not
-        * necessary. It is not necessary because we're in the "struct file"
-        * cleanup path, and this means that no one is using this file anymore.
-        * So, for example, epoll_ctl() cannot hit here since if we reach this
-        * point, the file counter already went to zero and fget() would fail.
-        * The only hit might come from ep_free() but by holding the mutex
-        * will correctly serialize the operation. We do need to acquire
-        * "ep->mtx" after "epmutex" because ep_remove() requires it when called
-        * from anywhere but ep_free().
-        *
-        * Besides, ep_remove() acquires the lock, so we can't hold it here.
+        * Use the 'dying' flag to prevent a concurrent ep_clear_and_put() from
+        * touching the epitems list before eventpoll_release_file() can access
+        * the ep->mtx.
         */
-       mutex_lock(&epmutex);
-       if (unlikely(!file->f_ep)) {
-               mutex_unlock(&epmutex);
-               return;
-       }
-       hlist_for_each_entry_safe(epi, next, file->f_ep, fllink) {
+ again:
+       spin_lock(&file->f_lock);
+       if (file->f_ep && file->f_ep->first) {
+               epi = hlist_entry(file->f_ep->first, struct epitem, fllink);
+               epi->dying = true;
+               spin_unlock(&file->f_lock);
+               /*
+                * ep access is safe as we still own a reference to the ep
+                * struct
+                */
                ep = epi->ep;
-               mutex_lock_nested(&ep->mtx, 0);
-               ep_remove(ep, epi);
+               mutex_lock(&ep->mtx);
+               dispose = __ep_remove(ep, epi, true);
                mutex_unlock(&ep->mtx);
+               if (dispose)
+                       ep_free(ep);
+               goto again;
        }
-       mutex_unlock(&epmutex);
+       spin_unlock(&file->f_lock);
  }
  
  static int ep_alloc(struct eventpoll **pep)
        ep->rbr = RB_ROOT_CACHED;
        ep->ovflist = EP_UNACTIVE_PTR;
        ep->user = user;
+       refcount_set(&ep->refcount, 1);
  
        *pep = ep;
  
@@@ -1223,10 -1262,10 +1262,10 @@@ out_unlock
                 */
                list_del_init(&wait->entry);
                /*
-                * ->whead != NULL protects us from the race with ep_free()
-                * or ep_remove(), ep_remove_wait_queue() takes whead->lock
-                * held by the caller. Once we nullify it, nothing protects
-                * ep/epi or even wait.
+                * ->whead != NULL protects us from the race with
+                * ep_clear_and_put() or ep_remove(), ep_remove_wait_queue()
+                * takes whead->lock held by the caller. Once we nullify it,
+                * nothing protects ep/epi or even wait.
                 */
                smp_store_release(&ep_pwq_from_wait(wait)->whead, NULL);
        }
@@@ -1298,7 -1337,7 +1337,7 @@@ static void ep_rbtree_insert(struct eve
   * is connected to n file sources. In this case each file source has 1 path
   * of length 1. Thus, the numbers below should be more than sufficient. These
   * path limits are enforced during an EPOLL_CTL_ADD operation, since a modify
-  * and delete can't add additional paths. Protected by the epmutex.
+  * and delete can't add additional paths. Protected by the epnested_mutex.
   */
  static const int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 };
  static int path_count[PATH_ARR_SIZE];
@@@ -1496,16 -1535,22 +1535,22 @@@ static int ep_insert(struct eventpoll *
        if (tep)
                mutex_unlock(&tep->mtx);
  
+       /*
+        * ep_remove_safe() calls in the later error paths can't lead to
+        * ep_free() as the ep file itself still holds an ep reference.
+        */
+       ep_get(ep);
        /* now check if we've created too many backpaths */
        if (unlikely(full_check && reverse_path_check())) {
-               ep_remove(ep, epi);
+               ep_remove_safe(ep, epi);
                return -EINVAL;
        }
  
        if (epi->event.events & EPOLLWAKEUP) {
                error = ep_create_wakeup_source(epi);
                if (error) {
-                       ep_remove(ep, epi);
+                       ep_remove_safe(ep, epi);
                        return error;
                }
        }
         * high memory pressure.
         */
        if (unlikely(!epq.epi)) {
-               ep_remove(ep, epi);
+               ep_remove_safe(ep, epi);
                return -ENOMEM;
        }
  
@@@ -2025,7 -2070,7 +2070,7 @@@ static int do_epoll_create(int flags
  out_free_fd:
        put_unused_fd(fd);
  out_free_ep:
-       ep_free(ep);
+       ep_clear_and_put(ep);
        return error;
  }
  
@@@ -2042,19 -2087,6 +2087,19 @@@ SYSCALL_DEFINE1(epoll_create, int, size
        return do_epoll_create(0);
  }
  
 +#ifdef CONFIG_PM_SLEEP
 +static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
 +{
 +      if ((epev->events & EPOLLWAKEUP) && !capable(CAP_BLOCK_SUSPEND))
 +              epev->events &= ~EPOLLWAKEUP;
 +}
 +#else
 +static inline void ep_take_care_of_epollwakeup(struct epoll_event *epev)
 +{
 +      epev->events &= ~EPOLLWAKEUP;
 +}
 +#endif
 +
  static inline int epoll_mutex_lock(struct mutex *mutex, int depth,
                                   bool nonblock)
  {
@@@ -2135,7 -2167,7 +2180,7 @@@ int do_epoll_ctl(int epfd, int op, int 
         * We do not need to take the global 'epumutex' on EPOLL_CTL_ADD when
         * the epoll file descriptor is attaching directly to a wakeup source,
         * unless the epoll file descriptor is nested. The purpose of taking the
-        * 'epmutex' on add is to prevent complex toplogies such as loops and
+        * 'epnested_mutex' on add is to prevent complex toplogies such as loops and
         * deep wakeup paths from forming in parallel through multiple
         * EPOLL_CTL_ADD operations.
         */
                if (READ_ONCE(f.file->f_ep) || ep->gen == loop_check_gen ||
                    is_file_epoll(tf.file)) {
                        mutex_unlock(&ep->mtx);
-                       error = epoll_mutex_lock(&epmutex, 0, nonblock);
+                       error = epoll_mutex_lock(&epnested_mutex, 0, nonblock);
                        if (error)
                                goto error_tgt_fput;
                        loop_check_gen++;
                        error = -EEXIST;
                break;
        case EPOLL_CTL_DEL:
-               if (epi)
-                       error = ep_remove(ep, epi);
-               else
+               if (epi) {
+                       /*
+                        * The eventpoll itself is still alive: the refcount
+                        * can't go to zero here.
+                        */
+                       ep_remove_safe(ep, epi);
+                       error = 0;
+               } else {
                        error = -ENOENT;
+               }
                break;
        case EPOLL_CTL_MOD:
                if (epi) {
@@@ -2201,7 -2239,7 +2252,7 @@@ error_tgt_fput
        if (full_check) {
                clear_tfile_check_list();
                loop_check_gen++;
-               mutex_unlock(&epmutex);
+               mutex_unlock(&epnested_mutex);
        }
  
        fdput(tf);
diff --combined fs/nfs/nfs3acl.c
@@@ -21,9 -21,8 +21,8 @@@ static void nfs3_prepare_get_acl(struc
  {
        struct posix_acl *sentinel = uncached_acl_sentinel(current);
  
-       if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) {
-               /* Not the first reader or sentinel already in place. */
-       }
+       /* If the ACL isn't being read yet, set our sentinel. */
+       cmpxchg(p, ACL_NOT_CACHED, sentinel);
  }
  
  static void nfs3_complete_get_acl(struct posix_acl **p, struct posix_acl *acl)
@@@ -300,6 -299,12 +299,6 @@@ fail
        goto out;
  }
  
 -const struct xattr_handler *nfs3_xattr_handlers[] = {
 -      &posix_acl_access_xattr_handler,
 -      &posix_acl_default_xattr_handler,
 -      NULL,
 -};
 -
  static int
  nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data,
                size_t size, ssize_t *result)
diff --combined fs/proc/base.c
@@@ -96,7 -96,6 +96,7 @@@
  #include <linux/time_namespace.h>
  #include <linux/resctrl.h>
  #include <linux/cn_proc.h>
 +#include <linux/ksm.h>
  #include <trace/events/oom.h>
  #include "internal.h"
  #include "fd.h"
@@@ -700,7 -699,6 +700,6 @@@ int proc_setattr(struct mnt_idmap *idma
                return error;
  
        setattr_copy(&nop_mnt_idmap, inode, attr);
-       mark_inode_dirty(inode);
        return 0;
  }
  
@@@ -3208,8 -3206,6 +3207,8 @@@ static int proc_pid_ksm_stat(struct seq
        mm = get_task_mm(task);
        if (mm) {
                seq_printf(m, "ksm_rmap_items %lu\n", mm->ksm_rmap_items);
 +              seq_printf(m, "ksm_merging_pages %lu\n", mm->ksm_merging_pages);
 +              seq_printf(m, "ksm_process_profit %ld\n", ksm_process_profit(mm));
                mmput(mm);
        }
  
diff --combined fs/proc/proc_sysctl.c
@@@ -841,7 -841,6 +841,6 @@@ static int proc_sys_setattr(struct mnt_
                return error;
  
        setattr_copy(&nop_mnt_idmap, inode, attr);
-       mark_inode_dirty(inode);
        return 0;
  }
  
        return err;
  }
  
 +/* Find the directory for the ctl_table. If one is not found create it. */
 +static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
 +{
 +      const char *name, *nextname;
 +
 +      for (name = path; name; name = nextname) {
 +              int namelen;
 +              nextname = strchr(name, '/');
 +              if (nextname) {
 +                      namelen = nextname - name;
 +                      nextname++;
 +              } else {
 +                      namelen = strlen(name);
 +              }
 +              if (namelen == 0)
 +                      continue;
 +
 +              /*
 +               * namelen ensures if name is "foo/bar/yay" only foo is
 +               * registered first. We traverse as if using mkdir -p and
 +               * return a ctl_dir for the last directory entry.
 +               */
 +              dir = get_subdir(dir, name, namelen);
 +              if (IS_ERR(dir))
 +                      break;
 +      }
 +      return dir;
 +}
 +
  /**
   * __register_sysctl_table - register a leaf sysctl table
   * @set: Sysctl tree to register on
   * @path: The path to the directory the sysctl table is in.
 - * @table: the top-level table structure
 + * @table: the top-level table structure without any child. This table
 + *     should not be free'd after registration. So it should not be
 + *     used on stack. It can either be a global or dynamically allocated
 + *     by the caller and free'd later after sysctl unregistration.
   *
   * Register a sysctl table hierarchy. @table should be a filled in ctl_table
   * array. A completely 0 filled entry terminates the table.
   * proc_handler - the text handler routine (described below)
   *
   * extra1, extra2 - extra pointers usable by the proc handler routines
 + * XXX: we should eventually modify these to use long min / max [0]
 + * [0] https://lkml.kernel.org/87zgpte9o4.fsf@email.froward.int.ebiederm.org
   *
   * Leaf nodes in the sysctl tree will be represented by a single file
 - * under /proc; non-leaf nodes will be represented by directories.
 + * under /proc; non-leaf nodes (where child is not NULL) are not allowed,
 + * sysctl_check_table() verifies this.
   *
   * There must be a proc_handler routine for any terminal nodes.
   * Several default handlers are available to cover common cases -
@@@ -1366,6 -1330,7 +1365,6 @@@ struct ctl_table_header *__register_sys
  {
        struct ctl_table_root *root = set->dir.header.root;
        struct ctl_table_header *header;
 -      const char *name, *nextname;
        struct ctl_dir *dir;
        struct ctl_table *entry;
        struct ctl_node *node;
  
        spin_lock(&sysctl_lock);
        dir = &set->dir;
 -      /* Reference moved down the diretory tree get_subdir */
 +      /* Reference moved down the directory tree get_subdir */
        dir->header.nreg++;
        spin_unlock(&sysctl_lock);
  
 -      /* Find the directory for the ctl_table */
 -      for (name = path; name; name = nextname) {
 -              int namelen;
 -              nextname = strchr(name, '/');
 -              if (nextname) {
 -                      namelen = nextname - name;
 -                      nextname++;
 -              } else {
 -                      namelen = strlen(name);
 -              }
 -              if (namelen == 0)
 -                      continue;
 -
 -              dir = get_subdir(dir, name, namelen);
 -              if (IS_ERR(dir))
 -                      goto fail;
 -      }
 -
 +      dir = sysctl_mkdir_p(dir, path);
 +      if (IS_ERR(dir))
 +              goto fail;
        spin_lock(&sysctl_lock);
        if (insert_header(dir, header))
                goto fail_put_dir_locked;
@@@ -1413,15 -1393,8 +1412,15 @@@ fail
  
  /**
   * register_sysctl - register a sysctl table
 - * @path: The path to the directory the sysctl table is in.
 - * @table: the table structure
 + * @path: The path to the directory the sysctl table is in. If the path
 + *    doesn't exist we will create it for you.
 + * @table: the table structure. The calller must ensure the life of the @table
 + *    will be kept during the lifetime use of the syctl. It must not be freed
 + *    until unregister_sysctl_table() is called with the given returned table
 + *    with this registration. If your code is non modular then you don't need
 + *    to call unregister_sysctl_table() and can instead use something like
 + *    register_sysctl_init() which does not care for the result of the syctl
 + *    registration.
   *
   * Register a sysctl table. @table should be a filled in ctl_table
   * array. A completely 0 filled entry terminates the table.
@@@ -1437,11 -1410,8 +1436,11 @@@ EXPORT_SYMBOL(register_sysctl)
  
  /**
   * __register_sysctl_init() - register sysctl table to path
 - * @path: path name for sysctl base
 - * @table: This is the sysctl table that needs to be registered to the path
 + * @path: path name for sysctl base. If that path doesn't exist we will create
 + *    it for you.
 + * @table: This is the sysctl table that needs to be registered to the path.
 + *    The caller must ensure the life of the @table will be kept during the
 + *    lifetime use of the sysctl.
   * @table_name: The name of sysctl table, only used for log printing when
   *              registration fails
   *
   * register_sysctl() failing on init are extremely low, and so for both reasons
   * this function does not return any error as it is used by initialization code.
   *
 - * Context: Can only be called after your respective sysctl base path has been
 - * registered. So for instance, most base directories are registered early on
 - * init before init levels are processed through proc_sys_init() and
 - * sysctl_init_bases().
 + * Context: if your base directory does not exist it will be created for you.
   */
  void __init __register_sysctl_init(const char *path, struct ctl_table *table,
                                 const char *table_name)
@@@ -1583,7 -1556,6 +1582,7 @@@ out
   *
   * Register a sysctl table hierarchy. @table should be a filled in ctl_table
   * array. A completely 0 filled entry terminates the table.
 + * We are slowly deprecating this call so avoid its use.
   *
   * See __register_sysctl_table for more details.
   */
@@@ -1655,7 -1627,6 +1654,7 @@@ err_register_leaves
   *
   * Register a sysctl table hierarchy. @table should be a filled in ctl_table
   * array. A completely 0 filled entry terminates the table.
 + * We are slowly deprecating this caller so avoid future uses of it.
   *
   * See __register_sysctl_paths for more details.
   */
diff --combined kernel/sched/core.c
@@@ -704,6 -704,7 +704,7 @@@ static void update_rq_clock_task(struc
        rq->prev_irq_time += irq_delta;
        delta -= irq_delta;
        psi_account_irqtime(rq->curr, irq_delta);
+       delayacct_irq(rq->curr, irq_delta);
  #endif
  #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
        if (static_key_false((&paravirt_steal_rq_enabled))) {
@@@ -5203,14 -5204,13 +5204,14 @@@ static struct rq *finish_task_switch(st
         * rq->curr, before returning to userspace, so provide them here:
         *
         * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly
 -       *   provided by mmdrop(),
 +       *   provided by mmdrop_lazy_tlb(),
         * - a sync_core for SYNC_CORE.
         */
        if (mm) {
                membarrier_mm_sync_core_before_usermode(mm);
 -              mmdrop_sched(mm);
 +              mmdrop_lazy_tlb_sched(mm);
        }
 +
        if (unlikely(prev_state == TASK_DEAD)) {
                if (prev->sched_class->task_dead)
                        prev->sched_class->task_dead(prev);
@@@ -5267,9 -5267,9 +5268,9 @@@ context_switch(struct rq *rq, struct ta
  
        /*
         * kernel -> kernel   lazy + transfer active
 -       *   user -> kernel   lazy + mmgrab() active
 +       *   user -> kernel   lazy + mmgrab_lazy_tlb() active
         *
 -       * kernel ->   user   switch + mmdrop() active
 +       * kernel ->   user   switch + mmdrop_lazy_tlb() active
         *   user ->   user   switch
         */
        if (!next->mm) {                                // to kernel
  
                next->active_mm = prev->active_mm;
                if (prev->mm)                           // from user
 -                      mmgrab(prev->active_mm);
 +                      mmgrab_lazy_tlb(prev->active_mm);
                else
                        prev->active_mm = NULL;
        } else {                                        // to user
                lru_gen_use_mm(next->mm);
  
                if (!prev->mm) {                        // from kernel
 -                      /* will mmdrop() in finish_task_switch(). */
 +                      /* will mmdrop_lazy_tlb() in finish_task_switch(). */
                        rq->prev_mm = prev->active_mm;
                        prev->active_mm = NULL;
                }
@@@ -9936,7 -9936,7 +9937,7 @@@ void __init sched_init(void
        /*
         * The boot idle thread does lazy MMU switching as well:
         */
 -      mmgrab(&init_mm);
 +      mmgrab_lazy_tlb(&init_mm);
        enter_lazy_tlb(&init_mm, current);
  
        /*
diff --combined scripts/checkpatch.pl
@@@ -620,6 -620,22 +620,22 @@@ our $signature_tags = qr{(?xi
        Cc:
  )};
  
+ our @link_tags = qw(Link Closes);
+ #Create a search and print patterns for all these strings to be used directly below
+ our $link_tags_search = "";
+ our $link_tags_print = "";
+ foreach my $entry (@link_tags) {
+       if ($link_tags_search ne "") {
+               $link_tags_search .= '|';
+               $link_tags_print .= ' or ';
+       }
+       $entry .= ':';
+       $link_tags_search .= $entry;
+       $link_tags_print .= "'$entry'";
+ }
+ $link_tags_search = "(?:${link_tags_search})";
  our $tracing_logging_tags = qr{(?xi:
        [=-]*> |
        <[=-]* |
@@@ -3158,14 -3174,14 +3174,14 @@@ sub process 
                                }
                        }
  
- # check if Reported-by: is followed by a Link:
+ # check if Reported-by: is followed by a Closes: tag
                        if ($sign_off =~ /^reported(?:|-and-tested)-by:$/i) {
                                if (!defined $lines[$linenr]) {
                                        WARN("BAD_REPORTED_BY_LINK",
-                                            "Reported-by: should be immediately followed by Link: to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
-                               } elsif ($rawlines[$linenr] !~ m{^link:\s*https?://}i) {
+                                            "Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . "\n");
+                               } elsif ($rawlines[$linenr] !~ /^closes:\s*/i) {
                                        WARN("BAD_REPORTED_BY_LINK",
-                                            "Reported-by: should be immediately followed by Link: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
+                                            "Reported-by: should be immediately followed by Closes: with a URL to the report\n" . $herecurr . $rawlines[$linenr] . "\n");
                                }
                        }
                }
                                        # file delta changes
                      $line =~ /^\s*(?:[\w\.\-\+]*\/)++[\w\.\-\+]+:/ ||
                                        # filename then :
-                     $line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
-                                       # A Fixes: or Link: line or signature tag line
+                     $line =~ /^\s*(?:Fixes:|$link_tags_search|$signature_tags)/i ||
+                                       # A Fixes:, link or signature tag line
                      $commit_log_possible_stack_dump)) {
                        WARN("COMMIT_LOG_LONG_LINE",
                             "Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
  
  # Check for odd tags before a URI/URL
                if ($in_commit_log &&
-                   $line =~ /^\s*(\w+):\s*http/ && $1 ne 'Link') {
+                   $line =~ /^\s*(\w+:)\s*http/ && $1 !~ /^$link_tags_search$/) {
                        if ($1 =~ /^v(?:ersion)?\d+/i) {
                                WARN("COMMIT_LOG_VERSIONING",
                                     "Patch version information should be after the --- line\n" . $herecurr);
                        } else {
                                WARN("COMMIT_LOG_USE_LINK",
-                                    "Unknown link reference '$1:', use 'Link:' instead\n" . $herecurr);
+                                    "Unknown link reference '$1', use $link_tags_print instead\n" . $herecurr);
+                       }
+               }
+ # Check for misuse of the link tags
+               if ($in_commit_log &&
+                   $line =~ /^\s*(\w+:)\s*(\S+)/) {
+                       my $tag = $1;
+                       my $value = $2;
+                       if ($tag =~ /^$link_tags_search$/ && $value !~ m{^https?://}) {
+                               WARN("COMMIT_LOG_WRONG_LINK",
+                                    "'$tag' should be followed by a public http(s) link\n" . $herecurr);
                        }
                }
  
                                                     "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
                                        }
                                        if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
-                                           not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
+                                           $spdx_license !~ /GPL-2\.0(?:-only)? OR BSD-2-Clause/) {
                                                my $msg_level = \&WARN;
                                                $msg_level = \&CHK if ($file);
                                                if (&{$msg_level}("SPDX_LICENSE_TAG",
                                                        $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
                                                }
                                        }
+                                       if ($realfile =~ m@^include/dt-bindings/@ &&
+                                           $spdx_license !~ /GPL-2\.0(?:-only)? OR \S+/) {
+                                               WARN("SPDX_LICENSE_TAG",
+                                                    "DT binding headers should be licensed (GPL-2.0-only OR .*)\n" . $herecurr);
+                                       }
                                }
                        }
                }
                            $var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
  #Ignore Page<foo> variants
                            $var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
+ #Ignore ETHTOOL_LINK_MODE_<foo> variants
+                           $var !~ /^ETHTOOL_LINK_MODE_/ &&
  #Ignore SI style variants like nS, mV and dB
  #(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
                            $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
                        }
                }
  
 +# check for soon-to-be-deprecated single-argument k[v]free_rcu() API
 +              if ($line =~ /\bk[v]?free_rcu\s*\([^(]+\)/) {
 +                      if ($line =~ /\bk[v]?free_rcu\s*\([^,]+\)/) {
 +                              ERROR("DEPRECATED_API",
 +                                    "Single-argument k[v]free_rcu() API is deprecated, please pass rcu_head object or call k[v]free_rcu_mightsleep()." . $herecurr);
 +                      }
 +              }
 +
 +
  # check for unnecessary "Out of Memory" messages
                if ($line =~ /^\+.*\b$logFunctions\s*\(/ &&
                    $prevline =~ /^[ \+]\s*if\s*\(\s*(\!\s*|NULL\s*==\s*)?($Lval)(\s*==\s*NULL\s*)?\s*\)/ &&
  #include <linux/clk-provider.h>
  #include <linux/fs.h>
  #include <linux/hrtimer.h>
+ #include <linux/irq.h>
  #include <linux/mount.h>
  #include <linux/of_fdt.h>
+ #include <linux/radix-tree.h>
  #include <linux/threads.h>
  
  /* We need to stringify expanded macros so that they can be parsed */
@@@ -39,6 -41,8 +41,8 @@@
  
  import gdb
  
+ LX_CONFIG(CONFIG_DEBUG_INFO_REDUCED)
  /* linux/clk-provider.h */
  if IS_BUILTIN(CONFIG_COMMON_CLK):
      LX_GDBPARSED(CLK_GET_RATE_NOCACHE)
@@@ -54,9 -58,10 +58,13 @@@ LX_VALUE(SB_NODIRATIME
  /* linux/htimer.h */
  LX_GDBPARSED(hrtimer_resolution)
  
+ /* linux/irq.h */
+ LX_GDBPARSED(IRQD_LEVEL)
+ LX_GDBPARSED(IRQ_HIDDEN)
 +/* linux/module.h */
 +LX_GDBPARSED(MOD_TEXT)
 +
  /* linux/mount.h */
  LX_VALUE(MNT_NOSUID)
  LX_VALUE(MNT_NODEV)
@@@ -71,6 -76,13 +79,13 @@@ LX_VALUE(NR_CPUS
  /* linux/of_fdt.h> */
  LX_VALUE(OF_DT_HEADER)
  
+ /* linux/radix-tree.h */
+ LX_GDBPARSED(RADIX_TREE_ENTRY_MASK)
+ LX_GDBPARSED(RADIX_TREE_INTERNAL_NODE)
+ LX_GDBPARSED(RADIX_TREE_MAP_SIZE)
+ LX_GDBPARSED(RADIX_TREE_MAP_SHIFT)
+ LX_GDBPARSED(RADIX_TREE_MAP_MASK)
  /* Kernel Configs */
  LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS)
  LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
@@@ -78,3 -90,12 +93,12 @@@ LX_CONFIG(CONFIG_HIGH_RES_TIMERS
  LX_CONFIG(CONFIG_NR_CPUS)
  LX_CONFIG(CONFIG_OF)
  LX_CONFIG(CONFIG_TICK_ONESHOT)
+ LX_CONFIG(CONFIG_GENERIC_IRQ_SHOW_LEVEL)
+ LX_CONFIG(CONFIG_X86_LOCAL_APIC)
+ LX_CONFIG(CONFIG_SMP)
+ LX_CONFIG(CONFIG_X86_THERMAL_VECTOR)
+ LX_CONFIG(CONFIG_X86_MCE_THRESHOLD)
+ LX_CONFIG(CONFIG_X86_MCE_AMD)
+ LX_CONFIG(CONFIG_X86_MCE)
+ LX_CONFIG(CONFIG_X86_IO_APIC)
+ LX_CONFIG(CONFIG_HAVE_KVM)
diff --combined tools/lib/bpf/libbpf.c
@@@ -53,7 -53,6 +53,7 @@@
  #include "libbpf_internal.h"
  #include "hashmap.h"
  #include "bpf_gen_internal.h"
 +#include "zip.h"
  
  #ifndef BPF_FS_MAGIC
  #define BPF_FS_MAGIC          0xcafe4a11
@@@ -116,7 -115,6 +116,7 @@@ static const char * const attach_type_n
        [BPF_SK_REUSEPORT_SELECT_OR_MIGRATE]    = "sk_reuseport_select_or_migrate",
        [BPF_PERF_EVENT]                = "perf_event",
        [BPF_TRACE_KPROBE_MULTI]        = "trace_kprobe_multi",
 +      [BPF_STRUCT_OPS]                = "struct_ops",
  };
  
  static const char * const link_type_name[] = {
        [BPF_LINK_TYPE_PERF_EVENT]              = "perf_event",
        [BPF_LINK_TYPE_KPROBE_MULTI]            = "kprobe_multi",
        [BPF_LINK_TYPE_STRUCT_OPS]              = "struct_ops",
 +      [BPF_LINK_TYPE_NETFILTER]               = "netfilter",
  };
  
  static const char * const map_type_name[] = {
@@@ -202,7 -199,6 +202,7 @@@ static const char * const prog_type_nam
        [BPF_PROG_TYPE_LSM]                     = "lsm",
        [BPF_PROG_TYPE_SK_LOOKUP]               = "sk_lookup",
        [BPF_PROG_TYPE_SYSCALL]                 = "syscall",
 +      [BPF_PROG_TYPE_NETFILTER]               = "netfilter",
  };
  
  static int __base_pr(enum libbpf_print_level level, const char *format,
@@@ -218,10 -214,9 +218,10 @@@ static libbpf_print_fn_t __libbpf_pr = 
  
  libbpf_print_fn_t libbpf_set_print(libbpf_print_fn_t fn)
  {
 -      libbpf_print_fn_t old_print_fn = __libbpf_pr;
 +      libbpf_print_fn_t old_print_fn;
 +
 +      old_print_fn = __atomic_exchange_n(&__libbpf_pr, fn, __ATOMIC_RELAXED);
  
 -      __libbpf_pr = fn;
        return old_print_fn;
  }
  
@@@ -230,10 -225,8 +230,10 @@@ void libbpf_print(enum libbpf_print_lev
  {
        va_list args;
        int old_errno;
 +      libbpf_print_fn_t print_fn;
  
 -      if (!__libbpf_pr)
 +      print_fn = __atomic_load_n(&__libbpf_pr, __ATOMIC_RELAXED);
 +      if (!print_fn)
                return;
  
        old_errno = errno;
@@@ -321,8 -314,8 +321,8 @@@ enum reloc_type 
        RELO_LD64,
        RELO_CALL,
        RELO_DATA,
 -      RELO_EXTERN_VAR,
 -      RELO_EXTERN_FUNC,
 +      RELO_EXTERN_LD64,
 +      RELO_EXTERN_CALL,
        RELO_SUBPROG_ADDR,
        RELO_CORE,
  };
@@@ -335,7 -328,6 +335,7 @@@ struct reloc_desc 
                struct {
                        int map_idx;
                        int sym_off;
 +                      int ext_idx;
                };
        };
  };
@@@ -474,7 -466,6 +474,7 @@@ struct bpf_struct_ops 
  #define KCONFIG_SEC ".kconfig"
  #define KSYMS_SEC ".ksyms"
  #define STRUCT_OPS_SEC ".struct_ops"
 +#define STRUCT_OPS_LINK_SEC ".struct_ops.link"
  
  enum libbpf_map_type {
        LIBBPF_MAP_UNSPEC,
@@@ -604,7 -595,6 +604,7 @@@ struct elf_state 
        Elf64_Ehdr *ehdr;
        Elf_Data *symbols;
        Elf_Data *st_ops_data;
 +      Elf_Data *st_ops_link_data;
        size_t shstrndx; /* section index for section name strings */
        size_t strtabidx;
        struct elf_sec_desc *secs;
        int text_shndx;
        int symbols_shndx;
        int st_ops_shndx;
 +      int st_ops_link_shndx;
  };
  
  struct usdt_manager;
@@@ -809,6 -798,7 +809,6 @@@ bpf_object__add_programs(struct bpf_obj
        progs = obj->programs;
        nr_progs = obj->nr_programs;
        nr_syms = symbols->d_size / sizeof(Elf64_Sym);
 -      sec_off = 0;
  
        for (i = 0; i < nr_syms; i++) {
                sym = elf_sym_by_idx(obj, i);
@@@ -1128,8 -1118,7 +1128,8 @@@ static int bpf_object__init_kern_struct
        return 0;
  }
  
 -static int bpf_object__init_struct_ops_maps(struct bpf_object *obj)
 +static int init_struct_ops_maps(struct bpf_object *obj, const char *sec_name,
 +                              int shndx, Elf_Data *data, __u32 map_flags)
  {
        const struct btf_type *type, *datasec;
        const struct btf_var_secinfo *vsi;
        struct bpf_map *map;
        __u32 i;
  
 -      if (obj->efile.st_ops_shndx == -1)
 +      if (shndx == -1)
                return 0;
  
        btf = obj->btf;
 -      datasec_id = btf__find_by_name_kind(btf, STRUCT_OPS_SEC,
 +      datasec_id = btf__find_by_name_kind(btf, sec_name,
                                            BTF_KIND_DATASEC);
        if (datasec_id < 0) {
                pr_warn("struct_ops init: DATASEC %s not found\n",
 -                      STRUCT_OPS_SEC);
 +                      sec_name);
                return -EINVAL;
        }
  
                type_id = btf__resolve_type(obj->btf, vsi->type);
                if (type_id < 0) {
                        pr_warn("struct_ops init: Cannot resolve var type_id %u in DATASEC %s\n",
 -                              vsi->type, STRUCT_OPS_SEC);
 +                              vsi->type, sec_name);
                        return -EINVAL;
                }
  
                if (IS_ERR(map))
                        return PTR_ERR(map);
  
 -              map->sec_idx = obj->efile.st_ops_shndx;
 +              map->sec_idx = shndx;
                map->sec_offset = vsi->offset;
                map->name = strdup(var_name);
                if (!map->name)
                map->def.key_size = sizeof(int);
                map->def.value_size = type->size;
                map->def.max_entries = 1;
 +              map->def.map_flags = map_flags;
  
                map->st_ops = calloc(1, sizeof(*map->st_ops));
                if (!map->st_ops)
                if (!st_ops->data || !st_ops->progs || !st_ops->kern_func_off)
                        return -ENOMEM;
  
 -              if (vsi->offset + type->size > obj->efile.st_ops_data->d_size) {
 +              if (vsi->offset + type->size > data->d_size) {
                        pr_warn("struct_ops init: var %s is beyond the end of DATASEC %s\n",
 -                              var_name, STRUCT_OPS_SEC);
 +                              var_name, sec_name);
                        return -EINVAL;
                }
  
                memcpy(st_ops->data,
 -                     obj->efile.st_ops_data->d_buf + vsi->offset,
 +                     data->d_buf + vsi->offset,
                       type->size);
                st_ops->tname = tname;
                st_ops->type = type;
        return 0;
  }
  
 +static int bpf_object_init_struct_ops(struct bpf_object *obj)
 +{
 +      int err;
 +
 +      err = init_struct_ops_maps(obj, STRUCT_OPS_SEC, obj->efile.st_ops_shndx,
 +                                 obj->efile.st_ops_data, 0);
 +      err = err ?: init_struct_ops_maps(obj, STRUCT_OPS_LINK_SEC,
 +                                        obj->efile.st_ops_link_shndx,
 +                                        obj->efile.st_ops_link_data,
 +                                        BPF_F_LINK);
 +      return err;
 +}
 +
  static struct bpf_object *bpf_object__new(const char *path,
                                          const void *obj_buf,
                                          size_t obj_buf_sz,
        obj->efile.obj_buf_sz = obj_buf_sz;
        obj->efile.btf_maps_shndx = -1;
        obj->efile.st_ops_shndx = -1;
 +      obj->efile.st_ops_link_shndx = -1;
        obj->kconfig_map_idx = -1;
  
        obj->kern_version = get_kernel_version();
@@@ -1290,7 -1264,6 +1290,7 @@@ static void bpf_object__elf_finish(stru
        obj->efile.elf = NULL;
        obj->efile.symbols = NULL;
        obj->efile.st_ops_data = NULL;
 +      obj->efile.st_ops_link_data = NULL;
  
        zfree(&obj->efile.secs);
        obj->efile.sec_cnt = 0;
@@@ -1361,7 -1334,7 +1361,7 @@@ static int bpf_object__elf_init(struct 
                goto errout;
        }
  
-       /* Elf is corrupted/truncated, avoid calling elf_strptr. */
+       /* ELF is corrupted/truncated, avoid calling elf_strptr. */
        if (!elf_rawdata(elf_getscn(elf, obj->efile.shstrndx), NULL)) {
                pr_warn("elf: failed to get section names strings from %s: %s\n",
                        obj->path, elf_errmsg(-1));
@@@ -2642,10 -2615,10 +2642,10 @@@ static int bpf_object__init_maps(struc
        strict = !OPTS_GET(opts, relaxed_maps, false);
        pin_root_path = OPTS_GET(opts, pin_root_path, NULL);
  
 -      err = err ?: bpf_object__init_user_btf_maps(obj, strict, pin_root_path);
 +      err = bpf_object__init_user_btf_maps(obj, strict, pin_root_path);
        err = err ?: bpf_object__init_global_data_maps(obj);
        err = err ?: bpf_object__init_kconfig_map(obj);
 -      err = err ?: bpf_object__init_struct_ops_maps(obj);
 +      err = err ?: bpf_object_init_struct_ops(obj);
  
        return err;
  }
@@@ -2779,13 -2752,12 +2779,13 @@@ static bool libbpf_needs_btf(const stru
  {
        return obj->efile.btf_maps_shndx >= 0 ||
               obj->efile.st_ops_shndx >= 0 ||
 +             obj->efile.st_ops_link_shndx >= 0 ||
               obj->nr_extern > 0;
  }
  
  static bool kernel_needs_btf(const struct bpf_object *obj)
  {
 -      return obj->efile.st_ops_shndx >= 0;
 +      return obj->efile.st_ops_shndx >= 0 || obj->efile.st_ops_link_shndx >= 0;
  }
  
  static int bpf_object__init_btf(struct bpf_object *obj,
@@@ -3478,9 -3450,6 +3478,9 @@@ static int bpf_object__elf_collect(stru
                        } else if (strcmp(name, STRUCT_OPS_SEC) == 0) {
                                obj->efile.st_ops_data = data;
                                obj->efile.st_ops_shndx = idx;
 +                      } else if (strcmp(name, STRUCT_OPS_LINK_SEC) == 0) {
 +                              obj->efile.st_ops_link_data = data;
 +                              obj->efile.st_ops_link_shndx = idx;
                        } else {
                                pr_info("elf: skipping unrecognized data section(%d) %s\n",
                                        idx, name);
                        /* Only do relo for section with exec instructions */
                        if (!section_have_execinstr(obj, targ_sec_idx) &&
                            strcmp(name, ".rel" STRUCT_OPS_SEC) &&
 +                          strcmp(name, ".rel" STRUCT_OPS_LINK_SEC) &&
                            strcmp(name, ".rel" MAPS_ELF_SEC)) {
                                pr_info("elf: skipping relo section(%d) %s for section(%d) %s\n",
                                        idx, name, targ_sec_idx,
@@@ -4041,11 -4009,11 +4041,11 @@@ static int bpf_program__record_reloc(st
                pr_debug("prog '%s': found extern #%d '%s' (sym %d) for insn #%u\n",
                         prog->name, i, ext->name, ext->sym_idx, insn_idx);
                if (insn->code == (BPF_JMP | BPF_CALL))
 -                      reloc_desc->type = RELO_EXTERN_FUNC;
 +                      reloc_desc->type = RELO_EXTERN_CALL;
                else
 -                      reloc_desc->type = RELO_EXTERN_VAR;
 +                      reloc_desc->type = RELO_EXTERN_LD64;
                reloc_desc->insn_idx = insn_idx;
 -              reloc_desc->sym_off = i; /* sym_off stores extern index */
 +              reloc_desc->ext_idx = i;
                return 0;
        }
  
@@@ -5814,8 -5782,8 +5814,8 @@@ out
  }
  
  /* base map load ldimm64 special constant, used also for log fixup logic */
 -#define MAP_LDIMM64_POISON_BASE 2001000000
 -#define MAP_LDIMM64_POISON_PFX "200100"
 +#define POISON_LDIMM64_MAP_BASE 2001000000
 +#define POISON_LDIMM64_MAP_PFX "200100"
  
  static void poison_map_ldimm64(struct bpf_program *prog, int relo_idx,
                               int insn_idx, struct bpf_insn *insn,
                 * invalid func unknown#2001000123
                 * where lower 123 is map index into obj->maps[] array
                 */
 -              insn->imm = MAP_LDIMM64_POISON_BASE + map_idx;
 +              insn->imm = POISON_LDIMM64_MAP_BASE + map_idx;
  
                insn++;
        }
  }
  
 +/* unresolved kfunc call special constant, used also for log fixup logic */
 +#define POISON_CALL_KFUNC_BASE 2002000000
 +#define POISON_CALL_KFUNC_PFX "2002"
 +
 +static void poison_kfunc_call(struct bpf_program *prog, int relo_idx,
 +                            int insn_idx, struct bpf_insn *insn,
 +                            int ext_idx, const struct extern_desc *ext)
 +{
 +      pr_debug("prog '%s': relo #%d: poisoning insn #%d that calls kfunc '%s'\n",
 +               prog->name, relo_idx, insn_idx, ext->name);
 +
 +      /* we turn kfunc call into invalid helper call with identifiable constant */
 +      insn->code = BPF_JMP | BPF_CALL;
 +      insn->dst_reg = 0;
 +      insn->src_reg = 0;
 +      insn->off = 0;
 +      /* if this instruction is reachable (not a dead code),
 +       * verifier will complain with something like:
 +       * invalid func unknown#2001000123
 +       * where lower 123 is extern index into obj->externs[] array
 +       */
 +      insn->imm = POISON_CALL_KFUNC_BASE + ext_idx;
 +}
 +
  /* Relocate data references within program code:
   *  - map references;
   *  - global variable references;
@@@ -5911,8 -5855,8 +5911,8 @@@ bpf_object__relocate_data(struct bpf_ob
                                                   relo->map_idx, map);
                        }
                        break;
 -              case RELO_EXTERN_VAR:
 -                      ext = &obj->externs[relo->sym_off];
 +              case RELO_EXTERN_LD64:
 +                      ext = &obj->externs[relo->ext_idx];
                        if (ext->type == EXT_KCFG) {
                                if (obj->gen_loader) {
                                        insn[0].src_reg = BPF_PSEUDO_MAP_IDX_VALUE;
                                }
                        }
                        break;
 -              case RELO_EXTERN_FUNC:
 -                      ext = &obj->externs[relo->sym_off];
 +              case RELO_EXTERN_CALL:
 +                      ext = &obj->externs[relo->ext_idx];
                        insn[0].src_reg = BPF_PSEUDO_KFUNC_CALL;
                        if (ext->is_set) {
                                insn[0].imm = ext->ksym.kernel_btf_id;
                                insn[0].off = ext->ksym.btf_fd_idx;
 -                      } else { /* unresolved weak kfunc */
 -                              insn[0].imm = 0;
 -                              insn[0].off = 0;
 +                      } else { /* unresolved weak kfunc call */
 +                              poison_kfunc_call(prog, i, relo->insn_idx, insn,
 +                                                relo->ext_idx, ext);
                        }
                        break;
                case RELO_SUBPROG_ADDR:
@@@ -6171,7 -6115,7 +6171,7 @@@ bpf_object__reloc_code(struct bpf_objec
                        continue;
  
                relo = find_prog_insn_relo(prog, insn_idx);
 -              if (relo && relo->type == RELO_EXTERN_FUNC)
 +              if (relo && relo->type == RELO_EXTERN_CALL)
                        /* kfunc relocations will be handled later
                         * in bpf_object__relocate_data()
                         */
@@@ -6666,7 -6610,7 +6666,7 @@@ static int bpf_object__collect_relos(st
                        return -LIBBPF_ERRNO__INTERNAL;
                }
  
 -              if (idx == obj->efile.st_ops_shndx)
 +              if (idx == obj->efile.st_ops_shndx || idx == obj->efile.st_ops_link_shndx)
                        err = bpf_object__collect_st_ops_relos(obj, shdr, data);
                else if (idx == obj->efile.btf_maps_shndx)
                        err = bpf_object__collect_map_relos(obj, shdr, data);
@@@ -7049,13 -6993,13 +7049,13 @@@ static void fixup_log_missing_map_load(
                                       char *buf, size_t buf_sz, size_t log_sz,
                                       char *line1, char *line2, char *line3)
  {
 -      /* Expected log for failed and not properly guarded CO-RE relocation:
 +      /* Expected log for failed and not properly guarded map reference:
         * line1 -> 123: (85) call unknown#2001000345
         * line2 -> invalid func unknown#2001000345
         * line3 -> <anything else or end of buffer>
         *
         * "123" is the index of the instruction that was poisoned.
 -       * "345" in "2001000345" are map index in obj->maps to fetch map name.
 +       * "345" in "2001000345" is a map index in obj->maps to fetch map name.
         */
        struct bpf_object *obj = prog->obj;
        const struct bpf_map *map;
        if (sscanf(line1, "%d: (%*d) call unknown#%d\n", &insn_idx, &map_idx) != 2)
                return;
  
 -      map_idx -= MAP_LDIMM64_POISON_BASE;
 +      map_idx -= POISON_LDIMM64_MAP_BASE;
        if (map_idx < 0 || map_idx >= obj->nr_maps)
                return;
        map = &obj->maps[map_idx];
        patch_log(buf, buf_sz, log_sz, line1, line3 - line1, patch);
  }
  
 +static void fixup_log_missing_kfunc_call(struct bpf_program *prog,
 +                                       char *buf, size_t buf_sz, size_t log_sz,
 +                                       char *line1, char *line2, char *line3)
 +{
 +      /* Expected log for failed and not properly guarded kfunc call:
 +       * line1 -> 123: (85) call unknown#2002000345
 +       * line2 -> invalid func unknown#2002000345
 +       * line3 -> <anything else or end of buffer>
 +       *
 +       * "123" is the index of the instruction that was poisoned.
 +       * "345" in "2002000345" is an extern index in obj->externs to fetch kfunc name.
 +       */
 +      struct bpf_object *obj = prog->obj;
 +      const struct extern_desc *ext;
 +      int insn_idx, ext_idx;
 +      char patch[128];
 +
 +      if (sscanf(line1, "%d: (%*d) call unknown#%d\n", &insn_idx, &ext_idx) != 2)
 +              return;
 +
 +      ext_idx -= POISON_CALL_KFUNC_BASE;
 +      if (ext_idx < 0 || ext_idx >= obj->nr_extern)
 +              return;
 +      ext = &obj->externs[ext_idx];
 +
 +      snprintf(patch, sizeof(patch),
 +               "%d: <invalid kfunc call>\n"
 +               "kfunc '%s' is referenced but wasn't resolved\n",
 +               insn_idx, ext->name);
 +
 +      patch_log(buf, buf_sz, log_sz, line1, line3 - line1, patch);
 +}
 +
  static void fixup_verifier_log(struct bpf_program *prog, char *buf, size_t buf_sz)
  {
        /* look for familiar error patterns in last N lines of the log */
                if (!cur_line)
                        return;
  
 -              /* failed CO-RE relocation case */
                if (str_has_pfx(cur_line, "invalid func unknown#195896080\n")) {
                        prev_line = find_prev_line(buf, cur_line);
                        if (!prev_line)
                                continue;
  
 +                      /* failed CO-RE relocation case */
                        fixup_log_failed_core_relo(prog, buf, buf_sz, log_sz,
                                                   prev_line, cur_line, next_line);
                        return;
 -              } else if (str_has_pfx(cur_line, "invalid func unknown#"MAP_LDIMM64_POISON_PFX)) {
 +              } else if (str_has_pfx(cur_line, "invalid func unknown#"POISON_LDIMM64_MAP_PFX)) {
                        prev_line = find_prev_line(buf, cur_line);
                        if (!prev_line)
                                continue;
  
 +                      /* reference to uncreated BPF map */
                        fixup_log_missing_map_load(prog, buf, buf_sz, log_sz,
                                                   prev_line, cur_line, next_line);
                        return;
 +              } else if (str_has_pfx(cur_line, "invalid func unknown#"POISON_CALL_KFUNC_PFX)) {
 +                      prev_line = find_prev_line(buf, cur_line);
 +                      if (!prev_line)
 +                              continue;
 +
 +                      /* reference to unresolved kfunc */
 +                      fixup_log_missing_kfunc_call(prog, buf, buf_sz, log_sz,
 +                                                   prev_line, cur_line, next_line);
 +                      return;
                }
        }
  }
@@@ -7168,22 -7069,19 +7168,22 @@@ static int bpf_program_record_relos(str
  
        for (i = 0; i < prog->nr_reloc; i++) {
                struct reloc_desc *relo = &prog->reloc_desc[i];
 -              struct extern_desc *ext = &obj->externs[relo->sym_off];
 +              struct extern_desc *ext = &obj->externs[relo->ext_idx];
 +              int kind;
  
                switch (relo->type) {
 -              case RELO_EXTERN_VAR:
 +              case RELO_EXTERN_LD64:
                        if (ext->type != EXT_KSYM)
                                continue;
 +                      kind = btf_is_var(btf__type_by_id(obj->btf, ext->btf_id)) ?
 +                              BTF_KIND_VAR : BTF_KIND_FUNC;
                        bpf_gen__record_extern(obj->gen_loader, ext->name,
                                               ext->is_weak, !ext->ksym.type_id,
 -                                             BTF_KIND_VAR, relo->insn_idx);
 +                                             true, kind, relo->insn_idx);
                        break;
 -              case RELO_EXTERN_FUNC:
 +              case RELO_EXTERN_CALL:
                        bpf_gen__record_extern(obj->gen_loader, ext->name,
 -                                             ext->is_weak, false, BTF_KIND_FUNC,
 +                                             ext->is_weak, false, false, BTF_KIND_FUNC,
                                               relo->insn_idx);
                        break;
                case RELO_CORE: {
@@@ -7606,9 -7504,8 +7606,9 @@@ static int bpf_object__resolve_ksym_fun
        ret = bpf_core_types_are_compat(obj->btf, local_func_proto_id,
                                        kern_btf, kfunc_proto_id);
        if (ret <= 0) {
 -              pr_warn("extern (func ksym) '%s': func_proto [%d] incompatible with kernel [%d]\n",
 -                      ext->name, local_func_proto_id, kfunc_proto_id);
 +              pr_warn("extern (func ksym) '%s': func_proto [%d] incompatible with %s [%d]\n",
 +                      ext->name, local_func_proto_id,
 +                      mod_btf ? mod_btf->name : "vmlinux", kfunc_proto_id);
                return -EINVAL;
        }
  
        ext->is_set = true;
        ext->ksym.kernel_btf_id = kfunc_id;
        ext->ksym.btf_fd_idx = mod_btf ? mod_btf->fd_array_idx : 0;
 -      pr_debug("extern (func ksym) '%s': resolved to kernel [%d]\n",
 -               ext->name, kfunc_id);
 +      /* Also set kernel_btf_obj_fd to make sure that bpf_object__relocate_data()
 +       * populates FD into ld_imm64 insn when it's used to point to kfunc.
 +       * {kernel_btf_id, btf_fd_idx} -> fixup bpf_call.
 +       * {kernel_btf_id, kernel_btf_obj_fd} -> fixup ld_imm64.
 +       */
 +      ext->ksym.kernel_btf_obj_fd = mod_btf ? mod_btf->fd : 0;
 +      pr_debug("extern (func ksym) '%s': resolved to %s [%d]\n",
 +               ext->name, mod_btf ? mod_btf->name : "vmlinux", kfunc_id);
  
        return 0;
  }
@@@ -7786,37 -7677,6 +7786,37 @@@ static int bpf_object__resolve_externs(
        return 0;
  }
  
 +static void bpf_map_prepare_vdata(const struct bpf_map *map)
 +{
 +      struct bpf_struct_ops *st_ops;
 +      __u32 i;
 +
 +      st_ops = map->st_ops;
 +      for (i = 0; i < btf_vlen(st_ops->type); i++) {
 +              struct bpf_program *prog = st_ops->progs[i];
 +              void *kern_data;
 +              int prog_fd;
 +
 +              if (!prog)
 +                      continue;
 +
 +              prog_fd = bpf_program__fd(prog);
 +              kern_data = st_ops->kern_vdata + st_ops->kern_func_off[i];
 +              *(unsigned long *)kern_data = prog_fd;
 +      }
 +}
 +
 +static int bpf_object_prepare_struct_ops(struct bpf_object *obj)
 +{
 +      int i;
 +
 +      for (i = 0; i < obj->nr_maps; i++)
 +              if (bpf_map__is_struct_ops(&obj->maps[i]))
 +                      bpf_map_prepare_vdata(&obj->maps[i]);
 +
 +      return 0;
 +}
 +
  static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const char *target_btf_path)
  {
        int err, i;
        err = err ? : bpf_object__relocate(obj, obj->btf_custom_path ? : target_btf_path);
        err = err ? : bpf_object__load_progs(obj, extra_log_level);
        err = err ? : bpf_object_init_prog_arrays(obj);
 +      err = err ? : bpf_object_prepare_struct_ops(obj);
  
        if (obj->gen_loader) {
                /* reset FDs */
@@@ -8539,7 -8398,6 +8539,7 @@@ int bpf_program__set_type(struct bpf_pr
                return libbpf_err(-EBUSY);
  
        prog->type = type;
 +      prog->sec_def = NULL;
        return 0;
  }
  
@@@ -8712,7 -8570,6 +8712,7 @@@ static const struct bpf_sec_def section
        SEC_DEF("struct_ops+",          STRUCT_OPS, 0, SEC_NONE),
        SEC_DEF("struct_ops.s+",        STRUCT_OPS, 0, SEC_SLEEPABLE),
        SEC_DEF("sk_lookup",            SK_LOOKUP, BPF_SK_LOOKUP, SEC_ATTACHABLE),
 +      SEC_DEF("netfilter",            NETFILTER, 0, SEC_NONE),
  };
  
  static size_t custom_sec_def_cnt;
@@@ -8954,7 -8811,6 +8954,7 @@@ const char *libbpf_bpf_prog_type_str(en
  }
  
  static struct bpf_map *find_struct_ops_map_by_offset(struct bpf_object *obj,
 +                                                   int sec_idx,
                                                     size_t offset)
  {
        struct bpf_map *map;
                map = &obj->maps[i];
                if (!bpf_map__is_struct_ops(map))
                        continue;
 -              if (map->sec_offset <= offset &&
 +              if (map->sec_idx == sec_idx &&
 +                  map->sec_offset <= offset &&
                    offset - map->sec_offset < map->def.value_size)
                        return map;
        }
@@@ -9007,7 -8862,7 +9007,7 @@@ static int bpf_object__collect_st_ops_r
                }
  
                name = elf_sym_str(obj, sym->st_name) ?: "<?>";
 -              map = find_struct_ops_map_by_offset(obj, rel->r_offset);
 +              map = find_struct_ops_map_by_offset(obj, shdr->sh_info, rel->r_offset);
                if (!map) {
                        pr_warn("struct_ops reloc: cannot find map at rel->r_offset %zu\n",
                                (size_t)rel->r_offset);
                }
  
                /* struct_ops BPF prog can be re-used between multiple
 -               * .struct_ops as long as it's the same struct_ops struct
 -               * definition and the same function pointer field
 +               * .struct_ops & .struct_ops.link as long as it's the
 +               * same struct_ops struct definition and the same
 +               * function pointer field
                 */
                if (prog->attach_btf_id != st_ops->type_id ||
                    prog->expected_attach_type != member_idx) {
@@@ -9870,7 -9724,6 +9870,7 @@@ struct bpf_link *bpf_program__attach_pe
        char errmsg[STRERR_BUFSIZE];
        struct bpf_link_perf *link;
        int prog_fd, link_fd = -1, err;
 +      bool force_ioctl_attach;
  
        if (!OPTS_VALID(opts, bpf_perf_event_opts))
                return libbpf_err_ptr(-EINVAL);
        link->link.dealloc = &bpf_link_perf_dealloc;
        link->perf_event_fd = pfd;
  
 -      if (kernel_supports(prog->obj, FEAT_PERF_LINK)) {
 +      force_ioctl_attach = OPTS_GET(opts, force_ioctl_attach, false);
 +      if (kernel_supports(prog->obj, FEAT_PERF_LINK) && !force_ioctl_attach) {
                DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts,
                        .perf_event.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0));
  
@@@ -10058,20 -9910,16 +10058,20 @@@ static int append_to_file(const char *f
  {
        int fd, n, err = 0;
        va_list ap;
 +      char buf[1024];
 +
 +      va_start(ap, fmt);
 +      n = vsnprintf(buf, sizeof(buf), fmt, ap);
 +      va_end(ap);
 +
 +      if (n < 0 || n >= sizeof(buf))
 +              return -EINVAL;
  
        fd = open(file, O_WRONLY | O_APPEND | O_CLOEXEC, 0);
        if (fd < 0)
                return -errno;
  
 -      va_start(ap, fmt);
 -      n = vdprintf(fd, fmt, ap);
 -      va_end(ap);
 -
 -      if (n < 0)
 +      if (write(fd, buf, n) < 0)
                err = -errno;
  
        close(fd);
@@@ -10258,7 -10106,6 +10258,7 @@@ bpf_program__attach_kprobe_opts(const s
                                const struct bpf_kprobe_opts *opts)
  {
        DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
 +      enum probe_attach_mode attach_mode;
        char errmsg[STRERR_BUFSIZE];
        char *legacy_probe = NULL;
        struct bpf_link *link;
        if (!OPTS_VALID(opts, bpf_kprobe_opts))
                return libbpf_err_ptr(-EINVAL);
  
 +      attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT);
        retprobe = OPTS_GET(opts, retprobe, false);
        offset = OPTS_GET(opts, offset, 0);
        pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
  
        legacy = determine_kprobe_perf_type() < 0;
 +      switch (attach_mode) {
 +      case PROBE_ATTACH_MODE_LEGACY:
 +              legacy = true;
 +              pe_opts.force_ioctl_attach = true;
 +              break;
 +      case PROBE_ATTACH_MODE_PERF:
 +              if (legacy)
 +                      return libbpf_err_ptr(-ENOTSUP);
 +              pe_opts.force_ioctl_attach = true;
 +              break;
 +      case PROBE_ATTACH_MODE_LINK:
 +              if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK))
 +                      return libbpf_err_ptr(-ENOTSUP);
 +              break;
 +      case PROBE_ATTACH_MODE_DEFAULT:
 +              break;
 +      default:
 +              return libbpf_err_ptr(-EINVAL);
 +      }
 +
        if (!legacy) {
                pfd = perf_event_open_probe(false /* uprobe */, retprobe,
                                            func_name, offset,
@@@ -10705,19 -10531,32 +10705,19 @@@ static Elf_Scn *elf_find_next_scn_by_ty
        return NULL;
  }
  
 -/* Find offset of function name in object specified by path.  "name" matches
 - * symbol name or name@@LIB for library functions.
 +/* Find offset of function name in the provided ELF object. "binary_path" is
 + * the path to the ELF binary represented by "elf", and only used for error
 + * reporting matters. "name" matches symbol name or name@@LIB for library
 + * functions.
   */
 -static long elf_find_func_offset(const char *binary_path, const char *name)
 +static long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
  {
 -      int fd, i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
 +      int i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
        bool is_shared_lib, is_name_qualified;
 -      char errmsg[STRERR_BUFSIZE];
        long ret = -ENOENT;
        size_t name_len;
        GElf_Ehdr ehdr;
 -      Elf *elf;
  
 -      fd = open(binary_path, O_RDONLY | O_CLOEXEC);
 -      if (fd < 0) {
 -              ret = -errno;
 -              pr_warn("failed to open %s: %s\n", binary_path,
 -                      libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
 -              return ret;
 -      }
 -      elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
 -      if (!elf) {
 -              pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1));
 -              close(fd);
 -              return -LIBBPF_ERRNO__FORMAT;
 -      }
        if (!gelf_getehdr(elf, &ehdr)) {
                pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1));
                ret = -LIBBPF_ERRNO__FORMAT;
        /* Does name specify "@@LIB"? */
        is_name_qualified = strstr(name, "@@") != NULL;
  
 -      /* Search SHT_DYNSYM, SHT_SYMTAB for symbol.  This search order is used because if
 +      /* Search SHT_DYNSYM, SHT_SYMTAB for symbol. This search order is used because if
         * a binary is stripped, it may only have SHT_DYNSYM, and a fully-statically
         * linked binary may not have SHT_DYMSYM, so absence of a section should not be
         * reported as a warning/error.
                }
        }
  out:
 +      return ret;
 +}
 +
 +/* Find offset of function name in ELF object specified by path. "name" matches
 + * symbol name or name@@LIB for library functions.
 + */
 +static long elf_find_func_offset_from_file(const char *binary_path, const char *name)
 +{
 +      char errmsg[STRERR_BUFSIZE];
 +      long ret = -ENOENT;
 +      Elf *elf;
 +      int fd;
 +
 +      fd = open(binary_path, O_RDONLY | O_CLOEXEC);
 +      if (fd < 0) {
 +              ret = -errno;
 +              pr_warn("failed to open %s: %s\n", binary_path,
 +                      libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
 +              return ret;
 +      }
 +      elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
 +      if (!elf) {
 +              pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1));
 +              close(fd);
 +              return -LIBBPF_ERRNO__FORMAT;
 +      }
 +
 +      ret = elf_find_func_offset(elf, binary_path, name);
        elf_end(elf);
        close(fd);
        return ret;
  }
  
 +/* Find offset of function name in archive specified by path. Currently
 + * supported are .zip files that do not compress their contents, as used on
 + * Android in the form of APKs, for example. "file_name" is the name of the ELF
 + * file inside the archive. "func_name" matches symbol name or name@@LIB for
 + * library functions.
 + *
 + * An overview of the APK format specifically provided here:
 + * https://en.wikipedia.org/w/index.php?title=Apk_(file_format)&oldid=1139099120#Package_contents
 + */
 +static long elf_find_func_offset_from_archive(const char *archive_path, const char *file_name,
 +                                            const char *func_name)
 +{
 +      struct zip_archive *archive;
 +      struct zip_entry entry;
 +      long ret;
 +      Elf *elf;
 +
 +      archive = zip_archive_open(archive_path);
 +      if (IS_ERR(archive)) {
 +              ret = PTR_ERR(archive);
 +              pr_warn("zip: failed to open %s: %ld\n", archive_path, ret);
 +              return ret;
 +      }
 +
 +      ret = zip_archive_find_entry(archive, file_name, &entry);
 +      if (ret) {
 +              pr_warn("zip: could not find archive member %s in %s: %ld\n", file_name,
 +                      archive_path, ret);
 +              goto out;
 +      }
 +      pr_debug("zip: found entry for %s in %s at 0x%lx\n", file_name, archive_path,
 +               (unsigned long)entry.data_offset);
 +
 +      if (entry.compression) {
 +              pr_warn("zip: entry %s of %s is compressed and cannot be handled\n", file_name,
 +                      archive_path);
 +              ret = -LIBBPF_ERRNO__FORMAT;
 +              goto out;
 +      }
 +
 +      elf = elf_memory((void *)entry.data, entry.data_length);
 +      if (!elf) {
 +              pr_warn("elf: could not read elf file %s from %s: %s\n", file_name, archive_path,
 +                      elf_errmsg(-1));
 +              ret = -LIBBPF_ERRNO__LIBELF;
 +              goto out;
 +      }
 +
 +      ret = elf_find_func_offset(elf, file_name, func_name);
 +      if (ret > 0) {
 +              pr_debug("elf: symbol address match for %s of %s in %s: 0x%x + 0x%lx = 0x%lx\n",
 +                       func_name, file_name, archive_path, entry.data_offset, ret,
 +                       ret + entry.data_offset);
 +              ret += entry.data_offset;
 +      }
 +      elf_end(elf);
 +
 +out:
 +      zip_archive_close(archive);
 +      return ret;
 +}
 +
  static const char *arch_specific_lib_paths(void)
  {
        /*
@@@ -11023,11 -10772,9 +11023,11 @@@ bpf_program__attach_uprobe_opts(const s
                                const char *binary_path, size_t func_offset,
                                const struct bpf_uprobe_opts *opts)
  {
 -      DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
 +      const char *archive_path = NULL, *archive_sep = NULL;
        char errmsg[STRERR_BUFSIZE], *legacy_probe = NULL;
 -      char full_binary_path[PATH_MAX];
 +      DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
 +      enum probe_attach_mode attach_mode;
 +      char full_path[PATH_MAX];
        struct bpf_link *link;
        size_t ref_ctr_off;
        int pfd, err;
        if (!OPTS_VALID(opts, bpf_uprobe_opts))
                return libbpf_err_ptr(-EINVAL);
  
 +      attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT);
        retprobe = OPTS_GET(opts, retprobe, false);
        ref_ctr_off = OPTS_GET(opts, ref_ctr_offset, 0);
        pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
        if (!binary_path)
                return libbpf_err_ptr(-EINVAL);
  
 -      if (!strchr(binary_path, '/')) {
 -              err = resolve_full_path(binary_path, full_binary_path,
 -                                      sizeof(full_binary_path));
 +      /* Check if "binary_path" refers to an archive. */
 +      archive_sep = strstr(binary_path, "!/");
 +      if (archive_sep) {
 +              full_path[0] = '\0';
 +              libbpf_strlcpy(full_path, binary_path,
 +                             min(sizeof(full_path), (size_t)(archive_sep - binary_path + 1)));
 +              archive_path = full_path;
 +              binary_path = archive_sep + 2;
 +      } else if (!strchr(binary_path, '/')) {
 +              err = resolve_full_path(binary_path, full_path, sizeof(full_path));
                if (err) {
                        pr_warn("prog '%s': failed to resolve full path for '%s': %d\n",
                                prog->name, binary_path, err);
                        return libbpf_err_ptr(err);
                }
 -              binary_path = full_binary_path;
 +              binary_path = full_path;
        }
        func_name = OPTS_GET(opts, func_name, NULL);
        if (func_name) {
                long sym_off;
  
 -              sym_off = elf_find_func_offset(binary_path, func_name);
 +              if (archive_path) {
 +                      sym_off = elf_find_func_offset_from_archive(archive_path, binary_path,
 +                                                                  func_name);
 +                      binary_path = archive_path;
 +              } else {
 +                      sym_off = elf_find_func_offset_from_file(binary_path, func_name);
 +              }
                if (sym_off < 0)
                        return libbpf_err_ptr(sym_off);
                func_offset += sym_off;
        }
  
        legacy = determine_uprobe_perf_type() < 0;
 +      switch (attach_mode) {
 +      case PROBE_ATTACH_MODE_LEGACY:
 +              legacy = true;
 +              pe_opts.force_ioctl_attach = true;
 +              break;
 +      case PROBE_ATTACH_MODE_PERF:
 +              if (legacy)
 +                      return libbpf_err_ptr(-ENOTSUP);
 +              pe_opts.force_ioctl_attach = true;
 +              break;
 +      case PROBE_ATTACH_MODE_LINK:
 +              if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK))
 +                      return libbpf_err_ptr(-ENOTSUP);
 +              break;
 +      case PROBE_ATTACH_MODE_DEFAULT:
 +              break;
 +      default:
 +              return libbpf_err_ptr(-EINVAL);
 +      }
 +
        if (!legacy) {
                pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path,
                                            func_offset, pid, ref_ctr_off);
@@@ -11716,30 -11429,22 +11716,30 @@@ struct bpf_link *bpf_program__attach(co
        return link;
  }
  
 +struct bpf_link_struct_ops {
 +      struct bpf_link link;
 +      int map_fd;
 +};
 +
  static int bpf_link__detach_struct_ops(struct bpf_link *link)
  {
 +      struct bpf_link_struct_ops *st_link;
        __u32 zero = 0;
  
 -      if (bpf_map_delete_elem(link->fd, &zero))
 -              return -errno;
 +      st_link = container_of(link, struct bpf_link_struct_ops, link);
  
 -      return 0;
 +      if (st_link->map_fd < 0)
 +              /* w/o a real link */
 +              return bpf_map_delete_elem(link->fd, &zero);
 +
 +      return close(link->fd);
  }
  
  struct bpf_link *bpf_map__attach_struct_ops(const struct bpf_map *map)
  {
 -      struct bpf_struct_ops *st_ops;
 -      struct bpf_link *link;
 -      __u32 i, zero = 0;
 -      int err;
 +      struct bpf_link_struct_ops *link;
 +      __u32 zero = 0;
 +      int err, fd;
  
        if (!bpf_map__is_struct_ops(map) || map->fd == -1)
                return libbpf_err_ptr(-EINVAL);
        if (!link)
                return libbpf_err_ptr(-EINVAL);
  
 -      st_ops = map->st_ops;
 -      for (i = 0; i < btf_vlen(st_ops->type); i++) {
 -              struct bpf_program *prog = st_ops->progs[i];
 -              void *kern_data;
 -              int prog_fd;
 +      /* kern_vdata should be prepared during the loading phase. */
 +      err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0);
 +      /* It can be EBUSY if the map has been used to create or
 +       * update a link before.  We don't allow updating the value of
 +       * a struct_ops once it is set.  That ensures that the value
 +       * never changed.  So, it is safe to skip EBUSY.
 +       */
 +      if (err && (!(map->def.map_flags & BPF_F_LINK) || err != -EBUSY)) {
 +              free(link);
 +              return libbpf_err_ptr(err);
 +      }
  
 -              if (!prog)
 -                      continue;
 +      link->link.detach = bpf_link__detach_struct_ops;
  
 -              prog_fd = bpf_program__fd(prog);
 -              kern_data = st_ops->kern_vdata + st_ops->kern_func_off[i];
 -              *(unsigned long *)kern_data = prog_fd;
 +      if (!(map->def.map_flags & BPF_F_LINK)) {
 +              /* w/o a real link */
 +              link->link.fd = map->fd;
 +              link->map_fd = -1;
 +              return &link->link;
        }
  
 -      err = bpf_map_update_elem(map->fd, &zero, st_ops->kern_vdata, 0);
 -      if (err) {
 -              err = -errno;
 +      fd = bpf_link_create(map->fd, 0, BPF_STRUCT_OPS, NULL);
 +      if (fd < 0) {
                free(link);
 -              return libbpf_err_ptr(err);
 +              return libbpf_err_ptr(fd);
        }
  
 -      link->detach = bpf_link__detach_struct_ops;
 -      link->fd = map->fd;
 +      link->link.fd = fd;
 +      link->map_fd = map->fd;
  
 -      return link;
 +      return &link->link;
 +}
 +
 +/*
 + * Swap the back struct_ops of a link with a new struct_ops map.
 + */
 +int bpf_link__update_map(struct bpf_link *link, const struct bpf_map *map)
 +{
 +      struct bpf_link_struct_ops *st_ops_link;
 +      __u32 zero = 0;
 +      int err;
 +
 +      if (!bpf_map__is_struct_ops(map) || map->fd < 0)
 +              return -EINVAL;
 +
 +      st_ops_link = container_of(link, struct bpf_link_struct_ops, link);
 +      /* Ensure the type of a link is correct */
 +      if (st_ops_link->map_fd < 0)
 +              return -EINVAL;
 +
 +      err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0);
 +      /* It can be EBUSY if the map has been used to create or
 +       * update a link before.  We don't allow updating the value of
 +       * a struct_ops once it is set.  That ensures that the value
 +       * never changed.  So, it is safe to skip EBUSY.
 +       */
 +      if (err && err != -EBUSY)
 +              return err;
 +
 +      err = bpf_link_update(link->fd, map->fd, NULL);
 +      if (err < 0)
 +              return err;
 +
 +      st_ops_link->map_fd = map->fd;
 +
 +      return 0;
  }
  
  typedef enum bpf_perf_event_ret (*bpf_perf_event_print_t)(struct perf_event_header *hdr,
diff --combined tools/lib/bpf/usdt.c
@@@ -771,7 -771,7 +771,7 @@@ static int collect_usdt_targets(struct 
                target->rel_ip = usdt_rel_ip;
                target->sema_off = usdt_sema_off;
  
-               /* notes.args references strings from Elf itself, so they can
+               /* notes.args references strings from ELF itself, so they can
                 * be referenced safely until elf_end() call
                 */
                target->spec_str = note.args;
@@@ -1141,13 -1141,12 +1141,13 @@@ static int parse_usdt_note(Elf *elf, co
        return 0;
  }
  
 -static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg);
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz);
  
  static int parse_usdt_spec(struct usdt_spec *spec, const struct usdt_note *note, __u64 usdt_cookie)
  {
 +      struct usdt_arg_spec *arg;
        const char *s;
 -      int len;
 +      int arg_sz, len;
  
        spec->usdt_cookie = usdt_cookie;
        spec->arg_cnt = 0;
                        return -E2BIG;
                }
  
 -              len = parse_usdt_arg(s, spec->arg_cnt, &spec->args[spec->arg_cnt]);
 +              arg = &spec->args[spec->arg_cnt];
 +              len = parse_usdt_arg(s, spec->arg_cnt, arg, &arg_sz);
                if (len < 0)
                        return len;
  
 +              arg->arg_signed = arg_sz < 0;
 +              if (arg_sz < 0)
 +                      arg_sz = -arg_sz;
 +
 +              switch (arg_sz) {
 +              case 1: case 2: case 4: case 8:
 +                      arg->arg_bitshift = 64 - arg_sz * 8;
 +                      break;
 +              default:
 +                      pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
 +                              spec->arg_cnt, s, arg_sz);
 +                      return -EINVAL;
 +              }
 +
                s += len;
                spec->arg_cnt++;
        }
@@@ -1235,13 -1219,13 +1235,13 @@@ static int calc_pt_regs_off(const char 
        return -ENOENT;
  }
  
 -static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
  {
        char reg_name[16];
 -      int arg_sz, len, reg_off;
 +      int len, reg_off;
        long off;
  
 -      if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", &arg_sz, &off, reg_name, &len) == 3) {
 +      if (sscanf(arg_str, " %d @ %ld ( %%%15[^)] ) %n", arg_sz, &off, reg_name, &len) == 3) {
                /* Memory dereference case, e.g., -4@-20(%rbp) */
                arg->arg_type = USDT_ARG_REG_DEREF;
                arg->val_off = off;
                if (reg_off < 0)
                        return reg_off;
                arg->reg_off = reg_off;
 -      } else if (sscanf(arg_str, " %d @ ( %%%15[^)] ) %n", &arg_sz, reg_name, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ ( %%%15[^)] ) %n", arg_sz, reg_name, &len) == 2) {
                /* Memory dereference case without offset, e.g., 8@(%rsp) */
                arg->arg_type = USDT_ARG_REG_DEREF;
                arg->val_off = 0;
                if (reg_off < 0)
                        return reg_off;
                arg->reg_off = reg_off;
 -      } else if (sscanf(arg_str, " %d @ %%%15s %n", &arg_sz, reg_name, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %%%15s %n", arg_sz, reg_name, &len) == 2) {
                /* Register read case, e.g., -4@%eax */
                arg->arg_type = USDT_ARG_REG;
                arg->val_off = 0;
                if (reg_off < 0)
                        return reg_off;
                arg->reg_off = reg_off;
 -      } else if (sscanf(arg_str, " %d @ $%ld %n", &arg_sz, &off, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ $%ld %n", arg_sz, &off, &len) == 2) {
                /* Constant value case, e.g., 4@$71 */
                arg->arg_type = USDT_ARG_CONST;
                arg->val_off = off;
                return -EINVAL;
        }
  
 -      arg->arg_signed = arg_sz < 0;
 -      if (arg_sz < 0)
 -              arg_sz = -arg_sz;
 -
 -      switch (arg_sz) {
 -      case 1: case 2: case 4: case 8:
 -              arg->arg_bitshift = 64 - arg_sz * 8;
 -              break;
 -      default:
 -              pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
 -                      arg_num, arg_str, arg_sz);
 -              return -EINVAL;
 -      }
 -
        return len;
  }
  
  
  /* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */
  
 -static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
  {
        unsigned int reg;
 -      int arg_sz, len;
 +      int len;
        long off;
  
 -      if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", &arg_sz, &off, &reg, &len) == 3) {
 +      if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", arg_sz, &off, &reg, &len) == 3) {
                /* Memory dereference case, e.g., -2@-28(%r15) */
                arg->arg_type = USDT_ARG_REG_DEREF;
                arg->val_off = off;
                        return -EINVAL;
                }
                arg->reg_off = offsetof(user_pt_regs, gprs[reg]);
 -      } else if (sscanf(arg_str, " %d @ %%r%u %n", &arg_sz, &reg, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %%r%u %n", arg_sz, &reg, &len) == 2) {
                /* Register read case, e.g., -8@%r0 */
                arg->arg_type = USDT_ARG_REG;
                arg->val_off = 0;
                        return -EINVAL;
                }
                arg->reg_off = offsetof(user_pt_regs, gprs[reg]);
 -      } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) {
                /* Constant value case, e.g., 4@71 */
                arg->arg_type = USDT_ARG_CONST;
                arg->val_off = off;
                return -EINVAL;
        }
  
 -      arg->arg_signed = arg_sz < 0;
 -      if (arg_sz < 0)
 -              arg_sz = -arg_sz;
 -
 -      switch (arg_sz) {
 -      case 1: case 2: case 4: case 8:
 -              arg->arg_bitshift = 64 - arg_sz * 8;
 -              break;
 -      default:
 -              pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
 -                      arg_num, arg_str, arg_sz);
 -              return -EINVAL;
 -      }
 -
        return len;
  }
  
@@@ -1336,13 -1348,13 +1336,13 @@@ static int calc_pt_regs_off(const char 
        return -ENOENT;
  }
  
 -static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
  {
        char reg_name[16];
 -      int arg_sz, len, reg_off;
 +      int len, reg_off;
        long off;
  
 -      if (sscanf(arg_str, " %d @ \[ %15[a-z0-9], %ld ] %n", &arg_sz, reg_name, &off, &len) == 3) {
 +      if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] , %ld ] %n", arg_sz, reg_name, &off, &len) == 3) {
                /* Memory dereference case, e.g., -4@[sp, 96] */
                arg->arg_type = USDT_ARG_REG_DEREF;
                arg->val_off = off;
                if (reg_off < 0)
                        return reg_off;
                arg->reg_off = reg_off;
 -      } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", &arg_sz, reg_name, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", arg_sz, reg_name, &len) == 2) {
                /* Memory dereference case, e.g., -4@[sp] */
                arg->arg_type = USDT_ARG_REG_DEREF;
                arg->val_off = 0;
                if (reg_off < 0)
                        return reg_off;
                arg->reg_off = reg_off;
 -      } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) {
                /* Constant value case, e.g., 4@5 */
                arg->arg_type = USDT_ARG_CONST;
                arg->val_off = off;
                arg->reg_off = 0;
 -      } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) {
                /* Register read case, e.g., -8@x4 */
                arg->arg_type = USDT_ARG_REG;
                arg->val_off = 0;
                return -EINVAL;
        }
  
 -      arg->arg_signed = arg_sz < 0;
 -      if (arg_sz < 0)
 -              arg_sz = -arg_sz;
 -
 -      switch (arg_sz) {
 -      case 1: case 2: case 4: case 8:
 -              arg->arg_bitshift = 64 - arg_sz * 8;
 -              break;
 -      default:
 -              pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
 -                      arg_num, arg_str, arg_sz);
 -              return -EINVAL;
 -      }
 -
        return len;
  }
  
@@@ -1430,13 -1456,13 +1430,13 @@@ static int calc_pt_regs_off(const char 
        return -ENOENT;
  }
  
 -static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
  {
        char reg_name[16];
 -      int arg_sz, len, reg_off;
 +      int len, reg_off;
        long off;
  
 -      if (sscanf(arg_str, " %d @ %ld ( %15[a-z0-9] ) %n", &arg_sz, &off, reg_name, &len) == 3) {
 +      if (sscanf(arg_str, " %d @ %ld ( %15[a-z0-9] ) %n", arg_sz, &off, reg_name, &len) == 3) {
                /* Memory dereference case, e.g., -8@-88(s0) */
                arg->arg_type = USDT_ARG_REG_DEREF;
                arg->val_off = off;
                if (reg_off < 0)
                        return reg_off;
                arg->reg_off = reg_off;
 -      } else if (sscanf(arg_str, " %d @ %ld %n", &arg_sz, &off, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %ld %n", arg_sz, &off, &len) == 2) {
                /* Constant value case, e.g., 4@5 */
                arg->arg_type = USDT_ARG_CONST;
                arg->val_off = off;
                arg->reg_off = 0;
 -      } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", &arg_sz, reg_name, &len) == 2) {
 +      } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) {
                /* Register read case, e.g., -8@a1 */
                arg->arg_type = USDT_ARG_REG;
                arg->val_off = 0;
                return -EINVAL;
        }
  
 -      arg->arg_signed = arg_sz < 0;
 -      if (arg_sz < 0)
 -              arg_sz = -arg_sz;
 +      return len;
 +}
  
 -      switch (arg_sz) {
 -      case 1: case 2: case 4: case 8:
 -              arg->arg_bitshift = 64 - arg_sz * 8;
 -              break;
 -      default:
 -              pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n",
 -                      arg_num, arg_str, arg_sz);
 +#elif defined(__arm__)
 +
 +static int calc_pt_regs_off(const char *reg_name)
 +{
 +      static struct {
 +              const char *name;
 +              size_t pt_regs_off;
 +      } reg_map[] = {
 +              { "r0", offsetof(struct pt_regs, uregs[0]) },
 +              { "r1", offsetof(struct pt_regs, uregs[1]) },
 +              { "r2", offsetof(struct pt_regs, uregs[2]) },
 +              { "r3", offsetof(struct pt_regs, uregs[3]) },
 +              { "r4", offsetof(struct pt_regs, uregs[4]) },
 +              { "r5", offsetof(struct pt_regs, uregs[5]) },
 +              { "r6", offsetof(struct pt_regs, uregs[6]) },
 +              { "r7", offsetof(struct pt_regs, uregs[7]) },
 +              { "r8", offsetof(struct pt_regs, uregs[8]) },
 +              { "r9", offsetof(struct pt_regs, uregs[9]) },
 +              { "r10", offsetof(struct pt_regs, uregs[10]) },
 +              { "fp", offsetof(struct pt_regs, uregs[11]) },
 +              { "ip", offsetof(struct pt_regs, uregs[12]) },
 +              { "sp", offsetof(struct pt_regs, uregs[13]) },
 +              { "lr", offsetof(struct pt_regs, uregs[14]) },
 +              { "pc", offsetof(struct pt_regs, uregs[15]) },
 +      };
 +      int i;
 +
 +      for (i = 0; i < ARRAY_SIZE(reg_map); i++) {
 +              if (strcmp(reg_name, reg_map[i].name) == 0)
 +                      return reg_map[i].pt_regs_off;
 +      }
 +
 +      pr_warn("usdt: unrecognized register '%s'\n", reg_name);
 +      return -ENOENT;
 +}
 +
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
 +{
 +      char reg_name[16];
 +      int len, reg_off;
 +      long off;
 +
 +      if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] , #%ld ] %n",
 +                 arg_sz, reg_name, &off, &len) == 3) {
 +              /* Memory dereference case, e.g., -4@[fp, #96] */
 +              arg->arg_type = USDT_ARG_REG_DEREF;
 +              arg->val_off = off;
 +              reg_off = calc_pt_regs_off(reg_name);
 +              if (reg_off < 0)
 +                      return reg_off;
 +              arg->reg_off = reg_off;
 +      } else if (sscanf(arg_str, " %d @ \[ %15[a-z0-9] ] %n", arg_sz, reg_name, &len) == 2) {
 +              /* Memory dereference case, e.g., -4@[sp] */
 +              arg->arg_type = USDT_ARG_REG_DEREF;
 +              arg->val_off = 0;
 +              reg_off = calc_pt_regs_off(reg_name);
 +              if (reg_off < 0)
 +                      return reg_off;
 +              arg->reg_off = reg_off;
 +      } else if (sscanf(arg_str, " %d @ #%ld %n", arg_sz, &off, &len) == 2) {
 +              /* Constant value case, e.g., 4@#5 */
 +              arg->arg_type = USDT_ARG_CONST;
 +              arg->val_off = off;
 +              arg->reg_off = 0;
 +      } else if (sscanf(arg_str, " %d @ %15[a-z0-9] %n", arg_sz, reg_name, &len) == 2) {
 +              /* Register read case, e.g., -8@r4 */
 +              arg->arg_type = USDT_ARG_REG;
 +              arg->val_off = 0;
 +              reg_off = calc_pt_regs_off(reg_name);
 +              if (reg_off < 0)
 +                      return reg_off;
 +              arg->reg_off = reg_off;
 +      } else {
 +              pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, arg_str);
                return -EINVAL;
        }
  
  
  #else
  
 -static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
 +static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg, int *arg_sz)
  {
        pr_warn("usdt: libbpf doesn't support USDTs on current architecture\n");
        return -ENOTSUP;