Merge tag 'soc-dt-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 19:11:54 +0000 (12:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 25 Apr 2023 19:11:54 +0000 (12:11 -0700)
Pull ARM SoC devicetree updates from Arnd Bergmann:
 "The devicetree changes overall are again dominated by the Qualcomm
  Snapdragon platform that weighs in at over 300 changesets, but there
  are many updates across other platforms as well, notably Mediatek,
  NXP, Rockchips, Renesas, TI, Samsung and ST Microelectronics. These
  all add new features for existing machines, as well as new machines
  and SoCs.

  The newly added SoCs are:

   - Allwinner T113-s, an Cortex-A7 based variant of the RISC-V based D1
     chip.

   - StarFive JH7110, a RISC-V SoC based on the Sifive U74 core like its
     JH7100 predecessor, but with additional CPU cores and a GPU.

   - Apple M2 as used in current Macbook Air/Pro and Mac Mini gets
     added, with comparable support as its M1 predecessor.

   - Unisoc UMS512 (Tiger T610) is a midrange smartphone SoC

   - Qualcomm IPQ5332 and IPQ9574 are Wi-Fi 7 networking SoCs, based on
     the Cortex-A53 and Cortex-A73 cores, respectively.

   - Qualcomm sa8775p is an automotive SoC derived from the Snapdragon
     family.

  Including the initial board support for the added SoC platforms, there
  are 52 new machines. The largest group are 19 boards industrial
  embedded boards based on the NXP i.MX6 (32-bit) and i.MX8 (64-bit)
  families.

  Others include:

   - Two boards based on the Allwinner f1c200s ultra-low-cost chip

   - Three 'Banana Pi' variants based on the Amlogic g12b (A311D, S922X)
     SoC.

   - The Gl.Inet mv1000 router based on Marvell Armada 3720

   - A Wifi/LTE Dongle based on Qualcomm msm8916

   - Two robotics boards based on Qualcomm QRB chips

   - Three Snapdragon based phones made by Xiaomi

   - Five developments boards based on various Rockchip SoCs, including
     the rk3588s-khadas-edge2 and a few NanoPi models

   - The AM625 Beagleplay industrial SBC

  Another 14 machines get removed: both boards for the obsolete 'oxnas'
  platform, three boards for the Renesas r8a77950 SoC that were only for
  pre-production chips, and various chromebook models based on the
  Qualcomm Sc7180 'trogdor' design that were never part of products"

* tag 'soc-dt-6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (836 commits)
  arm64: dts: rockchip: Add support for volume keys to rk3399-pinephone-pro
  arm64: dts: rockchip: Add vdd_cpu_big regulators to rk3588-rock-5b
  arm64: dts: rockchip: Use generic name for es8316 on Pinebook Pro and Rock 5B
  arm64: dts: rockchip: Drop RTC clock-frequency on rk3588-rock-5b
  arm64: dts: apple: t8112: Add PWM controller
  arm64: dts: apple: t600x: Add PWM controller
  arm64: dts: apple: t8103: Add PWM controller
  arm64: dts: rockchip: Add pinctrl gpio-ranges for rk356x
  ARM: dts: nomadik: Replace deprecated spi-gpio properties
  ARM: dts: aspeed-g6: Add UDMA node
  ARM: dts: aspeed: greatlakes: add mctp device
  ARM: dts: aspeed: greatlakes: Add gpio names
  ARM: dts: aspeed: p10bmc: Change power supply info
  arm64: dts: mediatek: mt6795-xperia-m5: Add Bosch BMM050 Magnetometer
  arm64: dts: mediatek: mt6795-xperia-m5: Add Bosch BMA255 Accelerometer
  arm64: dts: mediatek: mt6795: Add tertiary PWM node
  arm64: dts: rockchip: add panel to Anbernic RG353 series
  dt-bindings: arm: Add Data Modul i.MX8M Plus eDM SBC
  dt-bindings: arm: fsl: Add chargebyte Tarragon
  dt-bindings: vendor-prefixes: add chargebyte
  ...

2307 files changed:
.gitignore
.mailmap
CREDITS
Documentation/ABI/obsolete/sysfs-selinux-checkreqprot [deleted file]
Documentation/ABI/obsolete/sysfs-selinux-disable [deleted file]
Documentation/ABI/removed/sysfs-selinux-checkreqprot [new file with mode: 0644]
Documentation/ABI/removed/sysfs-selinux-disable [new file with mode: 0644]
Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.rst
Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.rst
Documentation/RCU/RTFP.txt
Documentation/RCU/UP.rst
Documentation/RCU/checklist.rst
Documentation/RCU/lockdep.rst
Documentation/RCU/torture.rst
Documentation/RCU/whatisRCU.rst
Documentation/admin-guide/hw-vuln/mds.rst
Documentation/admin-guide/hw-vuln/tsx_async_abort.rst
Documentation/admin-guide/index.rst
Documentation/admin-guide/kernel-parameters.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/quickly-build-trimmed-linux.rst [new file with mode: 0644]
Documentation/admin-guide/ras.rst
Documentation/admin-guide/reporting-issues.rst
Documentation/admin-guide/security-bugs.rst [deleted file]
Documentation/admin-guide/syscall-user-dispatch.rst
Documentation/admin-guide/sysctl/kernel.rst
Documentation/admin-guide/unicode.rst
Documentation/arc/arc.rst [deleted file]
Documentation/arc/features.rst [deleted file]
Documentation/arc/index.rst [deleted file]
Documentation/arch.rst [deleted file]
Documentation/arch/arc/arc.rst [new file with mode: 0644]
Documentation/arch/arc/features.rst [new file with mode: 0644]
Documentation/arch/arc/index.rst [new file with mode: 0644]
Documentation/arch/ia64/aliasing.rst [new file with mode: 0644]
Documentation/arch/ia64/efirtc.rst [new file with mode: 0644]
Documentation/arch/ia64/err_inject.rst [new file with mode: 0644]
Documentation/arch/ia64/features.rst [new file with mode: 0644]
Documentation/arch/ia64/fsys.rst [new file with mode: 0644]
Documentation/arch/ia64/ia64.rst [new file with mode: 0644]
Documentation/arch/ia64/index.rst [new file with mode: 0644]
Documentation/arch/ia64/irq-redir.rst [new file with mode: 0644]
Documentation/arch/ia64/mca.rst [new file with mode: 0644]
Documentation/arch/ia64/serial.rst [new file with mode: 0644]
Documentation/arch/index.rst [new file with mode: 0644]
Documentation/arch/m68k/buddha-driver.rst [new file with mode: 0644]
Documentation/arch/m68k/features.rst [new file with mode: 0644]
Documentation/arch/m68k/index.rst [new file with mode: 0644]
Documentation/arch/m68k/kernel-options.rst [new file with mode: 0644]
Documentation/arch/nios2/features.rst [new file with mode: 0644]
Documentation/arch/nios2/index.rst [new file with mode: 0644]
Documentation/arch/nios2/nios2.rst [new file with mode: 0644]
Documentation/arch/openrisc/features.rst [new file with mode: 0644]
Documentation/arch/openrisc/index.rst [new file with mode: 0644]
Documentation/arch/openrisc/openrisc_port.rst [new file with mode: 0644]
Documentation/arch/openrisc/todo.rst [new file with mode: 0644]
Documentation/arch/parisc/debugging.rst [new file with mode: 0644]
Documentation/arch/parisc/features.rst [new file with mode: 0644]
Documentation/arch/parisc/index.rst [new file with mode: 0644]
Documentation/arch/parisc/registers.rst [new file with mode: 0644]
Documentation/arch/sh/booting.rst [new file with mode: 0644]
Documentation/arch/sh/features.rst [new file with mode: 0644]
Documentation/arch/sh/index.rst [new file with mode: 0644]
Documentation/arch/sh/new-machine.rst [new file with mode: 0644]
Documentation/arch/sh/register-banks.rst [new file with mode: 0644]
Documentation/arch/sparc/adi.rst [new file with mode: 0644]
Documentation/arch/sparc/console.rst [new file with mode: 0644]
Documentation/arch/sparc/features.rst [new file with mode: 0644]
Documentation/arch/sparc/index.rst [new file with mode: 0644]
Documentation/arch/sparc/oradax/dax-hv-api.txt [new file with mode: 0644]
Documentation/arch/sparc/oradax/oracle-dax.rst [new file with mode: 0644]
Documentation/arch/x86/amd-memory-encryption.rst [new file with mode: 0644]
Documentation/arch/x86/amd_hsmp.rst [new file with mode: 0644]
Documentation/arch/x86/boot.rst [new file with mode: 0644]
Documentation/arch/x86/booting-dt.rst [new file with mode: 0644]
Documentation/arch/x86/buslock.rst [new file with mode: 0644]
Documentation/arch/x86/cpuinfo.rst [new file with mode: 0644]
Documentation/arch/x86/earlyprintk.rst [new file with mode: 0644]
Documentation/arch/x86/elf_auxvec.rst [new file with mode: 0644]
Documentation/arch/x86/entry_64.rst [new file with mode: 0644]
Documentation/arch/x86/exception-tables.rst [new file with mode: 0644]
Documentation/arch/x86/features.rst [new file with mode: 0644]
Documentation/arch/x86/i386/IO-APIC.rst [new file with mode: 0644]
Documentation/arch/x86/i386/index.rst [new file with mode: 0644]
Documentation/arch/x86/ifs.rst [new file with mode: 0644]
Documentation/arch/x86/index.rst [new file with mode: 0644]
Documentation/arch/x86/intel-hfi.rst [new file with mode: 0644]
Documentation/arch/x86/intel_txt.rst [new file with mode: 0644]
Documentation/arch/x86/iommu.rst [new file with mode: 0644]
Documentation/arch/x86/kernel-stacks.rst [new file with mode: 0644]
Documentation/arch/x86/mds.rst [new file with mode: 0644]
Documentation/arch/x86/microcode.rst [new file with mode: 0644]
Documentation/arch/x86/mtrr.rst [new file with mode: 0644]
Documentation/arch/x86/orc-unwinder.rst [new file with mode: 0644]
Documentation/arch/x86/pat.rst [new file with mode: 0644]
Documentation/arch/x86/pti.rst [new file with mode: 0644]
Documentation/arch/x86/resctrl.rst [new file with mode: 0644]
Documentation/arch/x86/sgx.rst [new file with mode: 0644]
Documentation/arch/x86/sva.rst [new file with mode: 0644]
Documentation/arch/x86/tdx.rst [new file with mode: 0644]
Documentation/arch/x86/tlb.rst [new file with mode: 0644]
Documentation/arch/x86/topology.rst [new file with mode: 0644]
Documentation/arch/x86/tsx_async_abort.rst [new file with mode: 0644]
Documentation/arch/x86/usb-legacy-support.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/5level-paging.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/boot-options.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/cpu-hotplug-spec.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/fake-numa-for-cpusets.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/fsgs.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/index.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/machinecheck.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/mm.rst [new file with mode: 0644]
Documentation/arch/x86/x86_64/uefi.rst [new file with mode: 0644]
Documentation/arch/x86/xstate.rst [new file with mode: 0644]
Documentation/arch/x86/zero-page.rst [new file with mode: 0644]
Documentation/arch/xtensa/atomctl.rst [new file with mode: 0644]
Documentation/arch/xtensa/booting.rst [new file with mode: 0644]
Documentation/arch/xtensa/features.rst [new file with mode: 0644]
Documentation/arch/xtensa/index.rst [new file with mode: 0644]
Documentation/arch/xtensa/mmu.rst [new file with mode: 0644]
Documentation/arm/index.rst
Documentation/arm/sti/overview.rst
Documentation/arm/sti/stih415-overview.rst [deleted file]
Documentation/arm/sti/stih416-overview.rst [deleted file]
Documentation/arm64/silicon-errata.rst
Documentation/conf.py
Documentation/core-api/asm-annotations.rst
Documentation/core-api/dma-api-howto.rst
Documentation/dev-tools/kmemleak.rst
Documentation/devicetree/bindings/arm/amlogic/amlogic,meson-gx-ao-secure.yaml
Documentation/devicetree/bindings/arm/amlogic/amlogic,meson-mx-secbus2.yaml
Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.yaml
Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml
Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/firmware/arm,scmi.yaml
Documentation/devicetree/bindings/firmware/qcom,scm.yaml
Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml [deleted file]
Documentation/devicetree/bindings/interrupt-controller/loongson,cpu-interrupt-controller.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.yaml
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.yaml
Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.yaml
Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
Documentation/devicetree/bindings/memory-controllers/samsung,exynos5422-dmc.yaml
Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
Documentation/devicetree/bindings/pinctrl/qcom,sm8550-lpass-lpi-pinctrl.yaml
Documentation/devicetree/bindings/serial/renesas,scif.yaml
Documentation/devicetree/bindings/soc/amlogic/amlogic,canvas.yaml
Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt [deleted file]
Documentation/devicetree/bindings/soc/mediatek/mediatek,mutex.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,pmic-glink.yaml
Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
Documentation/devicetree/bindings/sram/qcom,imem.yaml
Documentation/driver-api/clk.rst
Documentation/driver-api/device-io.rst
Documentation/driver-api/firmware/fw_search_path.rst
Documentation/driver-api/vfio.rst
Documentation/filesystems/erofs.rst
Documentation/filesystems/idmappings.rst
Documentation/filesystems/mount_api.rst
Documentation/filesystems/proc.rst
Documentation/filesystems/vfs.rst
Documentation/firmware-guide/acpi/enumeration.rst
Documentation/ia64/aliasing.rst [deleted file]
Documentation/ia64/efirtc.rst [deleted file]
Documentation/ia64/err_inject.rst [deleted file]
Documentation/ia64/features.rst [deleted file]
Documentation/ia64/fsys.rst [deleted file]
Documentation/ia64/ia64.rst [deleted file]
Documentation/ia64/index.rst [deleted file]
Documentation/ia64/irq-redir.rst [deleted file]
Documentation/ia64/mca.rst [deleted file]
Documentation/ia64/serial.rst [deleted file]
Documentation/index.rst
Documentation/kbuild/llvm.rst
Documentation/kernel-hacking/false-sharing.rst [new file with mode: 0644]
Documentation/kernel-hacking/index.rst
Documentation/litmus-tests/README
Documentation/litmus-tests/locking/DCL-broken.litmus [new file with mode: 0644]
Documentation/litmus-tests/locking/DCL-fixed.litmus [new file with mode: 0644]
Documentation/litmus-tests/locking/RM-broken.litmus [new file with mode: 0644]
Documentation/litmus-tests/locking/RM-fixed.litmus [new file with mode: 0644]
Documentation/m68k/buddha-driver.rst [deleted file]
Documentation/m68k/features.rst [deleted file]
Documentation/m68k/index.rst [deleted file]
Documentation/m68k/kernel-options.rst [deleted file]
Documentation/maintainer/rebasing-and-merging.rst
Documentation/mm/hugetlbfs_reserv.rst
Documentation/mm/physical_memory.rst
Documentation/mm/zsmalloc.rst
Documentation/netlink/genetlink-c.yaml
Documentation/netlink/genetlink-legacy.yaml
Documentation/netlink/genetlink.yaml
Documentation/netlink/specs/ethtool.yaml
Documentation/netlink/specs/fou.yaml
Documentation/netlink/specs/netdev.yaml
Documentation/networking/devlink/ice.rst
Documentation/networking/ip-sysctl.rst
Documentation/networking/xdp-rx-metadata.rst
Documentation/nios2/features.rst [deleted file]
Documentation/nios2/index.rst [deleted file]
Documentation/nios2/nios2.rst [deleted file]
Documentation/openrisc/features.rst [deleted file]
Documentation/openrisc/index.rst [deleted file]
Documentation/openrisc/openrisc_port.rst [deleted file]
Documentation/openrisc/todo.rst [deleted file]
Documentation/parisc/debugging.rst [deleted file]
Documentation/parisc/features.rst [deleted file]
Documentation/parisc/index.rst [deleted file]
Documentation/parisc/registers.rst [deleted file]
Documentation/process/coding-style.rst
Documentation/process/contribution-maturity-model.rst [new file with mode: 0644]
Documentation/process/howto.rst
Documentation/process/index.rst
Documentation/process/kernel-docs.rst
Documentation/process/maintainer-tip.rst
Documentation/process/programming-language.rst
Documentation/process/researcher-guidelines.rst
Documentation/process/security-bugs.rst [new file with mode: 0644]
Documentation/process/stable-kernel-rules.rst
Documentation/process/submitting-patches.rst
Documentation/riscv/vm-layout.rst
Documentation/rust/arch-support.rst
Documentation/scheduler/sched-capacity.rst
Documentation/sh/booting.rst [deleted file]
Documentation/sh/features.rst [deleted file]
Documentation/sh/index.rst [deleted file]
Documentation/sh/new-machine.rst [deleted file]
Documentation/sh/register-banks.rst [deleted file]
Documentation/sound/hd-audio/models.rst
Documentation/sparc/adi.rst [deleted file]
Documentation/sparc/console.rst [deleted file]
Documentation/sparc/features.rst [deleted file]
Documentation/sparc/index.rst [deleted file]
Documentation/sparc/oradax/dax-hv-api.txt [deleted file]
Documentation/sparc/oradax/oracle-dax.rst [deleted file]
Documentation/staging/tee.rst
Documentation/trace/ftrace.rst
Documentation/translations/it_IT/admin-guide/security-bugs.rst
Documentation/translations/it_IT/core-api/symbol-namespaces.rst
Documentation/translations/it_IT/doc-guide/parse-headers.rst
Documentation/translations/it_IT/index.rst
Documentation/translations/it_IT/kernel-hacking/locking.rst
Documentation/translations/it_IT/process/5.Posting.rst
Documentation/translations/it_IT/process/changes.rst
Documentation/translations/it_IT/process/clang-format.rst
Documentation/translations/it_IT/process/coding-style.rst
Documentation/translations/it_IT/process/deprecated.rst
Documentation/translations/it_IT/process/email-clients.rst
Documentation/translations/it_IT/process/index.rst
Documentation/translations/it_IT/process/maintainer-pgp-guide.rst
Documentation/translations/it_IT/process/programming-language.rst
Documentation/translations/it_IT/process/stable-kernel-rules.rst
Documentation/translations/it_IT/process/submitting-patches.rst
Documentation/translations/it_IT/process/volatile-considered-harmful.rst
Documentation/translations/ja_JP/howto.rst
Documentation/translations/ko_KR/howto.rst
Documentation/translations/sp_SP/howto.rst
Documentation/translations/sp_SP/memory-barriers.txt
Documentation/translations/sp_SP/process/deprecated.rst [new file with mode: 0644]
Documentation/translations/sp_SP/process/index.rst
Documentation/translations/sp_SP/process/submitting-patches.rst
Documentation/translations/zh_CN/admin-guide/mm/damon/lru_sort.rst
Documentation/translations/zh_CN/admin-guide/security-bugs.rst
Documentation/translations/zh_CN/arch.rst [deleted file]
Documentation/translations/zh_CN/arch/index.rst [new file with mode: 0644]
Documentation/translations/zh_CN/arch/openrisc/index.rst [new file with mode: 0644]
Documentation/translations/zh_CN/arch/openrisc/openrisc_port.rst [new file with mode: 0644]
Documentation/translations/zh_CN/arch/openrisc/todo.rst [new file with mode: 0644]
Documentation/translations/zh_CN/arch/parisc/debugging.rst [new file with mode: 0644]
Documentation/translations/zh_CN/arch/parisc/index.rst [new file with mode: 0644]
Documentation/translations/zh_CN/arch/parisc/registers.rst [new file with mode: 0644]
Documentation/translations/zh_CN/index.rst
Documentation/translations/zh_CN/mm/hugetlbfs_reserv.rst
Documentation/translations/zh_CN/openrisc/index.rst [deleted file]
Documentation/translations/zh_CN/openrisc/openrisc_port.rst [deleted file]
Documentation/translations/zh_CN/openrisc/todo.rst [deleted file]
Documentation/translations/zh_CN/parisc/debugging.rst [deleted file]
Documentation/translations/zh_CN/parisc/index.rst [deleted file]
Documentation/translations/zh_CN/parisc/registers.rst [deleted file]
Documentation/translations/zh_CN/process/howto.rst
Documentation/translations/zh_CN/scheduler/sched-capacity.rst
Documentation/translations/zh_TW/admin-guide/security-bugs.rst
Documentation/translations/zh_TW/process/howto.rst
Documentation/usb/gadget_uvc.rst [new file with mode: 0644]
Documentation/usb/index.rst
Documentation/userspace-api/ELF.rst [new file with mode: 0644]
Documentation/userspace-api/index.rst
Documentation/userspace-api/media/v4l/pixfmt-rgb.rst
Documentation/userspace-api/netlink/specs.rst
Documentation/virt/coco/sev-guest.rst
Documentation/virt/kvm/api.rst
Documentation/x86/amd-memory-encryption.rst [deleted file]
Documentation/x86/amd_hsmp.rst [deleted file]
Documentation/x86/boot.rst [deleted file]
Documentation/x86/booting-dt.rst [deleted file]
Documentation/x86/buslock.rst [deleted file]
Documentation/x86/cpuinfo.rst [deleted file]
Documentation/x86/earlyprintk.rst [deleted file]
Documentation/x86/elf_auxvec.rst [deleted file]
Documentation/x86/entry_64.rst [deleted file]
Documentation/x86/exception-tables.rst [deleted file]
Documentation/x86/features.rst [deleted file]
Documentation/x86/i386/IO-APIC.rst [deleted file]
Documentation/x86/i386/index.rst [deleted file]
Documentation/x86/ifs.rst [deleted file]
Documentation/x86/index.rst [deleted file]
Documentation/x86/intel-hfi.rst [deleted file]
Documentation/x86/intel_txt.rst [deleted file]
Documentation/x86/iommu.rst [deleted file]
Documentation/x86/kernel-stacks.rst [deleted file]
Documentation/x86/mds.rst [deleted file]
Documentation/x86/microcode.rst [deleted file]
Documentation/x86/mtrr.rst [deleted file]
Documentation/x86/orc-unwinder.rst [deleted file]
Documentation/x86/pat.rst [deleted file]
Documentation/x86/pti.rst [deleted file]
Documentation/x86/resctrl.rst [deleted file]
Documentation/x86/sgx.rst [deleted file]
Documentation/x86/sva.rst [deleted file]
Documentation/x86/tdx.rst [deleted file]
Documentation/x86/tlb.rst [deleted file]
Documentation/x86/topology.rst [deleted file]
Documentation/x86/tsx_async_abort.rst [deleted file]
Documentation/x86/usb-legacy-support.rst [deleted file]
Documentation/x86/x86_64/5level-paging.rst [deleted file]
Documentation/x86/x86_64/boot-options.rst [deleted file]
Documentation/x86/x86_64/cpu-hotplug-spec.rst [deleted file]
Documentation/x86/x86_64/fake-numa-for-cpusets.rst [deleted file]
Documentation/x86/x86_64/fsgs.rst [deleted file]
Documentation/x86/x86_64/index.rst [deleted file]
Documentation/x86/x86_64/machinecheck.rst [deleted file]
Documentation/x86/x86_64/mm.rst [deleted file]
Documentation/x86/x86_64/uefi.rst [deleted file]
Documentation/x86/xstate.rst [deleted file]
Documentation/x86/zero-page.rst [deleted file]
Documentation/xtensa/atomctl.rst [deleted file]
Documentation/xtensa/booting.rst [deleted file]
Documentation/xtensa/features.rst [deleted file]
Documentation/xtensa/index.rst [deleted file]
Documentation/xtensa/mmu.rst [deleted file]
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/dts/e60k02.dtsi
arch/arm/boot/dts/e70k02.dtsi
arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts
arch/arm/boot/dts/imx6ull-colibri.dtsi
arch/arm/boot/dts/imx7d-remarkable2.dts
arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts
arch/arm/boot/dts/rk3288.dtsi
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/common/scoop.c
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/oxnas_v6_defconfig [deleted file]
arch/arm/configs/shmobile_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/configs/vexpress_defconfig
arch/arm/include/asm/assembler.h
arch/arm/lib/uaccess_with_memcpy.c
arch/arm/mach-bcm/bcm_kona_smc.c
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/suspend.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-imx6ul.c
arch/arm/mach-imx/mmdc.c
arch/arm/mach-mmp/Kconfig
arch/arm/mach-mstar/Kconfig
arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-mv78xx0/common.h
arch/arm/mach-mv78xx0/mv78xx0.h
arch/arm/mach-mv78xx0/pcie.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/omap-dma.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/cm33xx.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm33xx-core.c
arch/arm/mach-oxnas/Kconfig [deleted file]
arch/arm/mach-oxnas/Makefile [deleted file]
arch/arm/mach-oxnas/headsmp.S [deleted file]
arch/arm/mach-oxnas/platsmp.c [deleted file]
arch/arm/mach-pxa/irq.c
arch/arm/mach-pxa/sharpsl_pm.c
arch/arm/mach-sa1100/jornada720_ssp.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-shmobile/platsmp-apmu.c
arch/arm/mach-spear/Kconfig
arch/arm/vdso/Makefile
arch/arm/vfp/entry.S
arch/arm/vfp/vfphw.S
arch/arm/vfp/vfpmodule.c
arch/arm64/Kconfig
arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-kbox-a-230-ls.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var1.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var2.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var4.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28.dts
arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
arch/arm64/boot/dts/freescale/imx8mm-nitrogen-r2.dts
arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
arch/arm64/boot/dts/freescale/imx8mn.dtsi
arch/arm64/boot/dts/freescale/imx8mp-verdin-dev.dtsi
arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
arch/arm64/boot/dts/freescale/imx8mp.dtsi
arch/arm64/boot/dts/freescale/imx93.dtsi
arch/arm64/boot/dts/nvidia/tegra194.dtsi
arch/arm64/boot/dts/nvidia/tegra234.dtsi
arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi
arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dts
arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi
arch/arm64/boot/dts/rockchip/rk3326-odroid-go2-v11.dts
arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi
arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
arch/arm64/boot/dts/rockchip/rk3399-rockpro64.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353x.dtsi
arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
arch/arm64/boot/dts/rockchip/rk3588s.dtsi
arch/arm64/configs/defconfig
arch/arm64/configs/virt.config
arch/arm64/include/asm/kvm_host.h
arch/arm64/kernel/compat_alignment.c
arch/arm64/kernel/efi-header.S
arch/arm64/kernel/vdso/Makefile
arch/arm64/kernel/vdso32/Makefile
arch/arm64/kvm/Kconfig
arch/arm64/kvm/arch_timer.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/include/nvhe/fixed_config.h
arch/arm64/kvm/hyp/nvhe/sys_regs.c
arch/arm64/kvm/hypercalls.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pmu-emul.c
arch/arm64/kvm/sys_regs.c
arch/arm64/net/bpf_jit.h
arch/arm64/net/bpf_jit_comp.c
arch/csky/include/asm/processor.h
arch/csky/kernel/vdso/Makefile
arch/ia64/kernel/efi.c
arch/ia64/kernel/fsys.S
arch/ia64/mm/ioremap.c
arch/ia64/pci/pci.c
arch/loongarch/Kconfig
arch/loongarch/include/asm/acpi.h
arch/loongarch/include/asm/addrspace.h
arch/loongarch/include/asm/bootinfo.h
arch/loongarch/include/asm/cpu-features.h
arch/loongarch/include/asm/cpu.h
arch/loongarch/include/asm/io.h
arch/loongarch/include/asm/loongarch.h
arch/loongarch/include/asm/module.lds.h
arch/loongarch/include/uapi/asm/ptrace.h
arch/loongarch/kernel/cpu-probe.c
arch/loongarch/kernel/proc.c
arch/loongarch/kernel/ptrace.c
arch/loongarch/kernel/setup.c
arch/loongarch/kernel/stacktrace.c
arch/loongarch/kernel/unwind.c
arch/loongarch/kernel/unwind_prologue.c
arch/loongarch/mm/init.c
arch/loongarch/net/bpf_jit.c
arch/loongarch/power/suspend_asm.S
arch/loongarch/vdso/Makefile
arch/m68k/Kconfig.debug
arch/m68k/Kconfig.machine
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/kernel/machine_kexec.c
arch/mips/bmips/dma.c
arch/mips/bmips/setup.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kvm/Kconfig
arch/mips/vdso/Makefile
arch/nios2/include/asm/thread_info.h
arch/powerpc/include/asm/book3s/64/tlbflush.h
arch/powerpc/include/asm/kasan.h
arch/powerpc/include/asm/string.h
arch/powerpc/kernel/prom_init_check.sh
arch/powerpc/kernel/ptrace/ptrace-view.c
arch/powerpc/kernel/vdso/Makefile
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/fault.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/pseries/Kconfig
arch/powerpc/platforms/pseries/papr_scm.c
arch/powerpc/platforms/pseries/vas.c
arch/riscv/Kconfig
arch/riscv/Kconfig.erratas
arch/riscv/Makefile
arch/riscv/boot/dts/canaan/k210.dtsi
arch/riscv/include/asm/fixmap.h
arch/riscv/include/asm/hwcap.h
arch/riscv/include/asm/irq.h
arch/riscv/include/asm/mmu.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/sbi.h
arch/riscv/include/asm/smp.h
arch/riscv/include/asm/tlbflush.h
arch/riscv/kernel/Makefile
arch/riscv/kernel/cpu-hotplug.c
arch/riscv/kernel/irq.c
arch/riscv/kernel/sbi-ipi.c [new file with mode: 0644]
arch/riscv/kernel/sbi.c
arch/riscv/kernel/setup.c
arch/riscv/kernel/signal.c
arch/riscv/kernel/smp.c
arch/riscv/kernel/smpboot.c
arch/riscv/kernel/vdso/Makefile
arch/riscv/kvm/Kconfig
arch/riscv/kvm/vcpu_timer.c
arch/riscv/mm/cacheflush.c
arch/riscv/mm/context.c
arch/riscv/mm/fault.c
arch/riscv/mm/init.c
arch/riscv/mm/tlbflush.c
arch/riscv/purgatory/Makefile
arch/s390/Makefile
arch/s390/boot/ipl_report.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/kernel/ptrace.c
arch/s390/kernel/vdso32/Makefile
arch/s390/kernel/vdso64/Makefile
arch/s390/kvm/Kconfig
arch/s390/kvm/intercept.c
arch/s390/kvm/kvm-s390.c
arch/s390/lib/uaccess.c
arch/s390/net/bpf_jit_comp.c
arch/s390/pci/pci.c
arch/s390/pci/pci_bus.c
arch/s390/pci/pci_bus.h
arch/sh/Kconfig.cpu
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/Makefile.um
arch/x86/boot/header.S
arch/x86/coco/core.c
arch/x86/entry/entry_64.S
arch/x86/entry/vdso/Makefile
arch/x86/events/amd/core.c
arch/x86/hyperv/hv_init.c
arch/x86/hyperv/ivm.c
arch/x86/include/asm/alternative.h
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/coco.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/mem_encrypt.h
arch/x86/include/asm/mmu_context.h
arch/x86/include/asm/mshyperv.h
arch/x86/include/asm/page_64_types.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pgtable_64_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/realmode.h
arch/x86/include/asm/sev-common.h
arch/x86/include/asm/sev.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/svm.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/x86_init.h
arch/x86/include/asm/xen/cpuid.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/asm-offsets.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpu.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/mce/internal.h
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/resctrl/ctrlmondata.c
arch/x86/kernel/cpu/resctrl/internal.h
arch/x86/kernel/cpu/resctrl/monitor.c
arch/x86/kernel/cpu/resctrl/rdtgroup.c
arch/x86/kernel/cpu/sgx/main.c
arch/x86/kernel/cpu/sgx/sgx.h
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/ftrace_64.S
arch/x86/kernel/head_64.S
arch/x86/kernel/kexec-bzimage64.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/sev.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/Kconfig
arch/x86/kvm/ioapic.c
arch/x86/kvm/kvm_onhyperv.h
arch/x86/kvm/svm/avic.c
arch/x86/kvm/svm/sev.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm_onhyperv.h
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmenter.S
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/Makefile
arch/x86/lib/clear_page_64.S
arch/x86/lib/copy_user_64.S
arch/x86/lib/copy_user_uncached_64.S [new file with mode: 0644]
arch/x86/lib/memcpy_64.S
arch/x86/lib/memset_64.S
arch/x86/lib/usercopy_64.c
arch/x86/mm/cpu_entry_area.c
arch/x86/mm/init.c
arch/x86/mm/ioremap.c
arch/x86/mm/mem_encrypt_amd.c
arch/x86/mm/mem_encrypt_identity.c
arch/x86/mm/pat/set_memory.c
arch/x86/mm/tlb.c
arch/x86/pci/fixup.c
arch/x86/platform/pvh/enlighten.c
arch/x86/purgatory/Makefile
arch/x86/xen/Makefile
arch/x86/xen/enlighten_pv.c
arch/x86/xen/enlighten_pvh.c
arch/x86/xen/mmu_pv.c
arch/x86/xen/time.c
arch/x86/xen/vga.c
arch/x86/xen/xen-head.S
arch/x86/xen/xen-ops.h
arch/xtensa/include/asm/initialize_mmu.h
arch/xtensa/kernel/traps.c
block/Kconfig
block/blk-core.c
block/blk-map.c
block/blk-mq.c
block/blk-mq.h
block/genhd.c
certs/system_keyring.c
crypto/asymmetric_keys/pkcs7_verify.c
crypto/asymmetric_keys/restrict.c
crypto/asymmetric_keys/verify_pefile.c
crypto/asymmetric_keys/x509_cert_parser.c
drivers/accel/Makefile
drivers/accel/ivpu/ivpu_drv.c
drivers/accel/ivpu/ivpu_drv.h
drivers/accel/ivpu/ivpu_hw_mtl.c
drivers/accel/ivpu/ivpu_ipc.h
drivers/accel/ivpu/ivpu_job.c
drivers/accel/ivpu/ivpu_pm.c
drivers/accel/ivpu/ivpu_pm.h
drivers/acpi/acpi_video.c
drivers/acpi/acpica/evevent.c
drivers/acpi/acpica/hwsleep.c
drivers/acpi/acpica/utglobal.c
drivers/acpi/bus.c
drivers/acpi/pptt.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_thermal.c
drivers/acpi/resource.c
drivers/acpi/video_detect.c
drivers/acpi/x86/utils.c
drivers/amba/tegra-ahb.c
drivers/ata/pata_parport/pata_parport.c
drivers/atm/idt77252.c
drivers/base/cacheinfo.c
drivers/base/cpu.c
drivers/block/drbd/drbd_nl.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_state.c
drivers/block/loop.c
drivers/block/null_blk/main.c
drivers/block/sunvdc.c
drivers/block/ublk_drv.c
drivers/block/virtio_blk.c
drivers/bluetooth/btbcm.c
drivers/bluetooth/btintel.c
drivers/bluetooth/btintel.h
drivers/bluetooth/btqcomsmd.c
drivers/bluetooth/btsdio.c
drivers/bluetooth/btusb.c
drivers/bus/brcmstb_gisb.c
drivers/bus/imx-weim.c
drivers/bus/ti-sysc.c
drivers/bus/vexpress-config.c
drivers/char/tpm/eventlog/common.c
drivers/char/tpm/st33zp24/i2c.c
drivers/char/tpm/st33zp24/spi.c
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_ftpm_tee.c
drivers/char/tpm/tpm_tis.c
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_core.h
drivers/char/tpm/tpm_tis_i2c_cr50.c
drivers/char/tpm/tpm_tis_spi_main.c
drivers/char/tpm/tpm_tis_synquacer.c
drivers/clk/Kconfig
drivers/clk/bcm/clk-bcm2835-aux.c
drivers/clk/bcm/clk-bcm2835.c
drivers/clk/clk-fixed-mmio.c
drivers/clk/clk-fsl-sai.c
drivers/clk/clk-k210.c
drivers/clk/clk-renesas-pcie.c
drivers/clk/hisilicon/clk-hi3559a.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/microchip/clk-mpfs-ccc.c
drivers/clk/sprd/common.c
drivers/clocksource/timer-clint.c
drivers/counter/104-quad-8.c
drivers/cpufreq/amd-pstate.c
drivers/cpuidle/cpuidle-psci-domain.c
drivers/crypto/ccp/sev-dev.c
drivers/cxl/core/hdm.c
drivers/cxl/core/pci.c
drivers/cxl/core/pmem.c
drivers/cxl/core/port.c
drivers/cxl/core/region.c
drivers/cxl/cxl.h
drivers/cxl/cxlpci.h
drivers/cxl/port.c
drivers/dma/apple-admac.c
drivers/dma/dmaengine.c
drivers/dma/xilinx/xdma.c
drivers/edac/altera_edac.c
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/amd8111_edac.c
drivers/edac/amd8131_edac.c
drivers/edac/e752x_edac.c
drivers/edac/e7xxx_edac.c
drivers/edac/i10nm_base.c
drivers/edac/i5000_edac.c
drivers/edac/i5100_edac.c
drivers/edac/i82860_edac.c
drivers/edac/layerscape_edac.c
drivers/edac/mpc85xx_edac.c
drivers/edac/qcom_edac.c
drivers/edac/r82600_edac.c
drivers/edac/skx_base.c
drivers/firmware/arm_scmi/bus.c
drivers/firmware/arm_scmi/driver.c
drivers/firmware/arm_scmi/mailbox.c
drivers/firmware/arm_scmi/optee.c
drivers/firmware/efi/earlycon.c
drivers/firmware/efi/efi-init.c
drivers/firmware/efi/libstub/Makefile.zboot
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/arm64.c
drivers/firmware/efi/libstub/efi-stub-entry.c
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/randomalloc.c
drivers/firmware/efi/libstub/screen_info.c
drivers/firmware/efi/libstub/smbios.c
drivers/firmware/efi/libstub/zboot-header.S
drivers/firmware/efi/libstub/zboot.c
drivers/firmware/efi/sysfb_efi.c
drivers/firmware/imx/imx-scu.c
drivers/firmware/imx/scu-pd.c
drivers/firmware/meson/meson_sm.c
drivers/firmware/psci/psci.c
drivers/firmware/qcom_scm.c
drivers/firmware/smccc/smccc.c
drivers/firmware/smccc/soc_id.c
drivers/firmware/sysfb.c
drivers/firmware/sysfb_simplefb.c
drivers/firmware/tegra/bpmp-debugfs.c
drivers/firmware/tegra/bpmp.c
drivers/firmware/turris-mox-rwtm.c
drivers/firmware/xilinx/zynqmp.c
drivers/fpga/dfl-pci.c
drivers/fpga/fpga-bridge.c
drivers/fpga/intel-m10-bmc-sec-update.c
drivers/fpga/xilinx-pr-decoupler.c
drivers/gpio/Kconfig
drivers/gpio/gpio-104-dio-48e.c
drivers/gpio/gpio-104-idi-48.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpiolib-acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/nv.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
drivers/gpu/drm/amd/amdkfd/kfd_module.c
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
drivers/gpu/drm/amd/display/dc/link/link_detection.c
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/armada/armada_drv.c
drivers/gpu/drm/bridge/lontium-lt8912b.c
drivers/gpu/drm/drm_buddy.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/drm_panel_orientation_quirks.c
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_color.c
drivers/gpu/drm/i915/display/intel_color.h
drivers/gpu/drm/i915/display/intel_crtc.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_dmc.c
drivers/gpu/drm/i915/display/intel_dp_aux.c
drivers/gpu/drm/i915/display/intel_dp_mst.c
drivers/gpu/drm/i915/display/intel_dpt.c
drivers/gpu/drm/i915/display/intel_fbdev.c
drivers/gpu/drm/i915/display/intel_psr.c
drivers/gpu/drm/i915/display/intel_snps_phy.c
drivers/gpu/drm/i915/display/intel_tc.c
drivers/gpu/drm/i915/gem/i915_gem_lmem.c
drivers/gpu/drm/i915/gem/i915_gem_object.h
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/i915/gt/intel_execlists_submission.c
drivers/gpu/drm/i915/gt/intel_gt.c
drivers/gpu/drm/i915/gt/intel_gt_pm.c
drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
drivers/gpu/drm/i915/gt/intel_rc6.c
drivers/gpu/drm/i915/gt/intel_rps.c
drivers/gpu/drm/i915/gt/intel_rps.h
drivers/gpu/drm/i915/gt/intel_sseu.h
drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
drivers/gpu/drm/i915/gt/uc/intel_huc.c
drivers/gpu/drm/i915/gt/uc/intel_huc.h
drivers/gpu/drm/i915/i915_active.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_perf_types.h
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/meson/meson_vpp.c
drivers/gpu/drm/msm/msm_gem_shrinker.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_backlight.c
drivers/gpu/drm/nouveau/nouveau_dp.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/tests/drm_buddy_test.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_device.c
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/host1x/dev.c
drivers/hid/Kconfig
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-sensor-custom.c
drivers/hid/hid-topre.c
drivers/hid/intel-ish-hid/ishtp/bus.c
drivers/hv/connection.c
drivers/hv/ring_buffer.c
drivers/hv/vmbus_drv.c
drivers/hwmon/adt7475.c
drivers/hwmon/hwmon.c
drivers/hwmon/ina3221.c
drivers/hwmon/it87.c
drivers/hwmon/ltc2992.c
drivers/hwmon/peci/cputemp.c
drivers/hwmon/pmbus/adm1266.c
drivers/hwmon/pmbus/ucd9000.c
drivers/hwmon/tmp513.c
drivers/hwmon/xgene-hwmon.c
drivers/hwtracing/coresight/coresight-etm4x-core.c
drivers/hwtracing/coresight/coresight-etm4x.h
drivers/i2c/busses/i2c-hisi.c
drivers/i2c/busses/i2c-imx-lpi2c.c
drivers/i2c/busses/i2c-mchp-pci1xxxx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/i2c-core-of.c
drivers/iio/accel/kionix-kx022a.c
drivers/iio/adc/ad7791.c
drivers/iio/adc/at91-sama5d2_adc.c
drivers/iio/adc/ltc2497.c
drivers/iio/adc/max11410.c
drivers/iio/adc/palmas_gpadc.c
drivers/iio/adc/qcom-spmi-adc5.c
drivers/iio/adc/ti-ads7950.c
drivers/iio/dac/ad5755.c
drivers/iio/dac/cio-dac.c
drivers/iio/imu/Kconfig
drivers/iio/industrialio-buffer.c
drivers/iio/light/cm32181.c
drivers/iio/light/tsl2772.c
drivers/iio/light/vcnl4000.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/erdma/erdma_cq.c
drivers/infiniband/hw/erdma/erdma_hw.h
drivers/infiniband/hw/erdma/erdma_main.c
drivers/infiniband/hw/erdma/erdma_qp.c
drivers/infiniband/hw/erdma/erdma_verbs.h
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/irdma/cm.c
drivers/infiniband/hw/irdma/cm.h
drivers/infiniband/hw/irdma/hw.c
drivers/infiniband/hw/irdma/utils.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/qib/qib_file_ops.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/input/joystick/xpad.c
drivers/input/mouse/alps.c
drivers/input/mouse/focaltech.c
drivers/input/serio/i8042-acpipnpio.h
drivers/input/tablet/pegasus_notetaker.c
drivers/input/touchscreen/cyttsp5.c
drivers/input/touchscreen/goodix.c
drivers/interconnect/core.c
drivers/interconnect/imx/imx.c
drivers/interconnect/qcom/icc-rpm.c
drivers/interconnect/qcom/icc-rpmh.c
drivers/interconnect/qcom/msm8974.c
drivers/interconnect/qcom/osm-l3.c
drivers/interconnect/qcom/qcm2290.c
drivers/interconnect/qcom/sm8450.c
drivers/interconnect/qcom/sm8550.c
drivers/interconnect/samsung/exynos.c
drivers/iommu/exynos-iommu.c
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.h
drivers/iommu/intel/irq_remapping.c
drivers/iommu/intel/perfmon.c
drivers/iommu/iommufd/pages.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-bcm6345-l1.c
drivers/irqchip/irq-csky-apb-intc.c
drivers/irqchip/irq-gic-v2m.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-loongson-eiointc.c
drivers/irqchip/irq-loongson-pch-pic.c
drivers/irqchip/irq-riscv-intc.c
drivers/irqchip/irq-sifive-plic.c
drivers/irqchip/irq-st.c
drivers/mailbox/mailbox-mpfs.c
drivers/md/Kconfig
drivers/md/dm-crypt.c
drivers/md/dm-stats.c
drivers/md/dm-stats.h
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/md.c
drivers/media/i2c/imx290.c
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/platform/qcom/venus/firmware.c
drivers/memory/Kconfig
drivers/memory/atmel-ebi.c
drivers/memory/bt1-l2-ctl.c
drivers/memory/da8xx-ddrctl.c
drivers/memory/fsl_ifc.c
drivers/memory/mtk-smi.c
drivers/memory/mvebu-devbus.c
drivers/memory/tegra/mc.c
drivers/memory/tegra/tegra124-emc.c
drivers/memory/tegra/tegra186-emc.c
drivers/memory/tegra/tegra20-emc.c
drivers/memory/tegra/tegra210-emc-cc-r21021.c
drivers/memory/tegra/tegra210-emc-table.c
drivers/memory/tegra/tegra30-emc.c
drivers/memstick/core/memstick.c
drivers/misc/fastrpc.c
drivers/misc/vmw_vmci/vmci_context.c
drivers/misc/vmw_vmci/vmci_event.c
drivers/mmc/host/dw_mmc-starfive.c
drivers/mmc/host/sdhci_am654.c
drivers/mtd/mtdblock.c
drivers/mtd/nand/ecc-mxic.c
drivers/mtd/nand/raw/meson_nand.c
drivers/mtd/nand/raw/nandsim.c
drivers/mtd/nand/raw/stm32_fmc2_nand.c
drivers/mtd/spi-nor/core.c
drivers/mtd/spi-nor/core.h
drivers/mtd/spi-nor/debugfs.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/wl.c
drivers/net/bonding/bond_main.c
drivers/net/can/cc770/cc770_platform.c
drivers/net/dsa/b53/b53_mmap.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz8863_smi.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/global2.c
drivers/net/dsa/mv88e6xxx/global2.h
drivers/net/dsa/realtek/realtek-mdio.c
drivers/net/ethernet/amazon/ena/ena_ethtool.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_tx.c
drivers/net/ethernet/i825xx/sni_82596.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/emac/rgmii.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e_diag.c
drivers/net/ethernet/intel/i40e/i40e_diag.h
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_common.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_txrx.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_sched.c
drivers/net/ethernet/intel/ice/ice_sriov.c
drivers/net/ethernet/intel/ice/ice_switch.c
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/intel/ice/ice_txrx_lib.c
drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
drivers/net/ethernet/intel/ice/ice_xsk.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/igbvf/vf.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h
drivers/net/ethernet/mediatek/mtk_ppe.c
drivers/net/ethernet/mediatek/mtk_ppe_offload.c
drivers/net/ethernet/mediatek/mtk_sgmii.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/ecpf.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc/int_port.c
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_ofld.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mscc/ocelot_stats.c
drivers/net/ethernet/natsemi/sonic.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/realtek/r8169_phy_config.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/rswitch.c
drivers/net/ethernet/renesas/rswitch.h
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/efx_common.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/ldmvsw.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/ethernet/ti/am65-cpts.c
drivers/net/ethernet/ti/cpsw-phy-sel.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_net.h
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/via/via-velocity.h
drivers/net/ethernet/wangxun/libwx/wx_type.h
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/hamradio/Kconfig
drivers/net/ieee802154/ca8210.c
drivers/net/ipa/gsi_reg.c
drivers/net/ipa/gsi_reg.h
drivers/net/ipa/gsi_trans.c
drivers/net/ipa/ipa_reg.c
drivers/net/ipa/ipa_reg.h
drivers/net/ipa/reg.h
drivers/net/ipa/reg/gsi_reg-v4.5.c
drivers/net/ipa/reg/gsi_reg-v4.9.c
drivers/net/ipvlan/ipvlan_l3s.c
drivers/net/mdio/acpi_mdio.c
drivers/net/mdio/mdio-thunder.c
drivers/net/mdio/of_mdio.c
drivers/net/net_failover.c
drivers/net/phy/dp83869.c
drivers/net/phy/mdio_devres.c
drivers/net/phy/micrel.c
drivers/net/phy/mscc/mscc_main.c
drivers/net/phy/nxp-c45-tja11xx.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/phy/sfp-bus.c
drivers/net/phy/sfp.c
drivers/net/phy/smsc.c
drivers/net/tun.c
drivers/net/usb/asix_devices.c
drivers/net/usb/lan78xx.c
drivers/net/usb/plusb.c
drivers/net/usb/r8152.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wireless/ath/ath10k/qmi.c
drivers/net/wireless/ath/ath11k/mhi.c
drivers/net/wireless/ath/ath9k/mci.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/marvell/mwifiex/pcie.c
drivers/net/wireless/marvell/mwifiex/sdio.c
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76.h
drivers/net/wireless/mediatek/mt76/mt7603/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt7615/main.c
drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt76x02_util.c
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7921/init.c
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/pci.c
drivers/net/wireless/mediatek/mt76/mt7996/main.c
drivers/net/wireless/ti/wlcore/spi.c
drivers/net/wwan/iosm/iosm_ipc_imem.c
drivers/net/wwan/iosm/iosm_ipc_pcie.c
drivers/net/wwan/t7xx/Makefile
drivers/net/xen-netback/common.h
drivers/net/xen-netback/netback.c
drivers/nfc/pn533/usb.c
drivers/nfc/st-nci/ndlc.c
drivers/nubus/bus.c
drivers/nvme/host/core.c
drivers/nvme/host/ioctl.c
drivers/nvme/host/multipath.c
drivers/nvme/host/pci.c
drivers/nvme/host/tcp.c
drivers/nvme/target/core.c
drivers/nvmem/core.c
drivers/of/dynamic.c
drivers/of/platform.c
drivers/pci/bus.c
drivers/pci/controller/dwc/pcie-designware.c
drivers/pci/doe.c
drivers/pci/msi/msi.c
drivers/pci/of.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/remove.c
drivers/perf/amlogic/meson_g12_ddr_pmu.c
drivers/pinctrl/mediatek/Kconfig
drivers/pinctrl/pinctrl-at91-pio4.c
drivers/pinctrl/pinctrl-ocelot.c
drivers/pinctrl/stm32/pinctrl-stm32.c
drivers/platform/chrome/cros_ec_chardev.c
drivers/platform/surface/aggregator/bus.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/gigabyte-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel/pmc/core.c
drivers/platform/x86/intel/tpmi.c
drivers/platform/x86/intel/vsec.c
drivers/platform/x86/think-lmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/power/supply/axp288_fuel_gauge.c
drivers/power/supply/bq24190_charger.c
drivers/power/supply/cros_usbpd-charger.c
drivers/power/supply/da9150-charger.c
drivers/power/supply/rk817_charger.c
drivers/ptp/ptp_qoriq.c
drivers/pwm/core.c
drivers/pwm/pwm-cros-ec.c
drivers/pwm/pwm-hibvt.c
drivers/pwm/pwm-iqs620a.c
drivers/pwm/pwm-meson.c
drivers/pwm/pwm-sprd.c
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/sm5703-regulator.c
drivers/remoteproc/qcom_q6v5_mss.c
drivers/remoteproc/qcom_q6v5_pas.c
drivers/s390/crypto/vfio_ap_drv.c
drivers/sbus/char/oradax.c
drivers/scsi/device_handler/scsi_dh_alua.c
drivers/scsi/hosts.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/mpi3mr/mpi3mr.h
drivers/scsi/mpi3mr/mpi3mr_fw.c
drivers/scsi/mpi3mr/mpi3mr_os.c
drivers/scsi/mpi3mr/mpi3mr_transport.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_transport.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_scan.c
drivers/scsi/ses.c
drivers/soc/amlogic/meson-gx-pwrc-vpu.c
drivers/soc/apple/rtkit.c
drivers/soc/bcm/bcm2835-power.c
drivers/soc/bcm/brcmstb/Kconfig
drivers/soc/bcm/brcmstb/biuctrl.c
drivers/soc/bcm/brcmstb/pm/Makefile
drivers/soc/bcm/brcmstb/pm/aon_defs.h [deleted file]
drivers/soc/bcm/brcmstb/pm/pm-arm.c [deleted file]
drivers/soc/bcm/brcmstb/pm/s2-arm.S [deleted file]
drivers/soc/bcm/raspberrypi-power.c
drivers/soc/canaan/Kconfig
drivers/soc/fsl/qbman/dpaa_sys.c
drivers/soc/imx/Kconfig
drivers/soc/imx/imx8m-blk-ctrl.c
drivers/soc/imx/imx8mp-blk-ctrl.c
drivers/soc/imx/soc-imx8m.c
drivers/soc/mediatek/Kconfig
drivers/soc/mediatek/mt8173-mmsys.h [new file with mode: 0644]
drivers/soc/mediatek/mt8195-mmsys.h
drivers/soc/mediatek/mtk-mmsys.c
drivers/soc/mediatek/mtk-mmsys.h
drivers/soc/mediatek/mtk-mutex.c
drivers/soc/mediatek/mtk-svs.c
drivers/soc/microchip/mpfs-sys-controller.c
drivers/soc/qcom/Kconfig
drivers/soc/qcom/Makefile
drivers/soc/qcom/icc-bwmon.c
drivers/soc/qcom/ice.c [new file with mode: 0644]
drivers/soc/qcom/llcc-qcom.c
drivers/soc/qcom/pmic_glink.c
drivers/soc/qcom/qcom_aoss.c
drivers/soc/qcom/qcom_gsbi.c
drivers/soc/qcom/rmtfs_mem.c
drivers/soc/qcom/rpmh-rsc.c
drivers/soc/qcom/rpmpd.c
drivers/soc/qcom/smd-rpm.c
drivers/soc/qcom/smem.c
drivers/soc/qcom/smsm.c
drivers/soc/qcom/socinfo.c
drivers/soc/renesas/Kconfig
drivers/soc/renesas/pwc-rzv2m.c
drivers/soc/renesas/r8a7795-sysc.c
drivers/soc/renesas/renesas-soc.c
drivers/soc/renesas/rmobile-sysc.c
drivers/soc/sunxi/sunxi_mbus.c
drivers/soc/sunxi/sunxi_sram.c
drivers/soc/tegra/cbb/tegra-cbb.c
drivers/soc/tegra/cbb/tegra194-cbb.c
drivers/soc/tegra/cbb/tegra234-cbb.c
drivers/soc/tegra/flowctrl.c
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/pmc.c
drivers/soc/tegra/powergate-bpmp.c
drivers/soc/ti/k3-ringacc.c
drivers/soc/ti/k3-socinfo.c
drivers/soc/ti/knav_dma.c
drivers/soc/ti/knav_qmss_acc.c
drivers/soc/ti/knav_qmss_queue.c
drivers/soc/ti/omap_prm.c
drivers/soc/ti/pm33xx.c
drivers/soc/ti/smartreflex.c
drivers/soc/ti/wkup_m3_ipc.c
drivers/spi/spi-rockchip-sfc.c
drivers/spi/spi.c
drivers/tee/amdtee/core.c
drivers/tee/optee/Kconfig
drivers/tee/optee/call.c
drivers/tee/optee/optee_msg.h
drivers/tee/optee/optee_private.h
drivers/tee/optee/optee_smc.h
drivers/tee/optee/smc_abi.c
drivers/tee/tee_shm.c
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
drivers/thermal/intel/intel_powerclamp.c
drivers/thermal/intel/therm_throt.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_core.h
drivers/thermal/thermal_sysfs.c
drivers/thunderbolt/debugfs.c
drivers/thunderbolt/nhi.c
drivers/thunderbolt/nhi_regs.h
drivers/thunderbolt/quirks.c
drivers/thunderbolt/retimer.c
drivers/thunderbolt/sb_regs.h
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/usb4.c
drivers/tty/hvc/hvc_xen.c
drivers/tty/serdev/core.c
drivers/tty/serial/8250/8250_em.c
drivers/tty/serial/8250/8250_fsl.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/Kconfig
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/sh-sci.c
drivers/tty/vt/vt.c
drivers/ufs/core/ufshcd.c
drivers/usb/cdns3/cdns3-pci-wrap.c
drivers/usb/cdns3/cdnsp-ep0.c
drivers/usb/cdns3/cdnsp-pci.c
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/core.c
drivers/usb/chipidea/otg.c
drivers/usb/dwc2/drd.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_audio.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-tegra.c
drivers/usb/host/xhci.c
drivers/usb/misc/onboard_usb_hub.c
drivers/usb/misc/onboard_usb_hub.h
drivers/usb/serial/cp210x.c
drivers/usb/serial/option.c
drivers/usb/storage/unusual_uas.h
drivers/usb/typec/altmodes/displayport.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/usb/typec/ucsi/ucsi_acpi.c
drivers/vdpa/mlx5/core/mlx5_vdpa.h
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vdpa/vdpa_sim/vdpa_sim_net.c
drivers/vdpa/virtio_pci/vp_vdpa.c
drivers/vfio/pci/mlx5/main.c
drivers/vhost/Kconfig
drivers/vhost/scsi.c
drivers/vhost/vdpa.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/fbdev/amba-clcd.c
drivers/video/fbdev/au1200fb.c
drivers/video/fbdev/bw2.c
drivers/video/fbdev/cg3.c
drivers/video/fbdev/chipsfb.c
drivers/video/fbdev/clps711x-fb.c
drivers/video/fbdev/core/fb_defio.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/geode/lxfb_core.c
drivers/video/fbdev/intelfb/intelfbdrv.c
drivers/video/fbdev/nvidia/nvidia.c
drivers/video/fbdev/offb.c
drivers/video/fbdev/omap/Makefile
drivers/video/fbdev/omap/lcd_osk.c [deleted file]
drivers/video/fbdev/omap/omapfb_main.c
drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c
drivers/video/fbdev/pxa3xx-gcu.c
drivers/video/fbdev/sm501fb.c
drivers/video/fbdev/stifb.c
drivers/video/fbdev/tcx.c
drivers/video/fbdev/tgafb.c
drivers/video/fbdev/wm8505fb.c
drivers/video/fbdev/xilinxfb.c
drivers/video/logo/pnmtologo.c
drivers/virt/coco/sev-guest/sev-guest.c
drivers/xen/xenfs/xensyms.c
fs/9p/xattr.c
fs/attr.c
fs/btrfs/backref.c
fs/btrfs/block-group.c
fs/btrfs/discard.c
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/fs.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/space-info.c
fs/btrfs/space-info.h
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/btrfs/zoned.c
fs/buffer.c
fs/ceph/xattr.c
fs/cifs/cached_dir.c
fs/cifs/cifs_debug.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dfs.c
fs/cifs/dfs.h
fs/cifs/dfs_cache.c
fs/cifs/dfs_cache.h
fs/cifs/file.c
fs/cifs/fs_context.c
fs/cifs/fs_context.h
fs/cifs/link.c
fs/cifs/misc.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2transport.c
fs/cifs/trace.h
fs/cifs/transport.c
fs/cifs/xattr.c
fs/configfs/dir.c
fs/crypto/keyring.c
fs/dax.c
fs/devpts/inode.c
fs/direct-io.c
fs/ecryptfs/inode.c
fs/erofs/data.c
fs/erofs/decompressor.c
fs/erofs/decompressor_lzma.c
fs/erofs/dir.c
fs/erofs/erofs_fs.h
fs/erofs/fscache.c
fs/erofs/inode.c
fs/erofs/internal.h
fs/erofs/namei.c
fs/erofs/super.c
fs/erofs/xattr.c
fs/erofs/xattr.h
fs/erofs/zdata.c
fs/erofs/zmap.c
fs/eventfd.c
fs/eventpoll.c
fs/ext2/xattr.c
fs/ext4/namei.c
fs/ext4/super.c
fs/ext4/xattr.c
fs/f2fs/xattr.c
fs/fs-writeback.c
fs/fuse/dev.c
fs/fuse/file.c
fs/gfs2/dentry.c
fs/gfs2/xattr.c
fs/hfsplus/inode.c
fs/inode.c
fs/internal.h
fs/jffs2/xattr.c
fs/jfs/jfs_metapage.c
fs/jfs/xattr.c
fs/kernfs/dir.c
fs/ksmbd/auth.c
fs/ksmbd/connection.c
fs/ksmbd/connection.h
fs/ksmbd/ksmbd_work.h
fs/ksmbd/server.c
fs/ksmbd/smb2pdu.c
fs/ksmbd/smb2pdu.h
fs/ksmbd/smb_common.c
fs/ksmbd/smb_common.h
fs/ksmbd/transport_rdma.c
fs/ksmbd/transport_tcp.c
fs/ksmbd/unicode.c
fs/libfs.c
fs/lockd/clnt4xdr.c
fs/lockd/xdr4.c
fs/namei.c
fs/namespace.c
fs/netfs/iterator.c
fs/nfs/Kconfig
fs/nfs/dir.c
fs/nfs/inode.c
fs/nfs/nfs3_fs.h
fs/nfs/nfs3acl.c
fs/nfs/nfs3super.c
fs/nfs/nfs4proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfsd/Kconfig
fs/nfsd/blocklayout.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4xdr.c
fs/nfsd/vfs.c
fs/nilfs2/btree.c
fs/nilfs2/direct.c
fs/nilfs2/ioctl.c
fs/nilfs2/segment.c
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.c
fs/notify/fanotify/fanotify_user.c
fs/nsfs.c
fs/ntfs3/xattr.c
fs/ocfs2/aops.c
fs/ocfs2/namei.c
fs/ocfs2/refcounttree.c
fs/ocfs2/xattr.c
fs/open.c
fs/orangefs/xattr.c
fs/overlayfs/copy_up.c
fs/overlayfs/super.c
fs/pnode.c
fs/posix_acl.c
fs/qnx4/README [deleted file]
fs/qnx6/README [deleted file]
fs/read_write.c
fs/reiserfs/file.c
fs/reiserfs/inode.c
fs/reiserfs/namei.c
fs/reiserfs/reiserfs.h
fs/reiserfs/xattr.c
fs/reiserfs/xattr_security.c
fs/splice.c
fs/super.c
fs/sysv/dir.c
fs/sysv/namei.c
fs/sysv/sysv.h
fs/ufs/dir.c
fs/userfaultfd.c
fs/verity/enable.c
fs/verity/verify.c
fs/xattr.c
fs/xfs/Makefile
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/xfs_dahash_test.c [new file with mode: 0644]
fs/xfs/xfs_dahash_test.h [new file with mode: 0644]
fs/xfs/xfs_iomap.c
fs/xfs/xfs_super.c
fs/xfs/xfs_trace.h
fs/xfs/xfs_xattr.c
fs/zonefs/file.c
include/acpi/acpi_bus.h
include/acpi/actypes.h
include/acpi/video.h
include/asm-generic/atomic.h
include/asm-generic/cmpxchg-local.h
include/asm-generic/cmpxchg.h
include/asm-generic/io.h
include/asm-generic/mshyperv.h
include/crypto/public_key.h
include/drm/drm_bridge.h
include/drm/drm_gem.h
include/drm/gpu_scheduler.h
include/dt-bindings/arm/qcom,ids.h
include/dt-bindings/power/r8a7795-sysc.h
include/kunit/resource.h
include/kunit/test.h
include/kvm/arm_arch_timer.h
include/linux/acpi_mdio.h
include/linux/arm-smccc.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/clk-provider.h
include/linux/context_tracking.h
include/linux/context_tracking_state.h
include/linux/cpuhotplug.h
include/linux/cpumask.h
include/linux/efi.h
include/linux/fb.h
include/linux/find.h
include/linux/firmware/qcom/qcom_scm.h
include/linux/fs.h
include/linux/fs_context.h
include/linux/ftrace.h
include/linux/instrumented.h
include/linux/interconnect-provider.h
include/linux/io_uring.h
include/linux/irqchip/arm-gic.h
include/linux/kmsan.h
include/linux/kvm_host.h
include/linux/kvm_irqfd.h
include/linux/lockd/xdr4.h
include/linux/lockdep.h
include/linux/lsm_hook_defs.h
include/linux/lsm_hooks.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mm_types.h
include/linux/netdevice.h
include/linux/notifier.h
include/linux/nvme-tcp.h
include/linux/nvme.h
include/linux/of_mdio.h
include/linux/pagemap.h
include/linux/pci-doe.h
include/linux/pci.h
include/linux/percpu_counter.h
include/linux/phy.h
include/linux/phylink.h
include/linux/pid.h
include/linux/posix-timers.h
include/linux/posix_acl.h
include/linux/posix_acl_xattr.h
include/linux/proc_ns.h
include/linux/rtnetlink.h
include/linux/sched.h
include/linux/sched/task.h
include/linux/sched/vhost_task.h [new file with mode: 0644]
include/linux/security.h
include/linux/sfp.h
include/linux/skbuff.h
include/linux/soc/mediatek/mtk-cmdq.h
include/linux/soc/mediatek/mtk-mmsys.h
include/linux/soc/mediatek/mtk-mutex.h
include/linux/soc/qcom/geni-se.h
include/linux/soc/qcom/llcc-qcom.h
include/linux/srcu.h
include/linux/srcutiny.h
include/linux/srcutree.h
include/linux/stmmac.h
include/linux/syscall_user_dispatch.h
include/linux/sysfb.h
include/linux/thermal.h
include/linux/tick.h
include/linux/tracepoint.h
include/linux/uio.h
include/linux/xattr.h
include/net/bluetooth/hci_core.h
include/net/bonding.h
include/net/netfilter/nf_tables.h
include/net/raw.h
include/net/xdp.h
include/scsi/scsi_device.h
include/scsi/scsi_devinfo.h
include/soc/qcom/ice.h [new file with mode: 0644]
include/trace/events/erofs.h
include/trace/events/f2fs.h
include/trace/events/irq.h
include/trace/events/mmap.h
include/trace/events/rcu.h
include/trace/events/timer.h
include/trace/stages/stage5_get_offsets.h
include/uapi/asm-generic/fcntl.h
include/uapi/linux/fou.h
include/uapi/linux/landlock.h
include/uapi/linux/netdev.h
include/uapi/linux/psp-sev.h
include/uapi/linux/ptrace.h
include/uapi/linux/rtnetlink.h
include/uapi/linux/sev-guest.h
include/uapi/linux/virtio_blk.h
include/ufs/ufshcd.h
include/xen/interface/platform.h
init/Kconfig
init/initramfs.c
init/main.c
io_uring/alloc_cache.h
io_uring/filetable.c
io_uring/io_uring.c
io_uring/kbuf.c
io_uring/msg_ring.c
io_uring/net.c
io_uring/poll.c
io_uring/rsrc.c
io_uring/rsrc.h
io_uring/rw.c
io_uring/sqpoll.c
io_uring/uring_cmd.c
kernel/Makefile
kernel/bpf/bpf_inode_storage.c
kernel/bpf/core.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/cgroup/cpuset.c
kernel/cgroup/legacy_freezer.c
kernel/cgroup/rstat.c
kernel/compat.c
kernel/dma/swiotlb.c
kernel/entry/common.c
kernel/entry/syscall_user_dispatch.c
kernel/events/core.c
kernel/fork.c
kernel/irq/manage.c
kernel/kcsan/Makefile
kernel/kcsan/core.c
kernel/kthread.c
kernel/locking/lockdep.c
kernel/locking/locktorture.c
kernel/locking/test-ww_mutex.c
kernel/nsproxy.c
kernel/pid.c
kernel/ptrace.c
kernel/rcu/Kconfig
kernel/rcu/rcu.h
kernel/rcu/rcuscale.c
kernel/rcu/rcutorture.c
kernel/rcu/refscale.c
kernel/rcu/srcutiny.c
kernel/rcu/srcutree.c
kernel/rcu/tasks.h
kernel/rcu/tree.c
kernel/rcu/tree_exp.h
kernel/rcu/tree_nocb.h
kernel/sched/core.c
kernel/sched/fair.c
kernel/signal.c
kernel/softirq.c
kernel/sys.c
kernel/time/posix-cpu-timers.c
kernel/time/posix-timers.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/time/tick-sched.h
kernel/trace/ftrace.c
kernel/trace/kprobe_event_gen_test.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_synth.c
kernel/trace/trace_hwlat.c
kernel/trace/trace_osnoise.c
kernel/trace/trace_probe.c
kernel/vhost_task.c [new file with mode: 0644]
lib/Kconfig.debug
lib/debugobjects.c
lib/dhry_run.c
lib/find_bit.c
lib/iov_iter.c
lib/kunit/debugfs.c
lib/kunit/kunit-test.c
lib/kunit/test.c
lib/list-test.c
lib/maple_tree.c
lib/percpu_counter.c
lib/test_maple_tree.c
lib/test_vmalloc.c
lib/vdso/Makefile
lib/zstd/common/zstd_deps.h
lib/zstd/decompress/huf_decompress.c
lib/zstd/decompress/zstd_decompress.c
mm/Kconfig
mm/backing-dev.c
mm/damon/paddr.c
mm/huge_memory.c
mm/hugetlb.c
mm/kfence/Makefile
mm/kfence/core.c
mm/khugepaged.c
mm/kmsan/hooks.c
mm/kmsan/shadow.c
mm/ksm.c
mm/madvise.c
mm/memory.c
mm/mempolicy.c
mm/migrate.c
mm/mincore.c
mm/mmap.c
mm/mprotect.c
mm/page-writeback.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/swap.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
net/9p/trans_xen.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/hidp/core.c
net/bluetooth/iso.c
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c
net/bluetooth/sco.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_switchdev.c
net/can/bcm.c
net/can/isotp.c
net/can/j1939/transport.c
net/core/dev.c
net/core/net_namespace.c
net/core/netdev-genl-gen.c
net/core/netdev-genl-gen.h
net/core/netpoll.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sysctl_net_core.c
net/core/xdp.c
net/dsa/slave.c
net/dsa/tag.c
net/dsa/tag_brcm.c
net/ethtool/linkmodes.c
net/hsr/hsr_framereg.c
net/ieee802154/nl802154.c
net/ipv4/fib_frontend.c
net/ipv4/fou_nl.c
net/ipv4/fou_nl.h
net/ipv4/icmp.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel.c
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/raw_diag.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/raw.c
net/ipv6/rpl.c
net/ipv6/udp.c
net/iucv/iucv.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/util.c
net/mac80211/wme.c
net/mac802154/scan.c
net/mptcp/fastopen.c
net/mptcp/options.c
net/mptcp/pm_netlink.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/subflow.c
net/ncsi/ncsi-manage.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_lookup.c
net/netfilter/nft_masq.c
net/netfilter/nft_nat.c
net/netfilter/nft_redir.c
net/netlink/af_netlink.c
net/openvswitch/actions.c
net/qrtr/af_qrtr.c
net/qrtr/ns.c
net/sched/act_api.c
net/sched/cls_api.c
net/sched/sch_qfq.c
net/sctp/socket.c
net/sctp/stream_interleave.c
net/smc/af_smc.c
net/smc/smc_cdc.c
net/smc/smc_core.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_test.c
net/sunrpc/svcauth_unix.c
net/sunrpc/xprtsock.c
net/vmw_vsock/virtio_transport_common.c
net/vmw_vsock/vmci_transport.c
net/vmw_vsock/vsock_loopback.c
net/wireless/nl80211.c
net/xdp/xdp_umem.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
rust/Makefile
rust/kernel/print.rs
rust/kernel/str.rs
scripts/.gitignore
scripts/Makefile
scripts/Makefile.package
scripts/asn1_compiler.c
scripts/cc-version.sh
scripts/check-git [new file with mode: 0755]
scripts/checkpatch.pl
scripts/checksyscalls.sh
scripts/generate_rust_analyzer.py
scripts/is_rust_module.sh
scripts/kallsyms.c
scripts/kconfig/confdata.c
scripts/kconfig/merge_config.sh
scripts/list-gitignored.c [deleted file]
scripts/mod/modpost.c
scripts/package/builddeb
scripts/package/deb-build-option
scripts/package/gen-diff-patch [new file with mode: 0755]
scripts/package/mkdebian
scripts/package/mkspec
scripts/setlocalversion
security/Kconfig
security/apparmor/lsm.c
security/bpf/hooks.c
security/commoncap.c
security/device_cgroup.c
security/integrity/Kconfig
security/integrity/digsig.c
security/integrity/iint.c
security/keys/request_key.c
security/landlock/cred.c
security/landlock/fs.c
security/landlock/ptrace.c
security/landlock/setup.c
security/loadpin/loadpin.c
security/lockdown/lockdown.c
security/security.c
security/selinux/Kconfig
security/selinux/Makefile
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/ibpkey.c
security/selinux/ima.c
security/selinux/include/avc.h
security/selinux/include/avc_ss.h
security/selinux/include/conditional.h
security/selinux/include/ima.h
security/selinux/include/security.h
security/selinux/netif.c
security/selinux/netlabel.c
security/selinux/netnode.c
security/selinux/netport.c
security/selinux/selinuxfs.c
security/selinux/ss/services.c
security/selinux/ss/services.h
security/selinux/status.c
security/selinux/xfrm.c
security/smack/smack_lsm.c
security/tomoyo/audit.c
security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/tomoyo.c
security/yama/yama_lsm.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/firewire/tascam/tascam-stream.c
sound/hda/intel-dsp-config.c
sound/i2c/cs8427.c
sound/pci/asihpi/hpi6205.c
sound/pci/emu10k1/emupcm.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/soc/amd/yc/acp6x-mach.c
sound/soc/codecs/da7213.c
sound/soc/codecs/da7219-aad.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/lpass-rx-macro.c
sound/soc/codecs/lpass-tx-macro.c
sound/soc/codecs/lpass-wsa-macro.c
sound/soc/codecs/max98373.c
sound/soc/fsl/Kconfig
sound/soc/fsl/fsl_asrc_dma.c
sound/soc/fsl/fsl_sai.c
sound/soc/intel/avs/boards/da7219.c
sound/soc/intel/avs/boards/max98357a.c
sound/soc/intel/avs/boards/nau8825.c
sound/soc/intel/avs/boards/rt5682.c
sound/soc/intel/avs/boards/ssm4567.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/intel/boards/sof_sdw.c
sound/soc/intel/common/soc-acpi-intel-adl-match.c
sound/soc/qcom/qdsp6/q6prm.c
sound/soc/soc-pcm.c
sound/soc/sof/intel/hda-ctrl.c
sound/soc/sof/intel/hda-dsp.c
sound/soc/sof/intel/pci-apl.c
sound/soc/sof/intel/pci-cnl.c
sound/soc/sof/intel/pci-icl.c
sound/soc/sof/intel/pci-mtl.c
sound/soc/sof/intel/pci-skl.c
sound/soc/sof/intel/pci-tgl.c
sound/soc/sof/intel/pci-tng.c
sound/soc/sof/ipc3-topology.c
sound/soc/sof/ipc3.c
sound/soc/sof/ipc4-control.c
sound/soc/sof/ipc4-topology.c
sound/soc/sof/ipc4-topology.h
sound/soc/sof/ipc4.c
sound/soc/sof/pm.c
sound/soc/sof/sof-audio.c
sound/soc/sof/topology.c
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/format.c
sound/usb/pcm.c
tools/Makefile
tools/arch/loongarch/include/uapi/asm/bitsperlong.h
tools/arch/x86/kcpuid/cpuid.csv
tools/arch/x86/kcpuid/kcpuid.c
tools/bootconfig/test-bootconfig.sh
tools/include/linux/err.h
tools/include/nolibc/.gitignore [new file with mode: 0644]
tools/include/nolibc/Makefile
tools/include/nolibc/arch-i386.h
tools/include/nolibc/arch-loongarch.h [new file with mode: 0644]
tools/include/nolibc/arch-x86_64.h
tools/include/nolibc/arch.h
tools/include/nolibc/nolibc.h
tools/include/nolibc/stackprotector.h [new file with mode: 0644]
tools/include/nolibc/std.h
tools/include/nolibc/stdint.h [new file with mode: 0644]
tools/include/nolibc/stdio.h
tools/include/nolibc/sys.h
tools/include/nolibc/types.h
tools/include/nolibc/unistd.h
tools/include/uapi/asm-generic/fcntl.h
tools/include/uapi/linux/netdev.h
tools/lib/bpf/libbpf_internal.h
tools/memory-model/Documentation/explanation.txt
tools/memory-model/Documentation/litmus-tests.txt
tools/memory-model/Documentation/locking.txt [new file with mode: 0644]
tools/memory-model/linux-kernel.bell
tools/memory-model/linux-kernel.cat
tools/memory-model/linux-kernel.def
tools/memory-model/litmus-tests/.gitignore
tools/memory-model/lock.cat
tools/memory-model/scripts/README
tools/memory-model/scripts/checkalllitmus.sh
tools/memory-model/scripts/checkghlitmus.sh
tools/memory-model/scripts/checklitmus.sh
tools/memory-model/scripts/checklitmushist.sh
tools/memory-model/scripts/checktheselitmus.sh [new file with mode: 0755]
tools/memory-model/scripts/cmplitmushist.sh
tools/memory-model/scripts/hwfnseg.sh [new file with mode: 0755]
tools/memory-model/scripts/initlitmushist.sh
tools/memory-model/scripts/judgelitmus.sh
tools/memory-model/scripts/newlitmushist.sh
tools/memory-model/scripts/parseargs.sh
tools/memory-model/scripts/runlitmus.sh [new file with mode: 0755]
tools/memory-model/scripts/runlitmushist.sh
tools/memory-model/scripts/simpletest.sh [new file with mode: 0755]
tools/mm/page_owner_sort.c
tools/net/ynl/lib/nlspec.py
tools/net/ynl/lib/ynl.py
tools/net/ynl/ynl-gen-c.py
tools/objtool/Documentation/objtool.txt
tools/objtool/check.c
tools/power/acpi/tools/pfrut/pfrut.c
tools/power/pm-graph/sleepgraph.py
tools/power/x86/turbostat/turbostat.8
tools/power/x86/turbostat/turbostat.c
tools/rcu/extract-stall.sh [changed mode: 0644->0755]
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_config.py
tools/testing/kunit/kunit_kernel.py
tools/testing/kunit/kunit_parser.py
tools/testing/kunit/kunit_printer.py
tools/testing/kunit/kunit_tool_test.py
tools/testing/kunit/qemu_config.py
tools/testing/kunit/qemu_configs/m68k.py [new file with mode: 0644]
tools/testing/kunit/qemu_configs/sh.py [new file with mode: 0644]
tools/testing/kunit/run_checks.py
tools/testing/radix-tree/maple.c
tools/testing/selftests/Makefile
tools/testing/selftests/amd-pstate/Makefile
tools/testing/selftests/amd-pstate/gitsource.sh
tools/testing/selftests/amd-pstate/run.sh
tools/testing/selftests/arm64/fp/Makefile
tools/testing/selftests/arm64/fp/za-fork.c
tools/testing/selftests/bpf/prog_tests/uninit_stack.c [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
tools/testing/selftests/bpf/progs/find_vma_fail1.c
tools/testing/selftests/bpf/progs/test_deny_namespace.c
tools/testing/selftests/bpf/progs/test_global_func10.c
tools/testing/selftests/bpf/progs/uninit_stack.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/xdp_hw_metadata.c
tools/testing/selftests/bpf/progs/xdp_metadata.c
tools/testing/selftests/bpf/progs/xdp_metadata2.c
tools/testing/selftests/bpf/verifier/calls.c
tools/testing/selftests/bpf/verifier/helper_access_var_len.c
tools/testing/selftests/bpf/verifier/int_ptr.c
tools/testing/selftests/bpf/verifier/search_pruning.c
tools/testing/selftests/bpf/verifier/sock.c
tools/testing/selftests/bpf/verifier/spill_fill.c
tools/testing/selftests/bpf/verifier/var_off.c
tools/testing/selftests/bpf/xdp_hw_metadata.c
tools/testing/selftests/bpf/xdp_metadata.h
tools/testing/selftests/cgroup/test_memcontrol.c
tools/testing/selftests/clone3/clone3.c
tools/testing/selftests/drivers/net/bonding/Makefile
tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/bonding/bond_options.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh [new file with mode: 0644]
tools/testing/selftests/drivers/net/bonding/option_prio.sh [deleted file]
tools/testing/selftests/kselftest.h
tools/testing/selftests/kvm/aarch64/psci_test.c
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/s390x/diag318_test_handler.c
tools/testing/selftests/kvm/lib/test_util.c
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/s390x/sync_regs_test.c
tools/testing/selftests/kvm/set_memory_region_test.c
tools/testing/selftests/kvm/x86_64/amx_test.c
tools/testing/selftests/kvm/x86_64/cr4_cpuid_sync_test.c
tools/testing/selftests/kvm/x86_64/debug_regs.c
tools/testing/selftests/kvm/x86_64/flds_emulation.h
tools/testing/selftests/kvm/x86_64/hyperv_clock.c
tools/testing/selftests/kvm/x86_64/hyperv_evmcs.c
tools/testing/selftests/kvm/x86_64/hyperv_features.c
tools/testing/selftests/kvm/x86_64/hyperv_ipi.c
tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c
tools/testing/selftests/kvm/x86_64/hyperv_tlb_flush.c
tools/testing/selftests/kvm/x86_64/kvm_clock_test.c
tools/testing/selftests/kvm/x86_64/kvm_pv_test.c
tools/testing/selftests/kvm/x86_64/monitor_mwait_test.c
tools/testing/selftests/kvm/x86_64/nested_exceptions_test.c
tools/testing/selftests/kvm/x86_64/platform_info_test.c
tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
tools/testing/selftests/kvm/x86_64/smm_test.c
tools/testing/selftests/kvm/x86_64/state_test.c
tools/testing/selftests/kvm/x86_64/svm_int_ctl_test.c
tools/testing/selftests/kvm/x86_64/svm_nested_shutdown_test.c
tools/testing/selftests/kvm/x86_64/svm_nested_soft_inject_test.c
tools/testing/selftests/kvm/x86_64/svm_vmcall_test.c
tools/testing/selftests/kvm/x86_64/sync_regs_test.c
tools/testing/selftests/kvm/x86_64/triple_fault_event_test.c
tools/testing/selftests/kvm/x86_64/tsc_scaling_sync.c
tools/testing/selftests/kvm/x86_64/ucna_injection_test.c
tools/testing/selftests/kvm/x86_64/userspace_io_test.c
tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c
tools/testing/selftests/kvm/x86_64/vmx_apic_access_test.c
tools/testing/selftests/kvm/x86_64/vmx_close_while_nested_test.c
tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c
tools/testing/selftests/kvm/x86_64/vmx_exception_with_invalid_guest_state.c
tools/testing/selftests/kvm/x86_64/vmx_invalid_nested_guest_state.c
tools/testing/selftests/kvm/x86_64/vmx_nested_tsc_scaling_test.c
tools/testing/selftests/kvm/x86_64/vmx_preemption_timer_test.c
tools/testing/selftests/kvm/x86_64/vmx_tsc_adjust_test.c
tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c
tools/testing/selftests/kvm/x86_64/xen_shinfo_test.c
tools/testing/selftests/kvm/x86_64/xen_vmcall_test.c
tools/testing/selftests/lib.mk
tools/testing/selftests/mm/mdwe_test.c
tools/testing/selftests/mount_setattr/mount_setattr_test.c
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/bind_wildcard.c [new file with mode: 0644]
tools/testing/selftests/net/config
tools/testing/selftests/net/devlink_port_split.py
tools/testing/selftests/net/mptcp/userspace_pm.sh
tools/testing/selftests/net/openvswitch/ovs-dpctl.py
tools/testing/selftests/net/rps_default_mask.sh
tools/testing/selftests/nolibc/Makefile
tools/testing/selftests/nolibc/nolibc-test.c
tools/testing/selftests/prctl/.gitignore
tools/testing/selftests/prctl/Makefile
tools/testing/selftests/prctl/config [new file with mode: 0644]
tools/testing/selftests/prctl/set-anon-vma-name-test.c [new file with mode: 0644]
tools/testing/selftests/proc/proc-uptime-001.c
tools/testing/selftests/proc/proc-uptime-002.c
tools/testing/selftests/proc/proc-uptime.h
tools/testing/selftests/ptrace/.gitignore
tools/testing/selftests/ptrace/Makefile
tools/testing/selftests/ptrace/get_set_sud.c [new file with mode: 0644]
tools/testing/selftests/ptrace/peeksiginfo.c
tools/testing/selftests/rcutorture/bin/kvm-again.sh
tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh [new file with mode: 0755]
tools/testing/selftests/rcutorture/bin/torture.sh
tools/testing/selftests/rcutorture/configs/lock/CFLIST
tools/testing/selftests/rcutorture/configs/lock/LOCK08 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/LOCK09 [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot [new file with mode: 0644]
tools/testing/selftests/rcutorture/configs/rcu/TREE01
tools/testing/selftests/rcutorture/configs/rcu/TREE04
tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
tools/testing/selftests/resctrl/cache.c
tools/testing/selftests/resctrl/cat_test.c
tools/testing/selftests/resctrl/cmt_test.c
tools/testing/selftests/resctrl/fill_buf.c
tools/testing/selftests/resctrl/mba_test.c
tools/testing/selftests/resctrl/mbm_test.c
tools/testing/selftests/resctrl/resctrl.h
tools/testing/selftests/resctrl/resctrl_tests.c
tools/testing/selftests/resctrl/resctrl_val.c
tools/testing/selftests/resctrl/resctrlfs.c
tools/testing/selftests/sched/cs_prctl_test.c
tools/testing/selftests/sigaltstack/current_stack_pointer.h [new file with mode: 0644]
tools/testing/selftests/sigaltstack/sas.c
tools/testing/selftests/timers/posix_timers.c
tools/testing/selftests/x86/amx.c
tools/testing/vsock/vsock_test.c
tools/virtio/.gitignore
tools/virtio/virtio-trace/README
usr/gen_init_cpio.c
virt/kvm/eventfd.c
virt/kvm/kvm_main.c

index 8fe465f251c0368f7d66ba687aa4c5cbbfaf1b76..7f86e0837909446b5a619b0c4aa6175af13451e9 100644 (file)
@@ -78,6 +78,7 @@ modules.order
 # RPM spec file (make rpm-pkg)
 #
 /*.spec
+/rpmbuild/
 
 #
 # Debian directory (make deb-pkg)
@@ -102,6 +103,7 @@ modules.order
 !.get_maintainer.ignore
 !.gitattributes
 !.gitignore
+!.kunitconfig
 !.mailmap
 !.rustfmt.toml
 
index 424564f40733ade9bbf057a3840b45e4418e3ae5..6686879ce0d5db65f5341df07e6a77538df15566 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -28,6 +28,7 @@ Alexander Lobakin <alobakin@pm.me> <bloodyreaper@yandex.ru>
 Alexander Mikhalitsyn <alexander@mihalicyn.com> <alexander.mikhalitsyn@virtuozzo.com>
 Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@canonical.com>
 Alexandre Belloni <alexandre.belloni@bootlin.com> <alexandre.belloni@free-electrons.com>
+Alexandre Ghiti <alex@ghiti.fr> <alexandre.ghiti@canonical.com>
 Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
 Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
 Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
@@ -121,7 +122,7 @@ Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@mips.com>
 <dev.kurt@vandijck-laurijssen.be> <kurt.van.dijck@eia.be>
-Dikshita Agarwal <dikshita@qti.qualcomm.com> <dikshita@codeaurora.org>
+Dikshita Agarwal <quic_dikshita@quicinc.com> <dikshita@codeaurora.org>
 Dmitry Baryshkov <dbaryshkov@gmail.com>
 Dmitry Baryshkov <dbaryshkov@gmail.com> <[dbaryshkov@gmail.com]>
 Dmitry Baryshkov <dbaryshkov@gmail.com> <dmitry_baryshkov@mentor.com>
@@ -132,6 +133,8 @@ Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
 Domen Puncer <domen@coderock.org>
 Douglas Gilbert <dougg@torque.net>
 Ed L. Cashin <ecashin@coraid.com>
+Enric Balletbo i Serra <eballetbo@kernel.org> <enric.balletbo@collabora.com>
+Enric Balletbo i Serra <eballetbo@kernel.org> <eballetbo@iseebcn.com>
 Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com>
 Eugen Hristev <eugen.hristev@collabora.com> <eugen.hristev@microchip.com>
 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
@@ -194,6 +197,7 @@ Jan Glauber <jan.glauber@gmail.com> <jang@linux.vnet.ibm.com>
 Jan Glauber <jan.glauber@gmail.com> <jglauber@cavium.com>
 Jarkko Sakkinen <jarkko@kernel.org> <jarkko.sakkinen@linux.intel.com>
 Jarkko Sakkinen <jarkko@kernel.org> <jarkko@profian.com>
+Jarkko Sakkinen <jarkko@kernel.org> <jarkko.sakkinen@tuni.fi>
 Jason Gunthorpe <jgg@ziepe.ca> <jgg@mellanox.com>
 Jason Gunthorpe <jgg@ziepe.ca> <jgg@nvidia.com>
 Jason Gunthorpe <jgg@ziepe.ca> <jgunthorpe@obsidianresearch.com>
@@ -213,6 +217,9 @@ Jens Axboe <axboe@suse.de>
 Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
 Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
 Jessica Zhang <quic_jesszhan@quicinc.com> <jesszhan@codeaurora.org>
+Jiri Pirko <jiri@resnulli.us> <jiri@nvidia.com>
+Jiri Pirko <jiri@resnulli.us> <jiri@mellanox.com>
+Jiri Pirko <jiri@resnulli.us> <jpirko@redhat.com>
 Jiri Slaby <jirislaby@kernel.org> <jirislaby@gmail.com>
 Jiri Slaby <jirislaby@kernel.org> <jslaby@novell.com>
 Jiri Slaby <jirislaby@kernel.org> <jslaby@suse.com>
@@ -225,6 +232,8 @@ Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
 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>
@@ -258,7 +267,9 @@ Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com>
 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>
@@ -288,6 +299,8 @@ Martin Kepplinger <martink@posteo.de> <martin.kepplinger@puri.sm>
 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>
@@ -374,6 +387,7 @@ Quentin Monnet <quentin@isovalent.com> <quentin.monnet@netronome.com>
 Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
 Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
 Rajeev Nandan <quic_rajeevny@quicinc.com> <rajeevny@codeaurora.org>
+Rajendra Nayak <quic_rjendra@quicinc.com> <rnayak@codeaurora.org>
 Rajesh Shah <rajesh.shah@intel.com>
 Ralf Baechle <ralf@linux-mips.org>
 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
@@ -382,6 +396,9 @@ Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
 Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
+Richard Leitner <richard.leitner@linux.dev> <dev@g0hl1n.net>
+Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
+Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
 Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
 Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
 Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
@@ -392,6 +409,7 @@ Ross Zwisler <zwisler@kernel.org> <ross.zwisler@linux.intel.com>
 Rudolf Marek <R.Marek@sh.cvut.cz>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Sachin P Sant <ssant@in.ibm.com>
+Sai Prakash Ranjan <quic_saipraka@quicinc.com> <saiprakash.ranjan@codeaurora.org>
 Sakari Ailus <sakari.ailus@linux.intel.com> <sakari.ailus@iki.fi>
 Sam Ravnborg <sam@mars.ravnborg.org>
 Sankeerth Billakanti <quic_sbillaka@quicinc.com> <sbillaka@codeaurora.org>
@@ -432,6 +450,10 @@ Thomas Graf <tgraf@suug.ch>
 Thomas Körper <socketcan@esd.eu> <thomas.koerper@esd.eu>
 Thomas Pedersen <twp@codeaurora.org>
 Tiezhu Yang <yangtiezhu@loongson.cn> <kernelpatch@126.com>
+Tobias Klauser <tklauser@distanz.ch> <tobias.klauser@gmail.com>
+Tobias Klauser <tklauser@distanz.ch> <klto@zhaw.ch>
+Tobias Klauser <tklauser@distanz.ch> <tklauser@nuerscht.ch>
+Tobias Klauser <tklauser@distanz.ch> <tklauser@xenon.tklauser.home>
 Todor Tomov <todor.too@gmail.com> <todor.tomov@linaro.org>
 Tony Luck <tony.luck@intel.com>
 TripleX Chung <xxx.phy@gmail.com> <triplex@zh-kernel.org>
diff --git a/CREDITS b/CREDITS
index 847059166a1528e86fb52e7b28744b1fdf50ef7b..b6c93e0a62c31b9bf396944b164e6b899eb228be 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -229,6 +229,10 @@ S: University of Notre Dame
 S: Notre Dame, Indiana
 S: USA
 
+N: Kai Bankett
+E: chaosman@ontika.net
+D: QNX6 filesystem
+
 N: Greg Banks
 E: gnb@alphalink.com.au
 D: IDT77105 ATM network driver
@@ -886,6 +890,10 @@ W: http://jdelvare.nerim.net/
 D: Several hardware monitoring drivers
 S: France
 
+N: Frank "Jedi/Sector One" Denis
+E: j@pureftpd.org
+D: QNX4 filesystem
+
 N: Peter Denison
 E: peterd@pnd-pc.demon.co.uk
 W: http://www.pnd-pc.demon.co.uk/promise/
@@ -1259,6 +1267,10 @@ S: USA
 N: Adam Fritzler
 E: mid@zigamorph.net
 
+N: Richard "Scuba" A. Frowijn
+E: scuba@wxs.nl
+D: QNX4 filesystem
+
 N: Fernando Fuganti
 E: fuganti@conectiva.com.br
 E: fuganti@netbank.com.br
@@ -2218,6 +2230,10 @@ D: Digiboard PC/Xe and PC/Xi, Digiboard EPCA
 D: NUMA support, Slab allocators, Page migration
 D: Scalability, Time subsystem
 
+N: Anders Larsen
+E: al@alarsen.net
+D: QNX4 filesystem
+
 N: Paul Laufer
 E: paul@laufernet.com
 D: Soundblaster driver fixes, ISAPnP quirk
diff --git a/Documentation/ABI/obsolete/sysfs-selinux-checkreqprot b/Documentation/ABI/obsolete/sysfs-selinux-checkreqprot
deleted file mode 100644 (file)
index ed6b52c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-What:          /sys/fs/selinux/checkreqprot
-Date:          April 2005 (predates git)
-KernelVersion: 2.6.12-rc2 (predates git)
-Contact:       selinux@vger.kernel.org
-Description:
-
-       The selinuxfs "checkreqprot" node allows SELinux to be configured
-       to check the protection requested by userspace for mmap/mprotect
-       calls instead of the actual protection applied by the kernel.
-       This was a compatibility mechanism for legacy userspace and
-       for the READ_IMPLIES_EXEC personality flag.  However, if set to
-       1, it weakens security by allowing mappings to be made executable
-       without authorization by policy.  The default value of checkreqprot
-       at boot was changed starting in Linux v4.4 to 0 (i.e. check the
-       actual protection), and Android and Linux distributions have been
-       explicitly writing a "0" to /sys/fs/selinux/checkreqprot during
-       initialization for some time.  Support for setting checkreqprot to 1
-       will be removed no sooner than June 2021, at which point the kernel
-       will always cease using checkreqprot internally and will always
-       check the actual protections being applied upon mmap/mprotect calls.
-       The checkreqprot selinuxfs node will remain for backward compatibility
-       but will discard writes of the "0" value and will reject writes of the
-       "1" value when this mechanism is removed.
diff --git a/Documentation/ABI/obsolete/sysfs-selinux-disable b/Documentation/ABI/obsolete/sysfs-selinux-disable
deleted file mode 100644 (file)
index c340278..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-What:          /sys/fs/selinux/disable
-Date:          April 2005 (predates git)
-KernelVersion: 2.6.12-rc2 (predates git)
-Contact:       selinux@vger.kernel.org
-Description:
-
-       The selinuxfs "disable" node allows SELinux to be disabled at runtime
-       prior to a policy being loaded into the kernel.  If disabled via this
-       mechanism, SELinux will remain disabled until the system is rebooted.
-
-       The preferred method of disabling SELinux is via the "selinux=0" boot
-       parameter, but the selinuxfs "disable" node was created to make it
-       easier for systems with primitive bootloaders that did not allow for
-       easy modification of the kernel command line.  Unfortunately, allowing
-       for SELinux to be disabled at runtime makes it difficult to secure the
-       kernel's LSM hooks using the "__ro_after_init" feature.
-
-       Thankfully, the need for the SELinux runtime disable appears to be
-       gone, the default Kconfig configuration disables this selinuxfs node,
-       and only one of the major distributions, Fedora, supports disabling
-       SELinux at runtime.  Fedora is in the process of removing the
-       selinuxfs "disable" node and once that is complete we will start the
-       slow process of removing this code from the kernel.
-
-       More information on /sys/fs/selinux/disable can be found under the
-       CONFIG_SECURITY_SELINUX_DISABLE Kconfig option.
diff --git a/Documentation/ABI/removed/sysfs-selinux-checkreqprot b/Documentation/ABI/removed/sysfs-selinux-checkreqprot
new file mode 100644 (file)
index 0000000..f599a0a
--- /dev/null
@@ -0,0 +1,26 @@
+What:          /sys/fs/selinux/checkreqprot
+Date:          April 2005 (predates git)
+KernelVersion: 2.6.12-rc2 (predates git)
+Contact:       selinux@vger.kernel.org
+Description:
+
+       REMOVAL UPDATE: The SELinux checkreqprot functionality was removed in
+       March 2023, the original deprecation notice is shown below.
+
+       The selinuxfs "checkreqprot" node allows SELinux to be configured
+       to check the protection requested by userspace for mmap/mprotect
+       calls instead of the actual protection applied by the kernel.
+       This was a compatibility mechanism for legacy userspace and
+       for the READ_IMPLIES_EXEC personality flag.  However, if set to
+       1, it weakens security by allowing mappings to be made executable
+       without authorization by policy.  The default value of checkreqprot
+       at boot was changed starting in Linux v4.4 to 0 (i.e. check the
+       actual protection), and Android and Linux distributions have been
+       explicitly writing a "0" to /sys/fs/selinux/checkreqprot during
+       initialization for some time.  Support for setting checkreqprot to 1
+       will be removed no sooner than June 2021, at which point the kernel
+       will always cease using checkreqprot internally and will always
+       check the actual protections being applied upon mmap/mprotect calls.
+       The checkreqprot selinuxfs node will remain for backward compatibility
+       but will discard writes of the "0" value and will reject writes of the
+       "1" value when this mechanism is removed.
diff --git a/Documentation/ABI/removed/sysfs-selinux-disable b/Documentation/ABI/removed/sysfs-selinux-disable
new file mode 100644 (file)
index 0000000..cb783c6
--- /dev/null
@@ -0,0 +1,29 @@
+What:          /sys/fs/selinux/disable
+Date:          April 2005 (predates git)
+KernelVersion: 2.6.12-rc2 (predates git)
+Contact:       selinux@vger.kernel.org
+Description:
+
+       REMOVAL UPDATE: The SELinux runtime disable functionality was removed
+       in March 2023, the original deprecation notice is shown below.
+
+       The selinuxfs "disable" node allows SELinux to be disabled at runtime
+       prior to a policy being loaded into the kernel.  If disabled via this
+       mechanism, SELinux will remain disabled until the system is rebooted.
+
+       The preferred method of disabling SELinux is via the "selinux=0" boot
+       parameter, but the selinuxfs "disable" node was created to make it
+       easier for systems with primitive bootloaders that did not allow for
+       easy modification of the kernel command line.  Unfortunately, allowing
+       for SELinux to be disabled at runtime makes it difficult to secure the
+       kernel's LSM hooks using the "__ro_after_init" feature.
+
+       Thankfully, the need for the SELinux runtime disable appears to be
+       gone, the default Kconfig configuration disables this selinuxfs node,
+       and only one of the major distributions, Fedora, supports disabling
+       SELinux at runtime.  Fedora is in the process of removing the
+       selinuxfs "disable" node and once that is complete we will start the
+       slow process of removing this code from the kernel.
+
+       More information on /sys/fs/selinux/disable can be found under the
+       CONFIG_SECURITY_SELINUX_DISABLE Kconfig option.
index c9c957c85bac1a5bdd4a69af5136ea4600a19250..93d899d532584003a5480b28ad823f1f76940b0c 100644 (file)
@@ -277,7 +277,7 @@ the following access functions:
 
 Again, only one request in a given batch need actually carry out a
 grace-period operation, which means there must be an efficient way to
-identify which of many concurrent reqeusts will initiate the grace
+identify which of many concurrent requests will initiate the grace
 period, and that there be an efficient way for the remaining requests to
 wait for that grace period to complete. However, that is the topic of
 the next section.
@@ -405,7 +405,7 @@ Use of Workqueues
 In earlier implementations, the task requesting the expedited grace
 period also drove it to completion. This straightforward approach had
 the disadvantage of needing to account for POSIX signals sent to user
-tasks, so more recent implemementations use the Linux kernel's
+tasks, so more recent implementations use the Linux kernel's
 workqueues (see Documentation/core-api/workqueue.rst).
 
 The requesting task still does counter snapshotting and funnel-lock
@@ -465,7 +465,7 @@ corresponding disadvantage that workqueues cannot be used until they are
 initialized, which does not happen until some time after the scheduler
 spawns the first task. Given that there are parts of the kernel that
 really do want to execute grace periods during this mid-boot “dead
-zone”, expedited grace periods must do something else during thie time.
+zone”, expedited grace periods must do something else during this time.
 
 What they do is to fall back to the old practice of requiring that the
 requesting task drive the expedited grace period, as was the case before
index 7fdf151a8680a2de1d85fc1819ac60aa234e1e8a..5750f125361b066b7e0d3668af7609d2027b0682 100644 (file)
@@ -168,7 +168,7 @@ an ``atomic_add_return()`` of zero) to detect idle CPUs.
 +-----------------------------------------------------------------------+
 
 The approach must be extended to handle one final case, that of waking a
-task blocked in ``synchronize_rcu()``. This task might be affinitied to
+task blocked in ``synchronize_rcu()``. This task might be affined to
 a CPU that is not yet aware that the grace period has ended, and thus
 might not yet be subject to the grace period's memory ordering.
 Therefore, there is an ``smp_mb()`` after the return from
index 588d97366a463bc7fb9e8f6451bb3c8e36e6c758..db8f16b392aa6d1525744767f0732cf090f8e170 100644 (file)
@@ -201,7 +201,7 @@ work looked at debugging uses of RCU [Seyster:2011:RFA:2075416.2075425].
 In 2012, Josh Triplett received his Ph.D. with his dissertation
 covering RCU-protected resizable hash tables and the relationship
 between memory barriers and read-side traversal order:  If the updater
-is making changes in the opposite direction from the read-side traveral
+is making changes in the opposite direction from the read-side traversal
 order, the updater need only execute a memory-barrier instruction,
 but if in the same direction, the updater needs to wait for a grace
 period between the individual updates [JoshTriplettPhD].  Also in 2012,
@@ -1245,7 +1245,7 @@ Oregon Health and Sciences University"
 [Viewed September 5, 2005]"
 ,annotation={
        First posting showing how RCU can be safely adapted for
-       preemptable RCU read side critical sections.
+       preemptible RCU read side critical sections.
 }
 }
 
@@ -1888,7 +1888,7 @@ Revised:
 \url{https://lore.kernel.org/r/20070910183004.GA3299@linux.vnet.ibm.com}
 [Viewed October 25, 2007]"
 ,annotation={
-       Final patch for preemptable RCU to -rt.  (Later patches were
+       Final patch for preemptible RCU to -rt.  (Later patches were
        to mainline, eventually incorporated.)
 }
 }
@@ -2275,7 +2275,7 @@ lot of {Linux} into your technology!!!"
 \url{https://lore.kernel.org/r/20090724001429.GA17374@linux.vnet.ibm.com}
 [Viewed August 15, 2009]"
 ,annotation={
-       First posting of simple and fast preemptable RCU.
+       First posting of simple and fast preemptible RCU.
 }
 }
 
@@ -2639,7 +2639,7 @@ lot of {Linux} into your technology!!!"
        RCU-protected hash tables, barriers vs. read-side traversal order.
        .
        If the updater is making changes in the opposite direction from
-       the read-side traveral order, the updater need only execute a
+       the read-side traversal order, the updater need only execute a
        memory-barrier instruction, but if in the same direction, the
        updater needs to wait for a grace period between the individual
        updates.
index 8b20fd45f2558d8d5d6d6076d624b134f0b70bdf..4060d7a2f62aa19a8ecc45cfaf686efaf5e1df97 100644 (file)
@@ -107,7 +107,7 @@ UP systems, including PREEMPT SMP builds running on UP systems.
 
 Quick Quiz #3:
        Why can't synchronize_rcu() return immediately on UP systems running
-       preemptable RCU?
+       preemptible RCU?
 
 .. _answer_quick_quiz_up:
 
@@ -143,7 +143,7 @@ Answer to Quick Quiz #2:
 
 Answer to Quick Quiz #3:
        Why can't synchronize_rcu() return immediately on UP systems
-       running preemptable RCU?
+       running preemptible RCU?
 
        Because some other task might have been preempted in the middle
        of an RCU read-side critical section.  If synchronize_rcu()
index cc361fb01ed4e3bf5c7d6ef7fe29564f17aef76a..bd3c58c44befdd3a04811c81e4887bad6f321255 100644 (file)
@@ -70,7 +70,7 @@ over a rather long period of time, but improvements are always welcome!
        can serve as rcu_read_lock_sched(), but is less readable and
        prevents lockdep from detecting locking issues.
 
-       Please not that you *cannot* rely on code known to be built
+       Please note that you *cannot* rely on code known to be built
        only in non-preemptible kernels.  Such code can and will break,
        especially in kernels built with CONFIG_PREEMPT_COUNT=y.
 
index 2749f43ec1b03f68c11291b956f07641e1bfd8ec..69e73a39bd112c3888d3ad117b1cc7d4d958fdbd 100644 (file)
@@ -65,7 +65,7 @@ checking of rcu_dereference() primitives:
        rcu_access_pointer(p):
                Return the value of the pointer and omit all barriers,
                but retain the compiler constraints that prevent duplicating
-               or coalescsing.  This is useful when testing the
+               or coalescing.  This is useful when testing the
                value of the pointer itself, for example, against NULL.
 
 The rcu_dereference_check() check expression can be any boolean
index 0316ba0c692255d523a885abba51997085f7e8be..b3b6dfa85248ea2e9619c259a87b16108441d875 100644 (file)
@@ -216,7 +216,7 @@ Kernel boot arguments can also be supplied, for example, to control
 rcutorture's module parameters.  For example, to test a change to RCU's
 CPU stall-warning code, use "--bootargs 'rcutorture.stall_cpu=30'".
 This will of course result in the scripting reporting a failure, namely
-the resuling RCU CPU stall warning.  As noted above, reducing memory may
+the resulting RCU CPU stall warning.  As noted above, reducing memory may
 require disabling rcutorture's callback-flooding tests::
 
        kvm.sh --cpus 448 --configs '56*TREE04' --memory 128M \
@@ -370,5 +370,5 @@ You can also re-run a previous remote run in a manner similar to kvm.sh:
                tools/testing/selftests/rcutorture/res/2022.11.03-11.26.28-remote \
                --duration 24h
 
-In this case, most of the kvm-again.sh parmeters may be supplied following
+In this case, most of the kvm-again.sh parameters may be supplied following
 the pathname of the old run-results directory.
index 2c5563a91998f93d25c2e81c49336b60c26d330e..8eddef28d3a1102a1442d9393d0120b81e3c44b3 100644 (file)
@@ -597,10 +597,10 @@ to avoid having to write your own callback::
 If the occasional sleep is permitted, the single-argument form may
 be used, omitting the rcu_head structure from struct foo.
 
-       kfree_rcu(old_fp);
+       kfree_rcu_mightsleep(old_fp);
 
-This variant of kfree_rcu() almost never blocks, but might do so by
-invoking synchronize_rcu() in response to memory-allocation failure.
+This variant almost never blocks, but might do so by invoking
+synchronize_rcu() in response to memory-allocation failure.
 
 Again, see checklist.rst for additional rules governing the use of RCU.
 
index f491de74ea79020392c74f905e48f8f34c799318..48ca0bd85604ecb84895c802bbfb22bcb8a60e6c 100644 (file)
@@ -58,7 +58,7 @@ Because the buffers are potentially shared between Hyper-Threads cross
 Hyper-Thread attacks are possible.
 
 Deeper technical information is available in the MDS specific x86
-architecture section: :ref:`Documentation/x86/mds.rst <mds>`.
+architecture section: :ref:`Documentation/arch/x86/mds.rst <mds>`.
 
 
 Attack scenarios
index 76673affd917351d2f34095adb5545d24105d5d1..014167ef8dd1b48da829d823b0324143e6a559ab 100644 (file)
@@ -63,7 +63,7 @@ attacker needs to begin a TSX transaction and raise an asynchronous abort
 which in turn potentially leaks data stored in the buffers.
 
 More detailed technical information is available in the TAA specific x86
-architecture section: :ref:`Documentation/x86/tsx_async_abort.rst <tsx_async_abort>`.
+architecture section: :ref:`Documentation/arch/x86/tsx_async_abort.rst <tsx_async_abort>`.
 
 
 Attack scenarios
index 0ad7e7ec0d2742ca2bc21b88820ec761c8f65a06..43ea35613dfcd464f2d861a5baaa62a4fd0fa18e 100644 (file)
@@ -36,7 +36,7 @@ problems and bugs in particular.
 
    reporting-issues
    reporting-regressions
-   security-bugs
+   quickly-build-trimmed-linux
    bug-hunting
    bug-bisect
    tainted-kernels
index 19600c50277b70a512ccfa7efb98ca8e24851262..1ba8f2a44aacdec188276ffbaa5bc6b5e0bf547f 100644 (file)
@@ -128,10 +128,11 @@ parameter is applicable::
        KVM     Kernel Virtual Machine support is enabled.
        LIBATA  Libata driver is enabled
        LP      Printer support is enabled.
+       LOONGARCH LoongArch architecture is enabled.
        LOOP    Loopback device support is enabled.
        M68k    M68k architecture is enabled.
                        These options have more detailed description inside of
-                       Documentation/m68k/kernel-options.rst.
+                       Documentation/arch/m68k/kernel-options.rst.
        MDA     MDA console support is enabled.
        MIPS    MIPS architecture is enabled.
        MOUSE   Appropriate mouse support is enabled.
@@ -177,7 +178,7 @@ parameter is applicable::
        X86-32  X86-32, aka i386 architecture is enabled.
        X86-64  X86-64 architecture is enabled.
                        More X86-64 boot options can be found in
-                       Documentation/x86/x86_64/boot-options.rst.
+                       Documentation/arch/x86/x86_64/boot-options.rst.
        X86     Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
        X86_UV  SGI UV support is enabled.
        XEN     Xen support is enabled
@@ -192,10 +193,10 @@ In addition, the following text indicates that the option::
 Parameters denoted with BOOT are actually interpreted by the boot
 loader, and have no meaning to the kernel directly.
 Do not modify the syntax of boot loader parameters without extreme
-need or coordination with <Documentation/x86/boot.rst>.
+need or coordination with <Documentation/arch/x86/boot.rst>.
 
 There are also arch-specific kernel-parameters not documented here.
-See for example <Documentation/x86/x86_64/boot-options.rst>.
+See for example <Documentation/arch/x86/x86_64/boot-options.rst>.
 
 Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
 a trailing = on the name of any parameter states that that parameter will
index 6221a1d057dd58de265283de65e785c618ea6758..10e2e5c3ff0bb23c3b6b1ce9f59e41d7aac0ca17 100644 (file)
 
        debug_objects   [KNL] Enable object debugging
 
-       no_debug_objects
-                       [KNL] Disable object debugging
-
        debug_guardpage_minorder=
                        [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
                        parameter allows control of the order of pages that will
 
        mce             [X86-32] Machine Check Exception
 
-       mce=option      [X86-64] See Documentation/x86/x86_64/boot-options.rst
+       mce=option      [X86-64] See Documentation/arch/x86/x86_64/boot-options.rst
 
        md=             [HW] RAID subsystems devices and level
                        See Documentation/admin-guide/md.rst.
                        deep    - Suspend-To-RAM or equivalent (if supported)
                        See Documentation/admin-guide/pm/sleep-states.rst.
 
-       meye.*=         [HW] Set MotionEye Camera parameters
-                       See Documentation/admin-guide/media/meye.rst.
-
        mfgpt_irq=      [IA-32] Specify the IRQ to use for the
                        Multi-Function General Purpose Timers on AMD Geode
                        platforms.
                        1 to enable accounting
                        Default value is 0.
 
-       nfsaddrs=       [NFS] Deprecated.  Use ip= instead.
-                       See Documentation/admin-guide/nfs/nfsroot.rst.
-
-       nfsroot=        [NFS] nfs root filesystem for disk-less boxes.
-                       See Documentation/admin-guide/nfs/nfsroot.rst.
+       nfs.cache_getent=
+                       [NFS] sets the pathname to the program which is used
+                       to update the NFS client cache entries.
 
-       nfsrootdebug    [NFS] enable nfsroot debugging messages.
-                       See Documentation/admin-guide/nfs/nfsroot.rst.
+       nfs.cache_getent_timeout=
+                       [NFS] sets the timeout after which an attempt to
+                       update a cache entry is deemed to have failed.
 
        nfs.callback_nr_threads=
                        [NFSv4] set the total number of threads that the
                        [NFS] set the TCP port on which the NFSv4 callback
                        channel should listen.
 
-       nfs.cache_getent=
-                       [NFS] sets the pathname to the program which is used
-                       to update the NFS client cache entries.
-
-       nfs.cache_getent_timeout=
-                       [NFS] sets the timeout after which an attempt to
-                       update a cache entry is deemed to have failed.
-
-       nfs.idmap_cache_timeout=
-                       [NFS] set the maximum lifetime for idmapper cache
-                       entries.
-
        nfs.enable_ino64=
                        [NFS] enable 64-bit inode numbers.
                        If zero, the NFS client will fake up a 32-bit inode
                        of returning the full 64-bit number.
                        The default is to return 64-bit inode numbers.
 
+       nfs.idmap_cache_timeout=
+                       [NFS] set the maximum lifetime for idmapper cache
+                       entries.
+
        nfs.max_session_cb_slots=
                        [NFSv4.1] Sets the maximum number of session
                        slots the client will assign to the callback
                        will be autodetected by the client, and it will fall
                        back to using the idmapper.
                        To turn off this behaviour, set the value to '0'.
+
        nfs.nfs4_unique_id=
                        [NFS4] Specify an additional fixed unique ident-
                        ification string that NFSv4 clients can insert into
                        their nfs_client_id4 string.  This is typically a
                        UUID that is generated at system install time.
 
-       nfs.send_implementation_id =
-                       [NFSv4.1] Send client implementation identification
-                       information in exchange_id requests.
-                       If zero, no implementation identification information
-                       will be sent.
-                       The default is to send the implementation identification
-                       information.
-
-       nfs.recover_lost_locks =
+       nfs.recover_lost_locks=
                        [NFSv4] Attempt to recover locks that were lost due
                        to a lease timeout on the server. Please note that
                        doing this risks data corruption, since there are
                        The default parameter value of '0' causes the kernel
                        not to attempt recovery of lost locks.
 
-       nfs4.layoutstats_timer =
+       nfs.send_implementation_id=
+                       [NFSv4.1] Send client implementation identification
+                       information in exchange_id requests.
+                       If zero, no implementation identification information
+                       will be sent.
+                       The default is to send the implementation identification
+                       information.
+
+       nfs4.layoutstats_timer=
                        [NFSv4.2] Change the rate at which the kernel sends
                        layoutstats to the pNFS metadata server.
 
                        driver. A non-zero value sets the minimum interval
                        in seconds between layoutstats transmissions.
 
-       nfsd.inter_copy_offload_enable =
+       nfsd.inter_copy_offload_enable=
                        [NFSv4.2] When set to 1, the server will support
                        server-to-server copies for which this server is
                        the destination of the copy.
 
-       nfsd.nfsd4_ssc_umount_timeout =
+       nfsd.nfs4_disable_idmapping=
+                       [NFSv4] When set to the default of '1', the NFSv4
+                       server will return only numeric uids and gids to
+                       clients using auth_sys, and will accept numeric uids
+                       and gids from such clients.  This is intended to ease
+                       migration from NFSv2/v3.
+
+       nfsd.nfsd4_ssc_umount_timeout=
                        [NFSv4.2] When used as the destination of a
                        server-to-server copy, knfsd temporarily mounts
                        the source server.  It caches the mount in case
                        used for the number of milliseconds specified by
                        this parameter.
 
-       nfsd.nfs4_disable_idmapping=
-                       [NFSv4] When set to the default of '1', the NFSv4
-                       server will return only numeric uids and gids to
-                       clients using auth_sys, and will accept numeric uids
-                       and gids from such clients.  This is intended to ease
-                       migration from NFSv2/v3.
+       nfsaddrs=       [NFS] Deprecated.  Use ip= instead.
+                       See Documentation/admin-guide/nfs/nfsroot.rst.
+
+       nfsroot=        [NFS] nfs root filesystem for disk-less boxes.
+                       See Documentation/admin-guide/nfs/nfsroot.rst.
 
+       nfsrootdebug    [NFS] enable nfsroot debugging messages.
+                       See Documentation/admin-guide/nfs/nfsroot.rst.
 
        nmi_backtrace.backtrace_idle [KNL]
                        Dump stacks even of idle CPUs in response to an
        no5lvl          [X86-64] Disable 5-level paging mode. Forces
                        kernel to use 4-level paging instead.
 
-       nofsgsbase      [X86] Disables FSGSBASE instructions.
+       noaliencache    [MM, NUMA, SLAB] Disables the allocation of alien
+                       caches in the slab allocator.  Saves per-node memory,
+                       but will impact performance.
+
+       noalign         [KNL,ARM]
+
+       noaltinstr      [S390] Disables alternative instructions patching
+                       (CPU alternatives feature).
+
+       noapic          [SMP,APIC] Tells the kernel to not make use of any
+                       IOAPICs that may be present in the system.
+
+       noautogroup     Disable scheduler automatic task group creation.
+
+       nocache         [ARM]
 
        no_console_suspend
                        [HW] Never suspend the console
                        /sys/module/printk/parameters/console_suspend) to
                        turn on/off it dynamically.
 
-       novmcoredd      [KNL,KDUMP]
-                       Disable device dump. Device dump allows drivers to
-                       append dump data to vmcore so you can collect driver
-                       specified debug info.  Drivers can append the data
-                       without any limit and this data is stored in memory,
-                       so this may cause significant memory stress.  Disabling
-                       device dump can help save memory but the driver debug
-                       data will be no longer available.  This parameter
-                       is only available when CONFIG_PROC_VMCORE_DEVICE_DUMP
-                       is set.
-
-       noaliencache    [MM, NUMA, SLAB] Disables the allocation of alien
-                       caches in the slab allocator.  Saves per-node memory,
-                       but will impact performance.
-
-       noalign         [KNL,ARM]
-
-       noaltinstr      [S390] Disables alternative instructions patching
-                       (CPU alternatives feature).
-
-       noapic          [SMP,APIC] Tells the kernel to not make use of any
-                       IOAPICs that may be present in the system.
-
-       noautogroup     Disable scheduler automatic task group creation.
-
-       nocache         [ARM]
+       no_debug_objects
+                       [KNL] Disable object debugging
 
        nodsp           [SH] Disable hardware DSP at boot time.
 
 
        noexec          [IA-64]
 
-       nosmap          [PPC]
-                       Disable SMAP (Supervisor Mode Access Prevention)
-                       even if it is supported by processor.
-
-       nosmep          [PPC64s]
-                       Disable SMEP (Supervisor Mode Execution Prevention)
-                       even if it is supported by processor.
-
        noexec32        [X86-64]
                        This affects only 32-bit executables.
                        noexec32=on: enable non-executable mappings (default)
                        noexec32=off: disable non-executable mappings
                                read implies executable mappings
 
+       no_file_caps    Tells the kernel not to honor file capabilities.  The
+                       only way then for a file to be executed with privilege
+                       is to be setuid root or executed by root.
+
        nofpu           [MIPS,SH] Disable hardware FPU at boot time.
 
+       nofsgsbase      [X86] Disables FSGSBASE instructions.
+
        nofxsr          [BUGS=X86-32] Disables x86 floating point extended
                        register save and restore. The kernel will only save
                        legacy floating-point registers on task switch.
 
-       nohugeiomap     [KNL,X86,PPC,ARM64] Disable kernel huge I/O mappings.
-
-       nohugevmalloc   [KNL,X86,PPC,ARM64] Disable kernel huge vmalloc mappings.
-
-       nosmt           [KNL,S390] Disable symmetric multithreading (SMT).
-                       Equivalent to smt=1.
-
-                       [KNL,X86] Disable symmetric multithreading (SMT).
-                       nosmt=force: Force disable SMT, cannot be undone
-                                    via the sysfs control file.
-
-       nospectre_v1    [X86,PPC] Disable mitigations for Spectre Variant 1
-                       (bounds check bypass). With this option data leaks are
-                       possible in the system.
-
-       nospectre_v2    [X86,PPC_E500,ARM64] Disable all mitigations for
-                       the Spectre variant 2 (indirect branch prediction)
-                       vulnerability. System may allow data leaks with this
-                       option.
-
-       nospectre_bhb   [ARM64] Disable all mitigations for Spectre-BHB (branch
-                       history injection) vulnerability. System may allow data leaks
-                       with this option.
-
-       nospec_store_bypass_disable
-                       [HW] Disable all mitigations for the Speculative Store Bypass vulnerability
-
-       no_uaccess_flush
-                       [PPC] Don't flush the L1-D cache after accessing user data.
-
-       noxsave         [BUGS=X86] Disables x86 extended register state save
-                       and restore using xsave. The kernel will fallback to
-                       enabling legacy floating-point and sse state.
-
-       noxsaveopt      [X86] Disables xsaveopt used in saving x86 extended
-                       register states. The kernel will fall back to use
-                       xsave to save the states. By using this parameter,
-                       performance of saving the states is degraded because
-                       xsave doesn't support modified optimization while
-                       xsaveopt supports it on xsaveopt enabled systems.
-
-       noxsaves        [X86] Disables xsaves and xrstors used in saving and
-                       restoring x86 extended register state in compacted
-                       form of xsave area. The kernel will fall back to use
-                       xsaveopt and xrstor to save and restore the states
-                       in standard form of xsave area. By using this
-                       parameter, xsave area per process might occupy more
-                       memory on xsaves enabled systems.
-
-       nohlt           [ARM,ARM64,MICROBLAZE,SH] Forces the kernel to busy wait
-                       in do_idle() and not use the arch_cpu_idle()
-                       implementation; requires CONFIG_GENERIC_IDLE_POLL_SETUP
-                       to be effective. This is useful on platforms where the
-                       sleep(SH) or wfi(ARM,ARM64) instructions do not work
-                       correctly or when doing power measurements to evaluate
-                       the impact of the sleep instructions. This is also
-                       useful when using JTAG debugger.
-
-       no_file_caps    Tells the kernel not to honor file capabilities.  The
-                       only way then for a file to be executed with privilege
-                       is to be setuid root or executed by root.
-
        nohalt          [IA-64] Tells the kernel not to use the power saving
                        function PAL_HALT_LIGHT when idle. This increases
                        power-consumption. On the positive side, it reduces
 
        nohibernate     [HIBERNATION] Disable hibernation and resume.
 
+       nohlt           [ARM,ARM64,MICROBLAZE,SH] Forces the kernel to busy wait
+                       in do_idle() and not use the arch_cpu_idle()
+                       implementation; requires CONFIG_GENERIC_IDLE_POLL_SETUP
+                       to be effective. This is useful on platforms where the
+                       sleep(SH) or wfi(ARM,ARM64) instructions do not work
+                       correctly or when doing power measurements to evaluate
+                       the impact of the sleep instructions. This is also
+                       useful when using JTAG debugger.
+
+       nohugeiomap     [KNL,X86,PPC,ARM64] Disable kernel huge I/O mappings.
+
+       nohugevmalloc   [KNL,X86,PPC,ARM64] Disable kernel huge vmalloc mappings.
+
        nohz=           [KNL] Boottime enable/disable dynamic ticks
                        Valid arguments: on, off
                        Default: on
                        Note that this argument takes precedence over
                        the CONFIG_RCU_NOCB_CPU_DEFAULT_ALL option.
 
-       noiotrap        [SH] Disables trapped I/O port accesses.
-
-       noirqdebug      [X86-32] Disables the code which attempts to detect and
-                       disable unhandled interrupt sources.
-
-       no_timer_check  [X86,APIC] Disables the code which tests for
-                       broken timer IRQ sources.
-
-       noisapnp        [ISAPNP] Disables ISA PnP code.
-
        noinitrd        [RAM] Tells the kernel not to load any configured
                        initial RAM disk.
 
 
        noinvpcid       [X86] Disable the INVPCID cpu feature.
 
+       noiotrap        [SH] Disables trapped I/O port accesses.
+
+       noirqdebug      [X86-32] Disables the code which attempts to detect and
+                       disable unhandled interrupt sources.
+
+       noisapnp        [ISAPNP] Disables ISA PnP code.
+
        nojitter        [IA-64] Disables jitter checking for ITC timers.
 
        nokaslr         [KNL]
                        kernel and module base offset ASLR (Address Space
                        Layout Randomization).
 
-       no-kvmclock     [X86,KVM] Disable paravirtualized KVM clock driver
-
        no-kvmapf       [X86,KVM] Disable paravirtualized asynchronous page
                        fault handling.
 
-       no-vmw-sched-clock
-                       [X86,PV_OPS] Disable paravirtualized VMware scheduler
-                       clock and use the default one.
-
-       no-steal-acc    [X86,PV_OPS,ARM64,PPC/PSERIES] Disable paravirtualized
-                       steal time accounting. steal time is computed, but
-                       won't influence scheduler behaviour
+       no-kvmclock     [X86,KVM] Disable paravirtualized KVM clock driver
 
        nolapic         [X86-32,APIC] Do not enable or use the local APIC.
 
        nomfgpt         [X86-32] Disable Multi-Function General Purpose
                        Timer usage (for AMD Geode machines).
 
-       nonmi_ipi       [X86] Disable using NMI IPIs during panic/reboot to
-                       shutdown the other cpus.  Instead use the REBOOT_VECTOR
-                       irq.
-
        nomodeset       Disable kernel modesetting. Most systems' firmware
                        sets up a display mode and provides framebuffer memory
                        for output. With nomodeset, DRM and fbdev drivers will
 
        nomodule        Disable module load
 
+       nonmi_ipi       [X86] Disable using NMI IPIs during panic/reboot to
+                       shutdown the other cpus.  Instead use the REBOOT_VECTOR
+                       irq.
+
        nopat           [X86] Disable PAT (page attribute table extension of
                        pagetables) support.
 
        nopku           [X86] Disable Memory Protection Keys CPU feature found
                        in some Intel CPUs.
 
+       nopti           [X86-64]
+                       Equivalent to pti=off
+
        nopv=           [X86,XEN,KVM,HYPER_V,VMWARE]
                        Disables the PV optimizations forcing the guest to run
                        as generic guest with no PV drivers. Currently support
        noresume        [SWSUSP] Disables resume and restores original swap
                        space.
 
+       nosbagart       [IA-64]
+
        no-scroll       [VGA] Disables scrollback.
                        This is required for the Braillex ib80-piezo Braille
                        reader made by F.H. Papenmeier (Germany).
 
-       nosbagart       [IA-64]
-
        nosgx           [X86-64,SGX] Disables Intel SGX kernel support.
 
+       nosmap          [PPC]
+                       Disable SMAP (Supervisor Mode Access Prevention)
+                       even if it is supported by processor.
+
+       nosmep          [PPC64s]
+                       Disable SMEP (Supervisor Mode Execution Prevention)
+                       even if it is supported by processor.
+
        nosmp           [SMP] Tells an SMP kernel to act as a UP kernel,
                        and disable the IO APIC.  legacy for "maxcpus=0".
 
+       nosmt           [KNL,S390] Disable symmetric multithreading (SMT).
+                       Equivalent to smt=1.
+
+                       [KNL,X86] Disable symmetric multithreading (SMT).
+                       nosmt=force: Force disable SMT, cannot be undone
+                                    via the sysfs control file.
+
        nosoftlockup    [KNL] Disable the soft-lockup detector.
 
+       nospec_store_bypass_disable
+                       [HW] Disable all mitigations for the Speculative Store Bypass vulnerability
+
+       nospectre_bhb   [ARM64] Disable all mitigations for Spectre-BHB (branch
+                       history injection) vulnerability. System may allow data leaks
+                       with this option.
+
+       nospectre_v1    [X86,PPC] Disable mitigations for Spectre Variant 1
+                       (bounds check bypass). With this option data leaks are
+                       possible in the system.
+
+       nospectre_v2    [X86,PPC_E500,ARM64] Disable all mitigations for
+                       the Spectre variant 2 (indirect branch prediction)
+                       vulnerability. System may allow data leaks with this
+                       option.
+
+       no-steal-acc    [X86,PV_OPS,ARM64,PPC/PSERIES] Disable paravirtualized
+                       steal time accounting. steal time is computed, but
+                       won't influence scheduler behaviour
+
        nosync          [HW,M68K] Disables sync negotiation for all devices.
 
+       no_timer_check  [X86,APIC] Disables the code which tests for
+                       broken timer IRQ sources.
+
+       no_uaccess_flush
+                       [PPC] Don't flush the L1-D cache after accessing user data.
+
+       novmcoredd      [KNL,KDUMP]
+                       Disable device dump. Device dump allows drivers to
+                       append dump data to vmcore so you can collect driver
+                       specified debug info.  Drivers can append the data
+                       without any limit and this data is stored in memory,
+                       so this may cause significant memory stress.  Disabling
+                       device dump can help save memory but the driver debug
+                       data will be no longer available.  This parameter
+                       is only available when CONFIG_PROC_VMCORE_DEVICE_DUMP
+                       is set.
+
+       no-vmw-sched-clock
+                       [X86,PV_OPS] Disable paravirtualized VMware scheduler
+                       clock and use the default one.
+
        nowatchdog      [KNL] Disable both lockup detectors, i.e.
                        soft-lockup and NMI watchdog (hard-lockup).
 
                        LEGACY_XAPIC_DISABLED bit set in the
                        IA32_XAPIC_DISABLE_STATUS MSR.
 
+       noxsave         [BUGS=X86] Disables x86 extended register state save
+                       and restore using xsave. The kernel will fallback to
+                       enabling legacy floating-point and sse state.
+
+       noxsaveopt      [X86] Disables xsaveopt used in saving x86 extended
+                       register states. The kernel will fall back to use
+                       xsave to save the states. By using this parameter,
+                       performance of saving the states is degraded because
+                       xsave doesn't support modified optimization while
+                       xsaveopt supports it on xsaveopt enabled systems.
+
+       noxsaves        [X86] Disables xsaves and xrstors used in saving and
+                       restoring x86 extended register state in compacted
+                       form of xsave area. The kernel will fall back to use
+                       xsaveopt and xrstor to save and restore the states
+                       in standard form of xsave area. By using this
+                       parameter, xsave area per process might occupy more
+                       memory on xsaves enabled systems.
+
        nps_mtm_hs_ctr= [KNL,ARC]
                        This parameter sets the maximum duration, in
                        cycles, each HW thread of the CTOP can run
                        and performance comparison.
 
        pirq=           [SMP,APIC] Manual mp-table setup
-                       See Documentation/x86/i386/IO-APIC.rst.
+                       See Documentation/arch/x86/i386/IO-APIC.rst.
 
        plip=           [PPT,NET] Parallel port network link
                        Format: { parport<nr> | timid | 0 }
 
                        Not specifying this option is equivalent to pti=auto.
 
-       nopti           [X86-64]
-                       Equivalent to pti=off
-
        pty.legacy_count=
                        [KNL] Number of legacy pty's. Overwrites compiled-in
                        default number.
 
        serialnumber    [BUGS=X86-32]
 
-       sev=option[,option...] [X86-64] See Documentation/x86/x86_64/boot-options.rst
+       sev=option[,option...] [X86-64] See Documentation/arch/x86/x86_64/boot-options.rst
 
        shapers=        [NET]
                        Maximal number of shapers.
                        Can be used multiple times for multiple devices.
 
        vga=            [BOOT,X86-32] Select a particular video mode
-                       See Documentation/x86/boot.rst and
+                       See Documentation/arch/x86/boot.rst and
                        Documentation/admin-guide/svga.rst.
                        Use vga=ask for menu.
                        This is actually a boot loader parameter; the value is
                        When enabled, memory and cache locality will be
                        impacted.
 
+       writecombine=   [LOONGARCH] Control the MAT (Memory Access Type) of
+                       ioremap_wc().
+
+                       on   - Enable writecombine, use WUC for ioremap_wc()
+                       off  - Disable writecombine, use SUC for ioremap_wc()
+
        x2apic_phys     [X86-64,APIC] Use x2apic physical mode instead of
                        default x2apic cluster mode on platforms
                        supporting x2apic.
diff --git a/Documentation/admin-guide/quickly-build-trimmed-linux.rst b/Documentation/admin-guide/quickly-build-trimmed-linux.rst
new file mode 100644 (file)
index 0000000..ff4f4cc
--- /dev/null
@@ -0,0 +1,1092 @@
+.. SPDX-License-Identifier: (GPL-2.0+ OR CC-BY-4.0)
+.. [see the bottom of this file for redistribution information]
+
+===========================================
+How to quickly build a trimmed Linux kernel
+===========================================
+
+This guide explains how to swiftly build Linux kernels that are ideal for
+testing purposes, but perfectly fine for day-to-day use, too.
+
+The essence of the process (aka 'TL;DR')
+========================================
+
+*[If you are new to compiling Linux, ignore this TLDR and head over to the next
+section below: it contains a step-by-step guide, which is more detailed, but
+still brief and easy to follow; that guide and its accompanying reference
+section also mention alternatives, pitfalls, and additional aspects, all of
+which might be relevant for you.]*
+
+If your system uses techniques like Secure Boot, prepare it to permit starting
+self-compiled Linux kernels; install compilers and everything else needed for
+building Linux; make sure to have 12 Gigabyte free space in your home directory.
+Now run the following commands to download fresh Linux mainline sources, which
+you then use to configure, build and install your own kernel::
+
+    git clone --depth 1 -b master \
+      https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git ~/linux/
+    cd ~/linux/
+    # Hint: if you want to apply patches, do it at this point. See below for details.
+    # Hint: it's recommended to tag your build at this point. See below for details.
+    yes "" | make localmodconfig
+    # Hint: at this point you might want to adjust the build configuration; you'll
+    #   have to, if you are running Debian. See below for details.
+    make -j $(nproc --all)
+    # Note: on many commodity distributions the next command suffices, but on Arch
+    #   Linux, its derivatives, and some others it does not. See below for details.
+    command -v installkernel && sudo make modules_install install
+    reboot
+
+If you later want to build a newer mainline snapshot, use these commands::
+
+    cd ~/linux/
+    git fetch --depth 1 origin
+    # Note: the next command will discard any changes you did to the code:
+    git checkout --force --detach origin/master
+    # Reminder: if you want to (re)apply patches, do it at this point.
+    # Reminder: you might want to add or modify a build tag at this point.
+    make olddefconfig
+    make -j $(nproc --all)
+    # Reminder: the next command on some distributions does not suffice.
+    command -v installkernel && sudo make modules_install install
+    reboot
+
+Step-by-step guide
+==================
+
+Compiling your own Linux kernel is easy in principle. There are various ways to
+do it. Which of them actually work and is the best depends on the circumstances.
+
+This guide describes a way perfectly suited for those who want to quickly
+install Linux from sources without being bothered by complicated details; the
+goal is to cover everything typically needed on mainstream Linux distributions
+running on commodity PC or server hardware.
+
+The described approach is great for testing purposes, for example to try a
+proposed fix or to check if a problem was already fixed in the latest codebase.
+Nonetheless, kernels built this way are also totally fine for day-to-day use
+while at the same time being easy to keep up to date.
+
+The following steps describe the important aspects of the process; a
+comprehensive reference section later explains each of them in more detail. It
+sometimes also describes alternative approaches, pitfalls, as well as errors
+that might occur at a particular point -- and how to then get things rolling
+again.
+
+..
+   Note: if you see this note, you are reading the text's source file. You
+   might want to switch to a rendered version, as it makes it a lot easier to
+   quickly look something up in the reference section and afterwards jump back
+   to where you left off. Find a the latest rendered version here:
+   https://docs.kernel.org/admin-guide/quickly-build-trimmed-linux.html
+
+.. _backup_sbs:
+
+ * Create a fresh backup and put system repair and restore tools at hand, just
+   to be prepared for the unlikely case of something going sideways.
+
+   [:ref:`details<backup>`]
+
+.. _secureboot_sbs:
+
+ * On platforms with 'Secure Boot' or similar techniques, prepare everything to
+   ensure the system will permit your self-compiled kernel to boot later. The
+   quickest and easiest way to achieve this on commodity x86 systems is to
+   disable such techniques in the BIOS setup utility; alternatively, remove
+   their restrictions through a process initiated by
+   ``mokutil --disable-validation``.
+
+   [:ref:`details<secureboot>`]
+
+.. _buildrequires_sbs:
+
+ * Install all software required to build a Linux kernel. Often you will need:
+   'bc', 'binutils' ('ld' et al.), 'bison', 'flex', 'gcc', 'git', 'openssl',
+   'pahole', 'perl', and the development headers for 'libelf' and 'openssl'. The
+   reference section shows how to quickly install those on various popular Linux
+   distributions.
+
+   [:ref:`details<buildrequires>`]
+
+.. _diskspace_sbs:
+
+ * Ensure to have enough free space for building and installing Linux. For the
+   latter 150 Megabyte in /lib/ and 100 in /boot/ are a safe bet. For storing
+   sources and build artifacts 12 Gigabyte in your home directory should
+   typically suffice. If you have less available, be sure to check the reference
+   section for the step that explains adjusting your kernels build
+   configuration: it mentions a trick that reduce the amount of required space
+   in /home/ to around 4 Gigabyte.
+
+   [:ref:`details<diskspace>`]
+
+.. _sources_sbs:
+
+ * Retrieve the sources of the Linux version you intend to build; then change
+   into the directory holding them, as all further commands in this guide are
+   meant to be executed from there.
+
+   *[Note: the following paragraphs describe how to retrieve the sources by
+   partially cloning the Linux stable git repository. This is called a shallow
+   clone. The reference section explains two alternatives:* :ref:`packaged
+   archives<sources_archive>` *and* :ref:`a full git clone<sources_full>` *;
+   prefer the latter, if downloading a lot of data does not bother you, as that
+   will avoid some* :ref:`peculiar characteristics of shallow clones the
+   reference section explains<sources_shallow>` *.]*
+
+   First, execute the following command to retrieve a fresh mainline codebase::
+
+     git clone --no-checkout --depth 1 -b master \
+       https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git ~/linux/
+     cd ~/linux/
+
+   If you want to access recent mainline releases and pre-releases, deepen you
+   clone's history to the oldest mainline version you are interested in::
+
+     git fetch --shallow-exclude=v6.0 origin
+
+   In case you want to access a stable/longterm release (say v6.1.5), simply add
+   the branch holding that series; afterwards fetch the history at least up to
+   the mainline version that started the series (v6.1)::
+
+     git remote set-branches --add origin linux-6.1.y
+     git fetch --shallow-exclude=v6.0 origin
+
+   Now checkout the code you are interested in. If you just performed the
+   initial clone, you will be able to check out a fresh mainline codebase, which
+   is ideal for checking whether developers already fixed an issue::
+
+      git checkout --detach origin/master
+
+   If you deepened your clone, you instead of ``origin/master`` can specify the
+   version you deepened to (``v6.0`` above); later releases like ``v6.1`` and
+   pre-release like ``v6.2-rc1`` will work, too. Stable or longterm versions
+   like ``v6.1.5`` work just the same, if you added the appropriate
+   stable/longterm branch as described.
+
+   [:ref:`details<sources>`]
+
+.. _patching_sbs:
+
+ * In case you want to apply a kernel patch, do so now. Often a command like
+   this will do the trick::
+
+     patch -p1 < ../proposed-fix.patch
+
+   If the ``-p1`` is actually needed, depends on how the patch was created; in
+   case it does not apply thus try without it.
+
+   If you cloned the sources with git and anything goes sideways, run ``git
+   reset --hard`` to undo any changes to the sources.
+
+   [:ref:`details<patching>`]
+
+.. _tagging_sbs:
+
+ * If you patched your kernel or have one of the same version installed already,
+   better add a unique tag to the one you are about to build::
+
+     echo "-proposed_fix" > localversion
+
+   Running ``uname -r`` under your kernel later will then print something like
+   '6.1-rc4-proposed_fix'.
+
+   [:ref:`details<tagging>`]
+
+ .. _configuration_sbs:
+
+ * Create the build configuration for your kernel based on an existing
+   configuration.
+
+   If you already prepared such a '.config' file yourself, copy it to
+   ~/linux/ and run ``make olddefconfig``.
+
+   Use the same command, if your distribution or somebody else already tailored
+   your running kernel to your or your hardware's needs: the make target
+   'olddefconfig' will then try to use that kernel's .config as base.
+
+   Using this make target is fine for everybody else, too -- but you often can
+   save a lot of time by using this command instead::
+
+     yes "" | make localmodconfig
+
+   This will try to pick your distribution's kernel as base, but then disable
+   modules for any features apparently superfluous for your setup. This will
+   reduce the compile time enormously, especially if you are running an
+   universal kernel from a commodity Linux distribution.
+
+   There is a catch: the make target 'localmodconfig' will disable kernel
+   features you have not directly or indirectly through some program utilized
+   since you booted the system. You can reduce or nearly eliminate that risk by
+   using tricks outlined in the reference section; for quick testing purposes
+   that risk is often negligible, but it is an aspect you want to keep in mind
+   in case your kernel behaves oddly.
+
+   [:ref:`details<configuration>`]
+
+.. _configmods_sbs:
+
+ * Check if you might want to or have to adjust some kernel configuration
+   options:
+
+  * Evaluate how you want to handle debug symbols. Enable them, if you later
+    might need to decode a stack trace found for example in a 'panic', 'Oops',
+    'warning', or 'BUG'; on the other hand disable them, if you are short on
+    storage space or prefer a smaller kernel binary. See the reference section
+    for details on how to do either. If neither applies, it will likely be fine
+    to simply not bother with this. [:ref:`details<configmods_debugsymbols>`]
+
+  * Are you running Debian? Then to avoid known problems by performing
+    additional adjustments explained in the reference section.
+    [:ref:`details<configmods_distros>`].
+
+  * If you want to influence the other aspects of the configuration, do so now
+    by using make targets like 'menuconfig' or 'xconfig'.
+    [:ref:`details<configmods_individual>`].
+
+.. _build_sbs:
+
+ * Build the image and the modules of your kernel::
+
+     make -j $(nproc --all)
+
+   If you want your kernel packaged up as deb, rpm, or tar file, see the
+   reference section for alternatives.
+
+   [:ref:`details<build>`]
+
+.. _install_sbs:
+
+ * Now install your kernel::
+
+     command -v installkernel && sudo make modules_install install
+
+   Often all left for you to do afterwards is a ``reboot``, as many commodity
+   Linux distributions will then create an initramfs (also known as initrd) and
+   an entry for your kernel in your bootloader's configuration; but on some
+   distributions you have to take care of these two steps manually for reasons
+   the reference section explains.
+
+   On a few distributions like Arch Linux and its derivatives the above command
+   does nothing at all; in that case you have to manually install your kernel,
+   as outlined in the reference section.
+
+   [:ref:`details<install>`]
+
+.. _another_sbs:
+
+ * To later build another kernel you need similar steps, but sometimes slightly
+   different commands.
+
+   First, switch back into the sources tree::
+
+      cd ~/linux/
+
+   In case you want to build a version from a stable/longterm series you have
+   not used yet (say 6.2.y), tell git to track it::
+
+      git remote set-branches --add origin linux-6.2.y
+
+   Now fetch the latest upstream changes; you again need to specify the earliest
+   version you care about, as git otherwise might retrieve the entire commit
+   history::
+
+     git fetch --shallow-exclude=v6.1 origin
+
+   If you modified the sources (for example by applying a patch), you now need
+   to discard those modifications; that's because git otherwise will not be able
+   to switch to the sources of another version due to potential conflicting
+   changes::
+
+     git reset --hard
+
+   Now checkout the version you are interested in, as explained above::
+
+     git checkout --detach origin/master
+
+   At this point you might want to patch the sources again or set/modify a build
+   tag, as explained earlier; afterwards adjust the build configuration to the
+   new codebase and build your next kernel::
+
+     # reminder: if you want to apply patches, do it at this point
+     # reminder: you might want to update your build tag at this point
+     make olddefconfig
+     make -j $(nproc --all)
+
+   Install the kernel as outlined above::
+
+     command -v installkernel && sudo make modules_install install
+
+   [:ref:`details<another>`]
+
+.. _uninstall_sbs:
+
+ * Your kernel is easy to remove later, as its parts are only stored in two
+   places and clearly identifiable by the kernel's release name. Just ensure to
+   not delete the kernel you are running, as that might render your system
+   unbootable.
+
+   Start by deleting the directory holding your kernel's modules, which is named
+   after its release name -- '6.0.1-foobar' in the following example::
+
+     sudo rm -rf /lib/modules/6.0.1-foobar
+
+   Now try the following command, which on some distributions will delete all
+   other kernel files installed while also removing the kernel's entry from the
+   bootloader configuration::
+
+     command -v kernel-install && sudo kernel-install -v remove 6.0.1-foobar
+
+   If that command does not output anything or fails, see the reference section;
+   do the same if any files named '*6.0.1-foobar*' remain in /boot/.
+
+   [:ref:`details<uninstall>`]
+
+.. _submit_improvements:
+
+Did you run into trouble following any of the above steps that is not cleared up
+by the reference section below? Or do you have ideas how to improve the text?
+Then please take a moment of your time and let the maintainer of this document
+know by email (Thorsten Leemhuis <linux@leemhuis.info>), ideally while CCing the
+Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is vital to
+improve this document further, which is in everybody's interest, as it will
+enable more people to master the task described here.
+
+Reference section for the step-by-step guide
+============================================
+
+This section holds additional information for each of the steps in the above
+guide.
+
+.. _backup:
+
+Prepare for emergencies
+-----------------------
+
+   *Create a fresh backup and put system repair and restore tools at hand*
+   [:ref:`... <backup_sbs>`]
+
+Remember, you are dealing with computers, which sometimes do unexpected things
+-- especially if you fiddle with crucial parts like the kernel of an operating
+system. That's what you are about to do in this process. Hence, better prepare
+for something going sideways, even if that should not happen.
+
+[:ref:`back to step-by-step guide <backup_sbs>`]
+
+.. _secureboot:
+
+Dealing with techniques like Secure Boot
+----------------------------------------
+
+   *On platforms with 'Secure Boot' or similar techniques, prepare everything to
+   ensure the system will permit your self-compiled kernel to boot later.*
+   [:ref:`... <secureboot_sbs>`]
+
+Many modern systems allow only certain operating systems to start; they thus by
+default will reject booting self-compiled kernels.
+
+You ideally deal with this by making your platform trust your self-built kernels
+with the help of a certificate and signing. How to do that is not described
+here, as it requires various steps that would take the text too far away from
+its purpose; 'Documentation/admin-guide/module-signing.rst' and various web
+sides already explain this in more detail.
+
+Temporarily disabling solutions like Secure Boot is another way to make your own
+Linux boot. On commodity x86 systems it is possible to do this in the BIOS Setup
+utility; the steps to do so are not described here, as they greatly vary between
+machines.
+
+On mainstream x86 Linux distributions there is a third and universal option:
+disable all Secure Boot restrictions for your Linux environment. You can
+initiate this process by running ``mokutil --disable-validation``; this will
+tell you to create a one-time password, which is safe to write down. Now
+restart; right after your BIOS performed all self-tests the bootloader Shim will
+show a blue box with a message 'Press any key to perform MOK management'. Hit
+some key before the countdown exposes. This will open a menu and choose 'Change
+Secure Boot state' there. Shim's 'MokManager' will now ask you to enter three
+randomly chosen characters from the one-time password specified earlier. Once
+you provided them, confirm that you really want to disable the validation.
+Afterwards, permit MokManager to reboot the machine.
+
+[:ref:`back to step-by-step guide <secureboot_sbs>`]
+
+.. _buildrequires:
+
+Install build requirements
+--------------------------
+
+   *Install all software required to build a Linux kernel.*
+   [:ref:`...<buildrequires_sbs>`]
+
+The kernel is pretty stand-alone, but besides tools like the compiler you will
+sometimes need a few libraries to build one. How to install everything needed
+depends on your Linux distribution and the configuration of the kernel you are
+about to build.
+
+Here are a few examples what you typically need on some mainstream
+distributions:
+
+ * Debian, Ubuntu, and derivatives::
+
+     sudo apt install bc binutils bison dwarves flex gcc git make openssl \
+       pahole perl-base libssl-dev libelf-dev
+
+ * Fedora and derivatives::
+
+     sudo dnf install binutils /usr/include/{libelf.h,openssl/pkcs7.h} \
+       /usr/bin/{bc,bison,flex,gcc,git,openssl,make,perl,pahole}
+
+ * openSUSE and derivatives::
+
+     sudo zypper install bc binutils bison dwarves flex gcc git make perl-base \
+       openssl openssl-devel libelf-dev
+
+In case you wonder why these lists include openssl and its development headers:
+they are needed for the Secure Boot support, which many distributions enable in
+their kernel configuration for x86 machines.
+
+Sometimes you will need tools for compression formats like bzip2, gzip, lz4,
+lzma, lzo, xz, or zstd as well.
+
+You might need additional libraries and their development headers in case you
+perform tasks not covered in this guide. For example, zlib will be needed when
+building kernel tools from the tools/ directory; adjusting the build
+configuration with make targets like 'menuconfig' or 'xconfig' will require
+development headers for ncurses or Qt5.
+
+[:ref:`back to step-by-step guide <buildrequires_sbs>`]
+
+.. _diskspace:
+
+Space requirements
+------------------
+
+   *Ensure to have enough free space for building and installing Linux.*
+   [:ref:`... <diskspace_sbs>`]
+
+The numbers mentioned are rough estimates with a big extra charge to be on the
+safe side, so often you will need less.
+
+If you have space constraints, remember to read the reference section when you
+reach the :ref:`section about configuration adjustments' <configmods>`, as
+ensuring debug symbols are disabled will reduce the consumed disk space by quite
+a few gigabytes.
+
+[:ref:`back to step-by-step guide <diskspace_sbs>`]
+
+
+.. _sources:
+
+Download the sources
+--------------------
+
+  *Retrieve the sources of the Linux version you intend to build.*
+  [:ref:`...<sources_sbs>`]
+
+The step-by-step guide outlines how to retrieve Linux' sources using a shallow
+git clone. There is :ref:`more to tell about this method<sources_shallow>` and
+two alternate ways worth describing: :ref:`packaged archives<sources_archive>`
+and :ref:`a full git clone<sources_full>`. And the aspects ':ref:`wouldn't it
+be wiser to use a proper pre-release than the latest mainline code
+<sources_snapshot>`' and ':ref:`how to get an even fresher mainline codebase
+<sources_fresher>`' need elaboration, too.
+
+Note, to keep things simple the commands used in this guide store the build
+artifacts in the source tree. If you prefer to separate them, simply add
+something like ``O=~/linux-builddir/`` to all make calls; also adjust the path
+in all commands that add files or modify any generated (like your '.config').
+
+[:ref:`back to step-by-step guide <sources_sbs>`]
+
+.. _sources_shallow:
+
+Noteworthy characteristics of shallow clones
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The step-by-step guide uses a shallow clone, as it is the best solution for most
+of this document's target audience. There are a few aspects of this approach
+worth mentioning:
+
+ * This document in most places uses ``git fetch`` with ``--shallow-exclude=``
+   to specify the earliest version you care about (or to be precise: its git
+   tag). You alternatively can use the parameter ``--shallow-since=`` to specify
+   an absolute (say ``'2023-07-15'``) or relative (``'12 months'``) date to
+   define the depth of the history you want to download. As a second
+   alternative, you can also specify a certain depth explicitly with a parameter
+   like ``--depth=1``, unless you add branches for stable/longterm kernels.
+
+ * When running ``git fetch``, remember to always specify the oldest version,
+   the time you care about, or an explicit depth as shown in the step-by-step
+   guide. Otherwise you will risk downloading nearly the entire git history,
+   which will consume quite a bit of time and bandwidth while also stressing the
+   servers.
+
+   Note, you do not have to use the same version or date all the time. But when
+   you change it over time, git will deepen or flatten the history to the
+   specified point. That allows you to retrieve versions you initially thought
+   you did not need -- or it will discard the sources of older versions, for
+   example in case you want to free up some disk space. The latter will happen
+   automatically when using ``--shallow-since=`` or
+   ``--depth=``.
+
+ * Be warned, when deepening your clone you might encounter an error like
+   'fatal: error in object: unshallow cafecaca0c0dacafecaca0c0dacafecaca0c0da'.
+   In that case run ``git repack -d`` and try again``
+
+ * In case you want to revert changes from a certain version (say Linux 6.3) or
+   perform a bisection (v6.2..v6.3), better tell ``git fetch`` to retrieve
+   objects up to three versions earlier (e.g. 6.0): ``git describe`` will then
+   be able to describe most commits just like it would in a full git clone.
+
+[:ref:`back to step-by-step guide <sources_sbs>`] [:ref:`back to section intro <sources>`]
+
+.. _sources_archive:
+
+Downloading the sources using a packages archive
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+People new to compiling Linux often assume downloading an archive via the
+front-page of https://kernel.org is the best approach to retrieve Linux'
+sources. It actually can be, if you are certain to build just one particular
+kernel version without changing any code. Thing is: you might be sure this will
+be the case, but in practice it often will turn out to be a wrong assumption.
+
+That's because when reporting or debugging an issue developers will often ask to
+give another version a try. They also might suggest temporarily undoing a commit
+with ``git revert`` or might provide various patches to try. Sometimes reporters
+will also be asked to use ``git bisect`` to find the change causing a problem.
+These things rely on git or are a lot easier and quicker to handle with it.
+
+A shallow clone also does not add any significant overhead. For example, when
+you use ``git clone --depth=1`` to create a shallow clone of the latest mainline
+codebase git will only retrieve a little more data than downloading the latest
+mainline pre-release (aka 'rc') via the front-page of kernel.org would.
+
+A shallow clone therefore is often the better choice. If you nevertheless want
+to use a packaged source archive, download one via kernel.org; afterwards
+extract its content to some directory and change to the subdirectory created
+during extraction. The rest of the step-by-step guide will work just fine, apart
+from things that rely on git -- but this mainly concerns the section on
+successive builds of other versions.
+
+[:ref:`back to step-by-step guide <sources_sbs>`] [:ref:`back to section intro <sources>`]
+
+.. _sources_full:
+
+Downloading the sources using a full git clone
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If downloading and storing a lot of data (~4,4 Gigabyte as of early 2023) is
+nothing that bothers you, instead of a shallow clone perform a full git clone
+instead. You then will avoid the specialties mentioned above and will have all
+versions and individual commits at hand at any time::
+
+    curl -L \
+      https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/clone.bundle \
+      -o linux-stable.git.bundle
+    git clone clone.bundle ~/linux/
+    rm linux-stable.git.bundle
+    cd ~/linux/
+    git remote set-url origin
+    https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
+    git fetch origin
+    git checkout --detach origin/master
+
+[:ref:`back to step-by-step guide <sources_sbs>`] [:ref:`back to section intro <sources>`]
+
+.. _sources_snapshot:
+
+Proper pre-releases (RCs) vs. latest mainline
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When cloning the sources using git and checking out origin/master, you often
+will retrieve a codebase that is somewhere between the latest and the next
+release or pre-release. This almost always is the code you want when giving
+mainline a shot: pre-releases like v6.1-rc5 are in no way special, as they do
+not get any significant extra testing before being published.
+
+There is one exception: you might want to stick to the latest mainline release
+(say v6.1) before its successor's first pre-release (v6.2-rc1) is out. That is
+because compiler errors and other problems are more likely to occur during this
+time, as mainline then is in its 'merge window': a usually two week long phase,
+in which the bulk of the changes for the next release is merged.
+
+[:ref:`back to step-by-step guide <sources_sbs>`] [:ref:`back to section intro <sources>`]
+
+.. _sources_fresher:
+
+Avoiding the mainline lag
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The explanations for both the shallow clone and the full clone both retrieve the
+code from the Linux stable git repository. That makes things simpler for this
+document's audience, as it allows easy access to both mainline and
+stable/longterm releases. This approach has just one downside:
+
+Changes merged into the mainline repository are only synced to the master branch
+of the Linux stable repository  every few hours. This lag most of the time is
+not something to worry about; but in case you really need the latest code, just
+add the mainline repo as additional remote and checkout the code from there::
+
+    git remote add mainline \
+      https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+    git fetch mainline
+    git checkout --detach mainline/master
+
+When doing this with a shallow clone, remember to call ``git fetch`` with one
+of the parameters described earlier to limit the depth.
+
+[:ref:`back to step-by-step guide <sources_sbs>`] [:ref:`back to section intro <sources>`]
+
+.. _patching:
+
+Patch the sources (optional)
+----------------------------
+
+  *In case you want to apply a kernel patch, do so now.*
+  [:ref:`...<patching_sbs>`]
+
+This is the point where you might want to patch your kernel -- for example when
+a developer proposed a fix and asked you to check if it helps. The step-by-step
+guide already explains everything crucial here.
+
+[:ref:`back to step-by-step guide <patching_sbs>`]
+
+.. _tagging:
+
+Tagging this kernel build (optional, often wise)
+------------------------------------------------
+
+  *If you patched your kernel or already have that kernel version installed,
+  better tag your kernel by extending its release name:*
+  [:ref:`...<tagging_sbs>`]
+
+Tagging your kernel will help avoid confusion later, especially when you patched
+your kernel. Adding an individual tag will also ensure the kernel's image and
+its modules are installed in parallel to any existing kernels.
+
+There are various ways to add such a tag. The step-by-step guide realizes one by
+creating a 'localversion' file in your build directory from which the kernel
+build scripts will automatically pick up the tag. You can later change that file
+to use a different tag in subsequent builds or simply remove that file to dump
+the tag.
+
+[:ref:`back to step-by-step guide <tagging_sbs>`]
+
+.. _configuration:
+
+Define the build configuration for your kernel
+----------------------------------------------
+
+  *Create the build configuration for your kernel based on an existing
+  configuration.* [:ref:`... <configuration_sbs>`]
+
+There are various aspects for this steps that require a more careful
+explanation:
+
+Pitfalls when using another configuration file as base
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Make targets like localmodconfig and olddefconfig share a few common snares you
+want to be aware of:
+
+ * These targets will reuse a kernel build configuration in your build directory
+   (e.g. '~/linux/.config'), if one exists. In case you want to start from
+   scratch you thus need to delete it.
+
+ * The make targets try to find the configuration for your running kernel
+   automatically, but might choose poorly. A line like '# using defaults found
+   in /boot/config-6.0.7-250.fc36.x86_64' or 'using config:
+   '/boot/config-6.0.7-250.fc36.x86_64' tells you which file they picked. If
+   that is not the intended one, simply store it as '~/linux/.config'
+   before using these make targets.
+
+ * Unexpected things might happen if you try to use a config file prepared for
+   one kernel (say v6.0) on an older generation (say v5.15). In that case you
+   might want to use a configuration as base which your distribution utilized
+   when they used that or an slightly older kernel version.
+
+Influencing the configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The make target olddefconfig and the ``yes "" |`` used when utilizing
+localmodconfig will set any undefined build options to their default value. This
+among others will disable many kernel features that were introduced after your
+base kernel was released.
+
+If you want to set these configurations options manually, use ``oldconfig``
+instead of ``olddefconfig`` or omit the ``yes "" |`` when utilizing
+localmodconfig. Then for each undefined configuration option you will be asked
+how to proceed. In case you are unsure what to answer, simply hit 'enter' to
+apply the default value.
+
+Big pitfall when using localmodconfig
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As explained briefly in the step-by-step guide already: with localmodconfig it
+can easily happen that your self-built kernel will lack modules for tasks you
+did not perform before utilizing this make target. That's because those tasks
+require kernel modules that are normally autoloaded when you perform that task
+for the first time; if you didn't perform that task at least once before using
+localmodonfig, the latter will thus assume these modules are superfluous and
+disable them.
+
+You can try to avoid this by performing typical tasks that often will autoload
+additional kernel modules: start a VM, establish VPN connections, loop-mount a
+CD/DVD ISO, mount network shares (CIFS, NFS, ...), and connect all external
+devices (2FA keys, headsets, webcams, ...) as well as storage devices with file
+systems you otherwise do not utilize (btrfs, ext4, FAT, NTFS, XFS, ...). But it
+is hard to think of everything that might be needed -- even kernel developers
+often forget one thing or another at this point.
+
+Do not let that risk bother you, especially when compiling a kernel only for
+testing purposes: everything typically crucial will be there. And if you forget
+something important you can turn on a missing feature later and quickly run the
+commands to compile and install a better kernel.
+
+But if you plan to build and use self-built kernels regularly, you might want to
+reduce the risk by recording which modules your system loads over the course of
+a few weeks. You can automate this with `modprobed-db
+<https://github.com/graysky2/modprobed-db>`_. Afterwards use ``LSMOD=<path>`` to
+point localmodconfig to the list of modules modprobed-db noticed being used::
+
+    yes "" | make LSMOD="${HOME}"/.config/modprobed.db localmodconfig
+
+Remote building with localmodconfig
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you want to use localmodconfig to build a kernel for another machine, run
+``lsmod > lsmod_foo-machine`` on it and transfer that file to your build host.
+Now point the build scripts to the file like this: ``yes "" | make
+LSMOD=~/lsmod_foo-machine localmodconfig``. Note, in this case
+you likely want to copy a base kernel configuration from the other machine over
+as well and place it as .config in your build directory.
+
+[:ref:`back to step-by-step guide <configuration_sbs>`]
+
+.. _configmods:
+
+Adjust build configuration
+--------------------------
+
+   *Check if you might want to or have to adjust some kernel configuration
+   options:*
+
+Depending on your needs you at this point might want or have to adjust some
+kernel configuration options.
+
+.. _configmods_debugsymbols:
+
+Debug symbols
+~~~~~~~~~~~~~
+
+   *Evaluate how you want to handle debug symbols.*
+   [:ref:`...<configmods_sbs>`]
+
+Most users do not need to care about this, it's often fine to leave everything
+as it is; but you should take a closer look at this, if you might need to decode
+a stack trace or want to reduce space consumption.
+
+Having debug symbols available can be important when your kernel throws a
+'panic', 'Oops', 'warning', or 'BUG' later when running, as then you will be
+able to find the exact place where the problem occurred in the code. But
+collecting and embedding the needed debug information takes time and consumes
+quite a bit of space: in late 2022 the build artifacts for a typical x86 kernel
+configured with localmodconfig consumed around 5 Gigabyte of space with debug
+symbols, but less than 1 when they were disabled. The resulting kernel image and
+the modules are bigger as well, which increases load times.
+
+Hence, if you want a small kernel and are unlikely to decode a stack trace
+later, you might want to disable debug symbols to avoid above downsides::
+
+    ./scripts/config --file .config -d DEBUG_INFO \
+      -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -d DEBUG_INFO_DWARF4 \
+      -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE
+    make olddefconfig
+
+You on the other hand definitely want to enable them, if there is a decent
+chance that you need to decode a stack trace later (as explained by 'Decode
+failure messages' in Documentation/admin-guide/tainted-kernels.rst in more
+detail)::
+
+    ./scripts/config --file .config -d DEBUG_INFO_NONE -e DEBUG_KERNEL
+      -e DEBUG_INFO -e DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -e KALLSYMS -e KALLSYMS_ALL
+    make olddefconfig
+
+Note, many mainstream distributions enable debug symbols in their kernel
+configurations -- make targets like localmodconfig and olddefconfig thus will
+often pick that setting up.
+
+[:ref:`back to step-by-step guide <configmods_sbs>`]
+
+.. _configmods_distros:
+
+Distro specific adjustments
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+   *Are you running* [:ref:`... <configmods_sbs>`]
+
+The following sections help you to avoid build problems that are known to occur
+when following this guide on a few commodity distributions.
+
+**Debian:**
+
+ * Remove a stale reference to a certificate file that would cause your build to
+   fail::
+
+    ./scripts/config --file .config --set-str SYSTEM_TRUSTED_KEYS ''
+
+   Alternatively, download the needed certificate and make that configuration
+   option point to it, as `the Debian handbook explains in more detail
+   <https://debian-handbook.info/browse/stable/sect.kernel-compilation.html>`_
+   -- or generate your own, as explained in
+   Documentation/admin-guide/module-signing.rst.
+
+[:ref:`back to step-by-step guide <configmods_sbs>`]
+
+.. _configmods_individual:
+
+Individual adjustments
+~~~~~~~~~~~~~~~~~~~~~~
+
+   *If you want to influence the other aspects of the configuration, do so
+   now* [:ref:`... <configmods_sbs>`]
+
+You at this point can use a command like ``make menuconfig`` to enable or
+disable certain features using a text-based user interface; to use a graphical
+configuration utilize, use the make target ``xconfig`` or ``gconfig`` instead.
+All of them require development libraries from toolkits they are based on
+(ncurses, Qt5, Gtk2); an error message will tell you if something required is
+missing.
+
+[:ref:`back to step-by-step guide <configmods_sbs>`]
+
+.. _build:
+
+Build your kernel
+-----------------
+
+  *Build the image and the modules of your kernel* [:ref:`... <build_sbs>`]
+
+A lot can go wrong at this stage, but the instructions below will help you help
+yourself. Another subsection explains how to directly package your kernel up as
+deb, rpm or tar file.
+
+Dealing with build errors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When a build error occurs, it might be caused by some aspect of your machine's
+setup that often can be fixed quickly; other times though the problem lies in
+the code and can only be fixed by a developer. A close examination of the
+failure messages coupled with some research on the internet will often tell you
+which of the two it is. To perform such a investigation, restart the build
+process like this::
+
+    make V=1
+
+The ``V=1`` activates verbose output, which might be needed to see the actual
+error. To make it easier to spot, this command also omits the ``-j $(nproc
+--all)`` used earlier to utilize every CPU core in the system for the job -- but
+this parallelism also results in some clutter when failures occur.
+
+After a few seconds the build process should run into the error again. Now try
+to find the most crucial line describing the problem. Then search the internet
+for the most important and non-generic section of that line (say 4 to 8 words);
+avoid or remove anything that looks remotely system-specific, like your username
+or local path names like ``/home/username/linux/``. First try your regular
+internet search engine with that string, afterwards search Linux kernel mailing
+lists via `lore.kernel.org/all/ <https://lore.kernel.org/all/>`_.
+
+This most of the time will find something that will explain what is wrong; quite
+often one of the hits will provide a solution for your problem, too. If you
+do not find anything that matches your problem, try again from a different angle
+by modifying your search terms or using another line from the error messages.
+
+In the end, most trouble you are to run into has likely been encountered and
+reported by others already. That includes issues where the cause is not your
+system, but lies the code. If you run into one of those, you might thus find a
+solution (e.g. a patch) or workaround for your problem, too.
+
+Package your kernel up
+~~~~~~~~~~~~~~~~~~~~~~
+
+The step-by-step guide uses the default make targets (e.g. 'bzImage' and
+'modules' on x86) to build the image and the modules of your kernel, which later
+steps of the guide then install. You instead can also directly build everything
+and directly package it up by using one of the following targets:
+
+ * ``make -j $(nproc --all) bindeb-pkg`` to generate a deb package
+
+ * ``make -j $(nproc --all) binrpm-pkg`` to generate a rpm package
+
+ * ``make -j $(nproc --all) tarbz2-pkg`` to generate a bz2 compressed tarball
+
+This is just a selection of available make targets for this purpose, see
+``make help`` for others. You can also use these targets after running
+``make -j $(nproc --all)``, as they will pick up everything already built.
+
+If you employ the targets to generate deb or rpm packages, ignore the
+step-by-step guide's instructions on installing and removing your kernel;
+instead install and remove the packages using the package utility for the format
+(e.g. dpkg and rpm) or a package management utility build on top of them (apt,
+aptitude, dnf/yum, zypper, ...). Be aware that the packages generated using
+these two make targets are designed to work on various distributions utilizing
+those formats, they thus will sometimes behave differently than your
+distribution's kernel packages.
+
+[:ref:`back to step-by-step guide <build_sbs>`]
+
+.. _install:
+
+Install your kernel
+-------------------
+
+  *Now install your kernel* [:ref:`... <install_sbs>`]
+
+What you need to do after executing the command in the step-by-step guide
+depends on the existence and the implementation of an ``installkernel``
+executable. Many commodity Linux distributions ship such a kernel installer in
+``/sbin/`` that does everything needed, hence there is nothing left for you
+except rebooting. But some distributions contain an installkernel that does
+only part of the job -- and a few lack it completely and leave all the work to
+you.
+
+If ``installkernel`` is found, the kernel's build system will delegate the
+actual installation of your kernel's image and related files to this executable.
+On almost all Linux distributions it will store the image as '/boot/vmlinuz-
+<your kernel's release name>' and put a 'System.map-<your kernel's release
+name>' alongside it. Your kernel will thus be installed in parallel to any
+existing ones, unless you already have one with exactly the same release name.
+
+Installkernel on many distributions will afterwards generate an 'initramfs'
+(often also called 'initrd'), which commodity distributions rely on for booting;
+hence be sure to keep the order of the two make targets used in the step-by-step
+guide, as things will go sideways if you install your kernel's image before its
+modules. Often installkernel will then add your kernel to the bootloader
+configuration, too. You have to take care of one or both of these tasks
+yourself, if your distributions installkernel doesn't handle them.
+
+A few distributions like Arch Linux and its derivatives totally lack an
+installkernel executable. On those just install the modules using the kernel's
+build system and then install the image and the System.map file manually::
+
+     sudo make modules_install
+     sudo install -m 0600 $(make -s image_name) /boot/vmlinuz-$(make -s kernelrelease)
+     sudo install -m 0600 System.map /boot/System.map-$(make -s kernelrelease)
+
+If your distribution boots with the help of an initramfs, now generate one for
+your kernel using the tools your distribution provides for this process.
+Afterwards add your kernel to your bootloader configuration and reboot.
+
+[:ref:`back to step-by-step guide <install_sbs>`]
+
+.. _another:
+
+Another round later
+-------------------
+
+  *To later build another kernel you need similar, but sometimes slightly
+  different commands* [:ref:`... <another_sbs>`]
+
+The process to build later kernels is similar, but at some points slightly
+different. You for example do not want to use 'localmodconfig' for succeeding
+kernel builds, as you already created a trimmed down configuration you want to
+use from now on. Hence instead just use ``oldconfig`` or ``olddefconfig`` to
+adjust your build configurations to the needs of the kernel version you are
+about to build.
+
+If you created a shallow-clone with git, remember what the :ref:`section that
+explained the setup described in more detail <sources>`: you need to use a
+slightly different ``git fetch`` command and when switching to another series
+need to add an additional remote branch.
+
+[:ref:`back to step-by-step guide <another_sbs>`]
+
+.. _uninstall:
+
+Uninstall the kernel later
+--------------------------
+
+  *All parts of your installed kernel are identifiable by its release name and
+  thus easy to remove later.* [:ref:`... <uninstall_sbs>`]
+
+Do not worry installing your kernel manually and thus bypassing your
+distribution's packaging system will totally mess up your machine: all parts of
+your kernel are easy to remove later, as files are stored in two places only and
+normally identifiable by the kernel's release name.
+
+One of the two places is a directory in /lib/modules/, which holds the modules
+for each installed kernel. This directory is named after the kernel's release
+name; hence, to remove all modules for one of your kernels, simply remove its
+modules directory in /lib/modules/.
+
+The other place is /boot/, where typically one to five files will be placed
+during installation of a kernel. All of them usually contain the release name in
+their file name, but how many files and their name depends somewhat on your
+distribution's installkernel executable (:ref:`see above <install>`) and its
+initramfs generator. On some distributions the ``kernel-install`` command
+mentioned in the step-by-step guide will remove all of these files for you --
+and the entry for your kernel in the bootloader configuration at the same time,
+too. On others you have to take care of these steps yourself. The following
+command should interactively remove the two main files of a kernel with the
+release name '6.0.1-foobar'::
+
+    rm -i /boot/{System.map,vmlinuz}-6.0.1-foobar
+
+Now remove the belonging initramfs, which often will be called something like
+``/boot/initramfs-6.0.1-foobar.img`` or ``/boot/initrd.img-6.0.1-foobar``.
+Afterwards check for other files in /boot/ that have '6.0.1-foobar' in their
+name and delete them as well. Now remove the kernel from your bootloader's
+configuration.
+
+Note, be very careful with wildcards like '*' when deleting files or directories
+for kernels manually: you might accidentally remove files of a 6.0.11 kernel
+when all you want is to remove 6.0 or 6.0.1.
+
+[:ref:`back to step-by-step guide <uninstall_sbs>`]
+
+.. _faq:
+
+FAQ
+===
+
+Why does this 'how-to' not work on my system?
+---------------------------------------------
+
+As initially stated, this guide is 'designed to cover everything typically
+needed [to build a kernel] on mainstream Linux distributions running on
+commodity PC or server hardware'. The outlined approach despite this should work
+on many other setups as well. But trying to cover every possible use-case in one
+guide would defeat its purpose, as without such a focus you would need dozens or
+hundreds of constructs along the lines of 'in case you are having <insert
+machine or distro>, you at this point have to do <this and that>
+<instead|additionally>'. Each of which would make the text longer, more
+complicated, and harder to follow.
+
+That being said: this of course is a balancing act. Hence, if you think an
+additional use-case is worth describing, suggest it to the maintainers of this
+document, as :ref:`described above <submit_improvements>`.
+
+
+..
+   end-of-content
+..
+   This document is maintained by Thorsten Leemhuis <linux@leemhuis.info>. If
+   you spot a typo or small mistake, feel free to let him know directly and
+   he'll fix it. You are free to do the same in a mostly informal way if you
+   want to contribute changes to the text -- but for copyright reasons please CC
+   linux-doc@vger.kernel.org and 'sign-off' your contribution as
+   Documentation/process/submitting-patches.rst explains in the section 'Sign
+   your work - the Developer's Certificate of Origin'.
+..
+   This text is available under GPL-2.0+ or CC-BY-4.0, as stated at the top
+   of the file. If you want to distribute this text under CC-BY-4.0 only,
+   please use 'The Linux kernel development community' for author attribution
+   and link this as source:
+   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/admin-guide/quickly-build-trimmed-linux.rst
+..
+   Note: Only the content of this RST file as found in the Linux kernel sources
+   is available under CC-BY-4.0, as versions of this text that were processed
+   (for example by the kernel's build system) might contain content taken from
+   files which use a more restrictive license.
+
index 7b481b2a368e7cbca173a665f339577dae1133f9..8e03751d126d01f6bed53b5f694f2c0a95c59893 100644 (file)
@@ -199,7 +199,7 @@ Architecture (MCA)\ [#f3]_.
   mode).
 
 .. [#f3] For more details about the Machine Check Architecture (MCA),
-  please read Documentation/x86/x86_64/machinecheck.rst at the Kernel tree.
+  please read Documentation/arch/x86/x86_64/machinecheck.rst at the Kernel tree.
 
 EDAC - Error Detection And Correction
 *************************************
index ec62151fe67209d28fe8b5043b80d042c35ad146..2fd5a030235ad05c72f4d167e5d56aaf280876d9 100644 (file)
@@ -395,7 +395,7 @@ might want to be aware of; it for example explains how to add your issue to the
 list of tracked regressions, to ensure it won't fall through the cracks.
 
 What qualifies as security issue is left to your judgment. Consider reading
-Documentation/admin-guide/security-bugs.rst before proceeding, as it
+Documentation/process/security-bugs.rst before proceeding, as it
 provides additional details how to best handle security issues.
 
 An issue is a 'really severe problem' when something totally unacceptably bad
@@ -1269,7 +1269,7 @@ them when sending the report by mail. If you filed it in a bug tracker, forward
 the report's text to these addresses; but on top of it put a small note where
 you mention that you filed it with a link to the ticket.
 
-See Documentation/admin-guide/security-bugs.rst for more information.
+See Documentation/process/security-bugs.rst for more information.
 
 
 Duties after the report went out
diff --git a/Documentation/admin-guide/security-bugs.rst b/Documentation/admin-guide/security-bugs.rst
deleted file mode 100644 (file)
index 82e2983..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-.. _securitybugs:
-
-Security bugs
-=============
-
-Linux kernel developers take security very seriously.  As such, we'd
-like to know when a security bug is found so that it can be fixed and
-disclosed as quickly as possible.  Please report security bugs to the
-Linux kernel security team.
-
-Contact
--------
-
-The Linux kernel security team can be contacted by email at
-<security@kernel.org>.  This is a private list of security officers
-who will help verify the bug report and develop and release a fix.
-If you already have a fix, please include it with your report, as
-that can speed up the process considerably.  It is possible that the
-security team will bring in extra help from area maintainers to
-understand and fix the security vulnerability.
-
-As it is with any bug, the more information provided the easier it
-will be to diagnose and fix.  Please review the procedure outlined in
-'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what
-information is helpful.  Any exploit code is very helpful and will not
-be released without consent from the reporter unless it has already been
-made public.
-
-Please send plain text emails without attachments where possible.
-It is much harder to have a context-quoted discussion about a complex
-issue if all the details are hidden away in attachments.  Think of it like a
-:doc:`regular patch submission <../process/submitting-patches>`
-(even if you don't have a patch yet): describe the problem and impact, list
-reproduction steps, and follow it with a proposed fix, all in plain text.
-
-Disclosure and embargoed information
-------------------------------------
-
-The security list is not a disclosure channel.  For that, see Coordination
-below.
-
-Once a robust fix has been developed, the release process starts.  Fixes
-for publicly known bugs are released immediately.
-
-Although our preference is to release fixes for publicly undisclosed bugs
-as soon as they become available, this may be postponed at the request of
-the reporter or an affected party for up to 7 calendar days from the start
-of the release process, with an exceptional extension to 14 calendar days
-if it is agreed that the criticality of the bug requires more time.  The
-only valid reason for deferring the publication of a fix is to accommodate
-the logistics of QA and large scale rollouts which require release
-coordination.
-
-While embargoed information may be shared with trusted individuals in
-order to develop a fix, such information will not be published alongside
-the fix or on any other disclosure channel without the permission of the
-reporter.  This includes but is not limited to the original bug report
-and followup discussions (if any), exploits, CVE information or the
-identity of the reporter.
-
-In other words our only interest is in getting bugs fixed.  All other
-information submitted to the security list and any followup discussions
-of the report are treated confidentially even after the embargo has been
-lifted, in perpetuity.
-
-Coordination
-------------
-
-Fixes for sensitive bugs, such as those that might lead to privilege
-escalations, may need to be coordinated with the private
-<linux-distros@vs.openwall.org> mailing list so that distribution vendors
-are well prepared to issue a fixed kernel upon public disclosure of the
-upstream fix. Distros will need some time to test the proposed patch and
-will generally request at least a few days of embargo, and vendor update
-publication prefers to happen Tuesday through Thursday. When appropriate,
-the security team can assist with this coordination, or the reporter can
-include linux-distros from the start. In this case, remember to prefix
-the email Subject line with "[vs]" as described in the linux-distros wiki:
-<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>
-
-CVE assignment
---------------
-
-The security team does not normally assign CVEs, nor do we require them
-for reports or fixes, as this can needlessly complicate the process and
-may delay the bug handling. If a reporter wishes to have a CVE identifier
-assigned ahead of public disclosure, they will need to contact the private
-linux-distros list, described above. When such a CVE identifier is known
-before a patch is provided, it is desirable to mention it in the commit
-message if the reporter agrees.
-
-Non-disclosure agreements
--------------------------
-
-The Linux kernel security team is not a formal body and therefore unable
-to enter any non-disclosure agreements.
index 60314953c72841bb9c43149e168edcc91c8a9e46..e3cfffef5a63364624136b6bc36a0e3856e244b9 100644 (file)
@@ -73,6 +73,10 @@ thread-wide, without the need to invoke the kernel directly.  selector
 can be set to SYSCALL_DISPATCH_FILTER_ALLOW or SYSCALL_DISPATCH_FILTER_BLOCK.
 Any other value should terminate the program with a SIGSYS.
 
+Additionally, a tasks syscall user dispatch configuration can be peeked
+and poked via the PTRACE_(GET|SET)_SYSCALL_USER_DISPATCH_CONFIG ptrace
+requests. This is useful for checkpoint/restart software.
+
 Security Notes
 --------------
 
index 4b7bfea28cd770278556e73596b471ef476310f7..d85d90f5d000d863ebd6dc17c8f6422a333899ea 100644 (file)
@@ -95,7 +95,7 @@ is 0x15 and the full version number is 0x234, this file will contain
 the value 340 = 0x154.
 
 See the ``type_of_loader`` and ``ext_loader_type`` fields in
-Documentation/x86/boot.rst for additional information.
+Documentation/arch/x86/boot.rst for additional information.
 
 
 bootloader_version (x86 only)
@@ -105,7 +105,7 @@ The complete bootloader version number.  In the example above, this
 file will contain the value 564 = 0x234.
 
 See the ``type_of_loader`` and ``ext_loader_ver`` fields in
-Documentation/x86/boot.rst for additional information.
+Documentation/arch/x86/boot.rst for additional information.
 
 
 bpf_stats_enabled
index 290fe83ebe828525938878367f2a9e01cbb874da..cba7e5017d3683f8798029a9063b4ca260b30996 100644 (file)
@@ -3,11 +3,10 @@ Unicode support
 
                 Last update: 2005-01-17, version 1.4
 
-This file is maintained by H. Peter Anvin <unicode@lanana.org> as part
-of the Linux Assigned Names And Numbers Authority (LANANA) project.
-The current version can be found at:
-
-           http://www.lanana.org/docs/unicode/admin-guide/unicode.rst
+Note: The original version of this document, which was maintained at
+lanana.org as part of the Linux Assigned Names And Numbers Authority
+(LANANA) project, is no longer existent.  So, this version in the
+mainline Linux kernel is now the maintained main document.
 
 Introduction
 ------------
diff --git a/Documentation/arc/arc.rst b/Documentation/arc/arc.rst
deleted file mode 100644 (file)
index 6c4d978..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-Linux kernel for ARC processors
-*******************************
-
-Other sources of information
-############################
-
-Below are some resources where more information can be found on
-ARC processors and relevant open source projects.
-
-- `<https://embarc.org>`_ - Community portal for open source on ARC.
-  Good place to start to find relevant FOSS projects, toolchain releases,
-  news items and more.
-
-- `<https://github.com/foss-for-synopsys-dwc-arc-processors>`_ -
-  Home for all development activities regarding open source projects for
-  ARC processors. Some of the projects are forks of various upstream projects,
-  where "work in progress" is hosted prior to submission to upstream projects.
-  Other projects are developed by Synopsys and made available to community
-  as open source for use on ARC Processors.
-
-- `Official Synopsys ARC Processors website
-  <https://www.synopsys.com/designware-ip/processor-solutions.html>`_ -
-  location, with access to some IP documentation (`Programmer's Reference
-  Manual, AKA PRM for ARC HS processors
-  <https://www.synopsys.com/dw/doc.php/ds/cc/programmers-reference-manual-ARC-HS.pdf>`_)
-  and free versions of some commercial tools (`Free nSIM
-  <https://www.synopsys.com/cgi-bin/dwarcnsim/req1.cgi>`_ and
-  `MetaWare Light Edition <https://www.synopsys.com/cgi-bin/arcmwtk_lite/reg1.cgi>`_).
-  Please note though, registration is required to access both the documentation and
-  the tools.
-
-Important note on ARC processors configurability
-################################################
-
-ARC processors are highly configurable and several configurable options
-are supported in Linux. Some options are transparent to software
-(i.e cache geometries, some can be detected at runtime and configured
-and used accordingly, while some need to be explicitly selected or configured
-in the kernel's configuration utility (AKA "make menuconfig").
-
-However not all configurable options are supported when an ARC processor
-is to run Linux. SoC design teams should refer to "Appendix E:
-Configuration for ARC Linux" in the ARC HS Databook for configurability
-guidelines.
-
-Following these guidelines and selecting valid configuration options
-up front is critical to help prevent any unwanted issues during
-SoC bringup and software development in general.
-
-Building the Linux kernel for ARC processors
-############################################
-
-The process of kernel building for ARC processors is the same as for any other
-architecture and could be done in 2 ways:
-
-- Cross-compilation: process of compiling for ARC targets on a development
-  host with a different processor architecture (generally x86_64/amd64).
-- Native compilation: process of compiling for ARC on a ARC platform
-  (hardware board or a simulator like QEMU) with complete development environment
-  (GNU toolchain, dtc, make etc) installed on the platform.
-
-In both cases, up-to-date GNU toolchain for ARC for the host is needed.
-Synopsys offers prebuilt toolchain releases which can be used for this purpose,
-available from:
-
-- Synopsys GNU toolchain releases:
-  `<https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases>`_
-
-- Linux kernel compilers collection:
-  `<https://mirrors.edge.kernel.org/pub/tools/crosstool>`_
-
-- Bootlin's toolchain collection: `<https://toolchains.bootlin.com>`_
-
-Once the toolchain is installed in the system, make sure its "bin" folder
-is added in your ``PATH`` environment variable. Then set ``ARCH=arc`` &
-``CROSS_COMPILE=arc-linux`` (or whatever matches installed ARC toolchain prefix)
-and then as usual ``make defconfig && make``.
-
-This will produce "vmlinux" file in the root of the kernel source tree
-usable for loading on the target system via JTAG.
-If you need to get an image usable with U-Boot bootloader,
-type ``make uImage`` and ``uImage`` will be produced in ``arch/arc/boot``
-folder.
diff --git a/Documentation/arc/features.rst b/Documentation/arc/features.rst
deleted file mode 100644 (file)
index b793583..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features arc
diff --git a/Documentation/arc/index.rst b/Documentation/arc/index.rst
deleted file mode 100644 (file)
index 7b098d4..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-===================
-ARC architecture
-===================
-
-.. toctree::
-    :maxdepth: 1
-
-    arc
-
-    features
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/arch.rst b/Documentation/arch.rst
deleted file mode 100644 (file)
index 41a66a8..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-CPU Architectures
-=================
-
-These books provide programming details about architecture-specific
-implementation.
-
-.. toctree::
-   :maxdepth: 2
-
-   arc/index
-   arm/index
-   arm64/index
-   ia64/index
-   loongarch/index
-   m68k/index
-   mips/index
-   nios2/index
-   openrisc/index
-   parisc/index
-   powerpc/index
-   riscv/index
-   s390/index
-   sh/index
-   sparc/index
-   x86/index
-   xtensa/index
diff --git a/Documentation/arch/arc/arc.rst b/Documentation/arch/arc/arc.rst
new file mode 100644 (file)
index 0000000..6c4d978
--- /dev/null
@@ -0,0 +1,85 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Linux kernel for ARC processors
+*******************************
+
+Other sources of information
+############################
+
+Below are some resources where more information can be found on
+ARC processors and relevant open source projects.
+
+- `<https://embarc.org>`_ - Community portal for open source on ARC.
+  Good place to start to find relevant FOSS projects, toolchain releases,
+  news items and more.
+
+- `<https://github.com/foss-for-synopsys-dwc-arc-processors>`_ -
+  Home for all development activities regarding open source projects for
+  ARC processors. Some of the projects are forks of various upstream projects,
+  where "work in progress" is hosted prior to submission to upstream projects.
+  Other projects are developed by Synopsys and made available to community
+  as open source for use on ARC Processors.
+
+- `Official Synopsys ARC Processors website
+  <https://www.synopsys.com/designware-ip/processor-solutions.html>`_ -
+  location, with access to some IP documentation (`Programmer's Reference
+  Manual, AKA PRM for ARC HS processors
+  <https://www.synopsys.com/dw/doc.php/ds/cc/programmers-reference-manual-ARC-HS.pdf>`_)
+  and free versions of some commercial tools (`Free nSIM
+  <https://www.synopsys.com/cgi-bin/dwarcnsim/req1.cgi>`_ and
+  `MetaWare Light Edition <https://www.synopsys.com/cgi-bin/arcmwtk_lite/reg1.cgi>`_).
+  Please note though, registration is required to access both the documentation and
+  the tools.
+
+Important note on ARC processors configurability
+################################################
+
+ARC processors are highly configurable and several configurable options
+are supported in Linux. Some options are transparent to software
+(i.e cache geometries, some can be detected at runtime and configured
+and used accordingly, while some need to be explicitly selected or configured
+in the kernel's configuration utility (AKA "make menuconfig").
+
+However not all configurable options are supported when an ARC processor
+is to run Linux. SoC design teams should refer to "Appendix E:
+Configuration for ARC Linux" in the ARC HS Databook for configurability
+guidelines.
+
+Following these guidelines and selecting valid configuration options
+up front is critical to help prevent any unwanted issues during
+SoC bringup and software development in general.
+
+Building the Linux kernel for ARC processors
+############################################
+
+The process of kernel building for ARC processors is the same as for any other
+architecture and could be done in 2 ways:
+
+- Cross-compilation: process of compiling for ARC targets on a development
+  host with a different processor architecture (generally x86_64/amd64).
+- Native compilation: process of compiling for ARC on a ARC platform
+  (hardware board or a simulator like QEMU) with complete development environment
+  (GNU toolchain, dtc, make etc) installed on the platform.
+
+In both cases, up-to-date GNU toolchain for ARC for the host is needed.
+Synopsys offers prebuilt toolchain releases which can be used for this purpose,
+available from:
+
+- Synopsys GNU toolchain releases:
+  `<https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases>`_
+
+- Linux kernel compilers collection:
+  `<https://mirrors.edge.kernel.org/pub/tools/crosstool>`_
+
+- Bootlin's toolchain collection: `<https://toolchains.bootlin.com>`_
+
+Once the toolchain is installed in the system, make sure its "bin" folder
+is added in your ``PATH`` environment variable. Then set ``ARCH=arc`` &
+``CROSS_COMPILE=arc-linux`` (or whatever matches installed ARC toolchain prefix)
+and then as usual ``make defconfig && make``.
+
+This will produce "vmlinux" file in the root of the kernel source tree
+usable for loading on the target system via JTAG.
+If you need to get an image usable with U-Boot bootloader,
+type ``make uImage`` and ``uImage`` will be produced in ``arch/arc/boot``
+folder.
diff --git a/Documentation/arch/arc/features.rst b/Documentation/arch/arc/features.rst
new file mode 100644 (file)
index 0000000..b793583
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features arc
diff --git a/Documentation/arch/arc/index.rst b/Documentation/arch/arc/index.rst
new file mode 100644 (file)
index 0000000..7b098d4
--- /dev/null
@@ -0,0 +1,17 @@
+===================
+ARC architecture
+===================
+
+.. toctree::
+    :maxdepth: 1
+
+    arc
+
+    features
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/arch/ia64/aliasing.rst b/Documentation/arch/ia64/aliasing.rst
new file mode 100644 (file)
index 0000000..36a1e1d
--- /dev/null
@@ -0,0 +1,246 @@
+==================================
+Memory Attribute Aliasing on IA-64
+==================================
+
+Bjorn Helgaas <bjorn.helgaas@hp.com>
+
+May 4, 2006
+
+
+Memory Attributes
+=================
+
+    Itanium supports several attributes for virtual memory references.
+    The attribute is part of the virtual translation, i.e., it is
+    contained in the TLB entry.  The ones of most interest to the Linux
+    kernel are:
+
+       ==              ======================
+        WB             Write-back (cacheable)
+       UC              Uncacheable
+       WC              Write-coalescing
+       ==              ======================
+
+    System memory typically uses the WB attribute.  The UC attribute is
+    used for memory-mapped I/O devices.  The WC attribute is uncacheable
+    like UC is, but writes may be delayed and combined to increase
+    performance for things like frame buffers.
+
+    The Itanium architecture requires that we avoid accessing the same
+    page with both a cacheable mapping and an uncacheable mapping[1].
+
+    The design of the chipset determines which attributes are supported
+    on which regions of the address space.  For example, some chipsets
+    support either WB or UC access to main memory, while others support
+    only WB access.
+
+Memory Map
+==========
+
+    Platform firmware describes the physical memory map and the
+    supported attributes for each region.  At boot-time, the kernel uses
+    the EFI GetMemoryMap() interface.  ACPI can also describe memory
+    devices and the attributes they support, but Linux/ia64 currently
+    doesn't use this information.
+
+    The kernel uses the efi_memmap table returned from GetMemoryMap() to
+    learn the attributes supported by each region of physical address
+    space.  Unfortunately, this table does not completely describe the
+    address space because some machines omit some or all of the MMIO
+    regions from the map.
+
+    The kernel maintains another table, kern_memmap, which describes the
+    memory Linux is actually using and the attribute for each region.
+    This contains only system memory; it does not contain MMIO space.
+
+    The kern_memmap table typically contains only a subset of the system
+    memory described by the efi_memmap.  Linux/ia64 can't use all memory
+    in the system because of constraints imposed by the identity mapping
+    scheme.
+
+    The efi_memmap table is preserved unmodified because the original
+    boot-time information is required for kexec.
+
+Kernel Identity Mappings
+========================
+
+    Linux/ia64 identity mappings are done with large pages, currently
+    either 16MB or 64MB, referred to as "granules."  Cacheable mappings
+    are speculative[2], so the processor can read any location in the
+    page at any time, independent of the programmer's intentions.  This
+    means that to avoid attribute aliasing, Linux can create a cacheable
+    identity mapping only when the entire granule supports cacheable
+    access.
+
+    Therefore, kern_memmap contains only full granule-sized regions that
+    can referenced safely by an identity mapping.
+
+    Uncacheable mappings are not speculative, so the processor will
+    generate UC accesses only to locations explicitly referenced by
+    software.  This allows UC identity mappings to cover granules that
+    are only partially populated, or populated with a combination of UC
+    and WB regions.
+
+User Mappings
+=============
+
+    User mappings are typically done with 16K or 64K pages.  The smaller
+    page size allows more flexibility because only 16K or 64K has to be
+    homogeneous with respect to memory attributes.
+
+Potential Attribute Aliasing Cases
+==================================
+
+    There are several ways the kernel creates new mappings:
+
+mmap of /dev/mem
+----------------
+
+       This uses remap_pfn_range(), which creates user mappings.  These
+       mappings may be either WB or UC.  If the region being mapped
+       happens to be in kern_memmap, meaning that it may also be mapped
+       by a kernel identity mapping, the user mapping must use the same
+       attribute as the kernel mapping.
+
+       If the region is not in kern_memmap, the user mapping should use
+       an attribute reported as being supported in the EFI memory map.
+
+       Since the EFI memory map does not describe MMIO on some
+       machines, this should use an uncacheable mapping as a fallback.
+
+mmap of /sys/class/pci_bus/.../legacy_mem
+-----------------------------------------
+
+       This is very similar to mmap of /dev/mem, except that legacy_mem
+       only allows mmap of the one megabyte "legacy MMIO" area for a
+       specific PCI bus.  Typically this is the first megabyte of
+       physical address space, but it may be different on machines with
+       several VGA devices.
+
+       "X" uses this to access VGA frame buffers.  Using legacy_mem
+       rather than /dev/mem allows multiple instances of X to talk to
+       different VGA cards.
+
+       The /dev/mem mmap constraints apply.
+
+mmap of /proc/bus/pci/.../??.?
+------------------------------
+
+       This is an MMIO mmap of PCI functions, which additionally may or
+       may not be requested as using the WC attribute.
+
+       If WC is requested, and the region in kern_memmap is either WC
+       or UC, and the EFI memory map designates the region as WC, then
+       the WC mapping is allowed.
+
+       Otherwise, the user mapping must use the same attribute as the
+       kernel mapping.
+
+read/write of /dev/mem
+----------------------
+
+       This uses copy_from_user(), which implicitly uses a kernel
+       identity mapping.  This is obviously safe for things in
+       kern_memmap.
+
+       There may be corner cases of things that are not in kern_memmap,
+       but could be accessed this way.  For example, registers in MMIO
+       space are not in kern_memmap, but could be accessed with a UC
+       mapping.  This would not cause attribute aliasing.  But
+       registers typically can be accessed only with four-byte or
+       eight-byte accesses, and the copy_from_user() path doesn't allow
+       any control over the access size, so this would be dangerous.
+
+ioremap()
+---------
+
+       This returns a mapping for use inside the kernel.
+
+       If the region is in kern_memmap, we should use the attribute
+       specified there.
+
+       If the EFI memory map reports that the entire granule supports
+       WB, we should use that (granules that are partially reserved
+       or occupied by firmware do not appear in kern_memmap).
+
+       If the granule contains non-WB memory, but we can cover the
+       region safely with kernel page table mappings, we can use
+       ioremap_page_range() as most other architectures do.
+
+       Failing all of the above, we have to fall back to a UC mapping.
+
+Past Problem Cases
+==================
+
+mmap of various MMIO regions from /dev/mem by "X" on Intel platforms
+--------------------------------------------------------------------
+
+      The EFI memory map may not report these MMIO regions.
+
+      These must be allowed so that X will work.  This means that
+      when the EFI memory map is incomplete, every /dev/mem mmap must
+      succeed.  It may create either WB or UC user mappings, depending
+      on whether the region is in kern_memmap or the EFI memory map.
+
+mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
+----------------------------------------------------------------------
+
+      The EFI memory map reports the following attributes:
+
+        =============== ======= ==================
+        0x00000-0x9FFFF WB only
+        0xA0000-0xBFFFF UC only (VGA frame buffer)
+        0xC0000-0xFFFFF WB only
+        =============== ======= ==================
+
+      This mmap is done with user pages, not kernel identity mappings,
+      so it is safe to use WB mappings.
+
+      The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
+      which uses a granule-sized UC mapping.  This granule will cover some
+      WB-only memory, but since UC is non-speculative, the processor will
+      never generate an uncacheable reference to the WB-only areas unless
+      the driver explicitly touches them.
+
+mmap of 0x0-0xFFFFF legacy_mem by "X"
+-------------------------------------
+
+      If the EFI memory map reports that the entire range supports the
+      same attributes, we can allow the mmap (and we will prefer WB if
+      supported, as is the case with HP sx[12]000 machines with VGA
+      disabled).
+
+      If EFI reports the range as partly WB and partly UC (as on sx[12]000
+      machines with VGA enabled), we must fail the mmap because there's no
+      safe attribute to use.
+
+      If EFI reports some of the range but not all (as on Intel firmware
+      that doesn't report the VGA frame buffer at all), we should fail the
+      mmap and force the user to map just the specific region of interest.
+
+mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
+------------------------------------------------------------------------
+
+      The EFI memory map reports the following attributes::
+
+        0x00000-0xFFFFF WB only (no VGA MMIO hole)
+
+      This is a special case of the previous case, and the mmap should
+      fail for the same reason as above.
+
+read of /sys/devices/.../rom
+----------------------------
+
+      For VGA devices, this may cause an ioremap() of 0xC0000.  This
+      used to be done with a UC mapping, because the VGA frame buffer
+      at 0xA0000 prevents use of a WB granule.  The UC mapping causes
+      an MCA on HP sx[12]000 chipsets.
+
+      We should use WB page table mappings to avoid covering the VGA
+      frame buffer.
+
+Notes
+=====
+
+    [1] SDM rev 2.2, vol 2, sec 4.4.1.
+    [2] SDM rev 2.2, vol 2, sec 4.4.6.
diff --git a/Documentation/arch/ia64/efirtc.rst b/Documentation/arch/ia64/efirtc.rst
new file mode 100644 (file)
index 0000000..fd83284
--- /dev/null
@@ -0,0 +1,144 @@
+==========================
+EFI Real Time Clock driver
+==========================
+
+S. Eranian <eranian@hpl.hp.com>
+
+March 2000
+
+1. Introduction
+===============
+
+This document describes the efirtc.c driver has provided for
+the IA-64 platform.
+
+The purpose of this driver is to supply an API for kernel and user applications
+to get access to the Time Service offered by EFI version 0.92.
+
+EFI provides 4 calls one can make once the OS is booted: GetTime(),
+SetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this
+driver. We describe those calls as well the design of the driver in the
+following sections.
+
+2. Design Decisions
+===================
+
+The original ideas was to provide a very simple driver to get access to,
+at first, the time of day service. This is required in order to access, in a
+portable way, the CMOS clock. A program like /sbin/hwclock uses such a clock
+to initialize the system view of the time during boot.
+
+Because we wanted to minimize the impact on existing user-level apps using
+the CMOS clock, we decided to expose an API that was very similar to the one
+used today with the legacy RTC driver (driver/char/rtc.c). However, because
+EFI provides a simpler services, not all ioctl() are available. Also
+new ioctl()s have been introduced for things that EFI provides but not the
+legacy.
+
+EFI uses a slightly different way of representing the time, noticeably
+the reference date is different. Year is the using the full 4-digit format.
+The Epoch is January 1st 1998. For backward compatibility reasons we don't
+expose this new way of representing time. Instead we use something very
+similar to the struct tm, i.e. struct rtc_time, as used by hwclock.
+One of the reasons for doing it this way is to allow for EFI to still evolve
+without necessarily impacting any of the user applications. The decoupling
+enables flexibility and permits writing wrapper code is ncase things change.
+
+The driver exposes two interfaces, one via the device file and a set of
+ioctl()s. The other is read-only via the /proc filesystem.
+
+As of today we don't offer a /proc/sys interface.
+
+To allow for a uniform interface between the legacy RTC and EFI time service,
+we have created the include/linux/rtc.h header file to contain only the
+"public" API of the two drivers.  The specifics of the legacy RTC are still
+in include/linux/mc146818rtc.h.
+
+
+3. Time of day service
+======================
+
+The part of the driver gives access to the time of day service of EFI.
+Two ioctl()s, compatible with the legacy RTC calls:
+
+       Read the CMOS clock::
+
+               ioctl(d, RTC_RD_TIME, &rtc);
+
+       Write the CMOS clock::
+
+               ioctl(d, RTC_SET_TIME, &rtc);
+
+The rtc is a pointer to a data structure defined in rtc.h which is close
+to a struct tm::
+
+  struct rtc_time {
+          int tm_sec;
+          int tm_min;
+          int tm_hour;
+          int tm_mday;
+          int tm_mon;
+          int tm_year;
+          int tm_wday;
+          int tm_yday;
+          int tm_isdst;
+  };
+
+The driver takes care of converting back an forth between the EFI time and
+this format.
+
+Those two ioctl()s can be exercised with the hwclock command:
+
+For reading::
+
+       # /sbin/hwclock --show
+       Mon Mar  6 15:32:32 2000  -0.910248 seconds
+
+For setting::
+
+       # /sbin/hwclock --systohc
+
+Root privileges are required to be able to set the time of day.
+
+4. Wakeup Alarm service
+=======================
+
+EFI provides an API by which one can program when a machine should wakeup,
+i.e. reboot. This is very different from the alarm provided by the legacy
+RTC which is some kind of interval timer alarm. For this reason we don't use
+the same ioctl()s to get access to the service. Instead we have
+introduced 2 news ioctl()s to the interface of an RTC.
+
+We have added 2 new ioctl()s that are specific to the EFI driver:
+
+       Read the current state of the alarm::
+
+               ioctl(d, RTC_WKALM_RD, &wkt)
+
+       Set the alarm or change its status::
+
+               ioctl(d, RTC_WKALM_SET, &wkt)
+
+The wkt structure encapsulates a struct rtc_time + 2 extra fields to get
+status information::
+
+  struct rtc_wkalrm {
+
+          unsigned char enabled; /* =1 if alarm is enabled */
+          unsigned char pending; /* =1 if alarm is pending  */
+
+          struct rtc_time time;
+  }
+
+As of today, none of the existing user-level apps supports this feature.
+However writing such a program should be hard by simply using those two
+ioctl().
+
+Root privileges are required to be able to set the alarm.
+
+5. References
+=============
+
+Checkout the following Web site for more information on EFI:
+
+http://developer.intel.com/technology/efi/
diff --git a/Documentation/arch/ia64/err_inject.rst b/Documentation/arch/ia64/err_inject.rst
new file mode 100644 (file)
index 0000000..900f71e
--- /dev/null
@@ -0,0 +1,1067 @@
+========================================
+IPF Machine Check (MC) error inject tool
+========================================
+
+IPF Machine Check (MC) error inject tool is used to inject MC
+errors from Linux. The tool is a test bed for IPF MC work flow including
+hardware correctable error handling, OS recoverable error handling, MC
+event logging, etc.
+
+The tool includes two parts: a kernel driver and a user application
+sample. The driver provides interface to PAL to inject error
+and query error injection capabilities. The driver code is in
+arch/ia64/kernel/err_inject.c. The application sample (shown below)
+provides a combination of various errors and calls the driver's interface
+(sysfs interface) to inject errors or query error injection capabilities.
+
+The tool can be used to test Intel IPF machine MC handling capabilities.
+It's especially useful for people who can not access hardware MC injection
+tool to inject error. It's also very useful to integrate with other
+software test suits to do stressful testing on IPF.
+
+Below is a sample application as part of the whole tool. The sample
+can be used as a working test tool. Or it can be expanded to include
+more features. It also can be a integrated into a library or other user
+application to have more thorough test.
+
+The sample application takes err.conf as error configuration input. GCC
+compiles the code. After you install err_inject driver, you can run
+this sample application to inject errors.
+
+Errata: Itanium 2 Processors Specification Update lists some errata against
+the pal_mc_error_inject PAL procedure. The following err.conf has been tested
+on latest Montecito PAL.
+
+err.conf::
+
+  #This is configuration file for err_inject_tool.
+  #The format of the each line is:
+  #cpu, loop, interval, err_type_info, err_struct_info, err_data_buffer
+  #where
+  #    cpu: logical cpu number the error will be inject in.
+  #    loop: times the error will be injected.
+  #    interval: In second. every so often one error is injected.
+  #    err_type_info, err_struct_info: PAL parameters.
+  #
+  #Note: All values are hex w/o or w/ 0x prefix.
+
+
+  #On cpu2, inject only total 0x10 errors, interval 5 seconds
+  #corrected, data cache, hier-2, physical addr(assigned by tool code).
+  #working on Montecito latest PAL.
+  2, 10, 5, 4101, 95
+
+  #On cpu4, inject and consume total 0x10 errors, interval 5 seconds
+  #corrected, data cache, hier-2, physical addr(assigned by tool code).
+  #working on Montecito latest PAL.
+  4, 10, 5, 4109, 95
+
+  #On cpu15, inject and consume total 0x10 errors, interval 5 seconds
+  #recoverable, DTR0, hier-2.
+  #working on Montecito latest PAL.
+  0xf, 0x10, 5, 4249, 15
+
+The sample application source code:
+
+err_injection_tool.c::
+
+  /*
+   * This program is free software; you can redistribute it and/or modify
+   * it under the terms of the GNU General Public License as published by
+   * the Free Software Foundation; either version 2 of the License, or
+   * (at your option) any later version.
+   *
+   * This program is distributed in the hope that it will be useful, but
+   * WITHOUT ANY WARRANTY; without even the implied warranty of
+   * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+   * NON INFRINGEMENT.  See the GNU General Public License for more
+   * details.
+   *
+   * You should have received a copy of the GNU General Public License
+   * along with this program; if not, write to the Free Software
+   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   *
+   * Copyright (C) 2006 Intel Co
+   *   Fenghua Yu <fenghua.yu@intel.com>
+   *
+   */
+  #include <sys/types.h>
+  #include <sys/stat.h>
+  #include <fcntl.h>
+  #include <stdio.h>
+  #include <sched.h>
+  #include <unistd.h>
+  #include <stdlib.h>
+  #include <stdarg.h>
+  #include <string.h>
+  #include <errno.h>
+  #include <time.h>
+  #include <sys/ipc.h>
+  #include <sys/sem.h>
+  #include <sys/wait.h>
+  #include <sys/mman.h>
+  #include <sys/shm.h>
+
+  #define MAX_FN_SIZE          256
+  #define MAX_BUF_SIZE                 256
+  #define DATA_BUF_SIZE                256
+  #define NR_CPUS              512
+  #define MAX_TASK_NUM         2048
+  #define MIN_INTERVAL         5       // seconds
+  #define      ERR_DATA_BUFFER_SIZE    3       // Three 8-byte.
+  #define PARA_FIELD_NUM               5
+  #define MASK_SIZE            (NR_CPUS/64)
+  #define PATH_FORMAT "/sys/devices/system/cpu/cpu%d/err_inject/"
+
+  int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);
+
+  int verbose;
+  #define vbprintf if (verbose) printf
+
+  int log_info(int cpu, const char *fmt, ...)
+  {
+       FILE *log;
+       char fn[MAX_FN_SIZE];
+       char buf[MAX_BUF_SIZE];
+       va_list args;
+
+       sprintf(fn, "%d.log", cpu);
+       log=fopen(fn, "a+");
+       if (log==NULL) {
+               perror("Error open:");
+               return -1;
+       }
+
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       memset(buf, 0, MAX_BUF_SIZE);
+       vsprintf(buf, fmt, args);
+       va_end(args);
+
+       fwrite(buf, sizeof(buf), 1, log);
+       fclose(log);
+
+       return 0;
+  }
+
+  typedef unsigned long u64;
+  typedef unsigned int  u32;
+
+  typedef union err_type_info_u {
+       struct {
+               u64     mode            : 3,    /* 0-2 */
+                       err_inj         : 3,    /* 3-5 */
+                       err_sev         : 2,    /* 6-7 */
+                       err_struct      : 5,    /* 8-12 */
+                       struct_hier     : 3,    /* 13-15 */
+                       reserved        : 48;   /* 16-63 */
+       } err_type_info_u;
+       u64     err_type_info;
+  } err_type_info_t;
+
+  typedef union err_struct_info_u {
+       struct {
+               u64     siv             : 1,    /* 0     */
+                       c_t             : 2,    /* 1-2   */
+                       cl_p            : 3,    /* 3-5   */
+                       cl_id           : 3,    /* 6-8   */
+                       cl_dp           : 1,    /* 9     */
+                       reserved1       : 22,   /* 10-31 */
+                       tiv             : 1,    /* 32    */
+                       trigger         : 4,    /* 33-36 */
+                       trigger_pl      : 3,    /* 37-39 */
+                       reserved2       : 24;   /* 40-63 */
+       } err_struct_info_cache;
+       struct {
+               u64     siv             : 1,    /* 0     */
+                       tt              : 2,    /* 1-2   */
+                       tc_tr           : 2,    /* 3-4   */
+                       tr_slot         : 8,    /* 5-12  */
+                       reserved1       : 19,   /* 13-31 */
+                       tiv             : 1,    /* 32    */
+                       trigger         : 4,    /* 33-36 */
+                       trigger_pl      : 3,    /* 37-39 */
+                       reserved2       : 24;   /* 40-63 */
+       } err_struct_info_tlb;
+       struct {
+               u64     siv             : 1,    /* 0     */
+                       regfile_id      : 4,    /* 1-4   */
+                       reg_num         : 7,    /* 5-11  */
+                       reserved1       : 20,   /* 12-31 */
+                       tiv             : 1,    /* 32    */
+                       trigger         : 4,    /* 33-36 */
+                       trigger_pl      : 3,    /* 37-39 */
+                       reserved2       : 24;   /* 40-63 */
+       } err_struct_info_register;
+       struct {
+               u64     reserved;
+       } err_struct_info_bus_processor_interconnect;
+       u64     err_struct_info;
+  } err_struct_info_t;
+
+  typedef union err_data_buffer_u {
+       struct {
+               u64     trigger_addr;           /* 0-63         */
+               u64     inj_addr;               /* 64-127       */
+               u64     way             : 5,    /* 128-132      */
+                       index           : 20,   /* 133-152      */
+                                       : 39;   /* 153-191      */
+       } err_data_buffer_cache;
+       struct {
+               u64     trigger_addr;           /* 0-63         */
+               u64     inj_addr;               /* 64-127       */
+               u64     way             : 5,    /* 128-132      */
+                       index           : 20,   /* 133-152      */
+                       reserved        : 39;   /* 153-191      */
+       } err_data_buffer_tlb;
+       struct {
+               u64     trigger_addr;           /* 0-63         */
+       } err_data_buffer_register;
+       struct {
+               u64     reserved;               /* 0-63         */
+       } err_data_buffer_bus_processor_interconnect;
+       u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
+  } err_data_buffer_t;
+
+  typedef union capabilities_u {
+       struct {
+               u64     i               : 1,
+                       d               : 1,
+                       rv              : 1,
+                       tag             : 1,
+                       data            : 1,
+                       mesi            : 1,
+                       dp              : 1,
+                       reserved1       : 3,
+                       pa              : 1,
+                       va              : 1,
+                       wi              : 1,
+                       reserved2       : 20,
+                       trigger         : 1,
+                       trigger_pl      : 1,
+                       reserved3       : 30;
+       } capabilities_cache;
+       struct {
+               u64     d               : 1,
+                       i               : 1,
+                       rv              : 1,
+                       tc              : 1,
+                       tr              : 1,
+                       reserved1       : 27,
+                       trigger         : 1,
+                       trigger_pl      : 1,
+                       reserved2       : 30;
+       } capabilities_tlb;
+       struct {
+               u64     gr_b0           : 1,
+                       gr_b1           : 1,
+                       fr              : 1,
+                       br              : 1,
+                       pr              : 1,
+                       ar              : 1,
+                       cr              : 1,
+                       rr              : 1,
+                       pkr             : 1,
+                       dbr             : 1,
+                       ibr             : 1,
+                       pmc             : 1,
+                       pmd             : 1,
+                       reserved1       : 3,
+                       regnum          : 1,
+                       reserved2       : 15,
+                       trigger         : 1,
+                       trigger_pl      : 1,
+                       reserved3       : 30;
+       } capabilities_register;
+       struct {
+               u64     reserved;
+       } capabilities_bus_processor_interconnect;
+  } capabilities_t;
+
+  typedef struct resources_s {
+       u64     ibr0            : 1,
+               ibr2            : 1,
+               ibr4            : 1,
+               ibr6            : 1,
+               dbr0            : 1,
+               dbr2            : 1,
+               dbr4            : 1,
+               dbr6            : 1,
+               reserved        : 48;
+  } resources_t;
+
+
+  long get_page_size(void)
+  {
+       long page_size=sysconf(_SC_PAGESIZE);
+       return page_size;
+  }
+
+  #define PAGE_SIZE (get_page_size()==-1?0x4000:get_page_size())
+  #define SHM_SIZE (2*PAGE_SIZE*NR_CPUS)
+  #define SHM_VA 0x2000000100000000
+
+  int shmid;
+  void *shmaddr;
+
+  int create_shm(void)
+  {
+       key_t key;
+       char fn[MAX_FN_SIZE];
+
+       /* cpu0 is always existing */
+       sprintf(fn, PATH_FORMAT, 0);
+       if ((key = ftok(fn, 's')) == -1) {
+               perror("ftok");
+               return -1;
+       }
+
+       shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
+       if (shmid == -1) {
+               if (errno==EEXIST) {
+                       shmid = shmget(key, SHM_SIZE, 0);
+                       if (shmid == -1) {
+                               perror("shmget");
+                               return -1;
+                       }
+               }
+               else {
+                       perror("shmget");
+                       return -1;
+               }
+       }
+       vbprintf("shmid=%d", shmid);
+
+       /* connect to the segment: */
+       shmaddr = shmat(shmid, (void *)SHM_VA, 0);
+       if (shmaddr == (void*)-1) {
+               perror("shmat");
+               return -1;
+       }
+
+       memset(shmaddr, 0, SHM_SIZE);
+       mlock(shmaddr, SHM_SIZE);
+
+       return 0;
+  }
+
+  int free_shm()
+  {
+       munlock(shmaddr, SHM_SIZE);
+          shmdt(shmaddr);
+       semctl(shmid, 0, IPC_RMID);
+
+       return 0;
+  }
+
+  #ifdef _SEM_SEMUN_UNDEFINED
+  union semun
+  {
+       int val;
+       struct semid_ds *buf;
+       unsigned short int *array;
+       struct seminfo *__buf;
+  };
+  #endif
+
+  u32 mode=1; /* 1: physical mode; 2: virtual mode. */
+  int one_lock=1;
+  key_t key[NR_CPUS];
+  int semid[NR_CPUS];
+
+  int create_sem(int cpu)
+  {
+       union semun arg;
+       char fn[MAX_FN_SIZE];
+       int sid;
+
+       sprintf(fn, PATH_FORMAT, cpu);
+       sprintf(fn, "%s/%s", fn, "err_type_info");
+       if ((key[cpu] = ftok(fn, 'e')) == -1) {
+               perror("ftok");
+               return -1;
+       }
+
+       if (semid[cpu]!=0)
+               return 0;
+
+       /* clear old semaphore */
+       if ((sid = semget(key[cpu], 1, 0)) != -1)
+               semctl(sid, 0, IPC_RMID);
+
+       /* get one semaphore */
+       if ((semid[cpu] = semget(key[cpu], 1, IPC_CREAT | IPC_EXCL)) == -1) {
+               perror("semget");
+               printf("Please remove semaphore with key=0x%lx, then run the tool.\n",
+                       (u64)key[cpu]);
+               return -1;
+       }
+
+       vbprintf("semid[%d]=0x%lx, key[%d]=%lx\n",cpu,(u64)semid[cpu],cpu,
+               (u64)key[cpu]);
+       /* initialize the semaphore to 1: */
+       arg.val = 1;
+       if (semctl(semid[cpu], 0, SETVAL, arg) == -1) {
+               perror("semctl");
+               return -1;
+       }
+
+       return 0;
+  }
+
+  static int lock(int cpu)
+  {
+       struct sembuf lock;
+
+       lock.sem_num = cpu;
+       lock.sem_op = 1;
+       semop(semid[cpu], &lock, 1);
+
+          return 0;
+  }
+
+  static int unlock(int cpu)
+  {
+       struct sembuf unlock;
+
+       unlock.sem_num = cpu;
+       unlock.sem_op = -1;
+       semop(semid[cpu], &unlock, 1);
+
+          return 0;
+  }
+
+  void free_sem(int cpu)
+  {
+       semctl(semid[cpu], 0, IPC_RMID);
+  }
+
+  int wr_multi(char *fn, unsigned long *data, int size)
+  {
+       int fd;
+       char buf[MAX_BUF_SIZE];
+       int ret;
+
+       if (size==1)
+               sprintf(buf, "%lx", *data);
+       else if (size==3)
+               sprintf(buf, "%lx,%lx,%lx", data[0], data[1], data[2]);
+       else {
+               fprintf(stderr,"write to file with wrong size!\n");
+               return -1;
+       }
+
+       fd=open(fn, O_RDWR);
+       if (!fd) {
+               perror("Error:");
+               return -1;
+       }
+       ret=write(fd, buf, sizeof(buf));
+       close(fd);
+       return ret;
+  }
+
+  int wr(char *fn, unsigned long data)
+  {
+       return wr_multi(fn, &data, 1);
+  }
+
+  int rd(char *fn, unsigned long *data)
+  {
+       int fd;
+       char buf[MAX_BUF_SIZE];
+
+       fd=open(fn, O_RDONLY);
+       if (fd<0) {
+               perror("Error:");
+               return -1;
+       }
+       read(fd, buf, MAX_BUF_SIZE);
+       *data=strtoul(buf, NULL, 16);
+       close(fd);
+       return 0;
+  }
+
+  int rd_status(char *path, int *status)
+  {
+       char fn[MAX_FN_SIZE];
+       sprintf(fn, "%s/status", path);
+       if (rd(fn, (u64*)status)<0) {
+               perror("status reading error.\n");
+               return -1;
+       }
+
+       return 0;
+  }
+
+  int rd_capabilities(char *path, u64 *capabilities)
+  {
+       char fn[MAX_FN_SIZE];
+       sprintf(fn, "%s/capabilities", path);
+       if (rd(fn, capabilities)<0) {
+               perror("capabilities reading error.\n");
+               return -1;
+       }
+
+       return 0;
+  }
+
+  int rd_all(char *path)
+  {
+       unsigned long err_type_info, err_struct_info, err_data_buffer;
+       int status;
+       unsigned long capabilities, resources;
+       char fn[MAX_FN_SIZE];
+
+       sprintf(fn, "%s/err_type_info", path);
+       if (rd(fn, &err_type_info)<0) {
+               perror("err_type_info reading error.\n");
+               return -1;
+       }
+       printf("err_type_info=%lx\n", err_type_info);
+
+       sprintf(fn, "%s/err_struct_info", path);
+       if (rd(fn, &err_struct_info)<0) {
+               perror("err_struct_info reading error.\n");
+               return -1;
+       }
+       printf("err_struct_info=%lx\n", err_struct_info);
+
+       sprintf(fn, "%s/err_data_buffer", path);
+       if (rd(fn, &err_data_buffer)<0) {
+               perror("err_data_buffer reading error.\n");
+               return -1;
+       }
+       printf("err_data_buffer=%lx\n", err_data_buffer);
+
+       sprintf(fn, "%s/status", path);
+       if (rd("status", (u64*)&status)<0) {
+               perror("status reading error.\n");
+               return -1;
+       }
+       printf("status=%d\n", status);
+
+       sprintf(fn, "%s/capabilities", path);
+       if (rd(fn,&capabilities)<0) {
+               perror("capabilities reading error.\n");
+               return -1;
+       }
+       printf("capabilities=%lx\n", capabilities);
+
+       sprintf(fn, "%s/resources", path);
+       if (rd(fn, &resources)<0) {
+               perror("resources reading error.\n");
+               return -1;
+       }
+       printf("resources=%lx\n", resources);
+
+       return 0;
+  }
+
+  int query_capabilities(char *path, err_type_info_t err_type_info,
+                       u64 *capabilities)
+  {
+       char fn[MAX_FN_SIZE];
+       err_struct_info_t err_struct_info;
+       err_data_buffer_t err_data_buffer;
+
+       err_struct_info.err_struct_info=0;
+       memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8);
+
+       sprintf(fn, "%s/err_type_info", path);
+       wr(fn, err_type_info.err_type_info);
+       sprintf(fn, "%s/err_struct_info", path);
+       wr(fn, 0x0);
+       sprintf(fn, "%s/err_data_buffer", path);
+       wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
+
+       // Fire pal_mc_error_inject procedure.
+       sprintf(fn, "%s/call_start", path);
+       wr(fn, mode);
+
+       if (rd_capabilities(path, capabilities)<0)
+               return -1;
+
+       return 0;
+  }
+
+  int query_all_capabilities()
+  {
+       int status;
+       err_type_info_t err_type_info;
+       int err_sev, err_struct, struct_hier;
+       int cap=0;
+       u64 capabilities;
+       char path[MAX_FN_SIZE];
+
+       err_type_info.err_type_info=0;                  // Initial
+       err_type_info.err_type_info_u.mode=0;           // Query mode;
+       err_type_info.err_type_info_u.err_inj=0;
+
+       printf("All capabilities implemented in pal_mc_error_inject:\n");
+       sprintf(path, PATH_FORMAT ,0);
+       for (err_sev=0;err_sev<3;err_sev++)
+               for (err_struct=0;err_struct<5;err_struct++)
+                       for (struct_hier=0;struct_hier<5;struct_hier++)
+       {
+               status=-1;
+               capabilities=0;
+               err_type_info.err_type_info_u.err_sev=err_sev;
+               err_type_info.err_type_info_u.err_struct=err_struct;
+               err_type_info.err_type_info_u.struct_hier=struct_hier;
+
+               if (query_capabilities(path, err_type_info, &capabilities)<0)
+                       continue;
+
+               if (rd_status(path, &status)<0)
+                       continue;
+
+               if (status==0) {
+                       cap=1;
+                       printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ",
+                               err_sev, err_struct, struct_hier);
+                       printf("capabilities 0x%lx\n", capabilities);
+               }
+       }
+       if (!cap) {
+               printf("No capabilities supported.\n");
+               return 0;
+       }
+
+       return 0;
+  }
+
+  int err_inject(int cpu, char *path, err_type_info_t err_type_info,
+               err_struct_info_t err_struct_info,
+               err_data_buffer_t err_data_buffer)
+  {
+       int status;
+       char fn[MAX_FN_SIZE];
+
+       log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ",
+               err_type_info.err_type_info,
+               err_struct_info.err_struct_info);
+       log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n",
+               err_data_buffer.err_data_buffer[0],
+               err_data_buffer.err_data_buffer[1],
+               err_data_buffer.err_data_buffer[2]);
+       sprintf(fn, "%s/err_type_info", path);
+       wr(fn, err_type_info.err_type_info);
+       sprintf(fn, "%s/err_struct_info", path);
+       wr(fn, err_struct_info.err_struct_info);
+       sprintf(fn, "%s/err_data_buffer", path);
+       wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
+
+       // Fire pal_mc_error_inject procedure.
+       sprintf(fn, "%s/call_start", path);
+       wr(fn,mode);
+
+       if (rd_status(path, &status)<0) {
+               vbprintf("fail: read status\n");
+               return -100;
+       }
+
+       if (status!=0) {
+               log_info(cpu, "fail: status=%d\n", status);
+               return status;
+       }
+
+       return status;
+  }
+
+  static int construct_data_buf(char *path, err_type_info_t err_type_info,
+               err_struct_info_t err_struct_info,
+               err_data_buffer_t *err_data_buffer,
+               void *va1)
+  {
+       char fn[MAX_FN_SIZE];
+       u64 virt_addr=0, phys_addr=0;
+
+       vbprintf("va1=%lx\n", (u64)va1);
+       memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8);
+
+       switch (err_type_info.err_type_info_u.err_struct) {
+               case 1: // Cache
+                       switch (err_struct_info.err_struct_info_cache.cl_id) {
+                               case 1: //Virtual addr
+                                       err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1;
+                                       break;
+                               case 2: //Phys addr
+                                       sprintf(fn, "%s/virtual_to_phys", path);
+                                       virt_addr=(u64)va1;
+                                       if (wr(fn,virt_addr)<0)
+                                               return -1;
+                                       rd(fn, &phys_addr);
+                                       err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr;
+                                       break;
+                               default:
+                                       printf("Not supported cl_id\n");
+                                       break;
+                       }
+                       break;
+               case 2: //  TLB
+                       break;
+               case 3: //  Register file
+                       break;
+               case 4: //  Bus/system interconnect
+               default:
+                       printf("Not supported err_struct\n");
+                       break;
+       }
+
+       return 0;
+  }
+
+  typedef struct {
+       u64 cpu;
+       u64 loop;
+       u64 interval;
+       u64 err_type_info;
+       u64 err_struct_info;
+       u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
+  } parameters_t;
+
+  parameters_t line_para;
+  int para;
+
+  static int empty_data_buffer(u64 *err_data_buffer)
+  {
+       int empty=1;
+       int i;
+
+       for (i=0;i<ERR_DATA_BUFFER_SIZE; i++)
+          if (err_data_buffer[i]!=-1)
+               empty=0;
+
+       return empty;
+  }
+
+  int err_inj()
+  {
+       err_type_info_t err_type_info;
+       err_struct_info_t err_struct_info;
+       err_data_buffer_t err_data_buffer;
+       int count;
+       FILE *fp;
+       unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf;
+       u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE];
+       int num;
+       int i;
+       char path[MAX_FN_SIZE];
+       parameters_t parameters[MAX_TASK_NUM]={};
+       pid_t child_pid[MAX_TASK_NUM];
+       time_t current_time;
+       int status;
+
+       if (!para) {
+           fp=fopen("err.conf", "r");
+           if (fp==NULL) {
+               perror("Error open err.conf");
+               return -1;
+           }
+
+           num=0;
+           while (!feof(fp)) {
+               char buf[256];
+               memset(buf,0,256);
+               fgets(buf, 256, fp);
+               count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
+                               &cpu, &loop, &interval,&err_type_info_conf,
+                               &err_struct_info_conf,
+                               &err_data_buffer_conf[0],
+                               &err_data_buffer_conf[1],
+                               &err_data_buffer_conf[2]);
+               if (count!=PARA_FIELD_NUM+3) {
+                       err_data_buffer_conf[0]=-1;
+                       err_data_buffer_conf[1]=-1;
+                       err_data_buffer_conf[2]=-1;
+                       count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n",
+                               &cpu, &loop, &interval,&err_type_info_conf,
+                               &err_struct_info_conf);
+                       if (count!=PARA_FIELD_NUM)
+                               continue;
+               }
+
+               parameters[num].cpu=cpu;
+               parameters[num].loop=loop;
+               parameters[num].interval= interval>MIN_INTERVAL
+                                         ?interval:MIN_INTERVAL;
+               parameters[num].err_type_info=err_type_info_conf;
+               parameters[num].err_struct_info=err_struct_info_conf;
+               memcpy(parameters[num++].err_data_buffer,
+                       err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ;
+
+               if (num>=MAX_TASK_NUM)
+                       break;
+           }
+       }
+       else {
+               parameters[0].cpu=line_para.cpu;
+               parameters[0].loop=line_para.loop;
+               parameters[0].interval= line_para.interval>MIN_INTERVAL
+                                         ?line_para.interval:MIN_INTERVAL;
+               parameters[0].err_type_info=line_para.err_type_info;
+               parameters[0].err_struct_info=line_para.err_struct_info;
+               memcpy(parameters[0].err_data_buffer,
+                       line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ;
+
+               num=1;
+       }
+
+       /* Create semaphore: If one_lock, one semaphore for all processors.
+          Otherwise, one semaphore for each processor. */
+       if (one_lock) {
+               if (create_sem(0)) {
+                       printf("Can not create semaphore...exit\n");
+                       free_sem(0);
+                       return -1;
+               }
+       }
+       else {
+               for (i=0;i<num;i++) {
+                  if (create_sem(parameters[i].cpu)) {
+                       printf("Can not create semaphore for cpu%d...exit\n",i);
+                       free_sem(parameters[num].cpu);
+                       return -1;
+                  }
+               }
+       }
+
+       /* Create a shm segment which will be used to inject/consume errors on.*/
+       if (create_shm()==-1) {
+               printf("Error to create shm...exit\n");
+               return -1;
+       }
+
+       for (i=0;i<num;i++) {
+               pid_t pid;
+
+               current_time=time(NULL);
+               log_info(parameters[i].cpu, "\nBegine at %s", ctime(&current_time));
+               log_info(parameters[i].cpu, "Configurations:\n");
+               log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)",
+                       parameters[i].cpu,
+                       parameters[i].loop,
+                       parameters[i].interval);
+               log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n",
+                       parameters[i].err_type_info,
+                       parameters[i].err_struct_info);
+
+               sprintf(path, PATH_FORMAT, (int)parameters[i].cpu);
+               err_type_info.err_type_info=parameters[i].err_type_info;
+               err_struct_info.err_struct_info=parameters[i].err_struct_info;
+               memcpy(err_data_buffer.err_data_buffer,
+                       parameters[i].err_data_buffer,
+                       ERR_DATA_BUFFER_SIZE*8);
+
+               pid=fork();
+               if (pid==0) {
+                       unsigned long mask[MASK_SIZE];
+                       int j, k;
+
+                       void *va1, *va2;
+
+                       /* Allocate two memory areas va1 and va2 in shm */
+                       va1=shmaddr+parameters[i].cpu*PAGE_SIZE;
+                       va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE;
+
+                       vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2);
+                       memset(va1, 0x1, PAGE_SIZE);
+                       memset(va2, 0x2, PAGE_SIZE);
+
+                       if (empty_data_buffer(err_data_buffer.err_data_buffer))
+                               /* If not specified yet, construct data buffer
+                                * with va1
+                                */
+                               construct_data_buf(path, err_type_info,
+                                       err_struct_info, &err_data_buffer,va1);
+
+                       for (j=0;j<MASK_SIZE;j++)
+                               mask[j]=0;
+
+                       cpu=parameters[i].cpu;
+                       k = cpu%64;
+                       j = cpu/64;
+                       mask[j] = 1UL << k;
+
+                       if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
+                               perror("Error sched_setaffinity:");
+                               return -1;
+                       }
+
+                       for (j=0; j<parameters[i].loop; j++) {
+                               log_info(parameters[i].cpu,"Injection ");
+                               log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ",
+
+                                       parameters[i].cpu,j+1, parameters[i].loop);
+
+                               /* Hold the lock */
+                               if (one_lock)
+                                       lock(0);
+                               else
+                               /* Hold lock on this cpu */
+                                       lock(parameters[i].cpu);
+
+                               if ((status=err_inject(parameters[i].cpu,
+                                          path, err_type_info,
+                                          err_struct_info, err_data_buffer))
+                                          ==0) {
+                                       /* consume the error for "inject only"*/
+                                       memcpy(va2, va1, PAGE_SIZE);
+                                       memcpy(va1, va2, PAGE_SIZE);
+                                       log_info(parameters[i].cpu,
+                                               "successful\n");
+                               }
+                               else {
+                                       log_info(parameters[i].cpu,"fail:");
+                                       log_info(parameters[i].cpu,
+                                               "status=%d\n", status);
+                                       unlock(parameters[i].cpu);
+                                       break;
+                               }
+                               if (one_lock)
+                               /* Release the lock */
+                                       unlock(0);
+                               /* Release lock on this cpu */
+                               else
+                                       unlock(parameters[i].cpu);
+
+                               if (j < parameters[i].loop-1)
+                                       sleep(parameters[i].interval);
+                       }
+                       current_time=time(NULL);
+                       log_info(parameters[i].cpu, "Done at %s", ctime(&current_time));
+                       return 0;
+               }
+               else if (pid<0) {
+                       perror("Error fork:");
+                       continue;
+               }
+               child_pid[i]=pid;
+       }
+       for (i=0;i<num;i++)
+               waitpid(child_pid[i], NULL, 0);
+
+       if (one_lock)
+               free_sem(0);
+       else
+               for (i=0;i<num;i++)
+                       free_sem(parameters[i].cpu);
+
+       printf("All done.\n");
+
+       return 0;
+  }
+
+  void help()
+  {
+       printf("err_inject_tool:\n");
+       printf("\t-q: query all capabilities. default: off\n");
+       printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n");
+       printf("\t-i: inject errors. default: off\n");
+       printf("\t-l: one lock per cpu. default: one lock for all\n");
+       printf("\t-e: error parameters:\n");
+       printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n");
+       printf("\t\t   cpu: logical cpu number the error will be inject in.\n");
+       printf("\t\t   loop: times the error will be injected.\n");
+       printf("\t\t   interval: In second. every so often one error is injected.\n");
+       printf("\t\t   err_type_info, err_struct_info: PAL parameters.\n");
+       printf("\t\t   err_data_buffer: PAL parameter. Optional. If not present,\n");
+       printf("\t\t                    it's constructed by tool automatically. Be\n");
+       printf("\t\t                    careful to provide err_data_buffer and make\n");
+       printf("\t\t                    sure it's working with the environment.\n");
+       printf("\t    Note:no space between error parameters.\n");
+       printf("\t    default: Take error parameters from err.conf instead of command line.\n");
+       printf("\t-v: verbose. default: off\n");
+       printf("\t-h: help\n\n");
+       printf("The tool will take err.conf file as ");
+       printf("input to inject single or multiple errors ");
+       printf("on one or multiple cpus in parallel.\n");
+  }
+
+  int main(int argc, char **argv)
+  {
+       char c;
+       int do_err_inj=0;
+       int do_query_all=0;
+       int count;
+       u32 m;
+
+       /* Default one lock for all cpu's */
+       one_lock=1;
+       while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF)
+               switch (c) {
+                       case 'm':       /* Procedure mode. 1: phys 2: virt */
+                               count=sscanf(optarg, "%x", &m);
+                               if (count!=1 || (m!=1 && m!=2)) {
+                                       printf("Wrong mode number.\n");
+                                       help();
+                                       return -1;
+                               }
+                               mode=m;
+                               break;
+                       case 'i':       /* Inject errors */
+                               do_err_inj=1;
+                               break;
+                       case 'q':       /* Query */
+                               do_query_all=1;
+                               break;
+                       case 'v':       /* Verbose */
+                               verbose=1;
+                               break;
+                       case 'l':       /* One lock per cpu */
+                               one_lock=0;
+                               break;
+                       case 'e':       /* error arguments */
+                               /* Take parameters:
+                                * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer]
+                                * err_data_buffer is optional. Recommend not to specify
+                                * err_data_buffer. Better to use tool to generate it.
+                                */
+                               count=sscanf(optarg,
+                                       "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
+                                       &line_para.cpu,
+                                       &line_para.loop,
+                                       &line_para.interval,
+                                       &line_para.err_type_info,
+                                       &line_para.err_struct_info,
+                                       &line_para.err_data_buffer[0],
+                                       &line_para.err_data_buffer[1],
+                                       &line_para.err_data_buffer[2]);
+                               if (count!=PARA_FIELD_NUM+3) {
+                                   line_para.err_data_buffer[0]=-1,
+                                   line_para.err_data_buffer[1]=-1,
+                                   line_para.err_data_buffer[2]=-1;
+                                   count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n",
+                                               &line_para.cpu,
+                                               &line_para.loop,
+                                               &line_para.interval,
+                                               &line_para.err_type_info,
+                                               &line_para.err_struct_info);
+                                   if (count!=PARA_FIELD_NUM) {
+                                       printf("Wrong error arguments.\n");
+                                       help();
+                                       return -1;
+                                   }
+                               }
+                               para=1;
+                               break;
+                       continue;
+                               break;
+                       case 'h':
+                               help();
+                               return 0;
+                       default:
+                               break;
+               }
+
+       if (do_query_all)
+               query_all_capabilities();
+       if (do_err_inj)
+               err_inj();
+
+       if (!do_query_all &&  !do_err_inj)
+               help();
+
+       return 0;
+  }
diff --git a/Documentation/arch/ia64/features.rst b/Documentation/arch/ia64/features.rst
new file mode 100644 (file)
index 0000000..d7226fd
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features ia64
diff --git a/Documentation/arch/ia64/fsys.rst b/Documentation/arch/ia64/fsys.rst
new file mode 100644 (file)
index 0000000..a702d2c
--- /dev/null
@@ -0,0 +1,303 @@
+===================================
+Light-weight System Calls for IA-64
+===================================
+
+                       Started: 13-Jan-2003
+
+                   Last update: 27-Sep-2003
+
+                     David Mosberger-Tang
+                     <davidm@hpl.hp.com>
+
+Using the "epc" instruction effectively introduces a new mode of
+execution to the ia64 linux kernel.  We call this mode the
+"fsys-mode".  To recap, the normal states of execution are:
+
+  - kernel mode:
+       Both the register stack and the memory stack have been
+       switched over to kernel memory.  The user-level state is saved
+       in a pt-regs structure at the top of the kernel memory stack.
+
+  - user mode:
+       Both the register stack and the kernel stack are in
+       user memory.  The user-level state is contained in the
+       CPU registers.
+
+  - bank 0 interruption-handling mode:
+       This is the non-interruptible state which all
+       interruption-handlers start execution in.  The user-level
+       state remains in the CPU registers and some kernel state may
+       be stored in bank 0 of registers r16-r31.
+
+In contrast, fsys-mode has the following special properties:
+
+  - execution is at privilege level 0 (most-privileged)
+
+  - CPU registers may contain a mixture of user-level and kernel-level
+    state (it is the responsibility of the kernel to ensure that no
+    security-sensitive kernel-level state is leaked back to
+    user-level)
+
+  - execution is interruptible and preemptible (an fsys-mode handler
+    can disable interrupts and avoid all other interruption-sources
+    to avoid preemption)
+
+  - neither the memory-stack nor the register-stack can be trusted while
+    in fsys-mode (they point to the user-level stacks, which may
+    be invalid, or completely bogus addresses)
+
+In summary, fsys-mode is much more similar to running in user-mode
+than it is to running in kernel-mode.  Of course, given that the
+privilege level is at level 0, this means that fsys-mode requires some
+care (see below).
+
+
+How to tell fsys-mode
+=====================
+
+Linux operates in fsys-mode when (a) the privilege level is 0 (most
+privileged) and (b) the stacks have NOT been switched to kernel memory
+yet.  For convenience, the header file <asm-ia64/ptrace.h> provides
+three macros::
+
+       user_mode(regs)
+       user_stack(task,regs)
+       fsys_mode(task,regs)
+
+The "regs" argument is a pointer to a pt_regs structure.  The "task"
+argument is a pointer to the task structure to which the "regs"
+pointer belongs to.  user_mode() returns TRUE if the CPU state pointed
+to by "regs" was executing in user mode (privilege level 3).
+user_stack() returns TRUE if the state pointed to by "regs" was
+executing on the user-level stack(s).  Finally, fsys_mode() returns
+TRUE if the CPU state pointed to by "regs" was executing in fsys-mode.
+The fsys_mode() macro is equivalent to the expression::
+
+       !user_mode(regs) && user_stack(task,regs)
+
+How to write an fsyscall handler
+================================
+
+The file arch/ia64/kernel/fsys.S contains a table of fsyscall-handlers
+(fsyscall_table).  This table contains one entry for each system call.
+By default, a system call is handled by fsys_fallback_syscall().  This
+routine takes care of entering (full) kernel mode and calling the
+normal Linux system call handler.  For performance-critical system
+calls, it is possible to write a hand-tuned fsyscall_handler.  For
+example, fsys.S contains fsys_getpid(), which is a hand-tuned version
+of the getpid() system call.
+
+The entry and exit-state of an fsyscall handler is as follows:
+
+Machine state on entry to fsyscall handler
+------------------------------------------
+
+  ========= ===============================================================
+  r10      0
+  r11      saved ar.pfs (a user-level value)
+  r15      system call number
+  r16      "current" task pointer (in normal kernel-mode, this is in r13)
+  r32-r39   system call arguments
+  b6       return address (a user-level value)
+  ar.pfs    previous frame-state (a user-level value)
+  PSR.be    cleared to zero (i.e., little-endian byte order is in effect)
+  -         all other registers may contain values passed in from user-mode
+  ========= ===============================================================
+
+Required machine state on exit to fsyscall handler
+--------------------------------------------------
+
+  ========= ===========================================================
+  r11      saved ar.pfs (as passed into the fsyscall handler)
+  r15      system call number (as passed into the fsyscall handler)
+  r32-r39   system call arguments (as passed into the fsyscall handler)
+  b6       return address (as passed into the fsyscall handler)
+  ar.pfs    previous frame-state (as passed into the fsyscall handler)
+  ========= ===========================================================
+
+Fsyscall handlers can execute with very little overhead, but with that
+speed comes a set of restrictions:
+
+ * Fsyscall-handlers MUST check for any pending work in the flags
+   member of the thread-info structure and if any of the
+   TIF_ALLWORK_MASK flags are set, the handler needs to fall back on
+   doing a full system call (by calling fsys_fallback_syscall).
+
+ * Fsyscall-handlers MUST preserve incoming arguments (r32-r39, r11,
+   r15, b6, and ar.pfs) because they will be needed in case of a
+   system call restart.  Of course, all "preserved" registers also
+   must be preserved, in accordance to the normal calling conventions.
+
+ * Fsyscall-handlers MUST check argument registers for containing a
+   NaT value before using them in any way that could trigger a
+   NaT-consumption fault.  If a system call argument is found to
+   contain a NaT value, an fsyscall-handler may return immediately
+   with r8=EINVAL, r10=-1.
+
+ * Fsyscall-handlers MUST NOT use the "alloc" instruction or perform
+   any other operation that would trigger mandatory RSE
+   (register-stack engine) traffic.
+
+ * Fsyscall-handlers MUST NOT write to any stacked registers because
+   it is not safe to assume that user-level called a handler with the
+   proper number of arguments.
+
+ * Fsyscall-handlers need to be careful when accessing per-CPU variables:
+   unless proper safe-guards are taken (e.g., interruptions are avoided),
+   execution may be pre-empted and resumed on another CPU at any given
+   time.
+
+ * Fsyscall-handlers must be careful not to leak sensitive kernel'
+   information back to user-level.  In particular, before returning to
+   user-level, care needs to be taken to clear any scratch registers
+   that could contain sensitive information (note that the current
+   task pointer is not considered sensitive: it's already exposed
+   through ar.k6).
+
+ * Fsyscall-handlers MUST NOT access user-memory without first
+   validating access-permission (this can be done typically via
+   probe.r.fault and/or probe.w.fault) and without guarding against
+   memory access exceptions (this can be done with the EX() macros
+   defined by asmmacro.h).
+
+The above restrictions may seem draconian, but remember that it's
+possible to trade off some of the restrictions by paying a slightly
+higher overhead.  For example, if an fsyscall-handler could benefit
+from the shadow register bank, it could temporarily disable PSR.i and
+PSR.ic, switch to bank 0 (bsw.0) and then use the shadow registers as
+needed.  In other words, following the above rules yields extremely
+fast system call execution (while fully preserving system call
+semantics), but there is also a lot of flexibility in handling more
+complicated cases.
+
+Signal handling
+===============
+
+The delivery of (asynchronous) signals must be delayed until fsys-mode
+is exited.  This is accomplished with the help of the lower-privilege
+transfer trap: arch/ia64/kernel/process.c:do_notify_resume_user()
+checks whether the interrupted task was in fsys-mode and, if so, sets
+PSR.lp and returns immediately.  When fsys-mode is exited via the
+"br.ret" instruction that lowers the privilege level, a trap will
+occur.  The trap handler clears PSR.lp again and returns immediately.
+The kernel exit path then checks for and delivers any pending signals.
+
+PSR Handling
+============
+
+The "epc" instruction doesn't change the contents of PSR at all.  This
+is in contrast to a regular interruption, which clears almost all
+bits.  Because of that, some care needs to be taken to ensure things
+work as expected.  The following discussion describes how each PSR bit
+is handled.
+
+======= =======================================================================
+PSR.be Cleared when entering fsys-mode.  A srlz.d instruction is used
+       to ensure the CPU is in little-endian mode before the first
+       load/store instruction is executed.  PSR.be is normally NOT
+       restored upon return from an fsys-mode handler.  In other
+       words, user-level code must not rely on PSR.be being preserved
+       across a system call.
+PSR.up Unchanged.
+PSR.ac Unchanged.
+PSR.mfl Unchanged.  Note: fsys-mode handlers must not write-registers!
+PSR.mfh        Unchanged.  Note: fsys-mode handlers must not write-registers!
+PSR.ic Unchanged.  Note: fsys-mode handlers can clear the bit, if needed.
+PSR.i  Unchanged.  Note: fsys-mode handlers can clear the bit, if needed.
+PSR.pk Unchanged.
+PSR.dt Unchanged.
+PSR.dfl        Unchanged.  Note: fsys-mode handlers must not write-registers!
+PSR.dfh        Unchanged.  Note: fsys-mode handlers must not write-registers!
+PSR.sp Unchanged.
+PSR.pp Unchanged.
+PSR.di Unchanged.
+PSR.si Unchanged.
+PSR.db Unchanged.  The kernel prevents user-level from setting a hardware
+       breakpoint that triggers at any privilege level other than
+       3 (user-mode).
+PSR.lp Unchanged.
+PSR.tb Lazy redirect.  If a taken-branch trap occurs while in
+       fsys-mode, the trap-handler modifies the saved machine state
+       such that execution resumes in the gate page at
+       syscall_via_break(), with privilege level 3.  Note: the
+       taken branch would occur on the branch invoking the
+       fsyscall-handler, at which point, by definition, a syscall
+       restart is still safe.  If the system call number is invalid,
+       the fsys-mode handler will return directly to user-level.  This
+       return will trigger a taken-branch trap, but since the trap is
+       taken _after_ restoring the privilege level, the CPU has already
+       left fsys-mode, so no special treatment is needed.
+PSR.rt Unchanged.
+PSR.cpl        Cleared to 0.
+PSR.is Unchanged (guaranteed to be 0 on entry to the gate page).
+PSR.mc Unchanged.
+PSR.it Unchanged (guaranteed to be 1).
+PSR.id Unchanged.  Note: the ia64 linux kernel never sets this bit.
+PSR.da Unchanged.  Note: the ia64 linux kernel never sets this bit.
+PSR.dd Unchanged.  Note: the ia64 linux kernel never sets this bit.
+PSR.ss Lazy redirect.  If set, "epc" will cause a Single Step Trap to
+       be taken.  The trap handler then modifies the saved machine
+       state such that execution resumes in the gate page at
+       syscall_via_break(), with privilege level 3.
+PSR.ri Unchanged.
+PSR.ed Unchanged.  Note: This bit could only have an effect if an fsys-mode
+       handler performed a speculative load that gets NaTted.  If so, this
+       would be the normal & expected behavior, so no special treatment is
+       needed.
+PSR.bn Unchanged.  Note: fsys-mode handlers may clear the bit, if needed.
+       Doing so requires clearing PSR.i and PSR.ic as well.
+PSR.ia Unchanged.  Note: the ia64 linux kernel never sets this bit.
+======= =======================================================================
+
+Using fast system calls
+=======================
+
+To use fast system calls, userspace applications need simply call
+__kernel_syscall_via_epc().  For example
+
+-- example fgettimeofday() call --
+
+-- fgettimeofday.S --
+
+::
+
+  #include <asm/asmmacro.h>
+
+  GLOBAL_ENTRY(fgettimeofday)
+  .prologue
+  .save ar.pfs, r11
+  mov r11 = ar.pfs
+  .body
+
+  mov r2 = 0xa000000000020660;;  // gate address
+                              // found by inspection of System.map for the
+                              // __kernel_syscall_via_epc() function.  See
+                              // below for how to do this for real.
+
+  mov b7 = r2
+  mov r15 = 1087                      // gettimeofday syscall
+  ;;
+  br.call.sptk.many b6 = b7
+  ;;
+
+  .restore sp
+
+  mov ar.pfs = r11
+  br.ret.sptk.many rp;;              // return to caller
+  END(fgettimeofday)
+
+-- end fgettimeofday.S --
+
+In reality, getting the gate address is accomplished by two extra
+values passed via the ELF auxiliary vector (include/asm-ia64/elf.h)
+
+ * AT_SYSINFO : is the address of __kernel_syscall_via_epc()
+ * AT_SYSINFO_EHDR : is the address of the kernel gate ELF DSO
+
+The ELF DSO is a pre-linked library that is mapped in by the kernel at
+the gate page.  It is a proper ELF shared object so, with a dynamic
+loader that recognises the library, you should be able to make calls to
+the exported functions within it as with any other shared library.
+AT_SYSINFO points into the kernel DSO at the
+__kernel_syscall_via_epc() function for historical reasons (it was
+used before the kernel DSO) and as a convenience.
diff --git a/Documentation/arch/ia64/ia64.rst b/Documentation/arch/ia64/ia64.rst
new file mode 100644 (file)
index 0000000..b725019
--- /dev/null
@@ -0,0 +1,49 @@
+===========================================
+Linux kernel release for the IA-64 Platform
+===========================================
+
+   These are the release notes for Linux since version 2.4 for IA-64
+   platform.  This document provides information specific to IA-64
+   ONLY, to get additional information about the Linux kernel also
+   read the original Linux README provided with the kernel.
+
+Installing the Kernel
+=====================
+
+ - IA-64 kernel installation is the same as the other platforms, see
+   original README for details.
+
+
+Software Requirements
+=====================
+
+   Compiling and running this kernel requires an IA-64 compliant GCC
+   compiler.  And various software packages also compiled with an
+   IA-64 compliant GCC compiler.
+
+
+Configuring the Kernel
+======================
+
+   Configuration is the same, see original README for details.
+
+
+Compiling the Kernel:
+
+ - Compiling this kernel doesn't differ from other platform so read
+   the original README for details BUT make sure you have an IA-64
+   compliant GCC compiler.
+
+IA-64 Specifics
+===============
+
+ - General issues:
+
+    * Hardly any performance tuning has been done. Obvious targets
+      include the library routines (IP checksum, etc.). Less
+      obvious targets include making sure we don't flush the TLB
+      needlessly, etc.
+
+    * SMP locks cleanup/optimization
+
+    * IA32 support.  Currently experimental.  It mostly works.
diff --git a/Documentation/arch/ia64/index.rst b/Documentation/arch/ia64/index.rst
new file mode 100644 (file)
index 0000000..761f215
--- /dev/null
@@ -0,0 +1,19 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==================
+IA-64 Architecture
+==================
+
+.. toctree::
+   :maxdepth: 1
+
+   ia64
+   aliasing
+   efirtc
+   err_inject
+   fsys
+   irq-redir
+   mca
+   serial
+
+   features
diff --git a/Documentation/arch/ia64/irq-redir.rst b/Documentation/arch/ia64/irq-redir.rst
new file mode 100644 (file)
index 0000000..6bbbbe4
--- /dev/null
@@ -0,0 +1,80 @@
+==============================
+IRQ affinity on IA64 platforms
+==============================
+
+07.01.2002, Erich Focht <efocht@ess.nec.de>
+
+
+By writing to /proc/irq/IRQ#/smp_affinity the interrupt routing can be
+controlled. The behavior on IA64 platforms is slightly different from
+that described in Documentation/core-api/irq/irq-affinity.rst for i386 systems.
+
+Because of the usage of SAPIC mode and physical destination mode the
+IRQ target is one particular CPU and cannot be a mask of several
+CPUs. Only the first non-zero bit is taken into account.
+
+
+Usage examples
+==============
+
+The target CPU has to be specified as a hexadecimal CPU mask. The
+first non-zero bit is the selected CPU. This format has been kept for
+compatibility reasons with i386.
+
+Set the delivery mode of interrupt 41 to fixed and route the
+interrupts to CPU #3 (logical CPU number) (2^3=0x08)::
+
+     echo "8" >/proc/irq/41/smp_affinity
+
+Set the default route for IRQ number 41 to CPU 6 in lowest priority
+delivery mode (redirectable)::
+
+     echo "r 40" >/proc/irq/41/smp_affinity
+
+The output of the command::
+
+     cat /proc/irq/IRQ#/smp_affinity
+
+gives the target CPU mask for the specified interrupt vector. If the CPU
+mask is preceded by the character "r", the interrupt is redirectable
+(i.e. lowest priority mode routing is used), otherwise its route is
+fixed.
+
+
+
+Initialization and default behavior
+===================================
+
+If the platform features IRQ redirection (info provided by SAL) all
+IO-SAPIC interrupts are initialized with CPU#0 as their default target
+and the routing is the so called "lowest priority mode" (actually
+fixed SAPIC mode with hint). The XTP chipset registers are used as hints
+for the IRQ routing. Currently in Linux XTP registers can have three
+values:
+
+       - minimal for an idle task,
+       - normal if any other task runs,
+       - maximal if the CPU is going to be switched off.
+
+The IRQ is routed to the CPU with lowest XTP register value, the
+search begins at the default CPU. Therefore most of the interrupts
+will be handled by CPU #0.
+
+If the platform doesn't feature interrupt redirection IOSAPIC fixed
+routing is used. The target CPUs are distributed in a round robin
+manner. IRQs will be routed only to the selected target CPUs. Check
+with::
+
+        cat /proc/interrupts
+
+
+
+Comments
+========
+
+On large (multi-node) systems it is recommended to route the IRQs to
+the node to which the corresponding device is connected.
+For systems like the NEC AzusA we get IRQ node-affinity for free. This
+is because usually the chipsets on each node redirect the interrupts
+only to their own CPUs (as they cannot see the XTP registers on the
+other nodes).
diff --git a/Documentation/arch/ia64/mca.rst b/Documentation/arch/ia64/mca.rst
new file mode 100644 (file)
index 0000000..08270bb
--- /dev/null
@@ -0,0 +1,198 @@
+=============================================================
+An ad-hoc collection of notes on IA64 MCA and INIT processing
+=============================================================
+
+Feel free to update it with notes about any area that is not clear.
+
+---
+
+MCA/INIT are completely asynchronous.  They can occur at any time, when
+the OS is in any state.  Including when one of the cpus is already
+holding a spinlock.  Trying to get any lock from MCA/INIT state is
+asking for deadlock.  Also the state of structures that are protected
+by locks is indeterminate, including linked lists.
+
+---
+
+The complicated ia64 MCA process.  All of this is mandated by Intel's
+specification for ia64 SAL, error recovery and unwind, it is not as
+if we have a choice here.
+
+* MCA occurs on one cpu, usually due to a double bit memory error.
+  This is the monarch cpu.
+
+* SAL sends an MCA rendezvous interrupt (which is a normal interrupt)
+  to all the other cpus, the slaves.
+
+* Slave cpus that receive the MCA interrupt call down into SAL, they
+  end up spinning disabled while the MCA is being serviced.
+
+* If any slave cpu was already spinning disabled when the MCA occurred
+  then it cannot service the MCA interrupt.  SAL waits ~20 seconds then
+  sends an unmaskable INIT event to the slave cpus that have not
+  already rendezvoused.
+
+* Because MCA/INIT can be delivered at any time, including when the cpu
+  is down in PAL in physical mode, the registers at the time of the
+  event are _completely_ undefined.  In particular the MCA/INIT
+  handlers cannot rely on the thread pointer, PAL physical mode can
+  (and does) modify TP.  It is allowed to do that as long as it resets
+  TP on return.  However MCA/INIT events expose us to these PAL
+  internal TP changes.  Hence curr_task().
+
+* If an MCA/INIT event occurs while the kernel was running (not user
+  space) and the kernel has called PAL then the MCA/INIT handler cannot
+  assume that the kernel stack is in a fit state to be used.  Mainly
+  because PAL may or may not maintain the stack pointer internally.
+  Because the MCA/INIT handlers cannot trust the kernel stack, they
+  have to use their own, per-cpu stacks.  The MCA/INIT stacks are
+  preformatted with just enough task state to let the relevant handlers
+  do their job.
+
+* Unlike most other architectures, the ia64 struct task is embedded in
+  the kernel stack[1].  So switching to a new kernel stack means that
+  we switch to a new task as well.  Because various bits of the kernel
+  assume that current points into the struct task, switching to a new
+  stack also means a new value for current.
+
+* Once all slaves have rendezvoused and are spinning disabled, the
+  monarch is entered.  The monarch now tries to diagnose the problem
+  and decide if it can recover or not.
+
+* Part of the monarch's job is to look at the state of all the other
+  tasks.  The only way to do that on ia64 is to call the unwinder,
+  as mandated by Intel.
+
+* The starting point for the unwind depends on whether a task is
+  running or not.  That is, whether it is on a cpu or is blocked.  The
+  monarch has to determine whether or not a task is on a cpu before it
+  knows how to start unwinding it.  The tasks that received an MCA or
+  INIT event are no longer running, they have been converted to blocked
+  tasks.  But (and its a big but), the cpus that received the MCA
+  rendezvous interrupt are still running on their normal kernel stacks!
+
+* To distinguish between these two cases, the monarch must know which
+  tasks are on a cpu and which are not.  Hence each slave cpu that
+  switches to an MCA/INIT stack, registers its new stack using
+  set_curr_task(), so the monarch can tell that the _original_ task is
+  no longer running on that cpu.  That gives us a decent chance of
+  getting a valid backtrace of the _original_ task.
+
+* MCA/INIT can be nested, to a depth of 2 on any cpu.  In the case of a
+  nested error, we want diagnostics on the MCA/INIT handler that
+  failed, not on the task that was originally running.  Again this
+  requires set_curr_task() so the MCA/INIT handlers can register their
+  own stack as running on that cpu.  Then a recursive error gets a
+  trace of the failing handler's "task".
+
+[1]
+    My (Keith Owens) original design called for ia64 to separate its
+    struct task and the kernel stacks.  Then the MCA/INIT data would be
+    chained stacks like i386 interrupt stacks.  But that required
+    radical surgery on the rest of ia64, plus extra hard wired TLB
+    entries with its associated performance degradation.  David
+    Mosberger vetoed that approach.  Which meant that separate kernel
+    stacks meant separate "tasks" for the MCA/INIT handlers.
+
+---
+
+INIT is less complicated than MCA.  Pressing the nmi button or using
+the equivalent command on the management console sends INIT to all
+cpus.  SAL picks one of the cpus as the monarch and the rest are
+slaves.  All the OS INIT handlers are entered at approximately the same
+time.  The OS monarch prints the state of all tasks and returns, after
+which the slaves return and the system resumes.
+
+At least that is what is supposed to happen.  Alas there are broken
+versions of SAL out there.  Some drive all the cpus as monarchs.  Some
+drive them all as slaves.  Some drive one cpu as monarch, wait for that
+cpu to return from the OS then drive the rest as slaves.  Some versions
+of SAL cannot even cope with returning from the OS, they spin inside
+SAL on resume.  The OS INIT code has workarounds for some of these
+broken SAL symptoms, but some simply cannot be fixed from the OS side.
+
+---
+
+The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer
+violations.  Unfortunately MCA/INIT start off as massive layer
+violations (can occur at _any_ time) and they build from there.
+
+At least ia64 makes an attempt at recovering from hardware errors, but
+it is a difficult problem because of the asynchronous nature of these
+errors.  When processing an unmaskable interrupt we sometimes need
+special code to cope with our inability to take any locks.
+
+---
+
+How is ia64 MCA/INIT different from x86 NMI?
+
+* x86 NMI typically gets delivered to one cpu.  MCA/INIT gets sent to
+  all cpus.
+
+* x86 NMI cannot be nested.  MCA/INIT can be nested, to a depth of 2
+  per cpu.
+
+* x86 has a separate struct task which points to one of multiple kernel
+  stacks.  ia64 has the struct task embedded in the single kernel
+  stack, so switching stack means switching task.
+
+* x86 does not call the BIOS so the NMI handler does not have to worry
+  about any registers having changed.  MCA/INIT can occur while the cpu
+  is in PAL in physical mode, with undefined registers and an undefined
+  kernel stack.
+
+* i386 backtrace is not very sensitive to whether a process is running
+  or not.  ia64 unwind is very, very sensitive to whether a process is
+  running or not.
+
+---
+
+What happens when MCA/INIT is delivered what a cpu is running user
+space code?
+
+The user mode registers are stored in the RSE area of the MCA/INIT on
+entry to the OS and are restored from there on return to SAL, so user
+mode registers are preserved across a recoverable MCA/INIT.  Since the
+OS has no idea what unwind data is available for the user space stack,
+MCA/INIT never tries to backtrace user space.  Which means that the OS
+does not bother making the user space process look like a blocked task,
+i.e. the OS does not copy pt_regs and switch_stack to the user space
+stack.  Also the OS has no idea how big the user space RSE and memory
+stacks are, which makes it too risky to copy the saved state to a user
+mode stack.
+
+---
+
+How do we get a backtrace on the tasks that were running when MCA/INIT
+was delivered?
+
+mca.c:::ia64_mca_modify_original_stack().  That identifies and
+verifies the original kernel stack, copies the dirty registers from
+the MCA/INIT stack's RSE to the original stack's RSE, copies the
+skeleton struct pt_regs and switch_stack to the original stack, fills
+in the skeleton structures from the PAL minstate area and updates the
+original stack's thread.ksp.  That makes the original stack look
+exactly like any other blocked task, i.e. it now appears to be
+sleeping.  To get a backtrace, just start with thread.ksp for the
+original task and unwind like any other sleeping task.
+
+---
+
+How do we identify the tasks that were running when MCA/INIT was
+delivered?
+
+If the previous task has been verified and converted to a blocked
+state, then sos->prev_task on the MCA/INIT stack is updated to point to
+the previous task.  You can look at that field in dumps or debuggers.
+To help distinguish between the handler and the original tasks,
+handlers have _TIF_MCA_INIT set in thread_info.flags.
+
+The sos data is always in the MCA/INIT handler stack, at offset
+MCA_SOS_OFFSET.  You can get that value from mca_asm.h or calculate it
+as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct
+ia64_sal_os_state), with 16 byte alignment for all structures.
+
+Also the comm field of the MCA/INIT task is modified to include the pid
+of the original task, for humans to use.  For example, a comm field of
+'MCA 12159' means that pid 12159 was running when the MCA was
+delivered.
diff --git a/Documentation/arch/ia64/serial.rst b/Documentation/arch/ia64/serial.rst
new file mode 100644 (file)
index 0000000..1de70c3
--- /dev/null
@@ -0,0 +1,165 @@
+==============
+Serial Devices
+==============
+
+Serial Device Naming
+====================
+
+    As of 2.6.10, serial devices on ia64 are named based on the
+    order of ACPI and PCI enumeration.  The first device in the
+    ACPI namespace (if any) becomes /dev/ttyS0, the second becomes
+    /dev/ttyS1, etc., and PCI devices are named sequentially
+    starting after the ACPI devices.
+
+    Prior to 2.6.10, there were confusing exceptions to this:
+
+       - Firmware on some machines (mostly from HP) provides an HCDP
+         table[1] that tells the kernel about devices that can be used
+         as a serial console.  If the user specified "console=ttyS0"
+         or the EFI ConOut path contained only UART devices, the
+         kernel registered the device described by the HCDP as
+         /dev/ttyS0.
+
+       - If there was no HCDP, we assumed there were UARTs at the
+         legacy COM port addresses (I/O ports 0x3f8 and 0x2f8), so
+         the kernel registered those as /dev/ttyS0 and /dev/ttyS1.
+
+    Any additional ACPI or PCI devices were registered sequentially
+    after /dev/ttyS0 as they were discovered.
+
+    With an HCDP, device names changed depending on EFI configuration
+    and "console=" arguments.  Without an HCDP, device names didn't
+    change, but we registered devices that might not really exist.
+
+    For example, an HP rx1600 with a single built-in serial port
+    (described in the ACPI namespace) plus an MP[2] (a PCI device) has
+    these ports:
+
+      ==========  ==========     ============    ============   =======
+      Type        MMIO           pre-2.6.10      pre-2.6.10     2.6.10+
+                 address
+                                (EFI console    (EFI console
+                                 on builtin)     on MP port)
+      ==========  ==========     ============    ============   =======
+      builtin     0xff5e0000        ttyS0           ttyS1         ttyS0
+      MP UPS      0xf8031000        ttyS1           ttyS2         ttyS1
+      MP Console  0xf8030000        ttyS2           ttyS0         ttyS2
+      MP 2        0xf8030010        ttyS3           ttyS3         ttyS3
+      MP 3        0xf8030038        ttyS4           ttyS4         ttyS4
+      ==========  ==========     ============    ============   =======
+
+Console Selection
+=================
+
+    EFI knows what your console devices are, but it doesn't tell the
+    kernel quite enough to actually locate them.  The DIG64 HCDP
+    table[1] does tell the kernel where potential serial console
+    devices are, but not all firmware supplies it.  Also, EFI supports
+    multiple simultaneous consoles and doesn't tell the kernel which
+    should be the "primary" one.
+
+    So how do you tell Linux which console device to use?
+
+       - If your firmware supplies the HCDP, it is simplest to
+         configure EFI with a single device (either a UART or a VGA
+         card) as the console.  Then you don't need to tell Linux
+         anything; the kernel will automatically use the EFI console.
+
+         (This works only in 2.6.6 or later; prior to that you had
+         to specify "console=ttyS0" to get a serial console.)
+
+       - Without an HCDP, Linux defaults to a VGA console unless you
+         specify a "console=" argument.
+
+    NOTE: Don't assume that a serial console device will be /dev/ttyS0.
+    It might be ttyS1, ttyS2, etc.  Make sure you have the appropriate
+    entries in /etc/inittab (for getty) and /etc/securetty (to allow
+    root login).
+
+Early Serial Console
+====================
+
+    The kernel can't start using a serial console until it knows where
+    the device lives.  Normally this happens when the driver enumerates
+    all the serial devices, which can happen a minute or more after the
+    kernel starts booting.
+
+    2.6.10 and later kernels have an "early uart" driver that works
+    very early in the boot process.  The kernel will automatically use
+    this if the user supplies an argument like "console=uart,io,0x3f8",
+    or if the EFI console path contains only a UART device and the
+    firmware supplies an HCDP.
+
+Troubleshooting Serial Console Problems
+=======================================
+
+    No kernel output after elilo prints "Uncompressing Linux... done":
+
+       - You specified "console=ttyS0" but Linux changed the device
+         to which ttyS0 refers.  Configure exactly one EFI console
+         device[3] and remove the "console=" option.
+
+       - The EFI console path contains both a VGA device and a UART.
+         EFI and elilo use both, but Linux defaults to VGA.  Remove
+         the VGA device from the EFI console path[3].
+
+       - Multiple UARTs selected as EFI console devices.  EFI and
+         elilo use all selected devices, but Linux uses only one.
+         Make sure only one UART is selected in the EFI console
+         path[3].
+
+       - You're connected to an HP MP port[2] but have a non-MP UART
+         selected as EFI console device.  EFI uses the MP as a
+         console device even when it isn't explicitly selected.
+         Either move the console cable to the non-MP UART, or change
+         the EFI console path[3] to the MP UART.
+
+    Long pause (60+ seconds) between "Uncompressing Linux... done" and
+    start of kernel output:
+
+       - No early console because you used "console=ttyS<n>".  Remove
+         the "console=" option if your firmware supplies an HCDP.
+
+       - If you don't have an HCDP, the kernel doesn't know where
+         your console lives until the driver discovers serial
+         devices.  Use "console=uart,io,0x3f8" (or appropriate
+         address for your machine).
+
+    Kernel and init script output works fine, but no "login:" prompt:
+
+       - Add getty entry to /etc/inittab for console tty.  Look for
+         the "Adding console on ttyS<n>" message that tells you which
+         device is the console.
+
+    "login:" prompt, but can't login as root:
+
+       - Add entry to /etc/securetty for console tty.
+
+    No ACPI serial devices found in 2.6.17 or later:
+
+       - Turn on CONFIG_PNP and CONFIG_PNPACPI.  Prior to 2.6.17, ACPI
+         serial devices were discovered by 8250_acpi.  In 2.6.17,
+         8250_acpi was replaced by the combination of 8250_pnp and
+         CONFIG_PNPACPI.
+
+
+
+[1]
+    http://www.dig64.org/specifications/agreement
+    The table was originally defined as the "HCDP" for "Headless
+    Console/Debug Port."  The current version is the "PCDP" for
+    "Primary Console and Debug Port Devices."
+
+[2]
+    The HP MP (management processor) is a PCI device that provides
+    several UARTs.  One of the UARTs is often used as a console; the
+    EFI Boot Manager identifies it as "Acpi(HWP0002,700)/Pci(...)/Uart".
+    The external connection is usually a 25-pin connector, and a
+    special dongle converts that to three 9-pin connectors, one of
+    which is labelled "Console."
+
+[3]
+    EFI console devices are configured using the EFI Boot Manager
+    "Boot option maintenance" menu.  You may have to interrupt the
+    boot sequence to use this menu, and you will have to reset the
+    box after changing console configuration.
diff --git a/Documentation/arch/index.rst b/Documentation/arch/index.rst
new file mode 100644 (file)
index 0000000..80ee310
--- /dev/null
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+CPU Architectures
+=================
+
+These books provide programming details about architecture-specific
+implementation.
+
+.. toctree::
+   :maxdepth: 2
+
+   arc/index
+   ../arm/index
+   ../arm64/index
+   ia64/index
+   ../loongarch/index
+   m68k/index
+   ../mips/index
+   nios2/index
+   openrisc/index
+   parisc/index
+   ../powerpc/index
+   ../riscv/index
+   ../s390/index
+   sh/index
+   sparc/index
+   x86/index
+   xtensa/index
diff --git a/Documentation/arch/m68k/buddha-driver.rst b/Documentation/arch/m68k/buddha-driver.rst
new file mode 100644 (file)
index 0000000..20e4014
--- /dev/null
@@ -0,0 +1,209 @@
+=====================================
+Amiga Buddha and Catweasel IDE Driver
+=====================================
+
+The Amiga Buddha and Catweasel IDE Driver (part of ide.c) was written by
+Geert Uytterhoeven based on the following specifications:
+
+------------------------------------------------------------------------
+
+Register map of the Buddha IDE controller and the
+Buddha-part of the Catweasel Zorro-II version
+
+The Autoconfiguration has been implemented just as Commodore
+described  in  their  manuals, no tricks have been used (for
+example leaving some address lines out of the equations...).
+If you want to configure the board yourself (for example let
+a  Linux  kernel  configure the card), look at the Commodore
+Docs.  Reading the nibbles should give this information::
+
+  Vendor number: 4626 ($1212)
+  product number: 0 (42 for Catweasel Z-II)
+  Serial number: 0
+  Rom-vector: $1000
+
+The  card  should be a Z-II board, size 64K, not for freemem
+list, Rom-Vektor is valid, no second Autoconfig-board on the
+same card, no space preference, supports "Shutup_forever".
+
+Setting  the  base address should be done in two steps, just
+as  the Amiga Kickstart does:  The lower nibble of the 8-Bit
+address is written to $4a, then the whole Byte is written to
+$48, while it doesn't matter how often you're writing to $4a
+as  long as $48 is not touched.  After $48 has been written,
+the  whole card disappears from $e8 and is mapped to the new
+address just written.  Make sure $4a is written before $48,
+otherwise your chance is only 1:16 to find the board :-).
+
+The local memory-map is even active when mapped to $e8:
+
+==============  ===========================================
+$0-$7e         Autokonfig-space, see Z-II docs.
+
+$80-$7fd       reserved
+
+$7fe           Speed-select Register: Read & Write
+               (description see further down)
+
+$800-$8ff      IDE-Select 0 (Port 0, Register set 0)
+
+$900-$9ff      IDE-Select 1 (Port 0, Register set 1)
+
+$a00-$aff      IDE-Select 2 (Port 1, Register set 0)
+
+$b00-$bff      IDE-Select 3 (Port 1, Register set 1)
+
+$c00-$cff      IDE-Select 4 (Port 2, Register set 0,
+                Catweasel only!)
+
+$d00-$dff      IDE-Select 5 (Port 3, Register set 1,
+               Catweasel only!)
+
+$e00-$eff      local expansion port, on Catweasel Z-II the
+               Catweasel registers are also mapped here.
+               Never touch, use multidisk.device!
+
+$f00           read only, Byte-access: Bit 7 shows the
+               level of the IRQ-line of IDE port 0.
+
+$f01-$f3f      mirror of $f00
+
+$f40           read only, Byte-access: Bit 7 shows the
+               level of the IRQ-line of IDE port 1.
+
+$f41-$f7f      mirror of $f40
+
+$f80           read only, Byte-access: Bit 7 shows the
+               level of the IRQ-line of IDE port 2.
+               (Catweasel only!)
+
+$f81-$fbf      mirror of $f80
+
+$fc0           write-only: Writing any value to this
+               register enables IRQs to be passed from the
+               IDE ports to the Zorro bus. This mechanism
+               has been implemented to be compatible with
+               harddisks that are either defective or have
+               a buggy firmware and pull the IRQ line up
+               while starting up. If interrupts would
+               always be passed to the bus, the computer
+               might not start up. Once enabled, this flag
+               can not be disabled again. The level of the
+               flag can not be determined by software
+               (what for? Write to me if it's necessary!).
+
+$fc1-$fff      mirror of $fc0
+
+$1000-$ffff    Buddha-Rom with offset $1000 in the rom
+               chip. The addresses $0 to $fff of the rom
+               chip cannot be read. Rom is Byte-wide and
+               mapped to even addresses.
+==============  ===========================================
+
+The  IDE ports issue an INT2.  You can read the level of the
+IRQ-lines  of  the  IDE-ports by reading from the three (two
+for  Buddha-only)  registers  $f00, $f40 and $f80.  This way
+more  than one I/O request can be handled and you can easily
+determine  what  driver  has  to serve the INT2.  Buddha and
+Catweasel  expansion  boards  can issue an INT6.  A separate
+memory  map  is available for the I/O module and the sysop's
+I/O module.
+
+The IDE ports are fed by the address lines A2 to A4, just as
+the  Amiga  1200  and  Amiga  4000  IDE ports are.  This way
+existing  drivers  can be easily ported to Buddha.  A move.l
+polls  two  words  out of the same address of IDE port since
+every  word  is  mirrored  once.  movem is not possible, but
+it's  not  necessary  either,  because  you can only speedup
+68000  systems  with  this  technique.   A 68020 system with
+fastmem is faster with move.l.
+
+If you're using the mirrored registers of the IDE-ports with
+A6=1,  the Buddha doesn't care about the speed that you have
+selected  in  the  speed  register (see further down).  With
+A6=1  (for example $840 for port 0, register set 0), a 780ns
+access  is being made.  These registers should be used for a
+command   access   to  the  harddisk/CD-Rom,  since  command
+accesses  are Byte-wide and have to be made slower according
+to the ATA-X3T9 manual.
+
+Now  for the speed-register:  The register is byte-wide, and
+only  the  upper  three  bits are used (Bits 7 to 5).  Bit 4
+must  always  be set to 1 to be compatible with later Buddha
+versions  (if  I'll  ever  update this one).  I presume that
+I'll  never use the lower four bits, but they have to be set
+to 1 by definition.
+
+The  values in this table have to be shifted 5 bits to the
+left and or'd with $1f (this sets the lower 5 bits).
+
+All  the timings have in common:  Select and IOR/IOW rise at
+the  same  time.   IOR  and  IOW have a propagation delay of
+about  30ns  to  the clocks on the Zorro bus, that's why the
+values  are no multiple of 71.  One clock-cycle is 71ns long
+(exactly 70,5 at 14,18 Mhz on PAL systems).
+
+value 0 (Default after reset)
+  497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles)
+  (same timing as the Amiga 1200 does on it's IDE port without
+  accelerator card)
+
+value 1
+  639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+
+value 2
+  781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+
+value 3
+  355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+
+value 4
+  355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles)
+
+value 5
+  355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+
+value 6
+  1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+
+value 7
+  355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+
+When accessing IDE registers with A6=1 (for example $84x),
+the timing will always be mode 0 8-bit compatible, no matter
+what you have selected in the speed register:
+
+781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive.
+
+All  the  timings with a very short select-signal (the 355ns
+fast  accesses)  depend  on the accelerator card used in the
+system:  Sometimes two more clock cycles are inserted by the
+bus  interface,  making  the  whole access 497ns long.  This
+doesn't  affect  the  reliability  of the controller nor the
+performance  of  the  card,  since  this doesn't happen very
+often.
+
+All  the  timings  are  calculated  and  only  confirmed  by
+measurements  that allowed me to count the clock cycles.  If
+the  system  is clocked by an oscillator other than 28,37516
+Mhz  (for  example  the  NTSC-frequency  28,63636 Mhz), each
+clock  cycle is shortened to a bit less than 70ns (not worth
+mentioning).   You  could think of a small performance boost
+by  overclocking  the  system,  but  you would either need a
+multisync  monitor,  or  a  graphics card, and your internal
+diskdrive would go crazy, that's why you shouldn't tune your
+Amiga this way.
+
+Giving  you  the  possibility  to  write  software  that  is
+compatible  with both the Buddha and the Catweasel Z-II, The
+Buddha  acts  just  like  a  Catweasel  Z-II  with no device
+connected  to  the  third  IDE-port.   The IRQ-register $f80
+always  shows a "no IRQ here" on the Buddha, and accesses to
+the  third  IDE  port  are  going into data's Nirwana on the
+Buddha.
+
+Jens Schönfeld february 19th, 1997
+
+updated may 27th, 1997
+
+eMail: sysop@nostlgic.tng.oche.de
diff --git a/Documentation/arch/m68k/features.rst b/Documentation/arch/m68k/features.rst
new file mode 100644 (file)
index 0000000..5107a21
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features m68k
diff --git a/Documentation/arch/m68k/index.rst b/Documentation/arch/m68k/index.rst
new file mode 100644 (file)
index 0000000..0f890db
--- /dev/null
@@ -0,0 +1,20 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+m68k Architecture
+=================
+
+.. toctree::
+   :maxdepth: 2
+
+   kernel-options
+   buddha-driver
+
+   features
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/arch/m68k/kernel-options.rst b/Documentation/arch/m68k/kernel-options.rst
new file mode 100644 (file)
index 0000000..2008a20
--- /dev/null
@@ -0,0 +1,911 @@
+===================================
+Command Line Options for Linux/m68k
+===================================
+
+Last Update: 2 May 1999
+
+Linux/m68k version: 2.2.6
+
+Author: Roman.Hodek@informatik.uni-erlangen.de (Roman Hodek)
+
+Update: jds@kom.auc.dk (Jes Sorensen) and faq@linux-m68k.org (Chris Lawrence)
+
+0) Introduction
+===============
+
+Often I've been asked which command line options the Linux/m68k
+kernel understands, or how the exact syntax for the ... option is, or
+... about the option ... . I hope, this document supplies all the
+answers...
+
+Note that some options might be outdated, their descriptions being
+incomplete or missing. Please update the information and send in the
+patches.
+
+
+1) Overview of the Kernel's Option Processing
+=============================================
+
+The kernel knows three kinds of options on its command line:
+
+  1) kernel options
+  2) environment settings
+  3) arguments for init
+
+To which of these classes an argument belongs is determined as
+follows: If the option is known to the kernel itself, i.e. if the name
+(the part before the '=') or, in some cases, the whole argument string
+is known to the kernel, it belongs to class 1. Otherwise, if the
+argument contains an '=', it is of class 2, and the definition is put
+into init's environment. All other arguments are passed to init as
+command line options.
+
+This document describes the valid kernel options for Linux/m68k in
+the version mentioned at the start of this file. Later revisions may
+add new such options, and some may be missing in older versions.
+
+In general, the value (the part after the '=') of an option is a
+list of values separated by commas. The interpretation of these values
+is up to the driver that "owns" the option. This association of
+options with drivers is also the reason that some are further
+subdivided.
+
+
+2) General Kernel Options
+=========================
+
+2.1) root=
+----------
+
+:Syntax: root=/dev/<device>
+:or:     root=<hex_number>
+
+This tells the kernel which device it should mount as the root
+filesystem. The device must be a block device with a valid filesystem
+on it.
+
+The first syntax gives the device by name. These names are converted
+into a major/minor number internally in the kernel in an unusual way.
+Normally, this "conversion" is done by the device files in /dev, but
+this isn't possible here, because the root filesystem (with /dev)
+isn't mounted yet... So the kernel parses the name itself, with some
+hardcoded name to number mappings. The name must always be a
+combination of two or three letters, followed by a decimal number.
+Valid names are::
+
+  /dev/ram: -> 0x0100 (initial ramdisk)
+  /dev/hda: -> 0x0300 (first IDE disk)
+  /dev/hdb: -> 0x0340 (second IDE disk)
+  /dev/sda: -> 0x0800 (first SCSI disk)
+  /dev/sdb: -> 0x0810 (second SCSI disk)
+  /dev/sdc: -> 0x0820 (third SCSI disk)
+  /dev/sdd: -> 0x0830 (forth SCSI disk)
+  /dev/sde: -> 0x0840 (fifth SCSI disk)
+  /dev/fd : -> 0x0200 (floppy disk)
+
+The name must be followed by a decimal number, that stands for the
+partition number. Internally, the value of the number is just
+added to the device number mentioned in the table above. The
+exceptions are /dev/ram and /dev/fd, where /dev/ram refers to an
+initial ramdisk loaded by your bootstrap program (please consult the
+instructions for your bootstrap program to find out how to load an
+initial ramdisk). As of kernel version 2.0.18 you must specify
+/dev/ram as the root device if you want to boot from an initial
+ramdisk. For the floppy devices, /dev/fd, the number stands for the
+floppy drive number (there are no partitions on floppy disks). I.e.,
+/dev/fd0 stands for the first drive, /dev/fd1 for the second, and so
+on. Since the number is just added, you can also force the disk format
+by adding a number greater than 3. If you look into your /dev
+directory, use can see the /dev/fd0D720 has major 2 and minor 16. You
+can specify this device for the root FS by writing "root=/dev/fd16" on
+the kernel command line.
+
+[Strange and maybe uninteresting stuff ON]
+
+This unusual translation of device names has some strange
+consequences: If, for example, you have a symbolic link from /dev/fd
+to /dev/fd0D720 as an abbreviation for floppy driver #0 in DD format,
+you cannot use this name for specifying the root device, because the
+kernel cannot see this symlink before mounting the root FS and it
+isn't in the table above. If you use it, the root device will not be
+set at all, without an error message. Another example: You cannot use a
+partition on e.g. the sixth SCSI disk as the root filesystem, if you
+want to specify it by name. This is, because only the devices up to
+/dev/sde are in the table above, but not /dev/sdf. Although, you can
+use the sixth SCSI disk for the root FS, but you have to specify the
+device by number... (see below). Or, even more strange, you can use the
+fact that there is no range checking of the partition number, and your
+knowledge that each disk uses 16 minors, and write "root=/dev/sde17"
+(for /dev/sdf1).
+
+[Strange and maybe uninteresting stuff OFF]
+
+If the device containing your root partition isn't in the table
+above, you can also specify it by major and minor numbers. These are
+written in hex, with no prefix and no separator between. E.g., if you
+have a CD with contents appropriate as a root filesystem in the first
+SCSI CD-ROM drive, you boot from it by "root=0b00". Here, hex "0b" =
+decimal 11 is the major of SCSI CD-ROMs, and the minor 0 stands for
+the first of these. You can find out all valid major numbers by
+looking into include/linux/major.h.
+
+In addition to major and minor numbers, if the device containing your
+root partition uses a partition table format with unique partition
+identifiers, then you may use them.  For instance,
+"root=PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF".  It is also
+possible to reference another partition on the same device using a
+known partition UUID as the starting point.  For example,
+if partition 5 of the device has the UUID of
+00112233-4455-6677-8899-AABBCCDDEEFF then partition 3 may be found as
+follows:
+
+  PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=-2
+
+Authoritative information can be found in
+"Documentation/admin-guide/kernel-parameters.rst".
+
+
+2.2) ro, rw
+-----------
+
+:Syntax: ro
+:or:     rw
+
+These two options tell the kernel whether it should mount the root
+filesystem read-only or read-write. The default is read-only, except
+for ramdisks, which default to read-write.
+
+
+2.3) debug
+----------
+
+:Syntax: debug
+
+This raises the kernel log level to 10 (the default is 7). This is the
+same level as set by the "dmesg" command, just that the maximum level
+selectable by dmesg is 8.
+
+
+2.4) debug=
+-----------
+
+:Syntax: debug=<device>
+
+This option causes certain kernel messages be printed to the selected
+debugging device. This can aid debugging the kernel, since the
+messages can be captured and analyzed on some other machine. Which
+devices are possible depends on the machine type. There are no checks
+for the validity of the device name. If the device isn't implemented,
+nothing happens.
+
+Messages logged this way are in general stack dumps after kernel
+memory faults or bad kernel traps, and kernel panics. To be exact: all
+messages of level 0 (panic messages) and all messages printed while
+the log level is 8 or more (their level doesn't matter). Before stack
+dumps, the kernel sets the log level to 10 automatically. A level of
+at least 8 can also be set by the "debug" command line option (see
+2.3) and at run time with "dmesg -n 8".
+
+Devices possible for Amiga:
+
+ - "ser":
+         built-in serial port; parameters: 9600bps, 8N1
+ - "mem":
+         Save the messages to a reserved area in chip mem. After
+          rebooting, they can be read under AmigaOS with the tool
+          'dmesg'.
+
+Devices possible for Atari:
+
+ - "ser1":
+          ST-MFP serial port ("Modem1"); parameters: 9600bps, 8N1
+ - "ser2":
+          SCC channel B serial port ("Modem2"); parameters: 9600bps, 8N1
+ - "ser" :
+          default serial port
+           This is "ser2" for a Falcon, and "ser1" for any other machine
+ - "midi":
+          The MIDI port; parameters: 31250bps, 8N1
+ - "par" :
+          parallel port
+
+           The printing routine for this implements a timeout for the
+           case there's no printer connected (else the kernel would
+           lock up). The timeout is not exact, but usually a few
+           seconds.
+
+
+2.6) ramdisk_size=
+------------------
+
+:Syntax: ramdisk_size=<size>
+
+This option instructs the kernel to set up a ramdisk of the given
+size in KBytes. Do not use this option if the ramdisk contents are
+passed by bootstrap! In this case, the size is selected automatically
+and should not be overwritten.
+
+The only application is for root filesystems on floppy disks, that
+should be loaded into memory. To do that, select the corresponding
+size of the disk as ramdisk size, and set the root device to the disk
+drive (with "root=").
+
+
+2.7) swap=
+
+  I can't find any sign of this option in 2.2.6.
+
+2.8) buff=
+-----------
+
+  I can't find any sign of this option in 2.2.6.
+
+
+3) General Device Options (Amiga and Atari)
+===========================================
+
+3.1) ether=
+-----------
+
+:Syntax: ether=[<irq>[,<base_addr>[,<mem_start>[,<mem_end>]]]],<dev-name>
+
+<dev-name> is the name of a net driver, as specified in
+drivers/net/Space.c in the Linux source. Most prominent are eth0, ...
+eth3, sl0, ... sl3, ppp0, ..., ppp3, dummy, and lo.
+
+The non-ethernet drivers (sl, ppp, dummy, lo) obviously ignore the
+settings by this options. Also, the existing ethernet drivers for
+Linux/m68k (ariadne, a2065, hydra) don't use them because Zorro boards
+are really Plug-'n-Play, so the "ether=" option is useless altogether
+for Linux/m68k.
+
+
+3.2) hd=
+--------
+
+:Syntax: hd=<cylinders>,<heads>,<sectors>
+
+This option sets the disk geometry of an IDE disk. The first hd=
+option is for the first IDE disk, the second for the second one.
+(I.e., you can give this option twice.) In most cases, you won't have
+to use this option, since the kernel can obtain the geometry data
+itself. It exists just for the case that this fails for one of your
+disks.
+
+
+3.3) max_scsi_luns=
+-------------------
+
+:Syntax: max_scsi_luns=<n>
+
+Sets the maximum number of LUNs (logical units) of SCSI devices to
+be scanned. Valid values for <n> are between 1 and 8. Default is 8 if
+"Probe all LUNs on each SCSI device" was selected during the kernel
+configuration, else 1.
+
+
+3.4) st=
+--------
+
+:Syntax: st=<buffer_size>,[<write_thres>,[<max_buffers>]]
+
+Sets several parameters of the SCSI tape driver. <buffer_size> is
+the number of 512-byte buffers reserved for tape operations for each
+device. <write_thres> sets the number of blocks which must be filled
+to start an actual write operation to the tape. Maximum value is the
+total number of buffers. <max_buffer> limits the total number of
+buffers allocated for all tape devices.
+
+
+3.5) dmasound=
+--------------
+
+:Syntax: dmasound=[<buffers>,<buffer-size>[,<catch-radius>]]
+
+This option controls some configurations of the Linux/m68k DMA sound
+driver (Amiga and Atari): <buffers> is the number of buffers you want
+to use (minimum 4, default 4), <buffer-size> is the size of each
+buffer in kilobytes (minimum 4, default 32) and <catch-radius> says
+how much percent of error will be tolerated when setting a frequency
+(maximum 10, default 0). For example with 3% you can play 8000Hz
+AU-Files on the Falcon with its hardware frequency of 8195Hz and thus
+don't need to expand the sound.
+
+
+
+4) Options for Atari Only
+=========================
+
+4.1) video=
+-----------
+
+:Syntax: video=<fbname>:<sub-options...>
+
+The <fbname> parameter specifies the name of the frame buffer,
+eg. most atari users will want to specify `atafb` here. The
+<sub-options> is a comma-separated list of the sub-options listed
+below.
+
+NB:
+    Please notice that this option was renamed from `atavideo` to
+    `video` during the development of the 1.3.x kernels, thus you
+    might need to update your boot-scripts if upgrading to 2.x from
+    an 1.2.x kernel.
+
+NBB:
+    The behavior of video= was changed in 2.1.57 so the recommended
+    option is to specify the name of the frame buffer.
+
+4.1.1) Video Mode
+-----------------
+
+This sub-option may be any of the predefined video modes, as listed
+in atari/atafb.c in the Linux/m68k source tree. The kernel will
+activate the given video mode at boot time and make it the default
+mode, if the hardware allows. Currently defined names are:
+
+ - stlow           : 320x200x4
+ - stmid, default5 : 640x200x2
+ - sthigh, default4: 640x400x1
+ - ttlow           : 320x480x8, TT only
+ - ttmid, default1 : 640x480x4, TT only
+ - tthigh, default2: 1280x960x1, TT only
+ - vga2            : 640x480x1, Falcon only
+ - vga4            : 640x480x2, Falcon only
+ - vga16, default3 : 640x480x4, Falcon only
+ - vga256          : 640x480x8, Falcon only
+ - falh2           : 896x608x1, Falcon only
+ - falh16          : 896x608x4, Falcon only
+
+If no video mode is given on the command line, the kernel tries the
+modes names "default<n>" in turn, until one is possible with the
+hardware in use.
+
+A video mode setting doesn't make sense, if the external driver is
+activated by a "external:" sub-option.
+
+4.1.2) inverse
+--------------
+
+Invert the display. This affects only text consoles.
+Usually, the background is chosen to be black. With this
+option, you can make the background white.
+
+4.1.3) font
+-----------
+
+:Syntax: font:<fontname>
+
+Specify the font to use in text modes. Currently you can choose only
+between `VGA8x8`, `VGA8x16` and `PEARL8x8`. `VGA8x8` is default, if the
+vertical size of the display is less than 400 pixel rows. Otherwise, the
+`VGA8x16` font is the default.
+
+4.1.4) `hwscroll_`
+------------------
+
+:Syntax: `hwscroll_<n>`
+
+The number of additional lines of video memory to reserve for
+speeding up the scrolling ("hardware scrolling"). Hardware scrolling
+is possible only if the kernel can set the video base address in steps
+fine enough. This is true for STE, MegaSTE, TT, and Falcon. It is not
+possible with plain STs and graphics cards (The former because the
+base address must be on a 256 byte boundary there, the latter because
+the kernel doesn't know how to set the base address at all.)
+
+By default, <n> is set to the number of visible text lines on the
+display. Thus, the amount of video memory is doubled, compared to no
+hardware scrolling. You can turn off the hardware scrolling altogether
+by setting <n> to 0.
+
+4.1.5) internal:
+----------------
+
+:Syntax: internal:<xres>;<yres>[;<xres_max>;<yres_max>;<offset>]
+
+This option specifies the capabilities of some extended internal video
+hardware, like e.g. OverScan. <xres> and <yres> give the (extended)
+dimensions of the screen.
+
+If your OverScan needs a black border, you have to write the last
+three arguments of the "internal:". <xres_max> is the maximum line
+length the hardware allows, <yres_max> the maximum number of lines.
+<offset> is the offset of the visible part of the screen memory to its
+physical start, in bytes.
+
+Often, extended interval video hardware has to be activated somehow.
+For this, see the "sw_*" options below.
+
+4.1.6) external:
+----------------
+
+:Syntax:
+  external:<xres>;<yres>;<depth>;<org>;<scrmem>[;<scrlen>[;<vgabase>
+  [;<colw>[;<coltype>[;<xres_virtual>]]]]]
+
+.. I had to break this line...
+
+This is probably the most complicated parameter... It specifies that
+you have some external video hardware (a graphics board), and how to
+use it under Linux/m68k. The kernel cannot know more about the hardware
+than you tell it here! The kernel also is unable to set or change any
+video modes, since it doesn't know about any board internal. So, you
+have to switch to that video mode before you start Linux, and cannot
+switch to another mode once Linux has started.
+
+The first 3 parameters of this sub-option should be obvious: <xres>,
+<yres> and <depth> give the dimensions of the screen and the number of
+planes (depth). The depth is the logarithm to base 2 of the number
+of colors possible. (Or, the other way round: The number of colors is
+2^depth).
+
+You have to tell the kernel furthermore how the video memory is
+organized. This is done by a letter as <org> parameter:
+
+ 'n':
+      "normal planes", i.e. one whole plane after another
+ 'i':
+      "interleaved planes", i.e. 16 bit of the first plane, than 16 bit
+      of the next, and so on... This mode is used only with the
+      built-in Atari video modes, I think there is no card that
+      supports this mode.
+ 'p':
+      "packed pixels", i.e. <depth> consecutive bits stand for all
+      planes of one pixel; this is the most common mode for 8 planes
+      (256 colors) on graphic cards
+ 't':
+      "true color" (more or less packed pixels, but without a color
+      lookup table); usually depth is 24
+
+For monochrome modes (i.e., <depth> is 1), the <org> letter has a
+different meaning:
+
+ 'n':
+      normal colors, i.e. 0=white, 1=black
+ 'i':
+      inverted colors, i.e. 0=black, 1=white
+
+The next important information about the video hardware is the base
+address of the video memory. That is given in the <scrmem> parameter,
+as a hexadecimal number with a "0x" prefix. You have to find out this
+address in the documentation of your hardware.
+
+The next parameter, <scrlen>, tells the kernel about the size of the
+video memory. If it's missing, the size is calculated from <xres>,
+<yres>, and <depth>. For now, it is not useful to write a value here.
+It would be used only for hardware scrolling (which isn't possible
+with the external driver, because the kernel cannot set the video base
+address), or for virtual resolutions under X (which the X server
+doesn't support yet). So, it's currently best to leave this field
+empty, either by ending the "external:" after the video address or by
+writing two consecutive semicolons, if you want to give a <vgabase>
+(it is allowed to leave this parameter empty).
+
+The <vgabase> parameter is optional. If it is not given, the kernel
+cannot read or write any color registers of the video hardware, and
+thus you have to set appropriate colors before you start Linux. But if
+your card is somehow VGA compatible, you can tell the kernel the base
+address of the VGA register set, so it can change the color lookup
+table. You have to look up this address in your board's documentation.
+To avoid misunderstandings: <vgabase> is the _base_ address, i.e. a 4k
+aligned address. For read/writing the color registers, the kernel
+uses the addresses vgabase+0x3c7...vgabase+0x3c9. The <vgabase>
+parameter is written in hexadecimal with a "0x" prefix, just as
+<scrmem>.
+
+<colw> is meaningful only if <vgabase> is specified. It tells the
+kernel how wide each of the color register is, i.e. the number of bits
+per single color (red/green/blue). Default is 6, another quite usual
+value is 8.
+
+Also <coltype> is used together with <vgabase>. It tells the kernel
+about the color register model of your gfx board. Currently, the types
+"vga" (which is also the default) and "mv300" (SANG MV300) are
+implemented.
+
+Parameter <xres_virtual> is required for ProMST or ET4000 cards where
+the physical linelength differs from the visible length. With ProMST,
+xres_virtual must be set to 2048. For ET4000, xres_virtual depends on the
+initialisation of the video-card.
+If you're missing a corresponding yres_virtual: the external part is legacy,
+therefore we don't support hardware-dependent functions like hardware-scroll,
+panning or blanking.
+
+4.1.7) eclock:
+--------------
+
+The external pixel clock attached to the Falcon VIDEL shifter. This
+currently works only with the ScreenWonder!
+
+4.1.8) monitorcap:
+-------------------
+
+:Syntax: monitorcap:<vmin>;<vmax>;<hmin>;<hmax>
+
+This describes the capabilities of a multisync monitor. Don't use it
+with a fixed-frequency monitor! For now, only the Falcon frame buffer
+uses the settings of "monitorcap:".
+
+<vmin> and <vmax> are the minimum and maximum, resp., vertical frequencies
+your monitor can work with, in Hz. <hmin> and <hmax> are the same for
+the horizontal frequency, in kHz.
+
+  The defaults are 58;62;31;32 (VGA compatible).
+
+  The defaults for TV/SC1224/SC1435 cover both PAL and NTSC standards.
+
+4.1.9) keep
+------------
+
+If this option is given, the framebuffer device doesn't do any video
+mode calculations and settings on its own. The only Atari fb device
+that does this currently is the Falcon.
+
+What you reach with this: Settings for unknown video extensions
+aren't overridden by the driver, so you can still use the mode found
+when booting, when the driver doesn't know to set this mode itself.
+But this also means, that you can't switch video modes anymore...
+
+An example where you may want to use "keep" is the ScreenBlaster for
+the Falcon.
+
+
+4.2) atamouse=
+--------------
+
+:Syntax: atamouse=<x-threshold>,[<y-threshold>]
+
+With this option, you can set the mouse movement reporting threshold.
+This is the number of pixels of mouse movement that have to accumulate
+before the IKBD sends a new mouse packet to the kernel. Higher values
+reduce the mouse interrupt load and thus reduce the chance of keyboard
+overruns. Lower values give a slightly faster mouse responses and
+slightly better mouse tracking.
+
+You can set the threshold in x and y separately, but usually this is
+of little practical use. If there's just one number in the option, it
+is used for both dimensions. The default value is 2 for both
+thresholds.
+
+
+4.3) ataflop=
+-------------
+
+:Syntax: ataflop=<drive type>[,<trackbuffering>[,<steprateA>[,<steprateB>]]]
+
+   The drive type may be 0, 1, or 2, for DD, HD, and ED, resp. This
+   setting affects how many buffers are reserved and which formats are
+   probed (see also below). The default is 1 (HD). Only one drive type
+   can be selected. If you have two disk drives, select the "better"
+   type.
+
+   The second parameter <trackbuffer> tells the kernel whether to use
+   track buffering (1) or not (0). The default is machine-dependent:
+   no for the Medusa and yes for all others.
+
+   With the two following parameters, you can change the default
+   steprate used for drive A and B, resp.
+
+
+4.4) atascsi=
+-------------
+
+:Syntax: atascsi=<can_queue>[,<cmd_per_lun>[,<scat-gat>[,<host-id>[,<tagged>]]]]
+
+This option sets some parameters for the Atari native SCSI driver.
+Generally, any number of arguments can be omitted from the end. And
+for each of the numbers, a negative value means "use default". The
+defaults depend on whether TT-style or Falcon-style SCSI is used.
+Below, defaults are noted as n/m, where the first value refers to
+TT-SCSI and the latter to Falcon-SCSI. If an illegal value is given
+for one parameter, an error message is printed and that one setting is
+ignored (others aren't affected).
+
+  <can_queue>:
+    This is the maximum number of SCSI commands queued internally to the
+    Atari SCSI driver. A value of 1 effectively turns off the driver
+    internal multitasking (if it causes problems). Legal values are >=
+    1. <can_queue> can be as high as you like, but values greater than
+    <cmd_per_lun> times the number of SCSI targets (LUNs) you have
+    don't make sense. Default: 16/8.
+
+  <cmd_per_lun>:
+    Maximum number of SCSI commands issued to the driver for one
+    logical unit (LUN, usually one SCSI target). Legal values start
+    from 1. If tagged queuing (see below) is not used, values greater
+    than 2 don't make sense, but waste memory. Otherwise, the maximum
+    is the number of command tags available to the driver (currently
+    32). Default: 8/1. (Note: Values > 1 seem to cause problems on a
+    Falcon, cause not yet known.)
+
+    The <cmd_per_lun> value at a great part determines the amount of
+    memory SCSI reserves for itself. The formula is rather
+    complicated, but I can give you some hints:
+
+      no scatter-gather:
+       cmd_per_lun * 232 bytes
+      full scatter-gather:
+       cmd_per_lun * approx. 17 Kbytes
+
+  <scat-gat>:
+    Size of the scatter-gather table, i.e. the number of requests
+    consecutive on the disk that can be merged into one SCSI command.
+    Legal values are between 0 and 255. Default: 255/0. Note: This
+    value is forced to 0 on a Falcon, since scatter-gather isn't
+    possible with the ST-DMA. Not using scatter-gather hurts
+    performance significantly.
+
+  <host-id>:
+    The SCSI ID to be used by the initiator (your Atari). This is
+    usually 7, the highest possible ID. Every ID on the SCSI bus must
+    be unique. Default: determined at run time: If the NV-RAM checksum
+    is valid, and bit 7 in byte 30 of the NV-RAM is set, the lower 3
+    bits of this byte are used as the host ID. (This method is defined
+    by Atari and also used by some TOS HD drivers.) If the above
+    isn't given, the default ID is 7. (both, TT and Falcon).
+
+  <tagged>:
+    0 means turn off tagged queuing support, all other values > 0 mean
+    use tagged queuing for targets that support it. Default: currently
+    off, but this may change when tagged queuing handling has been
+    proved to be reliable.
+
+    Tagged queuing means that more than one command can be issued to
+    one LUN, and the SCSI device itself orders the requests so they
+    can be performed in optimal order. Not all SCSI devices support
+    tagged queuing (:-().
+
+4.5 switches=
+-------------
+
+:Syntax: switches=<list of switches>
+
+With this option you can switch some hardware lines that are often
+used to enable/disable certain hardware extensions. Examples are
+OverScan, overclocking, ...
+
+The <list of switches> is a comma-separated list of the following
+items:
+
+  ikbd:
+       set RTS of the keyboard ACIA high
+  midi:
+       set RTS of the MIDI ACIA high
+  snd6:
+       set bit 6 of the PSG port A
+  snd7:
+       set bit 6 of the PSG port A
+
+It doesn't make sense to mention a switch more than once (no
+difference to only once), but you can give as many switches as you
+want to enable different features. The switch lines are set as early
+as possible during kernel initialization (even before determining the
+present hardware.)
+
+All of the items can also be prefixed with `ov_`, i.e. `ov_ikbd`,
+`ov_midi`, ... These options are meant for switching on an OverScan
+video extension. The difference to the bare option is that the
+switch-on is done after video initialization, and somehow synchronized
+to the HBLANK. A speciality is that ov_ikbd and ov_midi are switched
+off before rebooting, so that OverScan is disabled and TOS boots
+correctly.
+
+If you give an option both, with and without the `ov_` prefix, the
+earlier initialization (`ov_`-less) takes precedence. But the
+switching-off on reset still happens in this case.
+
+5) Options for Amiga Only:
+==========================
+
+5.1) video=
+-----------
+
+:Syntax: video=<fbname>:<sub-options...>
+
+The <fbname> parameter specifies the name of the frame buffer, valid
+options are `amifb`, `cyber`, 'virge', `retz3` and `clgen`, provided
+that the respective frame buffer devices have been compiled into the
+kernel (or compiled as loadable modules). The behavior of the <fbname>
+option was changed in 2.1.57 so it is now recommended to specify this
+option.
+
+The <sub-options> is a comma-separated list of the sub-options listed
+below. This option is organized similar to the Atari version of the
+"video"-option (4.1), but knows fewer sub-options.
+
+5.1.1) video mode
+-----------------
+
+Again, similar to the video mode for the Atari (see 4.1.1). Predefined
+modes depend on the used frame buffer device.
+
+OCS, ECS and AGA machines all use the color frame buffer. The following
+predefined video modes are available:
+
+NTSC modes:
+ - ntsc            : 640x200, 15 kHz, 60 Hz
+ - ntsc-lace       : 640x400, 15 kHz, 60 Hz interlaced
+
+PAL modes:
+ - pal             : 640x256, 15 kHz, 50 Hz
+ - pal-lace        : 640x512, 15 kHz, 50 Hz interlaced
+
+ECS modes:
+ - multiscan       : 640x480, 29 kHz, 57 Hz
+ - multiscan-lace  : 640x960, 29 kHz, 57 Hz interlaced
+ - euro36          : 640x200, 15 kHz, 72 Hz
+ - euro36-lace     : 640x400, 15 kHz, 72 Hz interlaced
+ - euro72          : 640x400, 29 kHz, 68 Hz
+ - euro72-lace     : 640x800, 29 kHz, 68 Hz interlaced
+ - super72         : 800x300, 23 kHz, 70 Hz
+ - super72-lace    : 800x600, 23 kHz, 70 Hz interlaced
+ - dblntsc-ff      : 640x400, 27 kHz, 57 Hz
+ - dblntsc-lace    : 640x800, 27 kHz, 57 Hz interlaced
+ - dblpal-ff       : 640x512, 27 kHz, 47 Hz
+ - dblpal-lace     : 640x1024, 27 kHz, 47 Hz interlaced
+ - dblntsc         : 640x200, 27 kHz, 57 Hz doublescan
+ - dblpal          : 640x256, 27 kHz, 47 Hz doublescan
+
+VGA modes:
+ - vga             : 640x480, 31 kHz, 60 Hz
+ - vga70           : 640x400, 31 kHz, 70 Hz
+
+Please notice that the ECS and VGA modes require either an ECS or AGA
+chipset, and that these modes are limited to 2-bit color for the ECS
+chipset and 8-bit color for the AGA chipset.
+
+5.1.2) depth
+------------
+
+:Syntax: depth:<nr. of bit-planes>
+
+Specify the number of bit-planes for the selected video-mode.
+
+5.1.3) inverse
+--------------
+
+Use inverted display (black on white). Functionally the same as the
+"inverse" sub-option for the Atari.
+
+5.1.4) font
+-----------
+
+:Syntax: font:<fontname>
+
+Specify the font to use in text modes. Functionally the same as the
+"font" sub-option for the Atari, except that `PEARL8x8` is used instead
+of `VGA8x8` if the vertical size of the display is less than 400 pixel
+rows.
+
+5.1.5) monitorcap:
+-------------------
+
+:Syntax: monitorcap:<vmin>;<vmax>;<hmin>;<hmax>
+
+This describes the capabilities of a multisync monitor. For now, only
+the color frame buffer uses the settings of "monitorcap:".
+
+<vmin> and <vmax> are the minimum and maximum, resp., vertical frequencies
+your monitor can work with, in Hz. <hmin> and <hmax> are the same for
+the horizontal frequency, in kHz.
+
+The defaults are 50;90;15;38 (Generic Amiga multisync monitor).
+
+
+5.2) fd_def_df0=
+----------------
+
+:Syntax: fd_def_df0=<value>
+
+Sets the df0 value for "silent" floppy drives. The value should be in
+hexadecimal with "0x" prefix.
+
+
+5.3) wd33c93=
+-------------
+
+:Syntax: wd33c93=<sub-options...>
+
+These options affect the A590/A2091, A3000 and GVP Series II SCSI
+controllers.
+
+The <sub-options> is a comma-separated list of the sub-options listed
+below.
+
+5.3.1) nosync
+-------------
+
+:Syntax: nosync:bitmask
+
+bitmask is a byte where the 1st 7 bits correspond with the 7
+possible SCSI devices. Set a bit to prevent sync negotiation on that
+device. To maintain backwards compatibility, a command-line such as
+"wd33c93=255" will be automatically translated to
+"wd33c93=nosync:0xff". The default is to disable sync negotiation for
+all devices, eg. nosync:0xff.
+
+5.3.2) period
+-------------
+
+:Syntax: period:ns
+
+`ns` is the minimum # of nanoseconds in a SCSI data transfer
+period. Default is 500; acceptable values are 250 - 1000.
+
+5.3.3) disconnect
+-----------------
+
+:Syntax: disconnect:x
+
+Specify x = 0 to never allow disconnects, 2 to always allow them.
+x = 1 does 'adaptive' disconnects, which is the default and generally
+the best choice.
+
+5.3.4) debug
+------------
+
+:Syntax: debug:x
+
+If `DEBUGGING_ON` is defined, x is a bit mask that causes various
+types of debug output to printed - see the DB_xxx defines in
+wd33c93.h.
+
+5.3.5) clock
+------------
+
+:Syntax: clock:x
+
+x = clock input in MHz for WD33c93 chip. Normal values would be from
+8 through 20. The default value depends on your hostadapter(s),
+default for the A3000 internal controller is 14, for the A2091 it's 8
+and for the GVP hostadapters it's either 8 or 14, depending on the
+hostadapter and the SCSI-clock jumper present on some GVP
+hostadapters.
+
+5.3.6) next
+-----------
+
+No argument. Used to separate blocks of keywords when there's more
+than one wd33c93-based host adapter in the system.
+
+5.3.7) nodma
+------------
+
+:Syntax: nodma:x
+
+If x is 1 (or if the option is just written as "nodma"), the WD33c93
+controller will not use DMA (= direct memory access) to access the
+Amiga's memory.  This is useful for some systems (like A3000's and
+A4000's with the A3640 accelerator, revision 3.0) that have problems
+using DMA to chip memory.  The default is 0, i.e. to use DMA if
+possible.
+
+
+5.4) gvp11=
+-----------
+
+:Syntax: gvp11=<addr-mask>
+
+The earlier versions of the GVP driver did not handle DMA
+address-mask settings correctly which made it necessary for some
+people to use this option, in order to get their GVP controller
+running under Linux. These problems have hopefully been solved and the
+use of this option is now highly unrecommended!
+
+Incorrect use can lead to unpredictable behavior, so please only use
+this option if you *know* what you are doing and have a reason to do
+so. In any case if you experience problems and need to use this
+option, please inform us about it by mailing to the Linux/68k kernel
+mailing list.
+
+The address mask set by this option specifies which addresses are
+valid for DMA with the GVP Series II SCSI controller. An address is
+valid, if no bits are set except the bits that are set in the mask,
+too.
+
+Some versions of the GVP can only DMA into a 24 bit address range,
+some can address a 25 bit address range while others can use the whole
+32 bit address range for DMA. The correct setting depends on your
+controller and should be autodetected by the driver. An example is the
+24 bit region which is specified by a mask of 0x00fffffe.
diff --git a/Documentation/arch/nios2/features.rst b/Documentation/arch/nios2/features.rst
new file mode 100644 (file)
index 0000000..8449e63
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features nios2
diff --git a/Documentation/arch/nios2/index.rst b/Documentation/arch/nios2/index.rst
new file mode 100644 (file)
index 0000000..4468fe1
--- /dev/null
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================
+Nios II Specific Documentation
+==============================
+
+.. toctree::
+   :maxdepth: 2
+   :numbered:
+
+   nios2
+   features
diff --git a/Documentation/arch/nios2/nios2.rst b/Documentation/arch/nios2/nios2.rst
new file mode 100644 (file)
index 0000000..43da3f7
--- /dev/null
@@ -0,0 +1,24 @@
+=================================
+Linux on the Nios II architecture
+=================================
+
+This is a port of Linux to Nios II (nios2) processor.
+
+In order to compile for Nios II, you need a version of GCC with support for the generic
+system call ABI. Please see this link for more information on how compiling and booting
+software for the Nios II platform:
+http://www.rocketboards.org/foswiki/Documentation/NiosIILinuxUserManual
+
+For reference, please see the following link:
+http://www.altera.com/literature/lit-nio2.jsp
+
+What is Nios II?
+================
+Nios II is a 32-bit embedded-processor architecture designed specifically for the
+Altera family of FPGAs. In order to support Linux, Nios II needs to be configured
+with MMU and hardware multiplier enabled.
+
+Nios II ABI
+===========
+Please refer to chapter "Application Binary Interface" in Nios II Processor Reference
+Handbook.
diff --git a/Documentation/arch/openrisc/features.rst b/Documentation/arch/openrisc/features.rst
new file mode 100644 (file)
index 0000000..3f7c40d
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features openrisc
diff --git a/Documentation/arch/openrisc/index.rst b/Documentation/arch/openrisc/index.rst
new file mode 100644 (file)
index 0000000..6879f99
--- /dev/null
@@ -0,0 +1,20 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================
+OpenRISC Architecture
+=====================
+
+.. toctree::
+   :maxdepth: 2
+
+   openrisc_port
+   todo
+
+   features
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/arch/openrisc/openrisc_port.rst b/Documentation/arch/openrisc/openrisc_port.rst
new file mode 100644 (file)
index 0000000..657ac4a
--- /dev/null
@@ -0,0 +1,121 @@
+==============
+OpenRISC Linux
+==============
+
+This is a port of Linux to the OpenRISC class of microprocessors; the initial
+target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
+
+For information about OpenRISC processors and ongoing development:
+
+       =======         =============================
+       website         https://openrisc.io
+       email           openrisc@lists.librecores.org
+       =======         =============================
+
+---------------------------------------------------------------------
+
+Build instructions for OpenRISC toolchain and Linux
+===================================================
+
+In order to build and run Linux for OpenRISC, you'll need at least a basic
+toolchain and, perhaps, the architectural simulator.  Steps to get these bits
+in place are outlined here.
+
+1) Toolchain
+
+Toolchain binaries can be obtained from openrisc.io or our github releases page.
+Instructions for building the different toolchains can be found on openrisc.io
+or Stafford's toolchain build and release scripts.
+
+       ==========      =================================================
+       binaries        https://github.com/openrisc/or1k-gcc/releases
+       toolchains      https://openrisc.io/software
+       building        https://github.com/stffrdhrn/or1k-toolchain-build
+       ==========      =================================================
+
+2) Building
+
+Build the Linux kernel as usual::
+
+       make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig
+       make ARCH=openrisc CROSS_COMPILE="or1k-linux-"
+
+3) Running on FPGA (optional)
+
+The OpenRISC community typically uses FuseSoC to manage building and programming
+an SoC into an FPGA.  The below is an example of programming a De0 Nano
+development board with the OpenRISC SoC.  During the build FPGA RTL is code
+downloaded from the FuseSoC IP cores repository and built using the FPGA vendor
+tools.  Binaries are loaded onto the board with openocd.
+
+::
+
+       git clone https://github.com/olofk/fusesoc
+       cd fusesoc
+       sudo pip install -e .
+
+       fusesoc init
+       fusesoc build de0_nano
+       fusesoc pgm de0_nano
+
+       openocd -f interface/altera-usb-blaster.cfg \
+               -f board/or1k_generic.cfg
+
+       telnet localhost 4444
+       > init
+       > halt; load_image vmlinux ; reset
+
+4) Running on a Simulator (optional)
+
+QEMU is a processor emulator which we recommend for simulating the OpenRISC
+platform.  Please follow the OpenRISC instructions on the QEMU website to get
+Linux running on QEMU.  You can build QEMU yourself, but your Linux distribution
+likely provides binary packages to support OpenRISC.
+
+       =============   ======================================================
+       qemu openrisc   https://wiki.qemu.org/Documentation/Platforms/OpenRISC
+       =============   ======================================================
+
+---------------------------------------------------------------------
+
+Terminology
+===========
+
+In the code, the following particles are used on symbols to limit the scope
+to more or less specific processor implementations:
+
+========= =======================================
+openrisc: the OpenRISC class of processors
+or1k:     the OpenRISC 1000 family of processors
+or1200:   the OpenRISC 1200 processor
+========= =======================================
+
+---------------------------------------------------------------------
+
+History
+========
+
+18-11-2003     Matjaz Breskvar (phoenix@bsemi.com)
+       initial port of linux to OpenRISC/or32 architecture.
+        all the core stuff is implemented and seams usable.
+
+08-12-2003     Matjaz Breskvar (phoenix@bsemi.com)
+       complete change of TLB miss handling.
+       rewrite of exceptions handling.
+       fully functional sash-3.6 in default initrd.
+       a much improved version with changes all around.
+
+10-04-2004     Matjaz Breskvar (phoenix@bsemi.com)
+       alot of bugfixes all over.
+       ethernet support, functional http and telnet servers.
+       running many standard linux apps.
+
+26-06-2004     Matjaz Breskvar (phoenix@bsemi.com)
+       port to 2.6.x
+
+30-11-2004     Matjaz Breskvar (phoenix@bsemi.com)
+       lots of bugfixes and enhancments.
+       added opencores framebuffer driver.
+
+09-10-2010    Jonas Bonn (jonas@southpole.se)
+       major rewrite to bring up to par with upstream Linux 2.6.36
diff --git a/Documentation/arch/openrisc/todo.rst b/Documentation/arch/openrisc/todo.rst
new file mode 100644 (file)
index 0000000..420b18b
--- /dev/null
@@ -0,0 +1,15 @@
+====
+TODO
+====
+
+The OpenRISC Linux port is fully functional and has been tracking upstream
+since 2.6.35.  There are, however, remaining items to be completed within
+the coming months.  Here's a list of known-to-be-less-than-stellar items
+that are due for investigation shortly, i.e. our TODO list:
+
+-  Implement the rest of the DMA API... dma_map_sg, etc.
+
+-  Finish the renaming cleanup... there are references to or32 in the code
+   which was an older name for the architecture.  The name we've settled on is
+   or1k and this change is slowly trickling through the stack.  For the time
+   being, or32 is equivalent to or1k.
diff --git a/Documentation/arch/parisc/debugging.rst b/Documentation/arch/parisc/debugging.rst
new file mode 100644 (file)
index 0000000..de1b604
--- /dev/null
@@ -0,0 +1,46 @@
+=================
+PA-RISC Debugging
+=================
+
+okay, here are some hints for debugging the lower-level parts of
+linux/parisc.
+
+
+1. Absolute addresses
+=====================
+
+A lot of the assembly code currently runs in real mode, which means
+absolute addresses are used instead of virtual addresses as in the
+rest of the kernel.  To translate an absolute address to a virtual
+address you can lookup in System.map, add __PAGE_OFFSET (0x10000000
+currently).
+
+
+2. HPMCs
+========
+
+When real-mode code tries to access non-existent memory, you'll get
+an HPMC instead of a kernel oops.  To debug an HPMC, try to find
+the System Responder/Requestor addresses.  The System Requestor
+address should match (one of the) processor HPAs (high addresses in
+the I/O range); the System Responder address is the address real-mode
+code tried to access.
+
+Typical values for the System Responder address are addresses larger
+than __PAGE_OFFSET (0x10000000) which mean a virtual address didn't
+get translated to a physical address before real-mode code tried to
+access it.
+
+
+3. Q bit fun
+============
+
+Certain, very critical code has to clear the Q bit in the PSW.  What
+happens when the Q bit is cleared is the CPU does not update the
+registers interruption handlers read to find out where the machine
+was interrupted - so if you get an interruption between the instruction
+that clears the Q bit and the RFI that sets it again you don't know
+where exactly it happened.  If you're lucky the IAOQ will point to the
+instruction that cleared the Q bit, if you're not it points anywhere
+at all.  Usually Q bit problems will show themselves in unexplainable
+system hangs or running off the end of physical memory.
diff --git a/Documentation/arch/parisc/features.rst b/Documentation/arch/parisc/features.rst
new file mode 100644 (file)
index 0000000..501d7c4
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features parisc
diff --git a/Documentation/arch/parisc/index.rst b/Documentation/arch/parisc/index.rst
new file mode 100644 (file)
index 0000000..2406857
--- /dev/null
@@ -0,0 +1,20 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================
+PA-RISC Architecture
+====================
+
+.. toctree::
+   :maxdepth: 2
+
+   debugging
+   registers
+
+   features
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/arch/parisc/registers.rst b/Documentation/arch/parisc/registers.rst
new file mode 100644 (file)
index 0000000..59c8ecf
--- /dev/null
@@ -0,0 +1,154 @@
+================================
+Register Usage for Linux/PA-RISC
+================================
+
+[ an asterisk is used for planned usage which is currently unimplemented ]
+
+General Registers as specified by ABI
+=====================================
+
+Control Registers
+-----------------
+
+===============================        ===============================================
+CR 0 (Recovery Counter)                used for ptrace
+CR 1-CR 7(undefined)           unused
+CR 8 (Protection ID)           per-process value*
+CR 9, 12, 13 (PIDS)            unused
+CR10 (CCR)                     lazy FPU saving*
+CR11                           as specified by ABI (SAR)
+CR14 (interruption vector)     initialized to fault_vector
+CR15 (EIEM)                    initialized to all ones*
+CR16 (Interval Timer)          read for cycle count/write starts Interval Tmr
+CR17-CR22                      interruption parameters
+CR19                           Interrupt Instruction Register
+CR20                           Interrupt Space Register
+CR21                           Interrupt Offset Register
+CR22                           Interrupt PSW
+CR23 (EIRR)                    read for pending interrupts/write clears bits
+CR24 (TR 0)                    Kernel Space Page Directory Pointer
+CR25 (TR 1)                    User   Space Page Directory Pointer
+CR26 (TR 2)                    not used
+CR27 (TR 3)                    Thread descriptor pointer
+CR28 (TR 4)                    not used
+CR29 (TR 5)                    not used
+CR30 (TR 6)                    current / 0
+CR31 (TR 7)                    Temporary register, used in various places
+===============================        ===============================================
+
+Space Registers (kernel mode)
+-----------------------------
+
+===============================        ===============================================
+SR0                            temporary space register
+SR4-SR7                        set to 0
+SR1                            temporary space register
+SR2                            kernel should not clobber this
+SR3                            used for userspace accesses (current process)
+===============================        ===============================================
+
+Space Registers (user mode)
+---------------------------
+
+===============================        ===============================================
+SR0                            temporary space register
+SR1                             temporary space register
+SR2                             holds space of linux gateway page
+SR3                             holds user address space value while in kernel
+SR4-SR7                         Defines short address space for user/kernel
+===============================        ===============================================
+
+
+Processor Status Word
+---------------------
+
+===============================        ===============================================
+W (64-bit addresses)           0
+E (Little-endian)              0
+S (Secure Interval Timer)      0
+T (Taken Branch Trap)          0
+H (Higher-privilege trap)      0
+L (Lower-privilege trap)       0
+N (Nullify next instruction)   used by C code
+X (Data memory break disable)  0
+B (Taken Branch)               used by C code
+C (code address translation)   1, 0 while executing real-mode code
+V (divide step correction)     used by C code
+M (HPMC mask)                  0, 1 while executing HPMC handler*
+C/B (carry/borrow bits)                used by C code
+O (ordered references)         1*
+F (performance monitor)                0
+R (Recovery Counter trap)      0
+Q (collect interruption state) 1 (0 in code directly preceding an rfi)
+P (Protection Identifiers)     1*
+D (Data address translation)   1, 0 while executing real-mode code
+I (external interrupt mask)    used by cli()/sti() macros
+===============================        ===============================================
+
+"Invisible" Registers
+---------------------
+
+===============================        ===============================================
+PSW default W value            0
+PSW default E value            0
+Shadow Registers               used by interruption handler code
+TOC enable bit                 1
+===============================        ===============================================
+
+-------------------------------------------------------------------------
+
+The PA-RISC architecture defines 7 registers as "shadow registers".
+Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce
+the state save and restore time by eliminating the need for general register
+(GR) saves and restores in interruption handlers.
+Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25.
+
+-------------------------------------------------------------------------
+
+Register usage notes, originally from John Marvin, with some additional
+notes from Randolph Chung.
+
+For the general registers:
+
+r1,r2,r19-r26,r28,r29 & r31 can be used without saving them first. And of
+course, you need to save them if you care about them, before calling
+another procedure. Some of the above registers do have special meanings
+that you should be aware of:
+
+    r1:
+       The addil instruction is hardwired to place its result in r1,
+       so if you use that instruction be aware of that.
+
+    r2:
+       This is the return pointer. In general you don't want to
+       use this, since you need the pointer to get back to your
+       caller. However, it is grouped with this set of registers
+       since the caller can't rely on the value being the same
+       when you return, i.e. you can copy r2 to another register
+       and return through that register after trashing r2, and
+       that should not cause a problem for the calling routine.
+
+    r19-r22:
+       these are generally regarded as temporary registers.
+       Note that in 64 bit they are arg7-arg4.
+
+    r23-r26:
+       these are arg3-arg0, i.e. you can use them if you
+       don't care about the values that were passed in anymore.
+
+    r28,r29:
+       are ret0 and ret1. They are what you pass return values
+       in. r28 is the primary return. When returning small structures
+       r29 may also be used to pass data back to the caller.
+
+    r30:
+       stack pointer
+
+    r31:
+       the ble instruction puts the return pointer in here.
+
+
+    r3-r18,r27,r30 need to be saved and restored. r3-r18 are just
+    general purpose registers. r27 is the data pointer, and is
+    used to make references to global variables easier. r30 is
+    the stack pointer.
diff --git a/Documentation/arch/sh/booting.rst b/Documentation/arch/sh/booting.rst
new file mode 100644 (file)
index 0000000..d851c49
--- /dev/null
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+DeviceTree Booting
+------------------
+
+  Device-tree compatible SH bootloaders are expected to provide the physical
+  address of the device tree blob in r4. Since legacy bootloaders did not
+  guarantee any particular initial register state, kernels built to
+  inter-operate with old bootloaders must either use a builtin DTB or
+  select a legacy board option (something other than CONFIG_SH_DEVICE_TREE)
+  that does not use device tree. Support for the latter is being phased out
+  in favor of device tree.
diff --git a/Documentation/arch/sh/features.rst b/Documentation/arch/sh/features.rst
new file mode 100644 (file)
index 0000000..f722af3
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features sh
diff --git a/Documentation/arch/sh/index.rst b/Documentation/arch/sh/index.rst
new file mode 100644 (file)
index 0000000..c647767
--- /dev/null
@@ -0,0 +1,56 @@
+=======================
+SuperH Interfaces Guide
+=======================
+
+:Author: Paul Mundt
+
+.. toctree::
+    :maxdepth: 1
+
+    booting
+    new-machine
+    register-banks
+
+    features
+
+Memory Management
+=================
+
+SH-4
+----
+
+Store Queue API
+~~~~~~~~~~~~~~~
+
+.. kernel-doc:: arch/sh/kernel/cpu/sh4/sq.c
+   :export:
+
+Machine Specific Interfaces
+===========================
+
+mach-dreamcast
+--------------
+
+.. kernel-doc:: arch/sh/boards/mach-dreamcast/rtc.c
+   :internal:
+
+mach-x3proto
+------------
+
+.. kernel-doc:: arch/sh/boards/mach-x3proto/ilsel.c
+   :export:
+
+Busses
+======
+
+SuperHyway
+----------
+
+.. kernel-doc:: drivers/sh/superhyway/superhyway.c
+   :export:
+
+Maple
+-----
+
+.. kernel-doc:: drivers/sh/maple/maple.c
+   :export:
diff --git a/Documentation/arch/sh/new-machine.rst b/Documentation/arch/sh/new-machine.rst
new file mode 100644 (file)
index 0000000..e501c52
--- /dev/null
@@ -0,0 +1,277 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============================
+Adding a new board to LinuxSH
+=============================
+
+               Paul Mundt <lethal@linux-sh.org>
+
+This document attempts to outline what steps are necessary to add support
+for new boards to the LinuxSH port under the new 2.5 and 2.6 kernels. This
+also attempts to outline some of the noticeable changes between the 2.4
+and the 2.5/2.6 SH backend.
+
+1. New Directory Structure
+==========================
+
+The first thing to note is the new directory structure. Under 2.4, most
+of the board-specific code (with the exception of stboards) ended up
+in arch/sh/kernel/ directly, with board-specific headers ending up in
+include/asm-sh/. For the new kernel, things are broken out by board type,
+companion chip type, and CPU type. Looking at a tree view of this directory
+hierarchy looks like the following:
+
+Board-specific code::
+
+    .
+    |-- arch
+    |   `-- sh
+    |       `-- boards
+    |           |-- adx
+    |           |   `-- board-specific files
+    |           |-- bigsur
+    |           |   `-- board-specific files
+    |           |
+    |           ... more boards here ...
+    |
+    `-- include
+       `-- asm-sh
+           |-- adx
+           |   `-- board-specific headers
+           |-- bigsur
+           |   `-- board-specific headers
+           |
+           .. more boards here ...
+
+Next, for companion chips::
+
+    .
+    `-- arch
+       `-- sh
+           `-- cchips
+               `-- hd6446x
+                   `-- hd64461
+                       `-- cchip-specific files
+
+... and so on. Headers for the companion chips are treated the same way as
+board-specific headers. Thus, include/asm-sh/hd64461 is home to all of the
+hd64461-specific headers.
+
+Finally, CPU family support is also abstracted::
+
+    .
+    |-- arch
+    |   `-- sh
+    |       |-- kernel
+    |       |   `-- cpu
+    |       |       |-- sh2
+    |       |       |   `-- SH-2 generic files
+    |       |       |-- sh3
+    |       |       |   `-- SH-3 generic files
+    |       |       `-- sh4
+    |       |           `-- SH-4 generic files
+    |       `-- mm
+    |           `-- This is also broken out per CPU family, so each family can
+    |               have their own set of cache/tlb functions.
+    |
+    `-- include
+       `-- asm-sh
+           |-- cpu-sh2
+           |   `-- SH-2 specific headers
+           |-- cpu-sh3
+           |   `-- SH-3 specific headers
+           `-- cpu-sh4
+               `-- SH-4 specific headers
+
+It should be noted that CPU subtypes are _not_ abstracted. Thus, these still
+need to be dealt with by the CPU family specific code.
+
+2. Adding a New Board
+=====================
+
+The first thing to determine is whether the board you are adding will be
+isolated, or whether it will be part of a family of boards that can mostly
+share the same board-specific code with minor differences.
+
+In the first case, this is just a matter of making a directory for your
+board in arch/sh/boards/ and adding rules to hook your board in with the
+build system (more on this in the next section). However, for board families
+it makes more sense to have a common top-level arch/sh/boards/ directory
+and then populate that with sub-directories for each member of the family.
+Both the Solution Engine and the hp6xx boards are an example of this.
+
+After you have setup your new arch/sh/boards/ directory, remember that you
+should also add a directory in include/asm-sh for headers localized to this
+board (if there are going to be more than one). In order to interoperate
+seamlessly with the build system, it's best to have this directory the same
+as the arch/sh/boards/ directory name, though if your board is again part of
+a family, the build system has ways of dealing with this (via incdir-y
+overloading), and you can feel free to name the directory after the family
+member itself.
+
+There are a few things that each board is required to have, both in the
+arch/sh/boards and the include/asm-sh/ hierarchy. In order to better
+explain this, we use some examples for adding an imaginary board. For
+setup code, we're required at the very least to provide definitions for
+get_system_type() and platform_setup(). For our imaginary board, this
+might look something like::
+
+    /*
+    * arch/sh/boards/vapor/setup.c - Setup code for imaginary board
+    */
+    #include <linux/init.h>
+
+    const char *get_system_type(void)
+    {
+           return "FooTech Vaporboard";
+    }
+
+    int __init platform_setup(void)
+    {
+           /*
+           * If our hardware actually existed, we would do real
+           * setup here. Though it's also sane to leave this empty
+           * if there's no real init work that has to be done for
+           * this board.
+           */
+
+           /* Start-up imaginary PCI ... */
+
+           /* And whatever else ... */
+
+           return 0;
+    }
+
+Our new imaginary board will also have to tie into the machvec in order for it
+to be of any use.
+
+machvec functions fall into a number of categories:
+
+ - I/O functions to IO memory (inb etc) and PCI/main memory (readb etc).
+ - I/O mapping functions (ioport_map, ioport_unmap, etc).
+ - a 'heartbeat' function.
+ - PCI and IRQ initialization routines.
+ - Consistent allocators (for boards that need special allocators,
+   particularly for allocating out of some board-specific SRAM for DMA
+   handles).
+
+There are machvec functions added and removed over time, so always be sure to
+consult include/asm-sh/machvec.h for the current state of the machvec.
+
+The kernel will automatically wrap in generic routines for undefined function
+pointers in the machvec at boot time, as machvec functions are referenced
+unconditionally throughout most of the tree. Some boards have incredibly
+sparse machvecs (such as the dreamcast and sh03), whereas others must define
+virtually everything (rts7751r2d).
+
+Adding a new machine is relatively trivial (using vapor as an example):
+
+If the board-specific definitions are quite minimalistic, as is the case for
+the vast majority of boards, simply having a single board-specific header is
+sufficient.
+
+ - add a new file include/asm-sh/vapor.h which contains prototypes for
+   any machine specific IO functions prefixed with the machine name, for
+   example vapor_inb. These will be needed when filling out the machine
+   vector.
+
+   Note that these prototypes are generated automatically by setting
+   __IO_PREFIX to something sensible. A typical example would be::
+
+       #define __IO_PREFIX vapor
+       #include <asm/io_generic.h>
+
+   somewhere in the board-specific header. Any boards being ported that still
+   have a legacy io.h should remove it entirely and switch to the new model.
+
+ - Add machine vector definitions to the board's setup.c. At a bare minimum,
+   this must be defined as something like::
+
+       struct sh_machine_vector mv_vapor __initmv = {
+               .mv_name = "vapor",
+       };
+       ALIAS_MV(vapor)
+
+ - finally add a file arch/sh/boards/vapor/io.c, which contains definitions of
+   the machine specific io functions (if there are enough to warrant it).
+
+3. Hooking into the Build System
+================================
+
+Now that we have the corresponding directories setup, and all of the
+board-specific code is in place, it's time to look at how to get the
+whole mess to fit into the build system.
+
+Large portions of the build system are now entirely dynamic, and merely
+require the proper entry here and there in order to get things done.
+
+The first thing to do is to add an entry to arch/sh/Kconfig, under the
+"System type" menu::
+
+    config SH_VAPOR
+           bool "Vapor"
+           help
+           select Vapor if configuring for a FooTech Vaporboard.
+
+next, this has to be added into arch/sh/Makefile. All boards require a
+machdir-y entry in order to be built. This entry needs to be the name of
+the board directory as it appears in arch/sh/boards, even if it is in a
+sub-directory (in which case, all parent directories below arch/sh/boards/
+need to be listed). For our new board, this entry can look like::
+
+    machdir-$(CONFIG_SH_VAPOR) += vapor
+
+provided that we've placed everything in the arch/sh/boards/vapor/ directory.
+
+Next, the build system assumes that your include/asm-sh directory will also
+be named the same. If this is not the case (as is the case with multiple
+boards belonging to a common family), then the directory name needs to be
+implicitly appended to incdir-y. The existing code manages this for the
+Solution Engine and hp6xx boards, so see these for an example.
+
+Once that is taken care of, it's time to add an entry for the mach type.
+This is done by adding an entry to the end of the arch/sh/tools/mach-types
+list. The method for doing this is self explanatory, and so we won't waste
+space restating it here. After this is done, you will be able to use
+implicit checks for your board if you need this somewhere throughout the
+common code, such as::
+
+       /* Make sure we're on the FooTech Vaporboard */
+       if (!mach_is_vapor())
+               return -ENODEV;
+
+also note that the mach_is_boardname() check will be implicitly forced to
+lowercase, regardless of the fact that the mach-types entries are all
+uppercase. You can read the script if you really care, but it's pretty ugly,
+so you probably don't want to do that.
+
+Now all that's left to do is providing a defconfig for your new board. This
+way, other people who end up with this board can simply use this config
+for reference instead of trying to guess what settings are supposed to be
+used on it.
+
+Also, as soon as you have copied over a sample .config for your new board
+(assume arch/sh/configs/vapor_defconfig), you can also use this directly as a
+build target, and it will be implicitly listed as such in the help text.
+
+Looking at the 'make help' output, you should now see something like:
+
+Architecture specific targets (sh):
+
+  =======================   =============================================
+  zImage                    Compressed kernel image (arch/sh/boot/zImage)
+  adx_defconfig             Build for adx
+  cqreek_defconfig          Build for cqreek
+  dreamcast_defconfig       Build for dreamcast
+  ...
+  vapor_defconfig           Build for vapor
+  =======================   =============================================
+
+which then allows you to do::
+
+    $ make ARCH=sh CROSS_COMPILE=sh4-linux- vapor_defconfig vmlinux
+
+which will in turn copy the defconfig for this board, run it through
+oldconfig (prompting you for any new options since the time of creation),
+and start you on your way to having a functional kernel for your new
+board.
diff --git a/Documentation/arch/sh/register-banks.rst b/Documentation/arch/sh/register-banks.rst
new file mode 100644 (file)
index 0000000..2bef5c8
--- /dev/null
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================================
+Notes on register bank usage in the kernel
+==========================================
+
+Introduction
+------------
+
+The SH-3 and SH-4 CPU families traditionally include a single partial register
+bank (selected by SR.RB, only r0 ... r7 are banked), whereas other families
+may have more full-featured banking or simply no such capabilities at all.
+
+SR.RB banking
+-------------
+
+In the case of this type of banking, banked registers are mapped directly to
+r0 ... r7 if SR.RB is set to the bank we are interested in, otherwise ldc/stc
+can still be used to reference the banked registers (as r0_bank ... r7_bank)
+when in the context of another bank. The developer must keep the SR.RB value
+in mind when writing code that utilizes these banked registers, for obvious
+reasons. Userspace is also not able to poke at the bank1 values, so these can
+be used rather effectively as scratch registers by the kernel.
+
+Presently the kernel uses several of these registers.
+
+       - r0_bank, r1_bank (referenced as k0 and k1, used for scratch
+         registers when doing exception handling).
+
+       - r2_bank (used to track the EXPEVT/INTEVT code)
+
+               - Used by do_IRQ() and friends for doing irq mapping based off
+                 of the interrupt exception vector jump table offset
+
+       - r6_bank (global interrupt mask)
+
+               - The SR.IMASK interrupt handler makes use of this to set the
+                 interrupt priority level (used by local_irq_enable())
+
+       - r7_bank (current)
diff --git a/Documentation/arch/sparc/adi.rst b/Documentation/arch/sparc/adi.rst
new file mode 100644 (file)
index 0000000..dbcd8b6
--- /dev/null
@@ -0,0 +1,286 @@
+================================
+Application Data Integrity (ADI)
+================================
+
+SPARC M7 processor adds the Application Data Integrity (ADI) feature.
+ADI allows a task to set version tags on any subset of its address
+space. Once ADI is enabled and version tags are set for ranges of
+address space of a task, the processor will compare the tag in pointers
+to memory in these ranges to the version set by the application
+previously. Access to memory is granted only if the tag in given pointer
+matches the tag set by the application. In case of mismatch, processor
+raises an exception.
+
+Following steps must be taken by a task to enable ADI fully:
+
+1. Set the user mode PSTATE.mcde bit. This acts as master switch for
+   the task's entire address space to enable/disable ADI for the task.
+
+2. Set TTE.mcd bit on any TLB entries that correspond to the range of
+   addresses ADI is being enabled on. MMU checks the version tag only
+   on the pages that have TTE.mcd bit set.
+
+3. Set the version tag for virtual addresses using stxa instruction
+   and one of the MCD specific ASIs. Each stxa instruction sets the
+   given tag for one ADI block size number of bytes. This step must
+   be repeated for entire page to set tags for entire page.
+
+ADI block size for the platform is provided by the hypervisor to kernel
+in machine description tables. Hypervisor also provides the number of
+top bits in the virtual address that specify the version tag.  Once
+version tag has been set for a memory location, the tag is stored in the
+physical memory and the same tag must be present in the ADI version tag
+bits of the virtual address being presented to the MMU. For example on
+SPARC M7 processor, MMU uses bits 63-60 for version tags and ADI block
+size is same as cacheline size which is 64 bytes. A task that sets ADI
+version to, say 10, on a range of memory, must access that memory using
+virtual addresses that contain 0xa in bits 63-60.
+
+ADI is enabled on a set of pages using mprotect() with PROT_ADI flag.
+When ADI is enabled on a set of pages by a task for the first time,
+kernel sets the PSTATE.mcde bit for the task. Version tags for memory
+addresses are set with an stxa instruction on the addresses using
+ASI_MCD_PRIMARY or ASI_MCD_ST_BLKINIT_PRIMARY. ADI block size is
+provided by the hypervisor to the kernel.  Kernel returns the value of
+ADI block size to userspace using auxiliary vector along with other ADI
+info. Following auxiliary vectors are provided by the kernel:
+
+       ============    ===========================================
+       AT_ADI_BLKSZ    ADI block size. This is the granularity and
+                       alignment, in bytes, of ADI versioning.
+       AT_ADI_NBITS    Number of ADI version bits in the VA
+       ============    ===========================================
+
+
+IMPORTANT NOTES
+===============
+
+- Version tag values of 0x0 and 0xf are reserved. These values match any
+  tag in virtual address and never generate a mismatch exception.
+
+- Version tags are set on virtual addresses from userspace even though
+  tags are stored in physical memory. Tags are set on a physical page
+  after it has been allocated to a task and a pte has been created for
+  it.
+
+- When a task frees a memory page it had set version tags on, the page
+  goes back to free page pool. When this page is re-allocated to a task,
+  kernel clears the page using block initialization ASI which clears the
+  version tags as well for the page. If a page allocated to a task is
+  freed and allocated back to the same task, old version tags set by the
+  task on that page will no longer be present.
+
+- ADI tag mismatches are not detected for non-faulting loads.
+
+- Kernel does not set any tags for user pages and it is entirely a
+  task's responsibility to set any version tags. Kernel does ensure the
+  version tags are preserved if a page is swapped out to the disk and
+  swapped back in. It also preserves that version tags if a page is
+  migrated.
+
+- ADI works for any size pages. A userspace task need not be aware of
+  page size when using ADI. It can simply select a virtual address
+  range, enable ADI on the range using mprotect() and set version tags
+  for the entire range. mprotect() ensures range is aligned to page size
+  and is a multiple of page size.
+
+- ADI tags can only be set on writable memory. For example, ADI tags can
+  not be set on read-only mappings.
+
+
+
+ADI related traps
+=================
+
+With ADI enabled, following new traps may occur:
+
+Disrupting memory corruption
+----------------------------
+
+       When a store accesses a memory location that has TTE.mcd=1,
+       the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
+       tag in the address used (bits 63:60) does not match the tag set on
+       the corresponding cacheline, a memory corruption trap occurs. By
+       default, it is a disrupting trap and is sent to the hypervisor
+       first. Hypervisor creates a sun4v error report and sends a
+       resumable error (TT=0x7e) trap to the kernel. The kernel sends
+       a SIGSEGV to the task that resulted in this trap with the following
+       info::
+
+               siginfo.si_signo = SIGSEGV;
+               siginfo.errno = 0;
+               siginfo.si_code = SEGV_ADIDERR;
+               siginfo.si_addr = addr; /* PC where first mismatch occurred */
+               siginfo.si_trapno = 0;
+
+
+Precise memory corruption
+-------------------------
+
+       When a store accesses a memory location that has TTE.mcd=1,
+       the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
+       tag in the address used (bits 63:60) does not match the tag set on
+       the corresponding cacheline, a memory corruption trap occurs. If
+       MCD precise exception is enabled (MCDPERR=1), a precise
+       exception is sent to the kernel with TT=0x1a. The kernel sends
+       a SIGSEGV to the task that resulted in this trap with the following
+       info::
+
+               siginfo.si_signo = SIGSEGV;
+               siginfo.errno = 0;
+               siginfo.si_code = SEGV_ADIPERR;
+               siginfo.si_addr = addr; /* address that caused trap */
+               siginfo.si_trapno = 0;
+
+       NOTE:
+               ADI tag mismatch on a load always results in precise trap.
+
+
+MCD disabled
+------------
+
+       When a task has not enabled ADI and attempts to set ADI version
+       on a memory address, processor sends an MCD disabled trap. This
+       trap is handled by hypervisor first and the hypervisor vectors this
+       trap through to the kernel as Data Access Exception trap with
+       fault type set to 0xa (invalid ASI). When this occurs, the kernel
+       sends the task SIGSEGV signal with following info::
+
+               siginfo.si_signo = SIGSEGV;
+               siginfo.errno = 0;
+               siginfo.si_code = SEGV_ACCADI;
+               siginfo.si_addr = addr; /* address that caused trap */
+               siginfo.si_trapno = 0;
+
+
+Sample program to use ADI
+-------------------------
+
+Following sample program is meant to illustrate how to use the ADI
+functionality::
+
+  #include <unistd.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <elf.h>
+  #include <sys/ipc.h>
+  #include <sys/shm.h>
+  #include <sys/mman.h>
+  #include <asm/asi.h>
+
+  #ifndef AT_ADI_BLKSZ
+  #define AT_ADI_BLKSZ 48
+  #endif
+  #ifndef AT_ADI_NBITS
+  #define AT_ADI_NBITS 49
+  #endif
+
+  #ifndef PROT_ADI
+  #define PROT_ADI     0x10
+  #endif
+
+  #define BUFFER_SIZE     32*1024*1024UL
+
+  main(int argc, char* argv[], char* envp[])
+  {
+          unsigned long i, mcde, adi_blksz, adi_nbits;
+          char *shmaddr, *tmp_addr, *end, *veraddr, *clraddr;
+          int shmid, version;
+       Elf64_auxv_t *auxv;
+
+       adi_blksz = 0;
+
+       while(*envp++ != NULL);
+       for (auxv = (Elf64_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
+               switch (auxv->a_type) {
+               case AT_ADI_BLKSZ:
+                       adi_blksz = auxv->a_un.a_val;
+                       break;
+               case AT_ADI_NBITS:
+                       adi_nbits = auxv->a_un.a_val;
+                       break;
+               }
+       }
+       if (adi_blksz == 0) {
+               fprintf(stderr, "Oops! ADI is not supported\n");
+               exit(1);
+       }
+
+       printf("ADI capabilities:\n");
+       printf("\tBlock size = %ld\n", adi_blksz);
+       printf("\tNumber of bits = %ld\n", adi_nbits);
+
+          if ((shmid = shmget(2, BUFFER_SIZE,
+                                  IPC_CREAT | SHM_R | SHM_W)) < 0) {
+                  perror("shmget failed");
+                  exit(1);
+          }
+
+          shmaddr = shmat(shmid, NULL, 0);
+          if (shmaddr == (char *)-1) {
+                  perror("shm attach failed");
+                  shmctl(shmid, IPC_RMID, NULL);
+                  exit(1);
+          }
+
+       if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE|PROT_ADI)) {
+               perror("mprotect failed");
+               goto err_out;
+       }
+
+          /* Set the ADI version tag on the shm segment
+           */
+          version = 10;
+          tmp_addr = shmaddr;
+          end = shmaddr + BUFFER_SIZE;
+          while (tmp_addr < end) {
+                  asm volatile(
+                          "stxa %1, [%0]0x90\n\t"
+                          :
+                          : "r" (tmp_addr), "r" (version));
+                  tmp_addr += adi_blksz;
+          }
+       asm volatile("membar #Sync\n\t");
+
+          /* Create a versioned address from the normal address by placing
+        * version tag in the upper adi_nbits bits
+           */
+          tmp_addr = (void *) ((unsigned long)shmaddr << adi_nbits);
+          tmp_addr = (void *) ((unsigned long)tmp_addr >> adi_nbits);
+          veraddr = (void *) (((unsigned long)version << (64-adi_nbits))
+                          | (unsigned long)tmp_addr);
+
+          printf("Starting the writes:\n");
+          for (i = 0; i < BUFFER_SIZE; i++) {
+                  veraddr[i] = (char)(i);
+                  if (!(i % (1024 * 1024)))
+                          printf(".");
+          }
+          printf("\n");
+
+          printf("Verifying data...");
+       fflush(stdout);
+          for (i = 0; i < BUFFER_SIZE; i++)
+                  if (veraddr[i] != (char)i)
+                          printf("\nIndex %lu mismatched\n", i);
+          printf("Done.\n");
+
+          /* Disable ADI and clean up
+           */
+       if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE)) {
+               perror("mprotect failed");
+               goto err_out;
+       }
+
+          if (shmdt((const void *)shmaddr) != 0)
+                  perror("Detach failure");
+          shmctl(shmid, IPC_RMID, NULL);
+
+          exit(0);
+
+  err_out:
+          if (shmdt((const void *)shmaddr) != 0)
+                  perror("Detach failure");
+          shmctl(shmid, IPC_RMID, NULL);
+          exit(1);
+  }
diff --git a/Documentation/arch/sparc/console.rst b/Documentation/arch/sparc/console.rst
new file mode 100644 (file)
index 0000000..73132db
--- /dev/null
@@ -0,0 +1,9 @@
+Steps for sending 'break' on sunhv console
+==========================================
+
+On Baremetal:
+   1. press   Esc + 'B'
+
+On LDOM:
+   1. press    Ctrl + ']'
+   2. telnet> send  break
diff --git a/Documentation/arch/sparc/features.rst b/Documentation/arch/sparc/features.rst
new file mode 100644 (file)
index 0000000..c0c9246
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features sparc
diff --git a/Documentation/arch/sparc/index.rst b/Documentation/arch/sparc/index.rst
new file mode 100644 (file)
index 0000000..ae88422
--- /dev/null
@@ -0,0 +1,13 @@
+==================
+Sparc Architecture
+==================
+
+.. toctree::
+   :maxdepth: 1
+
+   console
+   adi
+
+   oradax/oracle-dax
+
+   features
diff --git a/Documentation/arch/sparc/oradax/dax-hv-api.txt b/Documentation/arch/sparc/oradax/dax-hv-api.txt
new file mode 100644 (file)
index 0000000..7ecd0bf
--- /dev/null
@@ -0,0 +1,1433 @@
+Excerpt from UltraSPARC Virtual Machine Specification
+Compiled from version 3.0.20+15
+Publication date 2017-09-25 08:21
+Copyright © 2008, 2015 Oracle and/or its affiliates. All rights reserved.
+Extracted via "pdftotext -f 547 -l 572 -layout sun4v_20170925.pdf"
+Authors:
+        Charles Kunzman
+        Sam Glidden
+        Mark Cianchetti
+
+
+Chapter 36. Coprocessor services
+        The following APIs provide access via the Hypervisor to hardware assisted data processing functionality.
+        These APIs may only be provided by certain platforms, and may not be available to all virtual machines
+        even on supported platforms. Restrictions on the use of these APIs may be imposed in order to support
+        live-migration and other system management activities.
+
+36.1. Data Analytics Accelerator
+        The Data Analytics Accelerator (DAX) functionality is a collection of hardware coprocessors that provide
+        high speed processoring of database-centric operations. The coprocessors may support one or more of
+        the following data query operations: search, extraction, compression, decompression, and translation. The
+        functionality offered may vary by virtual machine implementation.
+
+        The DAX is a virtual device to sun4v guests, with supported data operations indicated by the virtual device
+        compatibility property. Functionality is accessed through the submission of Command Control Blocks
+        (CCBs) via the ccb_submit API function. The operations are processed asynchronously, with the status
+        of the submitted operations reported through a Completion Area linked to each CCB. Each CCB has a
+        separate Completion Area and, unless execution order is specifically restricted through the use of serial-
+        conditional flags, the execution order of submitted CCBs is arbitrary. Likewise, the time to completion
+        for a given CCB is never guaranteed.
+
+        Guest software may implement a software timeout on CCB operations, and if the timeout is exceeded, the
+        operation may be cancelled or killed via the ccb_kill API function. It is recommended for guest software
+        to implement a software timeout to account for certain RAS errors which may result in lost CCBs. It is
+        recommended such implementation use the ccb_info API function to check the status of a CCB prior to
+        killing it in order to determine if the CCB is still in queue, or may have been lost due to a RAS error.
+
+        There is no fixed limit on the number of outstanding CCBs guest software may have queued in the virtual
+        machine, however, internal resource limitations within the virtual machine can cause CCB submissions
+        to be temporarily rejected with EWOULDBLOCK. In such cases, guests should continue to attempt
+        submissions until they succeed; waiting for an outstanding CCB to complete is not necessary, and would
+        not be a guarantee that a future submission would succeed.
+
+        The availablility of DAX coprocessor command service is indicated by the presence of the DAX virtual
+        device node in the guest MD (Section 8.24.17, “Database Analytics Accelerators (DAX) virtual-device
+        node”).
+
+36.1.1. DAX Compatibility Property
+        The query functionality may vary based on the compatibility property of the virtual device:
+
+36.1.1.1. "ORCL,sun4v-dax" Device Compatibility
+        Available CCB commands:
+
+        • No-op/Sync
+
+        • Extract
+
+        • Scan Value
+
+        • Inverted Scan Value
+
+        • Scan Range
+
+
+                                                     509
+\f                                             Coprocessor services
+
+
+        • Inverted Scan Range
+
+        • Translate
+
+        • Inverted Translate
+
+        • Select
+
+        See Section 36.2.1, “Query CCB Command Formats” for the corresponding CCB input and output formats.
+
+        Only version 0 CCBs are available.
+
+36.1.1.2. "ORCL,sun4v-dax-fc" Device Compatibility
+        "ORCL,sun4v-dax-fc" is compatible with the "ORCL,sun4v-dax" interface, and includes additional CCB
+        bit fields and controls.
+
+36.1.1.3. "ORCL,sun4v-dax2" Device Compatibility
+        Available CCB commands:
+
+        • No-op/Sync
+
+        • Extract
+
+        • Scan Value
+
+        • Inverted Scan Value
+
+        • Scan Range
+
+        • Inverted Scan Range
+
+        • Translate
+
+        • Inverted Translate
+
+        • Select
+
+        See Section 36.2.1, “Query CCB Command Formats” for the corresponding CCB input and output formats.
+
+        Version 0 and 1 CCBs are available. Only version 0 CCBs may use Huffman encoded data, whereas only
+        version 1 CCBs may use OZIP.
+
+36.1.2. DAX Virtual Device Interrupts
+        The DAX virtual device has multiple interrupts associated with it which may be used by the guest if
+        desired. The number of device interrupts available to the guest is indicated in the virtual device node of the
+        guest MD (Section 8.24.17, “Database Analytics Accelerators (DAX) virtual-device node”). If the device
+        node indicates N interrupts available, the guest may use any value from 0 to N - 1 (inclusive) in a CCB
+        interrupt number field. Using values outside this range will result in the CCB being rejected for an invalid
+        field value.
+
+        The interrupts may be bound and managed using the standard sun4v device interrupts API (Chapter 16,
+        Device interrupt services). Sysino interrupts are not available for DAX devices.
+
+36.2. Coprocessor Control Block (CCB)
+        CCBs are either 64 or 128 bytes long, depending on the operation type. The exact contents of the CCB
+        are command specific, but all CCBs contain at least one memory buffer address. All memory locations
+
+
+                                                      510
+\f                                    Coprocessor services
+
+
+referenced by a CCB must be pinned in memory until the CCB either completes execution or is killed
+via the ccb_kill API call. Changes in virtual address mappings occurring after CCB submission are not
+guaranteed to be visible, and as such all virtual address updates need to be synchronized with CCB
+execution.
+
+All CCBs begin with a common 32-bit header.
+
+Table 36.1. CCB Header Format
+Bits          Field Description
+[31:28]       CCB version. For API version 2.0: set to 1 if CCB uses OZIP encoding; set to 0 if the CCB
+              uses Huffman encoding; otherwise either 0 or 1. For API version 1.0: always set to 0.
+[27]          When API version 2.0 is negotiated, this is the Pipeline Flag [512]. It is reserved in
+              API version 1.0
+[26]          Long CCB flag [512]
+[25]          Conditional synchronization flag [512]
+[24]          Serial synchronization flag
+[23:16]       CCB operation code:
+               0x00        No Operation (No-op) or Sync
+               0x01        Extract
+               0x02        Scan Value
+               0x12        Inverted Scan Value
+               0x03        Scan Range
+               0x13        Inverted Scan Range
+               0x04        Translate
+               0x14        Inverted Translate
+               0x05        Select
+[15:13]       Reserved
+[12:11]       Table address type
+               0b'00       No address
+               0b'01       Alternate context virtual address
+               0b'10       Real address
+               0b'11       Primary context virtual address
+[10:8]        Output/Destination address type
+               0b'000      No address
+               0b'001      Alternate context virtual address
+               0b'010      Real address
+               0b'011      Primary context virtual address
+               0b'100      Reserved
+               0b'101      Reserved
+               0b'110      Reserved
+               0b'111      Reserved
+[7:5]         Secondary source address type
+
+
+                                            511
+\f                                    Coprocessor services
+
+
+Bits           Field Description
+                0b'000       No address
+                0b'001       Alternate context virtual address
+                0b'010       Real address
+                0b'011       Primary context virtual address
+                0b'100       Reserved
+                0b'101       Reserved
+                0b'110       Reserved
+                0b'111       Reserved
+[4:2]          Primary source address type
+                0b'000       No address
+                0b'001       Alternate context virtual address
+                0b'010       Real address
+                0b'011       Primary context virtual address
+                0b'100       Reserved
+                0b'101       Reserved
+                0b'110       Reserved
+                0b'111       Reserved
+[1:0]          Completion area address type
+                0b'00        No address
+                0b'01        Alternate context virtual address
+                0b'10        Real address
+                0b'11        Primary context virtual address
+
+The Long CCB flag indicates whether the submitted CCB is 64 or 128 bytes long; value is 0 for 64 bytes
+and 1 for 128 bytes.
+
+The Serial and Conditional flags allow simple relative ordering between CCBs. Any CCB with the Serial
+flag set will execute sequentially relative to any previous CCB that is also marked as Serial in the same
+CCB submission. CCBs without the Serial flag set execute independently, even if they are between CCBs
+with the Serial flag set. CCBs marked solely with the Serial flag will execute upon the completion of the
+previous Serial CCB, regardless of the completion status of that CCB. The Conditional flag allows CCBs
+to conditionally execute based on the successful execution of the closest CCB marked with the Serial flag.
+A CCB may only be conditional on exactly one CCB, however, a CCB may be marked both Conditional
+and Serial to allow execution chaining. The flags do NOT allow fan-out chaining, where multiple CCBs
+execute in parallel based on the completion of another CCB.
+
+The Pipeline flag is an optimization that directs the output of one CCB (the "source" CCB) directly to
+the input of the next CCB (the "target" CCB). The target CCB thus does not need to read the input from
+memory. The Pipeline flag is advisory and may be dropped.
+
+Both the Pipeline and Serial bits must be set in the source CCB. The Conditional bit must be set in the
+target CCB. Exactly one CCB must be made conditional on the source CCB; either 0 or 2 target CCBs
+is invalid. However, Pipelines can be extended beyond two CCBs: the sequence would start with a CCB
+with both the Pipeline and Serial bits set, proceed through CCBs with the Pipeline, Serial, and Conditional
+bits set, and terminate at a CCB that has the Conditional bit set, but not the Pipeline bit.
+
+
+                                             512
+\f                                               Coprocessor services
+
+
+          The input of the target CCB must start within 64 bytes of the output of the source CCB or the pipeline flag
+          will be ignored. All CCBs in a pipeline must be submitted in the same call to ccb_submit.
+
+          The various address type fields indicate how the various address values used in the CCB should be
+          interpreted by the virtual machine. Not all of the types specified are used by every CCB format. Types
+          which are not applicable to the given CCB command should be indicated as type 0 (No address). Virtual
+          addresses used in the CCB must have translation entries present in either the TLB or a configured TSB
+          for the submitting virtual processor. Virtual addresses which cannot be translated by the virtual machine
+          will result in the CCB submission being rejected, with the causal virtual address indicated. The CCB
+          may be resubmitted after inserting the translation, or the address may be translated by guest software and
+          resubmitted using the real address translation.
+
+36.2.1. Query CCB Command Formats
+36.2.1.1. Supported Data Formats, Elements Sizes and Offsets
+          Data for query commands may be encoded in multiple possible formats. The data query commands use a
+          common set of values to indicate the encoding formats of the data being processed. Some encoding formats
+          require multiple data streams for processing, requiring the specification of both primary data formats (the
+          encoded data) and secondary data streams (meta-data for the encoded data).
+
+36.2.1.1.1. Primary Input Format
+
+          The primary input format code is a 4-bit field when it is used. There are 10 primary input formats available.
+          The packed formats are not endian neutral. Code values not listed below are reserved.
+
+          Code        Format                              Description
+          0x0         Fixed width byte packed             Up to 16 bytes
+          0x1         Fixed width bit packed              Up to 15 bits (CCB version 0) or 23 bits (CCB version
+                                                          1); bits are read most significant bit to least significant bit
+                                                          within a byte
+          0x2         Variable width byte packed          Data stream of lengths must be provided as a secondary
+                                                          input
+          0x4         Fixed width byte packed with run Up to 16 bytes; data stream of run lengths must be
+                      length encoding                  provided as a secondary input
+          0x5         Fixed width bit packed with run Up to 15 bits (CCB version 0) or 23 bits (CCB version
+                      length encoding                 1); bits are read most significant bit to least significant bit
+                                                      within a byte; data stream of run lengths must be provided
+                                                      as a secondary input
+          0x8         Fixed width byte packed with Up to 16 bytes before the encoding; compressed stream
+                      Huffman (CCB version 0) or bits are read most significant bit to least significant bit
+                      OZIP (CCB version 1) encoding within a byte; pointer to the encoding table must be
+                                                    provided
+          0x9         Fixed width bit packed with Up to 15 bits (CCB version 0) or 23 bits (CCB version
+                      Huffman (CCB version 0) or 1); compressed stream bits are read most significant bit to
+                      OZIP (CCB version 1) encoding least significant bit within a byte; pointer to the encoding
+                                                    table must be provided
+          0xA         Variable width byte packed with Up to 16 bytes before the encoding; compressed stream
+                      Huffman (CCB version 0) or bits are read most significant bit to least significant bit
+                      OZIP (CCB version 1) encoding within a byte; data stream of lengths must be provided as
+                                                      a secondary input; pointer to the encoding table must be
+                                                      provided
+
+
+                                                        513
+\f                                               Coprocessor services
+
+
+          Code        Format                              Description
+          0xC         Fixed width byte packed with        Up to 16 bytes before the encoding; compressed stream
+                      run length encoding, followed by    bits are read most significant bit to least significant bit
+                      Huffman (CCB version 0) or          within a byte; data stream of run lengths must be provided
+                      OZIP (CCB version 1) encoding       as a secondary input; pointer to the encoding table must
+                                                          be provided
+          0xD         Fixed width bit packed with         Up to 15 bits (CCB version 0) or 23 bits(CCB version 1)
+                      run length encoding, followed by    before the encoding; compressed stream bits are read most
+                      Huffman (CCB version 0) or          significant bit to least significant bit within a byte; data
+                      OZIP (CCB version 1) encoding       stream of run lengths must be provided as a secondary
+                                                          input; pointer to the encoding table must be provided
+
+          If OZIP encoding is used, there must be no reserved bytes in the table.
+
+36.2.1.1.2. Primary Input Element Size
+
+          For primary input data streams with fixed size elements, the element size must be indicated in the CCB
+          command. The size is encoded as the number of bits or bytes, minus one. The valid value range for this
+          field depends on the input format selected, as listed in the table above.
+
+36.2.1.1.3. Secondary Input Format
+
+          For primary input data streams which require a secondary input stream, the secondary input stream is
+          always encoded in a fixed width, bit-packed format. The bits are read from most significant bit to least
+          significant bit within a byte. There are two encoding options for the secondary input stream data elements,
+          depending on whether the value of 0 is needed:
+
+          Secondary           Input Description
+          Format Code
+          0                          Element is stored as value minus 1 (0 evaluates to 1, 1 evaluates
+                                     to 2, etc)
+          1                          Element is stored as value
+
+36.2.1.1.4. Secondary Input Element Size
+
+          Secondary input element size is encoded as a two bit field:
+
+          Secondary Input Size Description
+          Code
+          0x0                        1 bit
+          0x1                        2 bits
+          0x2                        4 bits
+          0x3                        8 bits
+
+36.2.1.1.5. Input Element Offsets
+
+          Bit-wise input data streams may have any alignment within the base addressed byte. The offset, specified
+          from most significant bit to least significant bit, is provided as a fixed 3 bit field for each input type. A
+          value of 0 indicates that the first input element begins at the most significant bit in the first byte, and a
+          value of 7 indicates it begins with the least significant bit.
+
+          This field should be zero for any byte-wise primary input data streams.
+
+
+                                                        514
+\f                                              Coprocessor services
+
+
+36.2.1.1.6. Output Format
+
+          Query commands support multiple sizes and encodings for output data streams. There are four possible
+          output encodings, and up to four supported element sizes per encoding. Not all output encodings are
+          supported for every command. The format is indicated by a 4-bit field in the CCB:
+
+           Output Format Code        Description
+           0x0                       Byte aligned, 1 byte elements
+           0x1                       Byte aligned, 2 byte elements
+           0x2                       Byte aligned, 4 byte elements
+           0x3                       Byte aligned, 8 byte elements
+           0x4                       16 byte aligned, 16 byte elements
+           0x5                       Reserved
+           0x6                       Reserved
+           0x7                       Reserved
+           0x8                       Packed vector of single bit elements
+           0x9                       Reserved
+           0xA                       Reserved
+           0xB                       Reserved
+           0xC                       Reserved
+           0xD                       2 byte elements where each element is the index value of a bit,
+                                     from an bit vector, which was 1.
+           0xE                       4 byte elements where each element is the index value of a bit,
+                                     from an bit vector, which was 1.
+           0xF                       Reserved
+
+36.2.1.1.7. Application Data Integrity (ADI)
+
+          On platforms which support ADI, the ADI version number may be specified for each separate memory
+          access type used in the CCB command. ADI checking only occurs when reading data. When writing data,
+          the specified ADI version number overwrites any existing ADI value in memory.
+
+          An ADI version value of 0 or 0xF indicates the ADI checking is disabled for that data access, even if it is
+          enabled in memory. By setting the appropriate flag in CCB_SUBMIT (Section 36.3.1, “ccb_submit”) it is
+          also an option to disable ADI checking for all inputs accessed via virtual address for all CCBs submitted
+          during that hypercall invocation.
+
+          The ADI value is only guaranteed to be checked on the first 64 bytes of each data access. Mismatches on
+          subsequent data chunks may not be detected, so guest software should be careful to use page size checking
+          to protect against buffer overruns.
+
+36.2.1.1.8. Page size checking
+
+          All data accesses used in CCB commands must be bounded within a single memory page. When addresses
+          are provided using a virtual address, the page size for checking is extracted from the TTE for that virtual
+          address. When using real addresses, the guest must supply the page size in the same field as the address
+          value. The page size must be one of the sizes supported by the underlying virtual machine. Using a value
+          that is not supported may result in the CCB submission being rejected or the generation of a CCB parsing
+          error in the completion area.
+
+
+                                                       515
+\f                                               Coprocessor services
+
+
+36.2.1.2. Extract command
+
+        Converts an input vector in one format to an output vector in another format. All input format types are
+        supported.
+
+        The only supported output format is a padded, byte-aligned output stream, using output codes 0x0 - 0x4.
+        When the specified output element size is larger than the extracted input element size, zeros are padded to
+        the extracted input element. First, if the decompressed input size is not a whole number of bytes, 0 bits are
+        padded to the most significant bit side till the next byte boundary. Next, if the output element size is larger
+        than the byte padded input element, bytes of value 0 are added based on the Padding Direction bit in the
+        CCB. If the output element size is smaller than the byte-padded input element size, the input element is
+        truncated by dropped from the least significant byte side until the selected output size is reached.
+
+        The return value of the CCB completion area is invalid. The “number of elements processed” field in the
+        CCB completion area will be valid.
+
+        The extract CCB is a 64-byte “short format” CCB.
+
+        The extract CCB command format can be specified by the following packed C structure for a big-endian
+        machine:
+
+
+                  struct extract_ccb {
+                         uint32_t header;
+                         uint32_t control;
+                         uint64_t completion;
+                         uint64_t primary_input;
+                         uint64_t data_access_control;
+                         uint64_t secondary_input;
+                         uint64_t reserved;
+                         uint64_t output;
+                         uint64_t table;
+                  };
+
+
+        The exact field offsets, sizes, and composition are as follows:
+
+         Offset         Size            Field Description
+         0              4               CCB header (Table 36.1, “CCB Header Format”)
+         4              4               Command control
+                                        Bits        Field Description
+                                        [31:28]     Primary Input Format (see Section 36.2.1.1.1, “Primary Input
+                                                    Format”)
+                                        [27:23]     Primary Input Element Size (see Section 36.2.1.1.2, “Primary
+                                                    Input Element Size”)
+                                        [22:20]     Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                                                    Element Offsets”)
+                                        [19]        Secondary Input Format (see Section 36.2.1.1.3, “Secondary
+                                                    Input Format”)
+                                        [18:16]     Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                                                    Element Offsets”)
+
+
+                                                       516
+\f                        Coprocessor services
+
+
+Offset   Size   Field Description
+                Bits         Field Description
+                [15:14]      Secondary Input Element Size (see Section 36.2.1.1.4,
+                             “Secondary Input Element Size”
+                [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
+                [9]          Padding Direction selector: A value of 1 causes padding bytes
+                             to be added to the left side of output elements. A value of 0
+                             causes padding bytes to be added to the right side of output
+                             elements.
+                [8:0]        Reserved
+8        8      Completion
+                Bits         Field Description
+                [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
+                             Integrity (ADI)”)
+                [59]         If set to 1, a virtual device interrupt will be generated using
+                             the device interrupt number specified in the lower bits of this
+                             completion word. If 0, the lower bits of this completion word
+                             are ignored.
+                [58:6]       Completion area address bits [58:6]. Address type is
+                             determined by CCB header.
+                [5:0]        Virtual device interrupt number for completion interrupt, if
+                             enabled.
+16       8      Primary Input
+                Bits         Field Description
+                [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
+                             Integrity (ADI)”)
+                [59:56]      If using real address, these bits should be filled in with the
+                             page size code for the page boundary checking the guest wants
+                             the virtual machine to use when accessing this data stream
+                             (checking is only guaranteed to be performed when using API
+                             version 1.1 and later). If using a virtual address, this field will
+                             be used as as primary input address bits [59:56].
+                [55:0]       Primary input address bits [55:0]. Address type is determined
+                             by CCB header.
+24       8      Data Access Control
+                Bits         Field Description
+                [63:62]      Flow Control
+                             Value      Description
+                             0b'00      Disable flow control
+                             0b'01      Enable flow control (only valid with "ORCL,sun4v-
+                                        dax-fc" compatible virtual device variants)
+                             0b'10      Reserved
+                             0b'11      Reserved
+                [61:60]      Reserved (API 1.0)
+
+
+                                517
+\f                       Coprocessor services
+
+
+Offset   Size   Field Description
+                Bits        Field Description
+                            Pipeline target (API 2.0)
+                            Value      Description
+                            0b'00      Connect to primary input
+                            0b'01      Connect to secondary input
+                            0b'10      Reserved
+                            0b'11      Reserved
+                [59:40]     Output buffer size given in units of 64 bytes, minus 1. Value of
+                            0 means 64 bytes, value of 1 means 128 bytes, etc. Buffer size is
+                            only enforced if flow control is enabled in Flow Control field.
+                [39:32]     Reserved
+                [31:30]     Output Data Cache Allocation
+                            Value      Description
+                            0b'00      Do not allocate cache lines for output data stream.
+                            0b'01      Force cache lines for output data stream to be
+                                       allocated in the cache that is local to the submitting
+                                       virtual cpu.
+                            0b'10      Allocate cache lines for output data stream, but allow
+                                       existing cache lines associated with the data to remain
+                                       in their current cache instance. Any memory not
+                                       already in cache will be allocated in the cache local
+                                       to the submitting virtual cpu.
+                            0b'11      Reserved
+                [29:26]     Reserved
+                [25:24]     Primary Input Length Format
+                            Value      Description
+                            0b'00      Number of primary symbols
+                            0b'01      Number of primary bytes
+                            0b'10      Number of primary bits
+                            0b'11      Reserved
+                [23:0]      Primary Input Length
+                            Format                      Field Value
+                            # of primary symbols        Number of input elements to process,
+                                                        minus 1. Command execution stops
+                                                        once count is reached.
+                            # of primary bytes          Number of input bytes to process,
+                                                        minus 1. Command execution stops
+                                                        once count is reached. The count is
+                                                        done before any decompression or
+                                                        decoding.
+                            # of primary bits           Number of input bits to process,
+                                                        minus 1. Command execution stops
+
+
+
+                               518
+\f                                                Coprocessor services
+
+
+        Offset          Size           Field Description
+                                        Bits         Field Description
+                                                     Format                     Field Value
+                                                                                once count is reached. The count is
+                                                                                done before any decompression or
+                                                                                decoding, and does not include any
+                                                                                bits skipped by the Primary Input
+                                                                                Offset field value of the command
+                                                                                control word.
+        32              8              Secondary Input, if used by Primary Input Format. Same fields as Primary
+                                       Input.
+        40              8              Reserved
+        48              8              Output (same fields as Primary Input)
+        56              8              Symbol Table (if used by Primary Input)
+                                        Bits         Field Description
+                                        [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
+                                                     Integrity (ADI)”)
+                                        [59:56]      If using real address, these bits should be filled in with the
+                                                     page size code for the page boundary checking the guest wants
+                                                     the virtual machine to use when accessing this data stream
+                                                     (checking is only guaranteed to be performed when using API
+                                                     version 1.1 and later). If using a virtual address, this field will
+                                                     be used as as symbol table address bits [59:56].
+                                        [55:4]       Symbol table address bits [55:4]. Address type is determined
+                                                     by CCB header.
+                                        [3:0]        Symbol table version
+                                                     Value     Description
+                                                     0         Huffman encoding. Must use 64 byte aligned table
+                                                               address. (Only available when using version 0 CCBs)
+                                                     1         OZIP encoding. Must use 16 byte aligned table
+                                                               address. (Only available when using version 1 CCBs)
+
+
+36.2.1.3. Scan commands
+
+        The scan commands search a stream of input data elements for values which match the selection criteria.
+        All the input format types are supported. There are multiple formats for the scan commands, allowing the
+        scan to search for exact matches to one value, exact matches to either of two values, or any value within
+        a specified range. The specific type of scan is indicated by the command code in the CCB header. For the
+        scan range commands, the boundary conditions can be specified as greater-than-or-equal-to a value, less-
+        than-or-equal-to a value, or both by using two boundary values.
+
+        There are two supported formats for the output stream: the bit vector and index array formats (codes 0x8,
+        0xD, and 0xE). For the standard scan command using the bit vector output, for each input element there
+        exists one bit in the vector that is set if the input element matched the scan criteria, or clear if not. The
+        inverted scan command inverts the polarity of the bits in the output. The most significant bit of the first
+        byte of the output stream corresponds to the first element in the input stream. The standard index array
+        output format contains one array entry for each input element that matched the scan criteria. Each array
+
+
+
+                                                         519
+\f                                       Coprocessor services
+
+
+entry is the index of an input element that matched the scan criteria. An inverted scan command produces
+a similar array, but of all the input elements which did NOT match the scan criteria.
+
+The return value of the CCB completion area contains the number of input elements found which match
+the scan criteria (or number that did not match for the inverted scans). The “number of elements processed”
+field in the CCB completion area will be valid, indicating the number of input elements processed.
+
+These commands are 128-byte “long format” CCBs.
+
+The scan CCB command format can be specified by the following packed C structure for a big-endian
+machine:
+
+
+         struct scan_ccb         {
+                uint32_t         header;
+                uint32_t         control;
+                uint64_t         completion;
+                uint64_t         primary_input;
+                uint64_t         data_access_control;
+                uint64_t         secondary_input;
+                uint64_t         match_criteria0;
+                uint64_t         output;
+                uint64_t         table;
+                uint64_t         match_criteria1;
+                uint64_t         match_criteria2;
+                uint64_t         match_criteria3;
+                uint64_t         reserved[5];
+         };
+
+
+The exact field offsets, sizes, and composition are as follows:
+
+Offset         Size            Field Description
+0              4               CCB header (Table 36.1, “CCB Header Format”)
+4              4               Command control
+                               Bits         Field Description
+                               [31:28]      Primary Input Format (see Section 36.2.1.1.1, “Primary Input
+                                            Format”)
+                               [27:23]      Primary Input Element Size (see Section 36.2.1.1.2, “Primary
+                                            Input Element Size”)
+                               [22:20]      Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                                            Element Offsets”)
+                               [19]         Secondary Input Format (see Section 36.2.1.1.3, “Secondary
+                                            Input Format”)
+                               [18:16]      Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                                            Element Offsets”)
+                               [15:14]      Secondary Input Element Size (see Section 36.2.1.1.4,
+                                            “Secondary Input Element Size”
+                               [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
+                               [9:5]        Operand size for first scan criteria value. In a scan value
+                                            operation, this is one of two potential exact match values.
+                                            In a scan range operation, this is the size of the upper range
+
+
+                                               520
+\f                        Coprocessor services
+
+
+Offset   Size   Field Description
+                Bits         Field Description
+                             boundary. The value of this field is the number of bytes in the
+                             operand, minus 1. Values 0xF-0x1E are reserved. A value of
+                             0x1F indicates this operand is not in use for this scan operation.
+                [4:0]        Operand size for second scan criteria value. In a scan value
+                             operation, this is one of two potential exact match values.
+                             In a scan range operation, this is the size of the lower range
+                             boundary. The value of this field is the number of bytes in the
+                             operand, minus 1. Values 0xF-0x1E are reserved. A value of
+                             0x1F indicates this operand is not in use for this scan operation.
+8        8      Completion (same fields as Section 36.2.1.2, “Extract command”)
+16       8      Primary Input (same fields as Section 36.2.1.2, “Extract command”)
+24       8      Data Access Control (same fields as Section 36.2.1.2, “Extract command”)
+32       8      Secondary Input, if used by Primary Input Format. Same fields as Primary
+                Input.
+40       4      Most significant 4 bytes of first scan criteria operand. If first operand is less
+                than 4 bytes, the value is left-aligned to the lowest address bytes.
+44       4      Most significant 4 bytes of second scan criteria operand. If second operand
+                is less than 4 bytes, the value is left-aligned to the lowest address bytes.
+48       8      Output (same fields as Primary Input)
+56       8      Symbol Table (if used by Primary Input). Same fields as Section 36.2.1.2,
+                “Extract command”
+64       4      Next 4 most significant bytes of first scan criteria operand occurring after the
+                bytes specified at offset 40, if needed by the operand size. If first operand
+                is less than 8 bytes, the valid bytes are left-aligned to the lowest address.
+68       4      Next 4 most significant bytes of second scan criteria operand occurring after
+                the bytes specified at offset 44, if needed by the operand size. If second
+                operand is less than 8 bytes, the valid bytes are left-aligned to the lowest
+                address.
+72       4      Next 4 most significant bytes of first scan criteria operand occurring after the
+                bytes specified at offset 64, if needed by the operand size. If first operand
+                is less than 12 bytes, the valid bytes are left-aligned to the lowest address.
+76       4      Next 4 most significant bytes of second scan criteria operand occurring after
+                the bytes specified at offset 68, if needed by the operand size. If second
+                operand is less than 12 bytes, the valid bytes are left-aligned to the lowest
+                address.
+80       4      Next 4 most significant bytes of first scan criteria operand occurring after the
+                bytes specified at offset 72, if needed by the operand size. If first operand
+                is less than 16 bytes, the valid bytes are left-aligned to the lowest address.
+84       4      Next 4 most significant bytes of second scan criteria operand occurring after
+                the bytes specified at offset 76, if needed by the operand size. If second
+                operand is less than 16 bytes, the valid bytes are left-aligned to the lowest
+                address.
+
+
+
+
+                                521
+\f                                               Coprocessor services
+
+
+36.2.1.4. Translate commands
+
+        The translate commands takes an input array of indices, and a table of single bit values indexed by those
+        indices, and outputs a bit vector or index array created by reading the tables bit value at each index in
+        the input array. The output should therefore contain exactly one bit per index in the input data stream,
+        when outputting as a bit vector. When outputting as an index array, the number of elements depends on the
+        values read in the bit table, but will always be less than, or equal to, the number of input elements. Only
+        a restricted subset of the possible input format types are supported. No variable width or Huffman/OZIP
+        encoded input streams are allowed. The primary input data element size must be 3 bytes or less.
+
+        The maximum table index size allowed is 15 bits, however, larger input elements may be used to provide
+        additional processing of the output values. If 2 or 3 byte values are used, the least significant 15 bits are
+        used as an index into the bit table. The most significant 9 bits (when using 3-byte input elements) or single
+        bit (when using 2-byte input elements) are compared against a fixed 9-bit test value provided in the CCB.
+        If the values match, the value from the bit table is used as the output element value. If the values do not
+        match, the output data element value is forced to 0.
+
+        In the inverted translate operation, the bit value read from bit table is inverted prior to its use. The additional
+        additional processing based on any additional non-index bits remains unchanged, and still forces the output
+        element value to 0 on a mismatch. The specific type of translate command is indicated by the command
+        code in the CCB header.
+
+        There are two supported formats for the output stream: the bit vector and index array formats (codes 0x8,
+        0xD, and 0xE). The index array format is an array of indices of bits which would have been set if the
+        output format was a bit array.
+
+        The return value of the CCB completion area contains the number of bits set in the output bit vector,
+        or number of elements in the output index array. The “number of elements processed” field in the CCB
+        completion area will be valid, indicating the number of input elements processed.
+
+        These commands are 64-byte “short format” CCBs.
+
+        The translate CCB command format can be specified by the following packed C structure for a big-endian
+        machine:
+
+
+                 struct translate_ccb {
+                        uint32_t header;
+                        uint32_t control;
+                        uint64_t completion;
+                        uint64_t primary_input;
+                        uint64_t data_access_control;
+                        uint64_t secondary_input;
+                        uint64_t reserved;
+                        uint64_t output;
+                        uint64_t table;
+                 };
+
+
+        The exact field offsets, sizes, and composition are as follows:
+
+
+        Offset          Size             Field Description
+        0               4                CCB header (Table 36.1, “CCB Header Format”)
+
+
+                                                        522
+\f                        Coprocessor services
+
+
+Offset   Size   Field Description
+4        4      Command control
+                Bits         Field Description
+                [31:28]      Primary Input Format (see Section 36.2.1.1.1, “Primary Input
+                             Format”)
+                [27:23]      Primary Input Element Size (see Section 36.2.1.1.2, “Primary
+                             Input Element Size”)
+                [22:20]      Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                             Element Offsets”)
+                [19]         Secondary Input Format (see Section 36.2.1.1.3, “Secondary
+                             Input Format”)
+                [18:16]      Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                             Element Offsets”)
+                [15:14]      Secondary Input Element Size (see Section 36.2.1.1.4,
+                             “Secondary Input Element Size”
+                [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
+                [9]          Reserved
+                [8:0]        Test value used for comparison against the most significant bits
+                             in the input values, when using 2 or 3 byte input elements.
+8        8      Completion (same fields as Section 36.2.1.2, “Extract command”
+16       8      Primary Input (same fields as Section 36.2.1.2, “Extract command”
+24       8      Data Access Control (same fields as Section 36.2.1.2, “Extract command”,
+                except Primary Input Length Format may not use the 0x0 value)
+32       8      Secondary Input, if used by Primary Input Format. Same fields as Primary
+                Input.
+40       8      Reserved
+48       8      Output (same fields as Primary Input)
+56       8      Bit Table
+                Bits         Field Description
+                [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
+                             Integrity (ADI)”)
+                [59:56]      If using real address, these bits should be filled in with the
+                             page size code for the page boundary checking the guest wants
+                             the virtual machine to use when accessing this data stream
+                             (checking is only guaranteed to be performed when using API
+                             version 1.1 and later). If using a virtual address, this field will
+                             be used as as bit table address bits [59:56]
+                [55:4]       Bit table address bits [55:4]. Address type is determined by
+                             CCB header. Address must be 64-byte aligned (CCB version
+                             0) or 16-byte aligned (CCB version 1).
+                [3:0]        Bit table version
+                             Value      Description
+                             0          4KB table size
+                             1          8KB table size
+
+
+
+                                 523
+\f                                              Coprocessor services
+
+
+36.2.1.5. Select command
+        The select command filters the primary input data stream by using a secondary input bit vector to determine
+        which input elements to include in the output. For each bit set at a given index N within the bit vector,
+        the Nth input element is included in the output. If the bit is not set, the element is not included. Only a
+        restricted subset of the possible input format types are supported. No variable width or run length encoded
+        input streams are allowed, since the secondary input stream is used for the filtering bit vector.
+
+        The only supported output format is a padded, byte-aligned output stream. The stream follows the same
+        rules and restrictions as padded output stream described in Section 36.2.1.2, “Extract command”.
+
+        The return value of the CCB completion area contains the number of bits set in the input bit vector. The
+        "number of elements processed" field in the CCB completion area will be valid, indicating the number
+        of input elements processed.
+
+        The select CCB is a 64-byte “short format” CCB.
+
+        The select CCB command format can be specified by the following packed C structure for a big-endian
+        machine:
+
+
+                  struct select_ccb {
+                         uint32_t header;
+                         uint32_t control;
+                         uint64_t completion;
+                         uint64_t primary_input;
+                         uint64_t data_access_control;
+                         uint64_t secondary_input;
+                         uint64_t reserved;
+                         uint64_t output;
+                         uint64_t table;
+                  };
+
+
+        The exact field offsets, sizes, and composition are as follows:
+
+         Offset        Size            Field Description
+         0             4               CCB header (Table 36.1, “CCB Header Format”)
+         4             4               Command control
+                                       Bits        Field Description
+                                       [31:28]     Primary Input Format (see Section 36.2.1.1.1, “Primary Input
+                                                   Format”)
+                                       [27:23]     Primary Input Element Size (see Section 36.2.1.1.2, “Primary
+                                                   Input Element Size”)
+                                       [22:20]     Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                                                   Element Offsets”)
+                                       [19]        Secondary Input Format (see Section 36.2.1.1.3, “Secondary
+                                                   Input Format”)
+                                       [18:16]     Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
+                                                   Element Offsets”)
+                                       [15:14]     Secondary Input Element Size (see Section 36.2.1.1.4,
+                                                   “Secondary Input Element Size”
+
+
+                                                      524
+\f                                               Coprocessor services
+
+
+        Offset         Size            Field Description
+                                       Bits         Field Description
+                                       [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
+                                       [9]          Padding Direction selector: A value of 1 causes padding bytes
+                                                    to be added to the left side of output elements. A value of 0
+                                                    causes padding bytes to be added to the right side of output
+                                                    elements.
+                                       [8:0]        Reserved
+        8              8               Completion (same fields as Section 36.2.1.2, “Extract command”
+        16             8               Primary Input (same fields as Section 36.2.1.2, “Extract command”
+        24             8               Data Access Control (same fields as Section 36.2.1.2, “Extract command”)
+        32             8               Secondary Bit Vector Input. Same fields as Primary Input.
+        40             8               Reserved
+        48             8               Output (same fields as Primary Input)
+        56             8               Symbol Table (if used by Primary Input). Same fields as Section 36.2.1.2,
+                                       “Extract command”
+
+36.2.1.6. No-op and Sync commands
+        The no-op (no operation) command is a CCB which has no processing effect. The CCB, when processed
+        by the virtual machine, simply updates the completion area with its execution status. The CCB may have
+        the serial-conditional flags set in order to restrict when it executes.
+
+        The sync command is a variant of the no-op command which with restricted execution timing. A sync
+        command CCB will only execute when all previous commands submitted in the same request have
+        completed. This is stronger than the conditional flag sequencing, which is only dependent on a single
+        previous serial CCB. While the relative ordering is guaranteed, virtual machine implementations with
+        shared hardware resources may cause the sync command to wait for longer than the minimum required
+        time.
+
+        The return value of the CCB completion area is invalid for these CCBs. The “number of elements
+        processed” field is also invalid for these CCBs.
+
+        These commands are 64-byte “short format” CCBs.
+
+        The no-op CCB command format can be specified by the following packed C structure for a big-endian
+        machine:
+
+
+                 struct nop_ccb {
+                        uint32_t header;
+                        uint32_t control;
+                        uint64_t completion;
+                        uint64_t reserved[6];
+                 };
+
+
+        The exact field offsets, sizes, and composition are as follows:
+
+        Offset         Size            Field Description
+        0              4               CCB header (Table 36.1, “CCB Header Format”)
+
+
+                                                       525
+\f                                          Coprocessor services
+
+
+       Offset        Size          Field Description
+       4             4             Command control
+                                   Bits        Field Description
+                                   [31]        If set, this CCB functions as a Sync command. If clear, this
+                                               CCB functions as a No-op command.
+                                   [30:0]      Reserved
+       8             8             Completion (same fields as Section 36.2.1.2, “Extract command”
+       16            46            Reserved
+
+36.2.2. CCB Completion Area
+       All CCB commands use a common 128-byte Completion Area format, which can be specified by the
+       following packed C structure for a big-endian machine:
+
+
+                struct completion_area {
+                       uint8_t status_flag;
+                       uint8_t error_note;
+                       uint8_t rsvd0[2];
+                       uint32_t error_values;
+                       uint32_t output_size;
+                       uint32_t rsvd1;
+                       uint64_t run_time;
+                       uint64_t run_stats;
+                       uint32_t elements;
+                       uint8_t rsvd2[20];
+                       uint64_t return_value;
+                       uint64_t extra_return_value[8];
+                };
+
+
+       The Completion Area must be a 128-byte aligned memory location. The exact layout can be described
+       using byte offsets and sizes relative to the memory base:
+
+       Offset        Size          Field Description
+       0             1             CCB execution status
+                                   0x0                  Command not yet completed
+                                   0x1                  Command ran and succeeded
+                                   0x2                  Command ran and failed (partial results may be been
+                                                        produced)
+                                   0x3                  Command ran and was killed (partial execution may
+                                                        have occurred)
+                                   0x4                  Command was not run
+                                   0x5-0xF              Reserved
+       1             1             Error reason code
+                                   0x0                  Reserved
+                                   0x1                  Buffer overflow
+
+
+                                                  526
+\f                                      Coprocessor services
+
+
+Offset          Size           Field Description
+                                0x2                 CCB decoding error
+                                0x3                 Page overflow
+                                0x4-0x6             Reserved
+                                0x7                 Command was killed
+                                0x8                 Command execution timeout
+                                0x9                 ADI miscompare error
+                                0xA                 Data format error
+                                0xB-0xD             Reserved
+                                0xE                 Unexpected hardware error (Do not retry)
+                                0xF                 Unexpected hardware error (Retry is ok)
+                                0x10-0x7F           Reserved
+                                0x80                Partial Symbol Warning
+                                0x81-0xFF           Reserved
+2               2              Reserved
+4               4              If a partial symbol warning was generated, this field contains the number
+                               of remaining bits which were not decoded.
+8               4              Number of bytes of output produced
+12              4              Reserved
+16              8              Runtime of command (unspecified time units)
+24              8              Reserved
+32              4              Number of elements processed
+36              20             Reserved
+56              8              Return value
+64              64             Extended return value
+
+The CCB completion area should be treated as read-only by guest software. The CCB execution status
+byte will be cleared by the Hypervisor to reflect the pending execution status when the CCB is submitted
+successfully. All other fields are considered invalid upon CCB submission until the CCB execution status
+byte becomes non-zero.
+
+CCBs which complete with status 0x2 or 0x3 may produce partial results and/or side effects due to partial
+execution of the CCB command. Some valid data may be accessible depending on the fault type, however,
+it is recommended that guest software treat the destination buffer as being in an unknown state. If a CCB
+completes with a status byte of 0x2, the error reason code byte can be read to determine what corrective
+action should be taken.
+
+A buffer overflow indicates that the results of the operation exceeded the size of the output buffer indicated
+in the CCB. The operation can be retried by resubmitting the CCB with a larger output buffer.
+
+A CCB decoding error indicates that the CCB contained some invalid field values. It may be also be
+triggered if the CCB output is directed at a non-existent secondary input and the pipelining hint is followed.
+
+A page overflow error indicates that the operation required accessing a memory location beyond the page
+size associated with a given address. No data will have been read or written past the page boundary, but
+partial results may have been written to the destination buffer. The CCB can be resubmitted with a larger
+page size memory allocation to complete the operation.
+
+
+                                              527
+\f                                            Coprocessor services
+
+
+       In the case of pipelined CCBs, a page overflow error will be triggered if the output from the pipeline source
+       CCB ends before the input of the pipeline target CCB. Page boundaries are ignored when the pipeline
+       hint is followed.
+
+       Command kill indicates that the CCB execution was halted or prevented by use of the ccb_kill API call.
+
+       Command timeout indicates that the CCB execution began, but did not complete within a pre-determined
+       limit set by the virtual machine. The command may have produced some or no output. The CCB may be
+       resubmitted with no alterations.
+
+       ADI miscompare indicates that the memory buffer version specified in the CCB did not match the value
+       in memory when accessed by the virtual machine. Guest software should not attempt to resubmit the CCB
+       without determining the cause of the version mismatch.
+
+       A data format error indicates that the input data stream did not follow the specified data input formatting
+       selected in the CCB.
+
+       Some CCBs which encounter hardware errors may be resubmitted without change. Persistent hardware
+       errors may result in multiple failures until RAS software can identify and isolate the faulty component.
+
+       The output size field indicates the number of bytes of valid output in the destination buffer. This field is
+       not valid for all possible CCB commands.
+
+       The runtime field indicates the execution time of the CCB command once it leaves the internal virtual
+       machine queue. The time units are fixed, but unspecified, allowing only relative timing comparisons
+       by guest software. The time units may also vary by hardware platform, and should not be construed to
+       represent any absolute time value.
+
+       Some data query commands process data in units of elements. If applicable to the command, the number of
+       elements processed is indicated in the listed field. This field is not valid for all possible CCB commands.
+
+       The return value and extended return value fields are output locations for commands which do not use
+       a destination output buffer, or have secondary return results. The field is not valid for all possible CCB
+       commands.
+
+36.3. Hypervisor API Functions
+36.3.1. ccb_submit
+       trap#             FAST_TRAP
+       function#         CCB_SUBMIT
+       arg0              address
+       arg1              length
+       arg2              flags
+       arg3              reserved
+       ret0              status
+       ret1              length
+       ret2              status data
+       ret3              reserved
+
+       Submit one or more coprocessor control blocks (CCBs) for evaluation and processing by the virtual
+       machine. The CCBs are passed in a linear array indicated by address. length indicates the size of
+       the array in bytes.
+
+
+                                                     528
+\f                                      Coprocessor services
+
+
+The address should be aligned to the size indicated by length, rounded up to the nearest power of
+two. Virtual machines implementations may reject submissions which do not adhere to that alignment.
+length must be a multiple of 64 bytes. If length is zero, the maximum supported array length will be
+returned as length in ret1. In all other cases, the length value in ret1 will reflect the number of bytes
+successfully consumed from the input CCB array.
+
+      Implementation note
+      Virtual machines should never reject submissions based on the alignment of address if the
+      entire array is contained within a single memory page of the smallest page size supported by the
+      virtual machine.
+
+A guest may choose to submit addresses used in this API function, including the CCB array address,
+as either a real or virtual addresses, with the type of each address indicated in flags. Virtual addresses
+must be present in either the TLB or an active TSB to be processed. The translation context for virtual
+addresses is determined by a combination of CCB contents and the flags argument.
+
+The flags argument is divided into multiple fields defined as follows:
+
+
+Bits            Field Description
+[63:16]         Reserved
+[15]            Disable ADI for VA reads (in API 2.0)
+                Reserved (in API 1.0)
+[14]            Virtual addresses within CCBs are translated in privileged context
+[13:12]         Alternate translation context for virtual addresses within CCBs:
+                 0b'00        CCBs requesting alternate context are rejected
+                 0b'01        Reserved
+                 0b'10        CCBs requesting alternate context use secondary context
+                 0b'11        CCBs requesting alternate context use nucleus context
+[11:9]          Reserved
+[8]             Queue info flag
+[7]             All-or-nothing flag
+[6]             If address is a virtual address, treat its translation context as privileged
+[5:4]           Address type of address:
+                 0b'00        Real address
+                 0b'01        Virtual address in primary context
+                 0b'10        Virtual address in secondary context
+                 0b'11        Virtual address in nucleus context
+[3:2]           Reserved
+[1:0]           CCB command type:
+                 0b'00        Reserved
+                 0b'01        Reserved
+                 0b'10        Query command
+                 0b'11        Reserved
+
+
+
+                                              529
+\f                                             Coprocessor services
+
+
+         The CCB submission type and address type for the CCB array must be provided in the flags argument.
+         All other fields are optional values which change the default behavior of the CCB processing.
+
+         When set to one, the "Disable ADI for VA reads" bit will turn off ADI checking when using a virtual
+         address to load data. ADI checking will still be done when loading real-addressed memory. This bit is only
+         available when using major version 2 of the coprocessor API group; at major version 1 it is reserved. For
+         more information about using ADI and DAX, see Section 36.2.1.1.7, “Application Data Integrity (ADI)”.
+
+         By default, all virtual addresses are treated as user addresses. If the virtual address translations are
+         privileged, they must be marked as such in the appropriate flags field. The virtual addresses used within
+         the submitted CCBs must all be translated with the same privilege level.
+
+         By default, all virtual addresses used within the submitted CCBs are translated using the primary context
+         active at the time of the submission. The address type field within a CCB allows each address to request
+         translation in an alternate address context. The address context used when the alternate address context is
+         requested is selected in the flags argument.
+
+         The all-or-nothing flag specifies whether the virtual machine should allow partial submissions of the
+         input CCB array. When using CCBs with serial-conditional flags, it is strongly recommended to use
+         the all-or-nothing flag to avoid broken conditional chains. Using long CCB chains on a machine under
+         high coprocessor load may make this impractical, however, and require submitting without the flag.
+         When submitting serial-conditional CCBs without the all-or-nothing flag, guest software must manually
+         implement the serial-conditional behavior at any point where the chain was not submitted in a single API
+         call, and resubmission of the remaining CCBs should clear any conditional flag that might be set in the
+         first remaining CCB. Failure to do so will produce indeterminate CCB execution status and ordering.
+
+         When the all-or-nothing flag is not specified, callers should check the value of length in ret1 to determine
+         how many CCBs from the array were successfully submitted. Any remaining CCBs can be resubmitted
+         without modifications.
+
+         The value of length in ret1 is also valid when the API call returns an error, and callers should always
+         check its value to determine which CCBs in the array were already processed. This will additionally
+         identify which CCB encountered the processing error, and was not submitted successfully.
+
+         If the queue info flag is used during submission, and at least one CCB was successfully submitted, the
+         length value in ret1 will be a multi-field value defined as follows:
+          Bits          Field Description
+          [63:48]       DAX unit instance identifier
+          [47:32]       DAX queue instance identifier
+          [31:16]       Reserved
+          [15:0]        Number of CCB bytes successfully submitted
+
+         The value of status data depends on the status value. See error status code descriptions for details.
+         The value is undefined for status values that do not specifically list a value for the status data.
+
+         The API has a reserved input and output register which will be used in subsequent minor versions of this
+         API function. Guest software implementations should treat that register as voltile across the function call
+         in order to maintain forward compatibility.
+
+36.3.1.1. Errors
+          EOK                       One or more CCBs have been accepted and enqueued in the virtual machine
+                                    and no errors were been encountered during submission. Some submitted
+                                    CCBs may not have been enqueued due to internal virtual machine limitations,
+                                    and may be resubmitted without changes.
+
+
+                                                       530
+\f                        Coprocessor services
+
+
+EWOULDBLOCK    An internal resource conflict within the virtual machine has prevented it from
+               being able to complete the CCB submissions sufficiently quickly, requiring
+               it to abandon processing before it was complete. Some CCBs may have been
+               successfully enqueued prior to the block, and all remaining CCBs may be
+               resubmitted without changes.
+EBADALIGN      CCB array is not on a 64-byte boundary, or the array length is not a multiple
+               of 64 bytes.
+ENORADDR       A real address used either for the CCB array, or within one of the submitted
+               CCBs, is not valid for the guest. Some CCBs may have been enqueued prior
+               to the error being detected.
+ENOMAP         A virtual address used either for the CCB array, or within one of the submitted
+               CCBs, could not be translated by the virtual machine using either the TLB
+               or TSB contents. The submission may be retried after adding the required
+               mapping, or by converting the virtual address into a real address. Due to the
+               shared nature of address translation resources, there is no theoretical limit on
+               the number of times the translation may fail, and it is recommended all guests
+               implement some real address based backup. The virtual address which failed
+               translation is returned as status data in ret2. Some CCBs may have been
+               enqueued prior to the error being detected.
+EINVAL         The virtual machine detected an invalid CCB during submission, or invalid
+               input arguments, such as bad flag values. Note that not all invalid CCB values
+               will be detected during submission, and some may be reported as errors in the
+               completion area instead. Some CCBs may have been enqueued prior to the
+               error being detected. This error may be returned if the CCB version is invalid.
+ETOOMANY       The request was submitted with the all-or-nothing flag set, and the array size is
+               greater than the virtual machine can support in a single request. The maximum
+               supported size for the current virtual machine can be queried by submitting a
+               request with a zero length array, as described above.
+ENOACCESS      The guest does not have permission to submit CCBs, or an address used in a
+               CCBs lacks sufficient permissions to perform the required operation (no write
+               permission on the destination buffer address, for example). A virtual address
+               which fails permission checking is returned as status data in ret2. Some
+               CCBs may have been enqueued prior to the error being detected.
+EUNAVAILABLE   The requested CCB operation could not be performed at this time. The
+               restricted operation availability may apply only to the first unsuccessfully
+               submitted CCB, or may apply to a larger scope. The status should not be
+               interpreted as permanent, and the guest should attempt to submit CCBs in
+               the future which had previously been unable to be performed. The status
+               data provides additional information about scope of the restricted availability
+               as follows:
+               Value       Description
+               0           Processing for the exact CCB instance submitted was unavailable,
+                           and it is recommended the guest emulate the operation. The
+                           guest should continue to submit all other CCBs, and assume no
+                           restrictions beyond this exact CCB instance.
+               1           Processing is unavailable for all CCBs using the requested opcode,
+                           and it is recommended the guest emulate the operation. The
+                           guest should continue to submit all other CCBs that use different
+                           opcodes, but can expect continued rejections of CCBs using the
+                           same opcode in the near future.
+
+
+                                 531
+\f                                              Coprocessor services
+
+
+                                      Value     Description
+                                      2         Processing is unavailable for all CCBs using the requested CCB
+                                                version, and it is recommended the guest emulate the operation.
+                                                The guest should continue to submit all other CCBs that use
+                                                different CCB versions, but can expect continued rejections of
+                                                CCBs using the same CCB version in the near future.
+                                      3         Processing is unavailable for all CCBs on the submitting vcpu,
+                                                and it is recommended the guest emulate the operation or resubmit
+                                                the CCB on a different vcpu. The guest should continue to submit
+                                                CCBs on all other vcpus but can expect continued rejections of all
+                                                CCBs on this vcpu in the near future.
+                                      4         Processing is unavailable for all CCBs, and it is recommended
+                                                the guest emulate the operation. The guest should expect all CCB
+                                                submissions to be similarly rejected in the near future.
+
+
+36.3.2. ccb_info
+
+        trap#               FAST_TRAP
+        function#           CCB_INFO
+        arg0                address
+        ret0                status
+        ret1                CCB state
+        ret2                position
+        ret3                dax
+        ret4                queue
+
+       Requests status information on a previously submitted CCB. The previously submitted CCB is identified
+       by the 64-byte aligned real address of the CCBs completion area.
+
+       A CCB can be in one of 4 states:
+
+
+        State                     Value       Description
+        COMPLETED                 0           The CCB has been fetched and executed, and is no longer active in
+                                              the virtual machine.
+        ENQUEUED                  1           The requested CCB is current in a queue awaiting execution.
+        INPROGRESS                2           The CCB has been fetched and is currently being executed. It may still
+                                              be possible to stop the execution using the ccb_kill hypercall.
+        NOTFOUND                  3           The CCB could not be located in the virtual machine, and does not
+                                              appear to have been executed. This may occur if the CCB was lost
+                                              due to a hardware error, or the CCB may not have been successfully
+                                              submitted to the virtual machine in the first place.
+
+               Implementation note
+               Some platforms may not be able to report CCBs that are currently being processed, and therefore
+               guest software should invoke the ccb_kill hypercall prior to assuming the request CCB will never
+               be executed because it was in the NOTFOUND state.
+
+
+                                                       532
+\f                                             Coprocessor services
+
+
+         The position return value is only valid when the state is ENQUEUED. The value returned is the number
+         of other CCBs ahead of the requested CCB, to provide a relative estimate of when the CCB may execute.
+
+         The dax return value is only valid when the state is ENQUEUED. The value returned is the DAX unit
+         instance identifier for the DAX unit processing the queue where the requested CCB is located. The value
+         matches the value that would have been, or was, returned by ccb_submit using the queue info flag.
+
+         The queue return value is only valid when the state is ENQUEUED. The value returned is the DAX
+         queue instance identifier for the DAX unit processing the queue where the requested CCB is located. The
+         value matches the value that would have been, or was, returned by ccb_submit using the queue info flag.
+
+36.3.2.1. Errors
+
+          EOK                       The request was processed and the CCB state is valid.
+          EBADALIGN                 address is not on a 64-byte aligned.
+          ENORADDR                  The real address provided for address is not valid.
+          EINVAL                    The CCB completion area contents are not valid.
+          EWOULDBLOCK               Internal resource constraints prevented the CCB state from being queried at this
+                                    time. The guest should retry the request.
+          ENOACCESS                 The guest does not have permission to access the coprocessor virtual device
+                                    functionality.
+
+36.3.3. ccb_kill
+
+          trap#           FAST_TRAP
+          function#       CCB_KILL
+          arg0            address
+          ret0            status
+          ret1            result
+
+         Request to stop execution of a previously submitted CCB. The previously submitted CCB is identified by
+         the 64-byte aligned real address of the CCBs completion area.
+
+         The kill attempt can produce one of several values in the result return value, reflecting the CCB state
+         and actions taken by the Hypervisor:
+
+          Result                Value       Description
+          COMPLETED             0           The CCB has been fetched and executed, and is no longer active in
+                                            the virtual machine. It could not be killed and no action was taken.
+          DEQUEUED              1           The requested CCB was still enqueued when the kill request was
+                                            submitted, and has been removed from the queue. Since the CCB
+                                            never began execution, no memory modifications were produced by
+                                            it, and the completion area will never be updated. The same CCB may
+                                            be submitted again, if desired, with no modifications required.
+          KILLED                2           The CCB had been fetched and was being executed when the kill
+                                            request was submitted. The CCB execution was stopped, and the CCB
+                                            is no longer active in the virtual machine. The CCB completion area
+                                            will reflect the killed status, with the subsequent implications that
+                                            partial results may have been produced. Partial results may include full
+
+
+                                                      533
+\f                                              Coprocessor services
+
+
+          Result                 Value       Description
+                                             command execution if the command was stopped just prior to writing
+                                             to the completion area.
+          NOTFOUND               3           The CCB could not be located in the virtual machine, and does not
+                                             appear to have been executed. This may occur if the CCB was lost
+                                             due to a hardware error, or the CCB may not have been successfully
+                                             submitted to the virtual machine in the first place. CCBs in the state
+                                             are guaranteed to never execute in the future unless resubmitted.
+
+36.3.3.1. Interactions with Pipelined CCBs
+
+         If the pipeline target CCB is killed but the pipeline source CCB was skipped, the completion area of the
+         target CCB may contain status (4,0) "Command was skipped" instead of (3,7) "Command was killed".
+
+         If the pipeline source CCB is killed, the pipeline target CCB's completion status may read (1,0) "Success".
+         This does not mean the target CCB was processed; since the source CCB was killed, there was no
+         meaningful output on which the target CCB could operate.
+
+36.3.3.2. Errors
+
+          EOK                        The request was processed and the result is valid.
+          EBADALIGN                  address is not on a 64-byte aligned.
+          ENORADDR                   The real address provided for address is not valid.
+          EINVAL                     The CCB completion area contents are not valid.
+          EWOULDBLOCK                Internal resource constraints prevented the CCB from being killed at this time.
+                                     The guest should retry the request.
+          ENOACCESS                  The guest does not have permission to access the coprocessor virtual device
+                                     functionality.
+
+36.3.4. dax_info
+          trap#            FAST_TRAP
+          function#        DAX_INFO
+          ret0             status
+          ret1             Number of enabled DAX units
+          ret2             Number of disabled DAX units
+
+         Returns the number of DAX units that are enabled for the calling guest to submit CCBs. The number of
+         DAX units that are disabled for the calling guest are also returned. A disabled DAX unit would have been
+         available for CCB submission to the calling guest had it not been offlined.
+
+36.3.4.1. Errors
+
+          EOK                        The request was processed and the number of enabled/disabled DAX units
+                                     are valid.
+
+
+
+
+                                                       534
+\f
diff --git a/Documentation/arch/sparc/oradax/oracle-dax.rst b/Documentation/arch/sparc/oradax/oracle-dax.rst
new file mode 100644 (file)
index 0000000..d1e14d5
--- /dev/null
@@ -0,0 +1,445 @@
+=======================================
+Oracle Data Analytics Accelerator (DAX)
+=======================================
+
+DAX is a coprocessor which resides on the SPARC M7 (DAX1) and M8
+(DAX2) processor chips, and has direct access to the CPU's L3 caches
+as well as physical memory. It can perform several operations on data
+streams with various input and output formats.  A driver provides a
+transport mechanism and has limited knowledge of the various opcodes
+and data formats. A user space library provides high level services
+and translates these into low level commands which are then passed
+into the driver and subsequently the Hypervisor and the coprocessor.
+The library is the recommended way for applications to use the
+coprocessor, and the driver interface is not intended for general use.
+This document describes the general flow of the driver, its
+structures, and its programmatic interface. It also provides example
+code sufficient to write user or kernel applications that use DAX
+functionality.
+
+The user library is open source and available at:
+
+    https://oss.oracle.com/git/gitweb.cgi?p=libdax.git
+
+The Hypervisor interface to the coprocessor is described in detail in
+the accompanying document, dax-hv-api.txt, which is a plain text
+excerpt of the (Oracle internal) "UltraSPARC Virtual Machine
+Specification" version 3.0.20+15, dated 2017-09-25.
+
+
+High Level Overview
+===================
+
+A coprocessor request is described by a Command Control Block
+(CCB). The CCB contains an opcode and various parameters. The opcode
+specifies what operation is to be done, and the parameters specify
+options, flags, sizes, and addresses.  The CCB (or an array of CCBs)
+is passed to the Hypervisor, which handles queueing and scheduling of
+requests to the available coprocessor execution units. A status code
+returned indicates if the request was submitted successfully or if
+there was an error.  One of the addresses given in each CCB is a
+pointer to a "completion area", which is a 128 byte memory block that
+is written by the coprocessor to provide execution status. No
+interrupt is generated upon completion; the completion area must be
+polled by software to find out when a transaction has finished, but
+the M7 and later processors provide a mechanism to pause the virtual
+processor until the completion status has been updated by the
+coprocessor. This is done using the monitored load and mwait
+instructions, which are described in more detail later.  The DAX
+coprocessor was designed so that after a request is submitted, the
+kernel is no longer involved in the processing of it.  The polling is
+done at the user level, which results in almost zero latency between
+completion of a request and resumption of execution of the requesting
+thread.
+
+
+Addressing Memory
+=================
+
+The kernel does not have access to physical memory in the Sun4v
+architecture, as there is an additional level of memory virtualization
+present. This intermediate level is called "real" memory, and the
+kernel treats this as if it were physical.  The Hypervisor handles the
+translations between real memory and physical so that each logical
+domain (LDOM) can have a partition of physical memory that is isolated
+from that of other LDOMs.  When the kernel sets up a virtual mapping,
+it specifies a virtual address and the real address to which it should
+be mapped.
+
+The DAX coprocessor can only operate on physical memory, so before a
+request can be fed to the coprocessor, all the addresses in a CCB must
+be converted into physical addresses. The kernel cannot do this since
+it has no visibility into physical addresses. So a CCB may contain
+either the virtual or real addresses of the buffers or a combination
+of them. An "address type" field is available for each address that
+may be given in the CCB. In all cases, the Hypervisor will translate
+all the addresses to physical before dispatching to hardware. Address
+translations are performed using the context of the process initiating
+the request.
+
+
+The Driver API
+==============
+
+An application makes requests to the driver via the write() system
+call, and gets results (if any) via read(). The completion areas are
+made accessible via mmap(), and are read-only for the application.
+
+The request may either be an immediate command or an array of CCBs to
+be submitted to the hardware.
+
+Each open instance of the device is exclusive to the thread that
+opened it, and must be used by that thread for all subsequent
+operations. The driver open function creates a new context for the
+thread and initializes it for use.  This context contains pointers and
+values used internally by the driver to keep track of submitted
+requests. The completion area buffer is also allocated, and this is
+large enough to contain the completion areas for many concurrent
+requests.  When the device is closed, any outstanding transactions are
+flushed and the context is cleaned up.
+
+On a DAX1 system (M7), the device will be called "oradax1", while on a
+DAX2 system (M8) it will be "oradax2". If an application requires one
+or the other, it should simply attempt to open the appropriate
+device. Only one of the devices will exist on any given system, so the
+name can be used to determine what the platform supports.
+
+The immediate commands are CCB_DEQUEUE, CCB_KILL, and CCB_INFO. For
+all of these, success is indicated by a return value from write()
+equal to the number of bytes given in the call. Otherwise -1 is
+returned and errno is set.
+
+CCB_DEQUEUE
+-----------
+
+Tells the driver to clean up resources associated with past
+requests. Since no interrupt is generated upon the completion of a
+request, the driver must be told when it may reclaim resources.  No
+further status information is returned, so the user should not
+subsequently call read().
+
+CCB_KILL
+--------
+
+Kills a CCB during execution. The CCB is guaranteed to not continue
+executing once this call returns successfully. On success, read() must
+be called to retrieve the result of the action.
+
+CCB_INFO
+--------
+
+Retrieves information about a currently executing CCB. Note that some
+Hypervisors might return 'notfound' when the CCB is in 'inprogress'
+state. To ensure a CCB in the 'notfound' state will never be executed,
+CCB_KILL must be invoked on that CCB. Upon success, read() must be
+called to retrieve the details of the action.
+
+Submission of an array of CCBs for execution
+---------------------------------------------
+
+A write() whose length is a multiple of the CCB size is treated as a
+submit operation. The file offset is treated as the index of the
+completion area to use, and may be set via lseek() or using the
+pwrite() system call. If -1 is returned then errno is set to indicate
+the error. Otherwise, the return value is the length of the array that
+was actually accepted by the coprocessor. If the accepted length is
+equal to the requested length, then the submission was completely
+successful and there is no further status needed; hence, the user
+should not subsequently call read(). Partial acceptance of the CCB
+array is indicated by a return value less than the requested length,
+and read() must be called to retrieve further status information.  The
+status will reflect the error caused by the first CCB that was not
+accepted, and status_data will provide additional data in some cases.
+
+MMAP
+----
+
+The mmap() function provides access to the completion area allocated
+in the driver.  Note that the completion area is not writeable by the
+user process, and the mmap call must not specify PROT_WRITE.
+
+
+Completion of a Request
+=======================
+
+The first byte in each completion area is the command status which is
+updated by the coprocessor hardware. Software may take advantage of
+new M7/M8 processor capabilities to efficiently poll this status byte.
+First, a "monitored load" is achieved via a Load from Alternate Space
+(ldxa, lduba, etc.) with ASI 0x84 (ASI_MONITOR_PRIMARY).  Second, a
+"monitored wait" is achieved via the mwait instruction (a write to
+%asr28). This instruction is like pause in that it suspends execution
+of the virtual processor for the given number of nanoseconds, but in
+addition will terminate early when one of several events occur. If the
+block of data containing the monitored location is modified, then the
+mwait terminates. This causes software to resume execution immediately
+(without a context switch or kernel to user transition) after a
+transaction completes. Thus the latency between transaction completion
+and resumption of execution may be just a few nanoseconds.
+
+
+Application Life Cycle of a DAX Submission
+==========================================
+
+ - open dax device
+ - call mmap() to get the completion area address
+ - allocate a CCB and fill in the opcode, flags, parameters, addresses, etc.
+ - submit CCB via write() or pwrite()
+ - go into a loop executing monitored load + monitored wait and
+   terminate when the command status indicates the request is complete
+   (CCB_KILL or CCB_INFO may be used any time as necessary)
+ - perform a CCB_DEQUEUE
+ - call munmap() for completion area
+ - close the dax device
+
+
+Memory Constraints
+==================
+
+The DAX hardware operates only on physical addresses. Therefore, it is
+not aware of virtual memory mappings and the discontiguities that may
+exist in the physical memory that a virtual buffer maps to. There is
+no I/O TLB or any scatter/gather mechanism. All buffers, whether input
+or output, must reside in a physically contiguous region of memory.
+
+The Hypervisor translates all addresses within a CCB to physical
+before handing off the CCB to DAX. The Hypervisor determines the
+virtual page size for each virtual address given, and uses this to
+program a size limit for each address. This prevents the coprocessor
+from reading or writing beyond the bound of the virtual page, even
+though it is accessing physical memory directly. A simpler way of
+saying this is that a DAX operation will never "cross" a virtual page
+boundary. If an 8k virtual page is used, then the data is strictly
+limited to 8k. If a user's buffer is larger than 8k, then a larger
+page size must be used, or the transaction size will be truncated to
+8k.
+
+Huge pages. A user may allocate huge pages using standard interfaces.
+Memory buffers residing on huge pages may be used to achieve much
+larger DAX transaction sizes, but the rules must still be followed,
+and no transaction will cross a page boundary, even a huge page.  A
+major caveat is that Linux on Sparc presents 8Mb as one of the huge
+page sizes. Sparc does not actually provide a 8Mb hardware page size,
+and this size is synthesized by pasting together two 4Mb pages. The
+reasons for this are historical, and it creates an issue because only
+half of this 8Mb page can actually be used for any given buffer in a
+DAX request, and it must be either the first half or the second half;
+it cannot be a 4Mb chunk in the middle, since that crosses a
+(hardware) page boundary. Note that this entire issue may be hidden by
+higher level libraries.
+
+
+CCB Structure
+-------------
+A CCB is an array of 8 64-bit words. Several of these words provide
+command opcodes, parameters, flags, etc., and the rest are addresses
+for the completion area, output buffer, and various inputs::
+
+   struct ccb {
+       u64   control;
+       u64   completion;
+       u64   input0;
+       u64   access;
+       u64   input1;
+       u64   op_data;
+       u64   output;
+       u64   table;
+   };
+
+See libdax/common/sys/dax1/dax1_ccb.h for a detailed description of
+each of these fields, and see dax-hv-api.txt for a complete description
+of the Hypervisor API available to the guest OS (ie, Linux kernel).
+
+The first word (control) is examined by the driver for the following:
+ - CCB version, which must be consistent with hardware version
+ - Opcode, which must be one of the documented allowable commands
+ - Address types, which must be set to "virtual" for all the addresses
+   given by the user, thereby ensuring that the application can
+   only access memory that it owns
+
+
+Example Code
+============
+
+The DAX is accessible to both user and kernel code.  The kernel code
+can make hypercalls directly while the user code must use wrappers
+provided by the driver. The setup of the CCB is nearly identical for
+both; the only difference is in preparation of the completion area. An
+example of user code is given now, with kernel code afterwards.
+
+In order to program using the driver API, the file
+arch/sparc/include/uapi/asm/oradax.h must be included.
+
+First, the proper device must be opened. For M7 it will be
+/dev/oradax1 and for M8 it will be /dev/oradax2. The simplest
+procedure is to attempt to open both, as only one will succeed::
+
+       fd = open("/dev/oradax1", O_RDWR);
+       if (fd < 0)
+               fd = open("/dev/oradax2", O_RDWR);
+       if (fd < 0)
+              /* No DAX found */
+
+Next, the completion area must be mapped::
+
+      completion_area = mmap(NULL, DAX_MMAP_LEN, PROT_READ, MAP_SHARED, fd, 0);
+
+All input and output buffers must be fully contained in one hardware
+page, since as explained above, the DAX is strictly constrained by
+virtual page boundaries.  In addition, the output buffer must be
+64-byte aligned and its size must be a multiple of 64 bytes because
+the coprocessor writes in units of cache lines.
+
+This example demonstrates the DAX Scan command, which takes as input a
+vector and a match value, and produces a bitmap as the output. For
+each input element that matches the value, the corresponding bit is
+set in the output.
+
+In this example, the input vector consists of a series of single bits,
+and the match value is 0. So each 0 bit in the input will produce a 1
+in the output, and vice versa, which produces an output bitmap which
+is the input bitmap inverted.
+
+For details of all the parameters and bits used in this CCB, please
+refer to section 36.2.1.3 of the DAX Hypervisor API document, which
+describes the Scan command in detail::
+
+       ccb->control =       /* Table 36.1, CCB Header Format */
+                 (2L << 48)     /* command = Scan Value */
+               | (3L << 40)     /* output address type = primary virtual */
+               | (3L << 34)     /* primary input address type = primary virtual */
+                            /* Section 36.2.1, Query CCB Command Formats */
+               | (1 << 28)     /* 36.2.1.1.1 primary input format = fixed width bit packed */
+               | (0 << 23)     /* 36.2.1.1.2 primary input element size = 0 (1 bit) */
+               | (8 << 10)     /* 36.2.1.1.6 output format = bit vector */
+               | (0 <<  5)     /* 36.2.1.3 First scan criteria size = 0 (1 byte) */
+               | (31 << 0);    /* 36.2.1.3 Disable second scan criteria */
+
+       ccb->completion = 0;    /* Completion area address, to be filled in by driver */
+
+       ccb->input0 = (unsigned long) input; /* primary input address */
+
+       ccb->access =       /* Section 36.2.1.2, Data Access Control */
+                 (2 << 24)    /* Primary input length format = bits */
+               | (nbits - 1); /* number of bits in primary input stream, minus 1 */
+
+       ccb->input1 = 0;       /* secondary input address, unused */
+
+       ccb->op_data = 0;      /* scan criteria (value to be matched) */
+
+       ccb->output = (unsigned long) output;   /* output address */
+
+       ccb->table = 0;        /* table address, unused */
+
+The CCB submission is a write() or pwrite() system call to the
+driver. If the call fails, then a read() must be used to retrieve the
+status::
+
+       if (pwrite(fd, ccb, 64, 0) != 64) {
+               struct ccb_exec_result status;
+               read(fd, &status, sizeof(status));
+               /* bail out */
+       }
+
+After a successful submission of the CCB, the completion area may be
+polled to determine when the DAX is finished. Detailed information on
+the contents of the completion area can be found in section 36.2.2 of
+the DAX HV API document::
+
+       while (1) {
+               /* Monitored Load */
+               __asm__ __volatile__("lduba [%1] 0x84, %0\n"
+                                    : "=r" (status)
+                                    : "r"  (completion_area));
+
+               if (status)          /* 0 indicates command in progress */
+                       break;
+
+               /* MWAIT */
+               __asm__ __volatile__("wr %%g0, 1000, %%asr28\n" ::);    /* 1000 ns */
+       }
+
+A completion area status of 1 indicates successful completion of the
+CCB and validity of the output bitmap, which may be used immediately.
+All other non-zero values indicate error conditions which are
+described in section 36.2.2::
+
+       if (completion_area[0] != 1) {  /* section 36.2.2, 1 = command ran and succeeded */
+               /* completion_area[0] contains the completion status */
+               /* completion_area[1] contains an error code, see 36.2.2 */
+       }
+
+After the completion area has been processed, the driver must be
+notified that it can release any resources associated with the
+request. This is done via the dequeue operation::
+
+       struct dax_command cmd;
+       cmd.command = CCB_DEQUEUE;
+       if (write(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+               /* bail out */
+       }
+
+Finally, normal program cleanup should be done, i.e., unmapping
+completion area, closing the dax device, freeing memory etc.
+
+Kernel example
+--------------
+
+The only difference in using the DAX in kernel code is the treatment
+of the completion area. Unlike user applications which mmap the
+completion area allocated by the driver, kernel code must allocate its
+own memory to use for the completion area, and this address and its
+type must be given in the CCB::
+
+       ccb->control |=      /* Table 36.1, CCB Header Format */
+               (3L << 32);     /* completion area address type = primary virtual */
+
+       ccb->completion = (unsigned long) completion_area;   /* Completion area address */
+
+The dax submit hypercall is made directly. The flags used in the
+ccb_submit call are documented in the DAX HV API in section 36.3.1/
+
+::
+
+  #include <asm/hypervisor.h>
+
+       hv_rv = sun4v_ccb_submit((unsigned long)ccb, 64,
+                                HV_CCB_QUERY_CMD |
+                                HV_CCB_ARG0_PRIVILEGED | HV_CCB_ARG0_TYPE_PRIMARY |
+                                HV_CCB_VA_PRIVILEGED,
+                                0, &bytes_accepted, &status_data);
+
+       if (hv_rv != HV_EOK) {
+               /* hv_rv is an error code, status_data contains */
+               /* potential additional status, see 36.3.1.1 */
+       }
+
+After the submission, the completion area polling code is identical to
+that in user land::
+
+       while (1) {
+               /* Monitored Load */
+               __asm__ __volatile__("lduba [%1] 0x84, %0\n"
+                                    : "=r" (status)
+                                    : "r"  (completion_area));
+
+               if (status)          /* 0 indicates command in progress */
+                       break;
+
+               /* MWAIT */
+               __asm__ __volatile__("wr %%g0, 1000, %%asr28\n" ::);    /* 1000 ns */
+       }
+
+       if (completion_area[0] != 1) {  /* section 36.2.2, 1 = command ran and succeeded */
+               /* completion_area[0] contains the completion status */
+               /* completion_area[1] contains an error code, see 36.2.2 */
+       }
+
+The output bitmap is ready for consumption immediately after the
+completion status indicates success.
+
+Excer[t from UltraSPARC Virtual Machine Specification
+=====================================================
+
+ .. include:: dax-hv-api.txt
+    :literal:
diff --git a/Documentation/arch/x86/amd-memory-encryption.rst b/Documentation/arch/x86/amd-memory-encryption.rst
new file mode 100644 (file)
index 0000000..934310c
--- /dev/null
@@ -0,0 +1,133 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================
+AMD Memory Encryption
+=====================
+
+Secure Memory Encryption (SME) and Secure Encrypted Virtualization (SEV) are
+features found on AMD processors.
+
+SME provides the ability to mark individual pages of memory as encrypted using
+the standard x86 page tables.  A page that is marked encrypted will be
+automatically decrypted when read from DRAM and encrypted when written to
+DRAM.  SME can therefore be used to protect the contents of DRAM from physical
+attacks on the system.
+
+SEV enables running encrypted virtual machines (VMs) in which the code and data
+of the guest VM are secured so that a decrypted version is available only
+within the VM itself. SEV guest VMs have the concept of private and shared
+memory. Private memory is encrypted with the guest-specific key, while shared
+memory may be encrypted with hypervisor key. When SME is enabled, the hypervisor
+key is the same key which is used in SME.
+
+A page is encrypted when a page table entry has the encryption bit set (see
+below on how to determine its position).  The encryption bit can also be
+specified in the cr3 register, allowing the PGD table to be encrypted. Each
+successive level of page tables can also be encrypted by setting the encryption
+bit in the page table entry that points to the next table. This allows the full
+page table hierarchy to be encrypted. Note, this means that just because the
+encryption bit is set in cr3, doesn't imply the full hierarchy is encrypted.
+Each page table entry in the hierarchy needs to have the encryption bit set to
+achieve that. So, theoretically, you could have the encryption bit set in cr3
+so that the PGD is encrypted, but not set the encryption bit in the PGD entry
+for a PUD which results in the PUD pointed to by that entry to not be
+encrypted.
+
+When SEV is enabled, instruction pages and guest page tables are always treated
+as private. All the DMA operations inside the guest must be performed on shared
+memory. Since the memory encryption bit is controlled by the guest OS when it
+is operating in 64-bit or 32-bit PAE mode, in all other modes the SEV hardware
+forces the memory encryption bit to 1.
+
+Support for SME and SEV can be determined through the CPUID instruction. The
+CPUID function 0x8000001f reports information related to SME::
+
+       0x8000001f[eax]:
+               Bit[0] indicates support for SME
+               Bit[1] indicates support for SEV
+       0x8000001f[ebx]:
+               Bits[5:0]  pagetable bit number used to activate memory
+                          encryption
+               Bits[11:6] reduction in physical address space, in bits, when
+                          memory encryption is enabled (this only affects
+                          system physical addresses, not guest physical
+                          addresses)
+
+If support for SME is present, MSR 0xc00100010 (MSR_AMD64_SYSCFG) can be used to
+determine if SME is enabled and/or to enable memory encryption::
+
+       0xc0010010:
+               Bit[23]   0 = memory encryption features are disabled
+                         1 = memory encryption features are enabled
+
+If SEV is supported, MSR 0xc0010131 (MSR_AMD64_SEV) can be used to determine if
+SEV is active::
+
+       0xc0010131:
+               Bit[0]    0 = memory encryption is not active
+                         1 = memory encryption is active
+
+Linux relies on BIOS to set this bit if BIOS has determined that the reduction
+in the physical address space as a result of enabling memory encryption (see
+CPUID information above) will not conflict with the address space resource
+requirements for the system.  If this bit is not set upon Linux startup then
+Linux itself will not set it and memory encryption will not be possible.
+
+The state of SME in the Linux kernel can be documented as follows:
+
+       - Supported:
+         The CPU supports SME (determined through CPUID instruction).
+
+       - Enabled:
+         Supported and bit 23 of MSR_AMD64_SYSCFG is set.
+
+       - Active:
+         Supported, Enabled and the Linux kernel is actively applying
+         the encryption bit to page table entries (the SME mask in the
+         kernel is non-zero).
+
+SME can also be enabled and activated in the BIOS. If SME is enabled and
+activated in the BIOS, then all memory accesses will be encrypted and it will
+not be necessary to activate the Linux memory encryption support.  If the BIOS
+merely enables SME (sets bit 23 of the MSR_AMD64_SYSCFG), then Linux can activate
+memory encryption by default (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y) or
+by supplying mem_encrypt=on on the kernel command line.  However, if BIOS does
+not enable SME, then Linux will not be able to activate memory encryption, even
+if configured to do so by default or the mem_encrypt=on command line parameter
+is specified.
+
+Secure Nested Paging (SNP)
+==========================
+
+SEV-SNP introduces new features (SEV_FEATURES[1:63]) which can be enabled
+by the hypervisor for security enhancements. Some of these features need
+guest side implementation to function correctly. The below table lists the
+expected guest behavior with various possible scenarios of guest/hypervisor
+SNP feature support.
+
++-----------------+---------------+---------------+------------------+
+| Feature Enabled | Guest needs   | Guest has     | Guest boot       |
+| by the HV       | implementation| implementation| behaviour        |
++=================+===============+===============+==================+
+|      No         |      No       |      No       |     Boot         |
+|                 |               |               |                  |
++-----------------+---------------+---------------+------------------+
+|      No         |      Yes      |      No       |     Boot         |
+|                 |               |               |                  |
++-----------------+---------------+---------------+------------------+
+|      No         |      Yes      |      Yes      |     Boot         |
+|                 |               |               |                  |
++-----------------+---------------+---------------+------------------+
+|      Yes        |      No       |      No       | Boot with        |
+|                 |               |               | feature enabled  |
++-----------------+---------------+---------------+------------------+
+|      Yes        |      Yes      |      No       | Graceful boot    |
+|                 |               |               | failure          |
++-----------------+---------------+---------------+------------------+
+|      Yes        |      Yes      |      Yes      | Boot with        |
+|                 |               |               | feature enabled  |
++-----------------+---------------+---------------+------------------+
+
+More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR
+
+[1] https://www.amd.com/system/files/TechDocs/40332.pdf
diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
new file mode 100644 (file)
index 0000000..440e4b6
--- /dev/null
@@ -0,0 +1,86 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================================
+AMD HSMP interface
+============================================
+
+Newer Fam19h EPYC server line of processors from AMD support system
+management functionality via HSMP (Host System Management Port).
+
+The Host System Management Port (HSMP) is an interface to provide
+OS-level software with access to system management functions via a
+set of mailbox registers.
+
+More details on the interface can be found in chapter
+"7 Host System Management Port (HSMP)" of the family/model PPR
+Eg: https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
+
+HSMP interface is supported on EPYC server CPU models only.
+
+
+HSMP device
+============================================
+
+amd_hsmp driver under the drivers/platforms/x86/ creates miscdevice
+/dev/hsmp to let user space programs run hsmp mailbox commands.
+
+$ ls -al /dev/hsmp
+crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp
+
+Characteristics of the dev node:
+ * Write mode is used for running set/configure commands
+ * Read mode is used for running get/status monitor commands
+
+Access restrictions:
+ * Only root user is allowed to open the file in write mode.
+ * The file can be opened in read mode by all the users.
+
+In-kernel integration:
+ * Other subsystems in the kernel can use the exported transport
+   function hsmp_send_message().
+ * Locking across callers is taken care by the driver.
+
+
+An example
+==========
+
+To access hsmp device from a C program.
+First, you need to include the headers::
+
+  #include <linux/amd_hsmp.h>
+
+Which defines the supported messages/message IDs.
+
+Next thing, open the device file, as follows::
+
+  int file;
+
+  file = open("/dev/hsmp", O_RDWR);
+  if (file < 0) {
+    /* ERROR HANDLING; you can check errno to see what went wrong */
+    exit(1);
+  }
+
+The following IOCTL is defined:
+
+``ioctl(file, HSMP_IOCTL_CMD, struct hsmp_message *msg)``
+  The argument is a pointer to a::
+
+    struct hsmp_message {
+       __u32   msg_id;                         /* Message ID */
+       __u16   num_args;                       /* Number of input argument words in message */
+       __u16   response_sz;                    /* Number of expected output/response words */
+       __u32   args[HSMP_MAX_MSG_LEN];         /* argument/response buffer */
+       __u16   sock_ind;                       /* socket number */
+    };
+
+The ioctl would return a non-zero on failure; you can read errno to see
+what happened. The transaction returns 0 on success.
+
+More details on the interface and message definitions can be found in chapter
+"7 Host System Management Port (HSMP)" of the respective family/model PPR
+eg: https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
+
+User space C-APIs are made available by linking against the esmi library,
+which is provided by the E-SMS project https://developer.amd.com/e-sms/.
+See: https://github.com/amd/esmi_ib_library
diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
new file mode 100644 (file)
index 0000000..33520ec
--- /dev/null
@@ -0,0 +1,1443 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================
+The Linux/x86 Boot Protocol
+===========================
+
+On the x86 platform, the Linux kernel uses a rather complicated boot
+convention.  This has evolved partially due to historical aspects, as
+well as the desire in the early days to have the kernel itself be a
+bootable image, the complicated PC memory model and due to changed
+expectations in the PC industry caused by the effective demise of
+real-mode DOS as a mainstream operating system.
+
+Currently, the following versions of the Linux/x86 boot protocol exist.
+
+=============  ============================================================
+Old kernels    zImage/Image support only.  Some very early kernels
+               may not even support a command line.
+
+Protocol 2.00  (Kernel 1.3.73) Added bzImage and initrd support, as
+               well as a formalized way to communicate between the
+               boot loader and the kernel.  setup.S made relocatable,
+               although the traditional setup area still assumed
+               writable.
+
+Protocol 2.01  (Kernel 1.3.76) Added a heap overrun warning.
+
+Protocol 2.02  (Kernel 2.4.0-test3-pre3) New command line protocol.
+               Lower the conventional memory ceiling.  No overwrite
+               of the traditional setup area, thus making booting
+               safe for systems which use the EBDA from SMM or 32-bit
+               BIOS entry points.  zImage deprecated but still
+               supported.
+
+Protocol 2.03  (Kernel 2.4.18-pre1) Explicitly makes the highest possible
+               initrd address available to the bootloader.
+
+Protocol 2.04  (Kernel 2.6.14) Extend the syssize field to four bytes.
+
+Protocol 2.05  (Kernel 2.6.20) Make protected mode kernel relocatable.
+               Introduce relocatable_kernel and kernel_alignment fields.
+
+Protocol 2.06  (Kernel 2.6.22) Added a field that contains the size of
+               the boot command line.
+
+Protocol 2.07  (Kernel 2.6.24) Added paravirtualised boot protocol.
+               Introduced hardware_subarch and hardware_subarch_data
+               and KEEP_SEGMENTS flag in load_flags.
+
+Protocol 2.08  (Kernel 2.6.26) Added crc32 checksum and ELF format
+               payload. Introduced payload_offset and payload_length
+               fields to aid in locating the payload.
+
+Protocol 2.09  (Kernel 2.6.26) Added a field of 64-bit physical
+               pointer to single linked list of struct setup_data.
+
+Protocol 2.10  (Kernel 2.6.31) Added a protocol for relaxed alignment
+               beyond the kernel_alignment added, new init_size and
+               pref_address fields.  Added extended boot loader IDs.
+
+Protocol 2.11  (Kernel 3.6) Added a field for offset of EFI handover
+               protocol entry point.
+
+Protocol 2.12  (Kernel 3.8) Added the xloadflags field and extension fields
+               to struct boot_params for loading bzImage and ramdisk
+               above 4G in 64bit.
+
+Protocol 2.13  (Kernel 3.14) Support 32- and 64-bit flags being set in
+               xloadflags to support booting a 64-bit kernel from 32-bit
+               EFI
+
+Protocol 2.14  BURNT BY INCORRECT COMMIT
+                ae7e1238e68f2a472a125673ab506d49158c1889
+               (x86/boot: Add ACPI RSDP address to setup_header)
+               DO NOT USE!!! ASSUME SAME AS 2.13.
+
+Protocol 2.15  (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max.
+=============  ============================================================
+
+.. note::
+     The protocol version number should be changed only if the setup header
+     is changed. There is no need to update the version number if boot_params
+     or kernel_info are changed. Additionally, it is recommended to use
+     xloadflags (in this case the protocol version number should not be
+     updated either) or kernel_info to communicate supported Linux kernel
+     features to the boot loader. Due to very limited space available in
+     the original setup header every update to it should be considered
+     with great care. Starting from the protocol 2.15 the primary way to
+     communicate things to the boot loader is the kernel_info.
+
+
+Memory Layout
+=============
+
+The traditional memory map for the kernel loader, used for Image or
+zImage kernels, typically looks like::
+
+               |                        |
+       0A0000  +------------------------+
+               |  Reserved for BIOS     |      Do not use.  Reserved for BIOS EBDA.
+       09A000  +------------------------+
+               |  Command line          |
+               |  Stack/heap            |      For use by the kernel real-mode code.
+       098000  +------------------------+
+               |  Kernel setup          |      The kernel real-mode code.
+       090200  +------------------------+
+               |  Kernel boot sector    |      The kernel legacy boot sector.
+       090000  +------------------------+
+               |  Protected-mode kernel |      The bulk of the kernel image.
+       010000  +------------------------+
+               |  Boot loader           |      <- Boot sector entry point 0000:7C00
+       001000  +------------------------+
+               |  Reserved for MBR/BIOS |
+       000800  +------------------------+
+               |  Typically used by MBR |
+       000600  +------------------------+
+               |  BIOS use only         |
+       000000  +------------------------+
+
+When using bzImage, the protected-mode kernel was relocated to
+0x100000 ("high memory"), and the kernel real-mode block (boot sector,
+setup, and stack/heap) was made relocatable to any address between
+0x10000 and end of low memory. Unfortunately, in protocols 2.00 and
+2.01 the 0x90000+ memory range is still used internally by the kernel;
+the 2.02 protocol resolves that problem.
+
+It is desirable to keep the "memory ceiling" -- the highest point in
+low memory touched by the boot loader -- as low as possible, since
+some newer BIOSes have begun to allocate some rather large amounts of
+memory, called the Extended BIOS Data Area, near the top of low
+memory.         The boot loader should use the "INT 12h" BIOS call to verify
+how much low memory is available.
+
+Unfortunately, if INT 12h reports that the amount of memory is too
+low, there is usually nothing the boot loader can do but to report an
+error to the user.  The boot loader should therefore be designed to
+take up as little space in low memory as it reasonably can.  For
+zImage or old bzImage kernels, which need data written into the
+0x90000 segment, the boot loader should make sure not to use memory
+above the 0x9A000 point; too many BIOSes will break above that point.
+
+For a modern bzImage kernel with boot protocol version >= 2.02, a
+memory layout like the following is suggested::
+
+               ~                        ~
+               |  Protected-mode kernel |
+       100000  +------------------------+
+               |  I/O memory hole       |
+       0A0000  +------------------------+
+               |  Reserved for BIOS     |      Leave as much as possible unused
+               ~                        ~
+               |  Command line          |      (Can also be below the X+10000 mark)
+       X+10000 +------------------------+
+               |  Stack/heap            |      For use by the kernel real-mode code.
+       X+08000 +------------------------+
+               |  Kernel setup          |      The kernel real-mode code.
+               |  Kernel boot sector    |      The kernel legacy boot sector.
+       X       +------------------------+
+               |  Boot loader           |      <- Boot sector entry point 0000:7C00
+       001000  +------------------------+
+               |  Reserved for MBR/BIOS |
+       000800  +------------------------+
+               |  Typically used by MBR |
+       000600  +------------------------+
+               |  BIOS use only         |
+       000000  +------------------------+
+
+  ... where the address X is as low as the design of the boot loader permits.
+
+
+The Real-Mode Kernel Header
+===========================
+
+In the following text, and anywhere in the kernel boot sequence, "a
+sector" refers to 512 bytes.  It is independent of the actual sector
+size of the underlying medium.
+
+The first step in loading a Linux kernel should be to load the
+real-mode code (boot sector and setup code) and then examine the
+following header at offset 0x01f1.  The real-mode code can total up to
+32K, although the boot loader may choose to load only the first two
+sectors (1K) and then examine the bootup sector size.
+
+The header looks like:
+
+===========    ========        =====================   ============================================
+Offset/Size    Proto           Name                    Meaning
+===========    ========        =====================   ============================================
+01F1/1         ALL(1)          setup_sects             The size of the setup in sectors
+01F2/2         ALL             root_flags              If set, the root is mounted readonly
+01F4/4         2.04+(2)        syssize                 The size of the 32-bit code in 16-byte paras
+01F8/2         ALL             ram_size                DO NOT USE - for bootsect.S use only
+01FA/2         ALL             vid_mode                Video mode control
+01FC/2         ALL             root_dev                Default root device number
+01FE/2         ALL             boot_flag               0xAA55 magic number
+0200/2         2.00+           jump                    Jump instruction
+0202/4         2.00+           header                  Magic signature "HdrS"
+0206/2         2.00+           version                 Boot protocol version supported
+0208/4         2.00+           realmode_swtch          Boot loader hook (see below)
+020C/2         2.00+           start_sys_seg           The load-low segment (0x1000) (obsolete)
+020E/2         2.00+           kernel_version          Pointer to kernel version string
+0210/1         2.00+           type_of_loader          Boot loader identifier
+0211/1         2.00+           loadflags               Boot protocol option flags
+0212/2         2.00+           setup_move_size         Move to high memory size (used with hooks)
+0214/4         2.00+           code32_start            Boot loader hook (see below)
+0218/4         2.00+           ramdisk_image           initrd load address (set by boot loader)
+021C/4         2.00+           ramdisk_size            initrd size (set by boot loader)
+0220/4         2.00+           bootsect_kludge         DO NOT USE - for bootsect.S use only
+0224/2         2.01+           heap_end_ptr            Free memory after setup end
+0226/1         2.02+(3)        ext_loader_ver          Extended boot loader version
+0227/1         2.02+(3)        ext_loader_type         Extended boot loader ID
+0228/4         2.02+           cmd_line_ptr            32-bit pointer to the kernel command line
+022C/4         2.03+           initrd_addr_max         Highest legal initrd address
+0230/4         2.05+           kernel_alignment        Physical addr alignment required for kernel
+0234/1         2.05+           relocatable_kernel      Whether kernel is relocatable or not
+0235/1         2.10+           min_alignment           Minimum alignment, as a power of two
+0236/2         2.12+           xloadflags              Boot protocol option flags
+0238/4         2.06+           cmdline_size            Maximum size of the kernel command line
+023C/4         2.07+           hardware_subarch        Hardware subarchitecture
+0240/8         2.07+           hardware_subarch_data   Subarchitecture-specific data
+0248/4         2.08+           payload_offset          Offset of kernel payload
+024C/4         2.08+           payload_length          Length of kernel payload
+0250/8         2.09+           setup_data              64-bit physical pointer to linked list
+                                                       of struct setup_data
+0258/8         2.10+           pref_address            Preferred loading address
+0260/4         2.10+           init_size               Linear memory required during initialization
+0264/4         2.11+           handover_offset         Offset of handover entry point
+0268/4         2.15+           kernel_info_offset      Offset of the kernel_info
+===========    ========        =====================   ============================================
+
+.. note::
+  (1) For backwards compatibility, if the setup_sects field contains 0, the
+      real value is 4.
+
+  (2) For boot protocol prior to 2.04, the upper two bytes of the syssize
+      field are unusable, which means the size of a bzImage kernel
+      cannot be determined.
+
+  (3) Ignored, but safe to set, for boot protocols 2.02-2.09.
+
+If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
+the boot protocol version is "old".  Loading an old kernel, the
+following parameters should be assumed::
+
+       Image type = zImage
+       initrd not supported
+       Real-mode kernel must be located at 0x90000.
+
+Otherwise, the "version" field contains the protocol version,
+e.g. protocol version 2.01 will contain 0x0201 in this field.  When
+setting fields in the header, you must make sure only to set fields
+supported by the protocol version in use.
+
+
+Details of Header Fields
+========================
+
+For each field, some are information from the kernel to the bootloader
+("read"), some are expected to be filled out by the bootloader
+("write"), and some are expected to be read and modified by the
+bootloader ("modify").
+
+All general purpose boot loaders should write the fields marked
+(obligatory).  Boot loaders who want to load the kernel at a
+nonstandard address should fill in the fields marked (reloc); other
+boot loaders can ignore those fields.
+
+The byte order of all fields is littleendian (this is x86, after all.)
+
+============   ===========
+Field name:    setup_sects
+Type:          read
+Offset/size:   0x1f1/1
+Protocol:      ALL
+============   ===========
+
+  The size of the setup code in 512-byte sectors.  If this field is
+  0, the real value is 4.  The real-mode code consists of the boot
+  sector (always one 512-byte sector) plus the setup code.
+
+============   =================
+Field name:    root_flags
+Type:          modify (optional)
+Offset/size:   0x1f2/2
+Protocol:      ALL
+============   =================
+
+  If this field is nonzero, the root defaults to readonly.  The use of
+  this field is deprecated; use the "ro" or "rw" options on the
+  command line instead.
+
+============   ===============================================
+Field name:    syssize
+Type:          read
+Offset/size:   0x1f4/4 (protocol 2.04+) 0x1f4/2 (protocol ALL)
+Protocol:      2.04+
+============   ===============================================
+
+  The size of the protected-mode code in units of 16-byte paragraphs.
+  For protocol versions older than 2.04 this field is only two bytes
+  wide, and therefore cannot be trusted for the size of a kernel if
+  the LOAD_HIGH flag is set.
+
+============   ===============
+Field name:    ram_size
+Type:          kernel internal
+Offset/size:   0x1f8/2
+Protocol:      ALL
+============   ===============
+
+  This field is obsolete.
+
+============   ===================
+Field name:    vid_mode
+Type:          modify (obligatory)
+Offset/size:   0x1fa/2
+============   ===================
+
+  Please see the section on SPECIAL COMMAND LINE OPTIONS.
+
+============   =================
+Field name:    root_dev
+Type:          modify (optional)
+Offset/size:   0x1fc/2
+Protocol:      ALL
+============   =================
+
+  The default root device device number.  The use of this field is
+  deprecated, use the "root=" option on the command line instead.
+
+============   =========
+Field name:    boot_flag
+Type:          read
+Offset/size:   0x1fe/2
+Protocol:      ALL
+============   =========
+
+  Contains 0xAA55.  This is the closest thing old Linux kernels have
+  to a magic number.
+
+============   =======
+Field name:    jump
+Type:          read
+Offset/size:   0x200/2
+Protocol:      2.00+
+============   =======
+
+  Contains an x86 jump instruction, 0xEB followed by a signed offset
+  relative to byte 0x202.  This can be used to determine the size of
+  the header.
+
+============   =======
+Field name:    header
+Type:          read
+Offset/size:   0x202/4
+Protocol:      2.00+
+============   =======
+
+  Contains the magic number "HdrS" (0x53726448).
+
+============   =======
+Field name:    version
+Type:          read
+Offset/size:   0x206/2
+Protocol:      2.00+
+============   =======
+
+  Contains the boot protocol version, in (major << 8)+minor format,
+  e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
+  10.17.
+
+============   =================
+Field name:    realmode_swtch
+Type:          modify (optional)
+Offset/size:   0x208/4
+Protocol:      2.00+
+============   =================
+
+  Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
+
+============   =============
+Field name:    start_sys_seg
+Type:          read
+Offset/size:   0x20c/2
+Protocol:      2.00+
+============   =============
+
+  The load low segment (0x1000).  Obsolete.
+
+============   ==============
+Field name:    kernel_version
+Type:          read
+Offset/size:   0x20e/2
+Protocol:      2.00+
+============   ==============
+
+  If set to a nonzero value, contains a pointer to a NUL-terminated
+  human-readable kernel version number string, less 0x200.  This can
+  be used to display the kernel version to the user.  This value
+  should be less than (0x200*setup_sects).
+
+  For example, if this value is set to 0x1c00, the kernel version
+  number string can be found at offset 0x1e00 in the kernel file.
+  This is a valid value if and only if the "setup_sects" field
+  contains the value 15 or higher, as::
+
+       0x1c00  < 15*0x200 (= 0x1e00) but
+       0x1c00 >= 14*0x200 (= 0x1c00)
+
+       0x1c00 >> 9 = 14, So the minimum value for setup_secs is 15.
+
+============   ==================
+Field name:    type_of_loader
+Type:          write (obligatory)
+Offset/size:   0x210/1
+Protocol:      2.00+
+============   ==================
+
+  If your boot loader has an assigned id (see table below), enter
+  0xTV here, where T is an identifier for the boot loader and V is
+  a version number.  Otherwise, enter 0xFF here.
+
+  For boot loader IDs above T = 0xD, write T = 0xE to this field and
+  write the extended ID minus 0x10 to the ext_loader_type field.
+  Similarly, the ext_loader_ver field can be used to provide more than
+  four bits for the bootloader version.
+
+  For example, for T = 0x15, V = 0x234, write::
+
+       type_of_loader  <- 0xE4
+       ext_loader_type <- 0x05
+       ext_loader_ver  <- 0x23
+
+  Assigned boot loader ids (hexadecimal):
+
+       == =======================================
+       0  LILO
+          (0x00 reserved for pre-2.00 bootloader)
+       1  Loadlin
+       2  bootsect-loader
+          (0x20, all other values reserved)
+       3  Syslinux
+       4  Etherboot/gPXE/iPXE
+       5  ELILO
+       7  GRUB
+       8  U-Boot
+       9  Xen
+       A  Gujin
+       B  Qemu
+       C  Arcturus Networks uCbootloader
+       D  kexec-tools
+       E  Extended (see ext_loader_type)
+       F  Special (0xFF = undefined)
+       10 Reserved
+       11 Minimal Linux Bootloader
+          <http://sebastian-plotz.blogspot.de>
+       12 OVMF UEFI virtualization stack
+       13 barebox
+       == =======================================
+
+  Please contact <hpa@zytor.com> if you need a bootloader ID value assigned.
+
+============   ===================
+Field name:    loadflags
+Type:          modify (obligatory)
+Offset/size:   0x211/1
+Protocol:      2.00+
+============   ===================
+
+  This field is a bitmask.
+
+  Bit 0 (read):        LOADED_HIGH
+
+       - If 0, the protected-mode code is loaded at 0x10000.
+       - If 1, the protected-mode code is loaded at 0x100000.
+
+  Bit 1 (kernel internal): KASLR_FLAG
+
+       - Used internally by the compressed kernel to communicate
+         KASLR status to kernel proper.
+
+           - If 1, KASLR enabled.
+           - If 0, KASLR disabled.
+
+  Bit 5 (write): QUIET_FLAG
+
+       - If 0, print early messages.
+       - If 1, suppress early messages.
+
+               This requests to the kernel (decompressor and early
+               kernel) to not write early messages that require
+               accessing the display hardware directly.
+
+  Bit 6 (obsolete): KEEP_SEGMENTS
+
+       Protocol: 2.07+
+
+        - This flag is obsolete.
+
+  Bit 7 (write): CAN_USE_HEAP
+
+       Set this bit to 1 to indicate that the value entered in the
+       heap_end_ptr is valid.  If this field is clear, some setup code
+       functionality will be disabled.
+
+
+============   ===================
+Field name:    setup_move_size
+Type:          modify (obligatory)
+Offset/size:   0x212/2
+Protocol:      2.00-2.01
+============   ===================
+
+  When using protocol 2.00 or 2.01, if the real mode kernel is not
+  loaded at 0x90000, it gets moved there later in the loading
+  sequence.  Fill in this field if you want additional data (such as
+  the kernel command line) moved in addition to the real-mode kernel
+  itself.
+
+  The unit is bytes starting with the beginning of the boot sector.
+
+  This field is can be ignored when the protocol is 2.02 or higher, or
+  if the real-mode code is loaded at 0x90000.
+
+============   ========================
+Field name:    code32_start
+Type:          modify (optional, reloc)
+Offset/size:   0x214/4
+Protocol:      2.00+
+============   ========================
+
+  The address to jump to in protected mode.  This defaults to the load
+  address of the kernel, and can be used by the boot loader to
+  determine the proper load address.
+
+  This field can be modified for two purposes:
+
+    1. as a boot loader hook (see Advanced Boot Loader Hooks below.)
+
+    2. if a bootloader which does not install a hook loads a
+       relocatable kernel at a nonstandard address it will have to modify
+       this field to point to the load address.
+
+============   ==================
+Field name:    ramdisk_image
+Type:          write (obligatory)
+Offset/size:   0x218/4
+Protocol:      2.00+
+============   ==================
+
+  The 32-bit linear address of the initial ramdisk or ramfs.  Leave at
+  zero if there is no initial ramdisk/ramfs.
+
+============   ==================
+Field name:    ramdisk_size
+Type:          write (obligatory)
+Offset/size:   0x21c/4
+Protocol:      2.00+
+============   ==================
+
+  Size of the initial ramdisk or ramfs.  Leave at zero if there is no
+  initial ramdisk/ramfs.
+
+============   ===============
+Field name:    bootsect_kludge
+Type:          kernel internal
+Offset/size:   0x220/4
+Protocol:      2.00+
+============   ===============
+
+  This field is obsolete.
+
+============   ==================
+Field name:    heap_end_ptr
+Type:          write (obligatory)
+Offset/size:   0x224/2
+Protocol:      2.01+
+============   ==================
+
+  Set this field to the offset (from the beginning of the real-mode
+  code) of the end of the setup stack/heap, minus 0x0200.
+
+============   ================
+Field name:    ext_loader_ver
+Type:          write (optional)
+Offset/size:   0x226/1
+Protocol:      2.02+
+============   ================
+
+  This field is used as an extension of the version number in the
+  type_of_loader field.  The total version number is considered to be
+  (type_of_loader & 0x0f) + (ext_loader_ver << 4).
+
+  The use of this field is boot loader specific.  If not written, it
+  is zero.
+
+  Kernels prior to 2.6.31 did not recognize this field, but it is safe
+  to write for protocol version 2.02 or higher.
+
+============   =====================================================
+Field name:    ext_loader_type
+Type:          write (obligatory if (type_of_loader & 0xf0) == 0xe0)
+Offset/size:   0x227/1
+Protocol:      2.02+
+============   =====================================================
+
+  This field is used as an extension of the type number in
+  type_of_loader field.  If the type in type_of_loader is 0xE, then
+  the actual type is (ext_loader_type + 0x10).
+
+  This field is ignored if the type in type_of_loader is not 0xE.
+
+  Kernels prior to 2.6.31 did not recognize this field, but it is safe
+  to write for protocol version 2.02 or higher.
+
+============   ==================
+Field name:    cmd_line_ptr
+Type:          write (obligatory)
+Offset/size:   0x228/4
+Protocol:      2.02+
+============   ==================
+
+  Set this field to the linear address of the kernel command line.
+  The kernel command line can be located anywhere between the end of
+  the setup heap and 0xA0000; it does not have to be located in the
+  same 64K segment as the real-mode code itself.
+
+  Fill in this field even if your boot loader does not support a
+  command line, in which case you can point this to an empty string
+  (or better yet, to the string "auto".)  If this field is left at
+  zero, the kernel will assume that your boot loader does not support
+  the 2.02+ protocol.
+
+============   ===============
+Field name:    initrd_addr_max
+Type:          read
+Offset/size:   0x22c/4
+Protocol:      2.03+
+============   ===============
+
+  The maximum address that may be occupied by the initial
+  ramdisk/ramfs contents.  For boot protocols 2.02 or earlier, this
+  field is not present, and the maximum address is 0x37FFFFFF.  (This
+  address is defined as the address of the highest safe byte, so if
+  your ramdisk is exactly 131072 bytes long and this field is
+  0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
+
+============   ============================
+Field name:    kernel_alignment
+Type:          read/modify (reloc)
+Offset/size:   0x230/4
+Protocol:      2.05+ (read), 2.10+ (modify)
+============   ============================
+
+  Alignment unit required by the kernel (if relocatable_kernel is
+  true.)  A relocatable kernel that is loaded at an alignment
+  incompatible with the value in this field will be realigned during
+  kernel initialization.
+
+  Starting with protocol version 2.10, this reflects the kernel
+  alignment preferred for optimal performance; it is possible for the
+  loader to modify this field to permit a lesser alignment.  See the
+  min_alignment and pref_address field below.
+
+============   ==================
+Field name:    relocatable_kernel
+Type:          read (reloc)
+Offset/size:   0x234/1
+Protocol:      2.05+
+============   ==================
+
+  If this field is nonzero, the protected-mode part of the kernel can
+  be loaded at any address that satisfies the kernel_alignment field.
+  After loading, the boot loader must set the code32_start field to
+  point to the loaded code, or to a boot loader hook.
+
+============   =============
+Field name:    min_alignment
+Type:          read (reloc)
+Offset/size:   0x235/1
+Protocol:      2.10+
+============   =============
+
+  This field, if nonzero, indicates as a power of two the minimum
+  alignment required, as opposed to preferred, by the kernel to boot.
+  If a boot loader makes use of this field, it should update the
+  kernel_alignment field with the alignment unit desired; typically::
+
+       kernel_alignment = 1 << min_alignment
+
+  There may be a considerable performance cost with an excessively
+  misaligned kernel.  Therefore, a loader should typically try each
+  power-of-two alignment from kernel_alignment down to this alignment.
+
+============   ==========
+Field name:    xloadflags
+Type:          read
+Offset/size:   0x236/2
+Protocol:      2.12+
+============   ==========
+
+  This field is a bitmask.
+
+  Bit 0 (read):        XLF_KERNEL_64
+
+       - If 1, this kernel has the legacy 64-bit entry point at 0x200.
+
+  Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G
+
+        - If 1, kernel/boot_params/cmdline/ramdisk can be above 4G.
+
+  Bit 2 (read):        XLF_EFI_HANDOVER_32
+
+       - If 1, the kernel supports the 32-bit EFI handoff entry point
+          given at handover_offset.
+
+  Bit 3 (read): XLF_EFI_HANDOVER_64
+
+       - If 1, the kernel supports the 64-bit EFI handoff entry point
+          given at handover_offset + 0x200.
+
+  Bit 4 (read): XLF_EFI_KEXEC
+
+       - If 1, the kernel supports kexec EFI boot with EFI runtime support.
+
+
+============   ============
+Field name:    cmdline_size
+Type:          read
+Offset/size:   0x238/4
+Protocol:      2.06+
+============   ============
+
+  The maximum size of the command line without the terminating
+  zero. This means that the command line can contain at most
+  cmdline_size characters. With protocol version 2.05 and earlier, the
+  maximum size was 255.
+
+============   ====================================
+Field name:    hardware_subarch
+Type:          write (optional, defaults to x86/PC)
+Offset/size:   0x23c/4
+Protocol:      2.07+
+============   ====================================
+
+  In a paravirtualized environment the hardware low level architectural
+  pieces such as interrupt handling, page table handling, and
+  accessing process control registers needs to be done differently.
+
+  This field allows the bootloader to inform the kernel we are in one
+  one of those environments.
+
+  ==========   ==============================
+  0x00000000   The default x86/PC environment
+  0x00000001   lguest
+  0x00000002   Xen
+  0x00000003   Moorestown MID
+  0x00000004   CE4100 TV Platform
+  ==========   ==============================
+
+============   =========================
+Field name:    hardware_subarch_data
+Type:          write (subarch-dependent)
+Offset/size:   0x240/8
+Protocol:      2.07+
+============   =========================
+
+  A pointer to data that is specific to hardware subarch
+  This field is currently unused for the default x86/PC environment,
+  do not modify.
+
+============   ==============
+Field name:    payload_offset
+Type:          read
+Offset/size:   0x248/4
+Protocol:      2.08+
+============   ==============
+
+  If non-zero then this field contains the offset from the beginning
+  of the protected-mode code to the payload.
+
+  The payload may be compressed. The format of both the compressed and
+  uncompressed data should be determined using the standard magic
+  numbers.  The currently supported compression formats are gzip
+  (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA
+  (magic number 5D 00), XZ (magic number FD 37), LZ4 (magic number
+  02 21) and ZSTD (magic number 28 B5). The uncompressed payload is
+  currently always ELF (magic number 7F 45 4C 46).
+
+============   ==============
+Field name:    payload_length
+Type:          read
+Offset/size:   0x24c/4
+Protocol:      2.08+
+============   ==============
+
+  The length of the payload.
+
+============   ===============
+Field name:    setup_data
+Type:          write (special)
+Offset/size:   0x250/8
+Protocol:      2.09+
+============   ===============
+
+  The 64-bit physical pointer to NULL terminated single linked list of
+  struct setup_data. This is used to define a more extensible boot
+  parameters passing mechanism. The definition of struct setup_data is
+  as follow::
+
+       struct setup_data {
+               u64 next;
+               u32 type;
+               u32 len;
+               u8  data[0];
+       };
+
+  Where, the next is a 64-bit physical pointer to the next node of
+  linked list, the next field of the last node is 0; the type is used
+  to identify the contents of data; the len is the length of data
+  field; the data holds the real payload.
+
+  This list may be modified at a number of points during the bootup
+  process.  Therefore, when modifying this list one should always make
+  sure to consider the case where the linked list already contains
+  entries.
+
+  The setup_data is a bit awkward to use for extremely large data objects,
+  both because the setup_data header has to be adjacent to the data object
+  and because it has a 32-bit length field. However, it is important that
+  intermediate stages of the boot process have a way to identify which
+  chunks of memory are occupied by kernel data.
+
+  Thus setup_indirect struct and SETUP_INDIRECT type were introduced in
+  protocol 2.15::
+
+    struct setup_indirect {
+      __u32 type;
+      __u32 reserved;  /* Reserved, must be set to zero. */
+      __u64 len;
+      __u64 addr;
+    };
+
+  The type member is a SETUP_INDIRECT | SETUP_* type. However, it cannot be
+  SETUP_INDIRECT itself since making the setup_indirect a tree structure
+  could require a lot of stack space in something that needs to parse it
+  and stack space can be limited in boot contexts.
+
+  Let's give an example how to point to SETUP_E820_EXT data using setup_indirect.
+  In this case setup_data and setup_indirect will look like this::
+
+    struct setup_data {
+      __u64 next = 0 or <addr_of_next_setup_data_struct>;
+      __u32 type = SETUP_INDIRECT;
+      __u32 len = sizeof(setup_indirect);
+      __u8 data[sizeof(setup_indirect)] = struct setup_indirect {
+        __u32 type = SETUP_INDIRECT | SETUP_E820_EXT;
+        __u32 reserved = 0;
+        __u64 len = <len_of_SETUP_E820_EXT_data>;
+        __u64 addr = <addr_of_SETUP_E820_EXT_data>;
+      }
+    }
+
+.. note::
+     SETUP_INDIRECT | SETUP_NONE objects cannot be properly distinguished
+     from SETUP_INDIRECT itself. So, this kind of objects cannot be provided
+     by the bootloaders.
+
+============   ============
+Field name:    pref_address
+Type:          read (reloc)
+Offset/size:   0x258/8
+Protocol:      2.10+
+============   ============
+
+  This field, if nonzero, represents a preferred load address for the
+  kernel.  A relocating bootloader should attempt to load at this
+  address if possible.
+
+  A non-relocatable kernel will unconditionally move itself and to run
+  at this address.
+
+============   =======
+Field name:    init_size
+Type:          read
+Offset/size:   0x260/4
+============   =======
+
+  This field indicates the amount of linear contiguous memory starting
+  at the kernel runtime start address that the kernel needs before it
+  is capable of examining its memory map.  This is not the same thing
+  as the total amount of memory the kernel needs to boot, but it can
+  be used by a relocating boot loader to help select a safe load
+  address for the kernel.
+
+  The kernel runtime start address is determined by the following algorithm::
+
+       if (relocatable_kernel)
+       runtime_start = align_up(load_address, kernel_alignment)
+       else
+       runtime_start = pref_address
+
+============   ===============
+Field name:    handover_offset
+Type:          read
+Offset/size:   0x264/4
+============   ===============
+
+  This field is the offset from the beginning of the kernel image to
+  the EFI handover protocol entry point. Boot loaders using the EFI
+  handover protocol to boot the kernel should jump to this offset.
+
+  See EFI HANDOVER PROTOCOL below for more details.
+
+============   ==================
+Field name:    kernel_info_offset
+Type:          read
+Offset/size:   0x268/4
+Protocol:      2.15+
+============   ==================
+
+  This field is the offset from the beginning of the kernel image to the
+  kernel_info. The kernel_info structure is embedded in the Linux image
+  in the uncompressed protected mode region.
+
+
+The kernel_info
+===============
+
+The relationships between the headers are analogous to the various data
+sections:
+
+  setup_header = .data
+  boot_params/setup_data = .bss
+
+What is missing from the above list? That's right:
+
+  kernel_info = .rodata
+
+We have been (ab)using .data for things that could go into .rodata or .bss for
+a long time, for lack of alternatives and -- especially early on -- inertia.
+Also, the BIOS stub is responsible for creating boot_params, so it isn't
+available to a BIOS-based loader (setup_data is, though).
+
+setup_header is permanently limited to 144 bytes due to the reach of the
+2-byte jump field, which doubles as a length field for the structure, combined
+with the size of the "hole" in struct boot_params that a protected-mode loader
+or the BIOS stub has to copy it into. It is currently 119 bytes long, which
+leaves us with 25 very precious bytes. This isn't something that can be fixed
+without revising the boot protocol entirely, breaking backwards compatibility.
+
+boot_params proper is limited to 4096 bytes, but can be arbitrarily extended
+by adding setup_data entries. It cannot be used to communicate properties of
+the kernel image, because it is .bss and has no image-provided content.
+
+kernel_info solves this by providing an extensible place for information about
+the kernel image. It is readonly, because the kernel cannot rely on a
+bootloader copying its contents anywhere, but that is OK; if it becomes
+necessary it can still contain data items that an enabled bootloader would be
+expected to copy into a setup_data chunk.
+
+All kernel_info data should be part of this structure. Fixed size data have to
+be put before kernel_info_var_len_data label. Variable size data have to be put
+after kernel_info_var_len_data label. Each chunk of variable size data has to
+be prefixed with header/magic and its size, e.g.::
+
+  kernel_info:
+          .ascii  "LToP"          /* Header, Linux top (structure). */
+          .long   kernel_info_var_len_data - kernel_info
+          .long   kernel_info_end - kernel_info
+          .long   0x01234567      /* Some fixed size data for the bootloaders. */
+  kernel_info_var_len_data:
+  example_struct:                 /* Some variable size data for the bootloaders. */
+          .ascii  "0123"          /* Header/Magic. */
+          .long   example_struct_end - example_struct
+          .ascii  "Struct"
+          .long   0x89012345
+  example_struct_end:
+  example_strings:                /* Some variable size data for the bootloaders. */
+          .ascii  "ABCD"          /* Header/Magic. */
+          .long   example_strings_end - example_strings
+          .asciz  "String_0"
+          .asciz  "String_1"
+  example_strings_end:
+  kernel_info_end:
+
+This way the kernel_info is self-contained blob.
+
+.. note::
+     Each variable size data header/magic can be any 4-character string,
+     without \0 at the end of the string, which does not collide with
+     existing variable length data headers/magics.
+
+
+Details of the kernel_info Fields
+=================================
+
+============   ========
+Field name:    header
+Offset/size:   0x0000/4
+============   ========
+
+  Contains the magic number "LToP" (0x506f544c).
+
+============   ========
+Field name:    size
+Offset/size:   0x0004/4
+============   ========
+
+  This field contains the size of the kernel_info including kernel_info.header.
+  It does not count kernel_info.kernel_info_var_len_data size. This field should be
+  used by the bootloaders to detect supported fixed size fields in the kernel_info
+  and beginning of kernel_info.kernel_info_var_len_data.
+
+============   ========
+Field name:    size_total
+Offset/size:   0x0008/4
+============   ========
+
+  This field contains the size of the kernel_info including kernel_info.header
+  and kernel_info.kernel_info_var_len_data.
+
+============   ==============
+Field name:    setup_type_max
+Offset/size:   0x000c/4
+============   ==============
+
+  This field contains maximal allowed type for setup_data and setup_indirect structs.
+
+
+The Image Checksum
+==================
+
+From boot protocol version 2.08 onwards the CRC-32 is calculated over
+the entire file using the characteristic polynomial 0x04C11DB7 and an
+initial remainder of 0xffffffff.  The checksum is appended to the
+file; therefore the CRC of the file up to the limit specified in the
+syssize field of the header is always 0.
+
+
+The Kernel Command Line
+=======================
+
+The kernel command line has become an important way for the boot
+loader to communicate with the kernel.  Some of its options are also
+relevant to the boot loader itself, see "special command line options"
+below.
+
+The kernel command line is a null-terminated string. The maximum
+length can be retrieved from the field cmdline_size.  Before protocol
+version 2.06, the maximum was 255 characters.  A string that is too
+long will be automatically truncated by the kernel.
+
+If the boot protocol version is 2.02 or later, the address of the
+kernel command line is given by the header field cmd_line_ptr (see
+above.)  This address can be anywhere between the end of the setup
+heap and 0xA0000.
+
+If the protocol version is *not* 2.02 or higher, the kernel
+command line is entered using the following protocol:
+
+  - At offset 0x0020 (word), "cmd_line_magic", enter the magic
+    number 0xA33F.
+
+  - At offset 0x0022 (word), "cmd_line_offset", enter the offset
+    of the kernel command line (relative to the start of the
+    real-mode kernel).
+
+  - The kernel command line *must* be within the memory region
+    covered by setup_move_size, so you may need to adjust this
+    field.
+
+
+Memory Layout of The Real-Mode Code
+===================================
+
+The real-mode code requires a stack/heap to be set up, as well as
+memory allocated for the kernel command line.  This needs to be done
+in the real-mode accessible memory in bottom megabyte.
+
+It should be noted that modern machines often have a sizable Extended
+BIOS Data Area (EBDA).  As a result, it is advisable to use as little
+of the low megabyte as possible.
+
+Unfortunately, under the following circumstances the 0x90000 memory
+segment has to be used:
+
+       - When loading a zImage kernel ((loadflags & 0x01) == 0).
+       - When loading a 2.01 or earlier boot protocol kernel.
+
+.. note::
+     For the 2.00 and 2.01 boot protocols, the real-mode code
+     can be loaded at another address, but it is internally
+     relocated to 0x90000.  For the "old" protocol, the
+     real-mode code must be loaded at 0x90000.
+
+When loading at 0x90000, avoid using memory above 0x9a000.
+
+For boot protocol 2.02 or higher, the command line does not have to be
+located in the same 64K segment as the real-mode setup code; it is
+thus permitted to give the stack/heap the full 64K segment and locate
+the command line above it.
+
+The kernel command line should not be located below the real-mode
+code, nor should it be located in high memory.
+
+
+Sample Boot Configuartion
+=========================
+
+As a sample configuration, assume the following layout of the real
+mode segment.
+
+    When loading below 0x90000, use the entire segment:
+
+        =============  ===================
+       0x0000-0x7fff   Real mode kernel
+       0x8000-0xdfff   Stack and heap
+       0xe000-0xffff   Kernel command line
+       =============   ===================
+
+    When loading at 0x90000 OR the protocol version is 2.01 or earlier:
+
+       =============   ===================
+       0x0000-0x7fff   Real mode kernel
+       0x8000-0x97ff   Stack and heap
+       0x9800-0x9fff   Kernel command line
+       =============   ===================
+
+Such a boot loader should enter the following fields in the header::
+
+       unsigned long base_ptr; /* base address for real-mode segment */
+
+       if ( setup_sects == 0 ) {
+               setup_sects = 4;
+       }
+
+       if ( protocol >= 0x0200 ) {
+               type_of_loader = <type code>;
+               if ( loading_initrd ) {
+                       ramdisk_image = <initrd_address>;
+                       ramdisk_size = <initrd_size>;
+               }
+
+               if ( protocol >= 0x0202 && loadflags & 0x01 )
+                       heap_end = 0xe000;
+               else
+                       heap_end = 0x9800;
+
+               if ( protocol >= 0x0201 ) {
+                       heap_end_ptr = heap_end - 0x200;
+                       loadflags |= 0x80; /* CAN_USE_HEAP */
+               }
+
+               if ( protocol >= 0x0202 ) {
+                       cmd_line_ptr = base_ptr + heap_end;
+                       strcpy(cmd_line_ptr, cmdline);
+               } else {
+                       cmd_line_magic  = 0xA33F;
+                       cmd_line_offset = heap_end;
+                       setup_move_size = heap_end + strlen(cmdline)+1;
+                       strcpy(base_ptr+cmd_line_offset, cmdline);
+               }
+       } else {
+               /* Very old kernel */
+
+               heap_end = 0x9800;
+
+               cmd_line_magic  = 0xA33F;
+               cmd_line_offset = heap_end;
+
+               /* A very old kernel MUST have its real-mode code
+                  loaded at 0x90000 */
+
+               if ( base_ptr != 0x90000 ) {
+                       /* Copy the real-mode kernel */
+                       memcpy(0x90000, base_ptr, (setup_sects+1)*512);
+                       base_ptr = 0x90000;              /* Relocated */
+               }
+
+               strcpy(0x90000+cmd_line_offset, cmdline);
+
+               /* It is recommended to clear memory up to the 32K mark */
+               memset(0x90000 + (setup_sects+1)*512, 0,
+                      (64-(setup_sects+1))*512);
+       }
+
+
+Loading The Rest of The Kernel
+==============================
+
+The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
+in the kernel file (again, if setup_sects == 0 the real value is 4.)
+It should be loaded at address 0x10000 for Image/zImage kernels and
+0x100000 for bzImage kernels.
+
+The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
+bit (LOAD_HIGH) in the loadflags field is set::
+
+       is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
+       load_address = is_bzImage ? 0x100000 : 0x10000;
+
+Note that Image/zImage kernels can be up to 512K in size, and thus use
+the entire 0x10000-0x90000 range of memory.  This means it is pretty
+much a requirement for these kernels to load the real-mode part at
+0x90000.  bzImage kernels allow much more flexibility.
+
+Special Command Line Options
+============================
+
+If the command line provided by the boot loader is entered by the
+user, the user may expect the following command line options to work.
+They should normally not be deleted from the kernel command line even
+though not all of them are actually meaningful to the kernel.  Boot
+loader authors who need additional command line options for the boot
+loader itself should get them registered in
+Documentation/admin-guide/kernel-parameters.rst to make sure they will not
+conflict with actual kernel options now or in the future.
+
+  vga=<mode>
+       <mode> here is either an integer (in C notation, either
+       decimal, octal, or hexadecimal) or one of the strings
+       "normal" (meaning 0xFFFF), "ext" (meaning 0xFFFE) or "ask"
+       (meaning 0xFFFD).  This value should be entered into the
+       vid_mode field, as it is used by the kernel before the command
+       line is parsed.
+
+  mem=<size>
+       <size> is an integer in C notation optionally followed by
+       (case insensitive) K, M, G, T, P or E (meaning << 10, << 20,
+       << 30, << 40, << 50 or << 60).  This specifies the end of
+       memory to the kernel. This affects the possible placement of
+       an initrd, since an initrd should be placed near end of
+       memory.  Note that this is an option to *both* the kernel and
+       the bootloader!
+
+  initrd=<file>
+       An initrd should be loaded.  The meaning of <file> is
+       obviously bootloader-dependent, and some boot loaders
+       (e.g. LILO) do not have such a command.
+
+In addition, some boot loaders add the following options to the
+user-specified command line:
+
+  BOOT_IMAGE=<file>
+       The boot image which was loaded.  Again, the meaning of <file>
+       is obviously bootloader-dependent.
+
+  auto
+       The kernel was booted without explicit user intervention.
+
+If these options are added by the boot loader, it is highly
+recommended that they are located *first*, before the user-specified
+or configuration-specified command line.  Otherwise, "init=/bin/sh"
+gets confused by the "auto" option.
+
+
+Running the Kernel
+==================
+
+The kernel is started by jumping to the kernel entry point, which is
+located at *segment* offset 0x20 from the start of the real mode
+kernel.  This means that if you loaded your real-mode kernel code at
+0x90000, the kernel entry point is 9020:0000.
+
+At entry, ds = es = ss should point to the start of the real-mode
+kernel code (0x9000 if the code is loaded at 0x90000), sp should be
+set up properly, normally pointing to the top of the heap, and
+interrupts should be disabled.  Furthermore, to guard against bugs in
+the kernel, it is recommended that the boot loader sets fs = gs = ds =
+es = ss.
+
+In our example from above, we would do::
+
+       /* Note: in the case of the "old" kernel protocol, base_ptr must
+          be == 0x90000 at this point; see the previous sample code */
+
+       seg = base_ptr >> 4;
+
+       cli();  /* Enter with interrupts disabled! */
+
+       /* Set up the real-mode kernel stack */
+       _SS = seg;
+       _SP = heap_end;
+
+       _DS = _ES = _FS = _GS = seg;
+       jmp_far(seg+0x20, 0);   /* Run the kernel */
+
+If your boot sector accesses a floppy drive, it is recommended to
+switch off the floppy motor before running the kernel, since the
+kernel boot leaves interrupts off and thus the motor will not be
+switched off, especially if the loaded kernel has the floppy driver as
+a demand-loaded module!
+
+
+Advanced Boot Loader Hooks
+==========================
+
+If the boot loader runs in a particularly hostile environment (such as
+LOADLIN, which runs under DOS) it may be impossible to follow the
+standard memory location requirements.  Such a boot loader may use the
+following hooks that, if set, are invoked by the kernel at the
+appropriate time.  The use of these hooks should probably be
+considered an absolutely last resort!
+
+IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
+%edi across invocation.
+
+  realmode_swtch:
+       A 16-bit real mode far subroutine invoked immediately before
+       entering protected mode.  The default routine disables NMI, so
+       your routine should probably do so, too.
+
+  code32_start:
+       A 32-bit flat-mode routine *jumped* to immediately after the
+       transition to protected mode, but before the kernel is
+       uncompressed.  No segments, except CS, are guaranteed to be
+       set up (current kernels do, but older ones do not); you should
+       set them up to BOOT_DS (0x18) yourself.
+
+       After completing your hook, you should jump to the address
+       that was in this field before your boot loader overwrote it
+       (relocated, if appropriate.)
+
+
+32-bit Boot Protocol
+====================
+
+For machine with some new BIOS other than legacy BIOS, such as EFI,
+LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel
+based on legacy BIOS can not be used, so a 32-bit boot protocol needs
+to be defined.
+
+In 32-bit boot protocol, the first step in loading a Linux kernel
+should be to setup the boot parameters (struct boot_params,
+traditionally known as "zero page"). The memory for struct boot_params
+should be allocated and initialized to all zero. Then the setup header
+from offset 0x01f1 of kernel image on should be loaded into struct
+boot_params and examined. The end of setup header can be calculated as
+follow::
+
+       0x0202 + byte value at offset 0x0201
+
+In addition to read/modify/write the setup header of the struct
+boot_params as that of 16-bit boot protocol, the boot loader should
+also fill the additional fields of the struct boot_params as
+described in chapter Documentation/arch/x86/zero-page.rst.
+
+After setting up the struct boot_params, the boot loader can load the
+32/64-bit kernel in the same way as that of 16-bit boot protocol.
+
+In 32-bit boot protocol, the kernel is started by jumping to the
+32-bit kernel entry point, which is the start address of loaded
+32/64-bit kernel.
+
+At entry, the CPU must be in 32-bit protected mode with paging
+disabled; a GDT must be loaded with the descriptors for selectors
+__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat
+segment; __BOOT_CS must have execute/read permission, and __BOOT_DS
+must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
+must be __BOOT_DS; interrupt must be disabled; %esi must hold the base
+address of the struct boot_params; %ebp, %edi and %ebx must be zero.
+
+64-bit Boot Protocol
+====================
+
+For machine with 64bit cpus and 64bit kernel, we could use 64bit bootloader
+and we need a 64-bit boot protocol.
+
+In 64-bit boot protocol, the first step in loading a Linux kernel
+should be to setup the boot parameters (struct boot_params,
+traditionally known as "zero page"). The memory for struct boot_params
+could be allocated anywhere (even above 4G) and initialized to all zero.
+Then, the setup header at offset 0x01f1 of kernel image on should be
+loaded into struct boot_params and examined. The end of setup header
+can be calculated as follows::
+
+       0x0202 + byte value at offset 0x0201
+
+In addition to read/modify/write the setup header of the struct
+boot_params as that of 16-bit boot protocol, the boot loader should
+also fill the additional fields of the struct boot_params as described
+in chapter Documentation/arch/x86/zero-page.rst.
+
+After setting up the struct boot_params, the boot loader can load
+64-bit kernel in the same way as that of 16-bit boot protocol, but
+kernel could be loaded above 4G.
+
+In 64-bit boot protocol, the kernel is started by jumping to the
+64-bit kernel entry point, which is the start address of loaded
+64-bit kernel plus 0x200.
+
+At entry, the CPU must be in 64-bit mode with paging enabled.
+The range with setup_header.init_size from start address of loaded
+kernel and zero page and command line buffer get ident mapping;
+a GDT must be loaded with the descriptors for selectors
+__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat
+segment; __BOOT_CS must have execute/read permission, and __BOOT_DS
+must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
+must be __BOOT_DS; interrupt must be disabled; %rsi must hold the base
+address of the struct boot_params.
+
+EFI Handover Protocol (deprecated)
+==================================
+
+This protocol allows boot loaders to defer initialisation to the EFI
+boot stub. The boot loader is required to load the kernel/initrd(s)
+from the boot media and jump to the EFI handover protocol entry point
+which is hdr->handover_offset bytes from the beginning of
+startup_{32,64}.
+
+The boot loader MUST respect the kernel's PE/COFF metadata when it comes
+to section alignment, the memory footprint of the executable image beyond
+the size of the file itself, and any other aspect of the PE/COFF header
+that may affect correct operation of the image as a PE/COFF binary in the
+execution context provided by the EFI firmware.
+
+The function prototype for the handover entry point looks like this::
+
+    efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp)
+
+'handle' is the EFI image handle passed to the boot loader by the EFI
+firmware, 'table' is the EFI system table - these are the first two
+arguments of the "handoff state" as described in section 2.3 of the
+UEFI specification. 'bp' is the boot loader-allocated boot params.
+
+The boot loader *must* fill out the following fields in bp::
+
+  - hdr.cmd_line_ptr
+  - hdr.ramdisk_image (if applicable)
+  - hdr.ramdisk_size  (if applicable)
+
+All other fields should be zero.
+
+NOTE: The EFI Handover Protocol is deprecated in favour of the ordinary PE/COFF
+      entry point, combined with the LINUX_EFI_INITRD_MEDIA_GUID based initrd
+      loading protocol (refer to [0] for an example of the bootloader side of
+      this), which removes the need for any knowledge on the part of the EFI
+      bootloader regarding the internal representation of boot_params or any
+      requirements/limitations regarding the placement of the command line
+      and ramdisk in memory, or the placement of the kernel image itself.
+
+[0] https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5d717d4739b0fd0
diff --git a/Documentation/arch/x86/booting-dt.rst b/Documentation/arch/x86/booting-dt.rst
new file mode 100644 (file)
index 0000000..b089ffd
--- /dev/null
@@ -0,0 +1,21 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+DeviceTree Booting
+------------------
+
+  There is one single 32bit entry point to the kernel at code32_start,
+  the decompressor (the real mode entry point goes to the same  32bit
+  entry point once it switched into protected mode). That entry point
+  supports one calling convention which is documented in
+  Documentation/arch/x86/boot.rst
+  The physical pointer to the device-tree block is passed via setup_data
+  which requires at least boot protocol 2.09.
+  The type filed is defined as
+
+  #define SETUP_DTB                      2
+
+  This device-tree is used as an extension to the "boot page". As such it
+  does not parse / consider data which is already covered by the boot
+  page. This includes memory size, reserved ranges, command line arguments
+  or initrd address. It simply holds information which can not be retrieved
+  otherwise like interrupt routing or a list of devices behind an I2C bus.
diff --git a/Documentation/arch/x86/buslock.rst b/Documentation/arch/x86/buslock.rst
new file mode 100644 (file)
index 0000000..31ec0ef
--- /dev/null
@@ -0,0 +1,132 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: <isonum.txt>
+
+===============================
+Bus lock detection and handling
+===============================
+
+:Copyright: |copy| 2021 Intel Corporation
+:Authors: - Fenghua Yu <fenghua.yu@intel.com>
+          - Tony Luck <tony.luck@intel.com>
+
+Problem
+=======
+
+A split lock is any atomic operation whose operand crosses two cache lines.
+Since the operand spans two cache lines and the operation must be atomic,
+the system locks the bus while the CPU accesses the two cache lines.
+
+A bus lock is acquired through either split locked access to writeback (WB)
+memory or any locked access to non-WB memory. This is typically thousands of
+cycles slower than an atomic operation within a cache line. It also disrupts
+performance on other cores and brings the whole system to its knees.
+
+Detection
+=========
+
+Intel processors may support either or both of the following hardware
+mechanisms to detect split locks and bus locks.
+
+#AC exception for split lock detection
+--------------------------------------
+
+Beginning with the Tremont Atom CPU split lock operations may raise an
+Alignment Check (#AC) exception when a split lock operation is attemped.
+
+#DB exception for bus lock detection
+------------------------------------
+
+Some CPUs have the ability to notify the kernel by an #DB trap after a user
+instruction acquires a bus lock and is executed. This allows the kernel to
+terminate the application or to enforce throttling.
+
+Software handling
+=================
+
+The kernel #AC and #DB handlers handle bus lock based on the kernel
+parameter "split_lock_detect". Here is a summary of different options:
+
++------------------+----------------------------+-----------------------+
+|split_lock_detect=|#AC for split lock         |#DB for bus lock       |
++------------------+----------------------------+-----------------------+
+|off              |Do nothing                  |Do nothing             |
++------------------+----------------------------+-----------------------+
+|warn             |Kernel OOPs                 |Warn once per task and |
+|(default)        |Warn once per task, add a   |and continues to run.  |
+|                 |delay, add synchronization  |                       |
+|                 |to prevent more than one    |                       |
+|                 |core from executing a       |                       |
+|                 |split lock in parallel.     |                       |
+|                 |sysctl split_lock_mitigate  |                       |
+|                 |can be used to avoid the    |                       |
+|                 |delay and synchronization   |                       |
+|                 |When both features are      |                       |
+|                 |supported, warn in #AC      |                       |
++------------------+----------------------------+-----------------------+
+|fatal            |Kernel OOPs                 |Send SIGBUS to user.   |
+|                 |Send SIGBUS to user         |                       |
+|                 |When both features are      |                       |
+|                 |supported, fatal in #AC     |                       |
++------------------+----------------------------+-----------------------+
+|ratelimit:N      |Do nothing                  |Limit bus lock rate to |
+|(0 < N <= 1000)   |                           |N bus locks per second |
+|                 |                            |system wide and warn on|
+|                 |                            |bus locks.             |
++------------------+----------------------------+-----------------------+
+
+Usages
+======
+
+Detecting and handling bus lock may find usages in various areas:
+
+It is critical for real time system designers who build consolidated real
+time systems. These systems run hard real time code on some cores and run
+"untrusted" user processes on other cores. The hard real time cannot afford
+to have any bus lock from the untrusted processes to hurt real time
+performance. To date the designers have been unable to deploy these
+solutions as they have no way to prevent the "untrusted" user code from
+generating split lock and bus lock to block the hard real time code to
+access memory during bus locking.
+
+It's also useful for general computing to prevent guests or user
+applications from slowing down the overall system by executing instructions
+with bus lock.
+
+
+Guidance
+========
+off
+---
+
+Disable checking for split lock and bus lock. This option can be useful if
+there are legacy applications that trigger these events at a low rate so
+that mitigation is not needed.
+
+warn
+----
+
+A warning is emitted when a bus lock is detected which allows to identify
+the offending application. This is the default behavior.
+
+fatal
+-----
+
+In this case, the bus lock is not tolerated and the process is killed.
+
+ratelimit
+---------
+
+A system wide bus lock rate limit N is specified where 0 < N <= 1000. This
+allows a bus lock rate up to N bus locks per second. When the bus lock rate
+is exceeded then any task which is caught via the buslock #DB exception is
+throttled by enforced sleeps until the rate goes under the limit again.
+
+This is an effective mitigation in cases where a minimal impact can be
+tolerated, but an eventual Denial of Service attack has to be prevented. It
+allows to identify the offending processes and analyze whether they are
+malicious or just badly written.
+
+Selecting a rate limit of 1000 allows the bus to be locked for up to about
+seven million cycles each second (assuming 7000 cycles for each bus
+lock). On a 2 GHz processor that would be about 0.35% system slowdown.
diff --git a/Documentation/arch/x86/cpuinfo.rst b/Documentation/arch/x86/cpuinfo.rst
new file mode 100644 (file)
index 0000000..08246e8
--- /dev/null
@@ -0,0 +1,154 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+x86 Feature Flags
+=================
+
+Introduction
+============
+
+On x86, flags appearing in /proc/cpuinfo have an X86_FEATURE definition
+in arch/x86/include/asm/cpufeatures.h. If the kernel cares about a feature
+or KVM want to expose the feature to a KVM guest, it can and should have
+an X86_FEATURE_* defined. These flags represent hardware features as
+well as software features.
+
+If users want to know if a feature is available on a given system, they
+try to find the flag in /proc/cpuinfo. If a given flag is present, it
+means that the kernel supports it and is currently making it available.
+If such flag represents a hardware feature, it also means that the
+hardware supports it.
+
+If the expected flag does not appear in /proc/cpuinfo, things are murkier.
+Users need to find out the reason why the flag is missing and find the way
+how to enable it, which is not always easy. There are several factors that
+can explain missing flags: the expected feature failed to enable, the feature
+is missing in hardware, platform firmware did not enable it, the feature is
+disabled at build or run time, an old kernel is in use, or the kernel does
+not support the feature and thus has not enabled it. In general, /proc/cpuinfo
+shows features which the kernel supports. For a full list of CPUID flags
+which the CPU supports, use tools/arch/x86/kcpuid.
+
+How are feature flags created?
+==============================
+
+a: Feature flags can be derived from the contents of CPUID leaves.
+------------------------------------------------------------------
+These feature definitions are organized mirroring the layout of CPUID
+leaves and grouped in words with offsets as mapped in enum cpuid_leafs
+in cpufeatures.h (see arch/x86/include/asm/cpufeatures.h for details).
+If a feature is defined with a X86_FEATURE_<name> definition in
+cpufeatures.h, and if it is detected at run time, the flags will be
+displayed accordingly in /proc/cpuinfo. For example, the flag "avx2"
+comes from X86_FEATURE_AVX2 in cpufeatures.h.
+
+b: Flags can be from scattered CPUID-based features.
+----------------------------------------------------
+Hardware features enumerated in sparsely populated CPUID leaves get
+software-defined values. Still, CPUID needs to be queried to determine
+if a given feature is present. This is done in init_scattered_cpuid_features().
+For instance, X86_FEATURE_CQM_LLC is defined as 11*32 + 0 and its presence is
+checked at runtime in the respective CPUID leaf [EAX=f, ECX=0] bit EDX[1].
+
+The intent of scattering CPUID leaves is to not bloat struct
+cpuinfo_x86.x86_capability[] unnecessarily. For instance, the CPUID leaf
+[EAX=7, ECX=0] has 30 features and is dense, but the CPUID leaf [EAX=7, EAX=1]
+has only one feature and would waste 31 bits of space in the x86_capability[]
+array. Since there is a struct cpuinfo_x86 for each possible CPU, the wasted
+memory is not trivial.
+
+c: Flags can be created synthetically under certain conditions for hardware features.
+-------------------------------------------------------------------------------------
+Examples of conditions include whether certain features are present in
+MSR_IA32_CORE_CAPS or specific CPU models are identified. If the needed
+conditions are met, the features are enabled by the set_cpu_cap or
+setup_force_cpu_cap macros. For example, if bit 5 is set in MSR_IA32_CORE_CAPS,
+the feature X86_FEATURE_SPLIT_LOCK_DETECT will be enabled and
+"split_lock_detect" will be displayed. The flag "ring3mwait" will be
+displayed only when running on INTEL_FAM6_XEON_PHI_[KNL|KNM] processors.
+
+d: Flags can represent purely software features.
+------------------------------------------------
+These flags do not represent hardware features. Instead, they represent a
+software feature implemented in the kernel. For example, Kernel Page Table
+Isolation is purely software feature and its feature flag X86_FEATURE_PTI is
+also defined in cpufeatures.h.
+
+Naming of Flags
+===============
+
+The script arch/x86/kernel/cpu/mkcapflags.sh processes the
+#define X86_FEATURE_<name> from cpufeatures.h and generates the
+x86_cap/bug_flags[] arrays in kernel/cpu/capflags.c. The names in the
+resulting x86_cap/bug_flags[] are used to populate /proc/cpuinfo. The naming
+of flags in the x86_cap/bug_flags[] are as follows:
+
+a: The name of the flag is from the string in X86_FEATURE_<name> by default.
+----------------------------------------------------------------------------
+By default, the flag <name> in /proc/cpuinfo is extracted from the respective
+X86_FEATURE_<name> in cpufeatures.h. For example, the flag "avx2" is from
+X86_FEATURE_AVX2.
+
+b: The naming can be overridden.
+--------------------------------
+If the comment on the line for the #define X86_FEATURE_* starts with a
+double-quote character (""), the string inside the double-quote characters
+will be the name of the flags. For example, the flag "sse4_1" comes from
+the comment "sse4_1" following the X86_FEATURE_XMM4_1 definition.
+
+There are situations in which overriding the displayed name of the flag is
+needed. For instance, /proc/cpuinfo is a userspace interface and must remain
+constant. If, for some reason, the naming of X86_FEATURE_<name> changes, one
+shall override the new naming with the name already used in /proc/cpuinfo.
+
+c: The naming override can be "", which means it will not appear in /proc/cpuinfo.
+----------------------------------------------------------------------------------
+The feature shall be omitted from /proc/cpuinfo if it does not make sense for
+the feature to be exposed to userspace. For example, X86_FEATURE_ALWAYS is
+defined in cpufeatures.h but that flag is an internal kernel feature used
+in the alternative runtime patching functionality. So, its name is overridden
+with "". Its flag will not appear in /proc/cpuinfo.
+
+Flags are missing when one or more of these happen
+==================================================
+
+a: The hardware does not enumerate support for it.
+--------------------------------------------------
+For example, when a new kernel is running on old hardware or the feature is
+not enabled by boot firmware. Even if the hardware is new, there might be a
+problem enabling the feature at run time, the flag will not be displayed.
+
+b: The kernel does not know about the flag.
+-------------------------------------------
+For example, when an old kernel is running on new hardware.
+
+c: The kernel disabled support for it at compile-time.
+------------------------------------------------------
+For example, if 5-level-paging is not enabled when building (i.e.,
+CONFIG_X86_5LEVEL is not selected) the flag "la57" will not show up [#f1]_.
+Even though the feature will still be detected via CPUID, the kernel disables
+it by clearing via setup_clear_cpu_cap(X86_FEATURE_LA57).
+
+d: The feature is disabled at boot-time.
+----------------------------------------
+A feature can be disabled either using a command-line parameter or because
+it failed to be enabled. The command-line parameter clearcpuid= can be used
+to disable features using the feature number as defined in
+/arch/x86/include/asm/cpufeatures.h. For instance, User Mode Instruction
+Protection can be disabled using clearcpuid=514. The number 514 is calculated
+from #define X86_FEATURE_UMIP (16*32 + 2).
+
+In addition, there exists a variety of custom command-line parameters that
+disable specific features. The list of parameters includes, but is not limited
+to, nofsgsbase, nosgx, noxsave, etc. 5-level paging can also be disabled using
+"no5lvl".
+
+e: The feature was known to be non-functional.
+----------------------------------------------
+The feature was known to be non-functional because a dependency was
+missing at runtime. For example, AVX flags will not show up if XSAVE feature
+is disabled since they depend on XSAVE feature. Another example would be broken
+CPUs and them missing microcode patches. Due to that, the kernel decides not to
+enable a feature.
+
+.. [#f1] 5-level paging uses linear address of 57 bits.
diff --git a/Documentation/arch/x86/earlyprintk.rst b/Documentation/arch/x86/earlyprintk.rst
new file mode 100644 (file)
index 0000000..51ef11e
--- /dev/null
@@ -0,0 +1,151 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Early Printk
+============
+
+Mini-HOWTO for using the earlyprintk=dbgp boot option with a
+USB2 Debug port key and a debug cable, on x86 systems.
+
+You need two computers, the 'USB debug key' special gadget and
+two USB cables, connected like this::
+
+  [host/target] <-------> [USB debug key] <-------> [client/console]
+
+Hardware requirements
+=====================
+
+  a) Host/target system needs to have USB debug port capability.
+
+     You can check this capability by looking at a 'Debug port' bit in
+     the lspci -vvv output::
+
+       # lspci -vvv
+       ...
+       00:1d.7 USB Controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #1 (rev 03) (prog-if 20 [EHCI])
+               Subsystem: Lenovo ThinkPad T61
+               Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
+               Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
+               Latency: 0
+               Interrupt: pin D routed to IRQ 19
+               Region 0: Memory at fe227000 (32-bit, non-prefetchable) [size=1K]
+               Capabilities: [50] Power Management version 2
+                       Flags: PMEClk- DSI- D1- D2- AuxCurrent=375mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
+                       Status: D0 PME-Enable- DSel=0 DScale=0 PME+
+               Capabilities: [58] Debug port: BAR=1 offset=00a0
+                            ^^^^^^^^^^^ <==================== [ HERE ]
+               Kernel driver in use: ehci_hcd
+               Kernel modules: ehci-hcd
+       ...
+
+     .. note::
+       If your system does not list a debug port capability then you probably
+       won't be able to use the USB debug key.
+
+  b) You also need a NetChip USB debug cable/key:
+
+        http://www.plxtech.com/products/NET2000/NET20DC/default.asp
+
+     This is a small blue plastic connector with two USB connections;
+     it draws power from its USB connections.
+
+  c) You need a second client/console system with a high speed USB 2.0 port.
+
+  d) The NetChip device must be plugged directly into the physical
+     debug port on the "host/target" system. You cannot use a USB hub in
+     between the physical debug port and the "host/target" system.
+
+     The EHCI debug controller is bound to a specific physical USB
+     port and the NetChip device will only work as an early printk
+     device in this port.  The EHCI host controllers are electrically
+     wired such that the EHCI debug controller is hooked up to the
+     first physical port and there is no way to change this via software.
+     You can find the physical port through experimentation by trying
+     each physical port on the system and rebooting.  Or you can try
+     and use lsusb or look at the kernel info messages emitted by the
+     usb stack when you plug a usb device into various ports on the
+     "host/target" system.
+
+     Some hardware vendors do not expose the usb debug port with a
+     physical connector and if you find such a device send a complaint
+     to the hardware vendor, because there is no reason not to wire
+     this port into one of the physically accessible ports.
+
+  e) It is also important to note, that many versions of the NetChip
+     device require the "client/console" system to be plugged into the
+     right hand side of the device (with the product logo facing up and
+     readable left to right).  The reason being is that the 5 volt
+     power supply is taken from only one side of the device and it
+     must be the side that does not get rebooted.
+
+Software requirements
+=====================
+
+  a) On the host/target system:
+
+    You need to enable the following kernel config option::
+
+      CONFIG_EARLY_PRINTK_DBGP=y
+
+    And you need to add the boot command line: "earlyprintk=dbgp".
+
+    .. note::
+      If you are using Grub, append it to the 'kernel' line in
+      /etc/grub.conf.  If you are using Grub2 on a BIOS firmware system,
+      append it to the 'linux' line in /boot/grub2/grub.cfg. If you are
+      using Grub2 on an EFI firmware system, append it to the 'linux'
+      or 'linuxefi' line in /boot/grub2/grub.cfg or
+      /boot/efi/EFI/<distro>/grub.cfg.
+
+    On systems with more than one EHCI debug controller you must
+    specify the correct EHCI debug controller number.  The ordering
+    comes from the PCI bus enumeration of the EHCI controllers.  The
+    default with no number argument is "0" or the first EHCI debug
+    controller.  To use the second EHCI debug controller, you would
+    use the command line: "earlyprintk=dbgp1"
+
+    .. note::
+      normally earlyprintk console gets turned off once the
+      regular console is alive - use "earlyprintk=dbgp,keep" to keep
+      this channel open beyond early bootup. This can be useful for
+      debugging crashes under Xorg, etc.
+
+  b) On the client/console system:
+
+    You should enable the following kernel config option::
+
+      CONFIG_USB_SERIAL_DEBUG=y
+
+    On the next bootup with the modified kernel you should
+    get a /dev/ttyUSBx device(s).
+
+    Now this channel of kernel messages is ready to be used: start
+    your favorite terminal emulator (minicom, etc.) and set
+    it up to use /dev/ttyUSB0 - or use a raw 'cat /dev/ttyUSBx' to
+    see the raw output.
+
+  c) On Nvidia Southbridge based systems: the kernel will try to probe
+     and find out which port has a debug device connected.
+
+Testing
+=======
+
+You can test the output by using earlyprintk=dbgp,keep and provoking
+kernel messages on the host/target system. You can provoke a harmless
+kernel message by for example doing::
+
+     echo h > /proc/sysrq-trigger
+
+On the host/target system you should see this help line in "dmesg" output::
+
+     SysRq : HELP : loglevel(0-9) reBoot Crashdump terminate-all-tasks(E) memory-full-oom-kill(F) kill-all-tasks(I) saK show-backtrace-all-active-cpus(L) show-memory-usage(M) nice-all-RT-tasks(N) powerOff show-registers(P) show-all-timers(Q) unRaw Sync show-task-states(T) Unmount show-blocked-tasks(W) dump-ftrace-buffer(Z)
+
+On the client/console system do::
+
+       cat /dev/ttyUSB0
+
+And you should see the help line above displayed shortly after you've
+provoked it on the host system.
+
+If it does not work then please ask about it on the linux-kernel@vger.kernel.org
+mailing list or contact the x86 maintainers.
diff --git a/Documentation/arch/x86/elf_auxvec.rst b/Documentation/arch/x86/elf_auxvec.rst
new file mode 100644 (file)
index 0000000..18e4744
--- /dev/null
@@ -0,0 +1,53 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==================================
+x86-specific ELF Auxiliary Vectors
+==================================
+
+This document describes the semantics of the x86 auxiliary vectors.
+
+Introduction
+============
+
+ELF Auxiliary vectors enable the kernel to efficiently provide
+configuration-specific parameters to userspace. In this example, a program
+allocates an alternate stack based on the kernel-provided size::
+
+   #include <sys/auxv.h>
+   #include <elf.h>
+   #include <signal.h>
+   #include <stdlib.h>
+   #include <assert.h>
+   #include <err.h>
+
+   #ifndef AT_MINSIGSTKSZ
+   #define AT_MINSIGSTKSZ      51
+   #endif
+
+   ....
+   stack_t ss;
+
+   ss.ss_sp = malloc(ss.ss_size);
+   assert(ss.ss_sp);
+
+   ss.ss_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ;
+   ss.ss_flags = 0;
+
+   if (sigaltstack(&ss, NULL))
+        err(1, "sigaltstack");
+
+
+The exposed auxiliary vectors
+=============================
+
+AT_SYSINFO is used for locating the vsyscall entry point.  It is not
+exported on 64-bit mode.
+
+AT_SYSINFO_EHDR is the start address of the page containing the vDSO.
+
+AT_MINSIGSTKSZ denotes the minimum stack size required by the kernel to
+deliver a signal to user-space.  AT_MINSIGSTKSZ comprehends the space
+consumed by the kernel to accommodate the user context for the current
+hardware configuration.  It does not comprehend subsequent user-space stack
+consumption, which must be added by the user.  (e.g. Above, user-space adds
+SIGSTKSZ to AT_MINSIGSTKSZ.)
diff --git a/Documentation/arch/x86/entry_64.rst b/Documentation/arch/x86/entry_64.rst
new file mode 100644 (file)
index 0000000..0afdce3
--- /dev/null
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============
+Kernel Entries
+==============
+
+This file documents some of the kernel entries in
+arch/x86/entry/entry_64.S.  A lot of this explanation is adapted from
+an email from Ingo Molnar:
+
+https://lore.kernel.org/r/20110529191055.GC9835%40elte.hu
+
+The x86 architecture has quite a few different ways to jump into
+kernel code.  Most of these entry points are registered in
+arch/x86/kernel/traps.c and implemented in arch/x86/entry/entry_64.S
+for 64-bit, arch/x86/entry/entry_32.S for 32-bit and finally
+arch/x86/entry/entry_64_compat.S which implements the 32-bit compatibility
+syscall entry points and thus provides for 32-bit processes the
+ability to execute syscalls when running on 64-bit kernels.
+
+The IDT vector assignments are listed in arch/x86/include/asm/irq_vectors.h.
+
+Some of these entries are:
+
+ - system_call: syscall instruction from 64-bit code.
+
+ - entry_INT80_compat: int 0x80 from 32-bit or 64-bit code; compat syscall
+   either way.
+
+ - entry_INT80_compat, ia32_sysenter: syscall and sysenter from 32-bit
+   code
+
+ - interrupt: An array of entries.  Every IDT vector that doesn't
+   explicitly point somewhere else gets set to the corresponding
+   value in interrupts.  These point to a whole array of
+   magically-generated functions that make their way to common_interrupt()
+   with the interrupt number as a parameter.
+
+ - APIC interrupts: Various special-purpose interrupts for things
+   like TLB shootdown.
+
+ - Architecturally-defined exceptions like divide_error.
+
+There are a few complexities here.  The different x86-64 entries
+have different calling conventions.  The syscall and sysenter
+instructions have their own peculiar calling conventions.  Some of
+the IDT entries push an error code onto the stack; others don't.
+IDT entries using the IST alternative stack mechanism need their own
+magic to get the stack frames right.  (You can find some
+documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM,
+Volume 3, Chapter 6.)
+
+Dealing with the swapgs instruction is especially tricky.  Swapgs
+toggles whether gs is the kernel gs or the user gs.  The swapgs
+instruction is rather fragile: it must nest perfectly and only in
+single depth, it should only be used if entering from user mode to
+kernel mode and then when returning to user-space, and precisely
+so. If we mess that up even slightly, we crash.
+
+So when we have a secondary entry, already in kernel mode, we *must
+not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's
+not switched/swapped yet.
+
+Now, there's a secondary complication: there's a cheap way to test
+which mode the CPU is in and an expensive way.
+
+The cheap way is to pick this info off the entry frame on the kernel
+stack, from the CS of the ptregs area of the kernel stack::
+
+       xorl %ebx,%ebx
+       testl $3,CS+8(%rsp)
+       je error_kernelspace
+       SWAPGS
+
+The expensive (paranoid) way is to read back the MSR_GS_BASE value
+(which is what SWAPGS modifies)::
+
+       movl $1,%ebx
+       movl $MSR_GS_BASE,%ecx
+       rdmsr
+       testl %edx,%edx
+       js 1f   /* negative -> in kernel */
+       SWAPGS
+       xorl %ebx,%ebx
+  1:   ret
+
+If we are at an interrupt or user-trap/gate-alike boundary then we can
+use the faster check: the stack will be a reliable indicator of
+whether SWAPGS was already done: if we see that we are a secondary
+entry interrupting kernel mode execution, then we know that the GS
+base has already been switched. If it says that we interrupted
+user-space execution then we must do the SWAPGS.
+
+But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context,
+which might have triggered right after a normal entry wrote CS to the
+stack but before we executed SWAPGS, then the only safe way to check
+for GS is the slower method: the RDMSR.
+
+Therefore, super-atomic entries (except NMI, which is handled separately)
+must use idtentry with paranoid=1 to handle gsbase correctly.  This
+triggers three main behavior changes:
+
+ - Interrupt entry will use the slower gsbase check.
+ - Interrupt entry from user mode will switch off the IST stack.
+ - Interrupt exit to kernel mode will not attempt to reschedule.
+
+We try to only use IST entries and the paranoid entry code for vectors
+that absolutely need the more expensive check for the GS base - and we
+generate all 'normal' entry points with the regular (faster) paranoid=0
+variant.
diff --git a/Documentation/arch/x86/exception-tables.rst b/Documentation/arch/x86/exception-tables.rst
new file mode 100644 (file)
index 0000000..efde1fe
--- /dev/null
@@ -0,0 +1,357 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================
+Kernel level exception handling
+===============================
+
+Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>
+
+When a process runs in kernel mode, it often has to access user
+mode memory whose address has been passed by an untrusted program.
+To protect itself the kernel has to verify this address.
+
+In older versions of Linux this was done with the
+int verify_area(int type, const void * addr, unsigned long size)
+function (which has since been replaced by access_ok()).
+
+This function verified that the memory area starting at address
+'addr' and of size 'size' was accessible for the operation specified
+in type (read or write). To do this, verify_read had to look up the
+virtual memory area (vma) that contained the address addr. In the
+normal case (correctly working program), this test was successful.
+It only failed for a few buggy programs. In some kernel profiling
+tests, this normally unneeded verification used up a considerable
+amount of time.
+
+To overcome this situation, Linus decided to let the virtual memory
+hardware present in every Linux-capable CPU handle this test.
+
+How does this work?
+
+Whenever the kernel tries to access an address that is currently not
+accessible, the CPU generates a page fault exception and calls the
+page fault handler::
+
+  void exc_page_fault(struct pt_regs *regs, unsigned long error_code)
+
+in arch/x86/mm/fault.c. The parameters on the stack are set up by
+the low level assembly glue in arch/x86/entry/entry_32.S. The parameter
+regs is a pointer to the saved registers on the stack, error_code
+contains a reason code for the exception.
+
+exc_page_fault() first obtains the inaccessible address from the CPU
+control register CR2. If the address is within the virtual address
+space of the process, the fault probably occurred, because the page
+was not swapped in, write protected or something similar. However,
+we are interested in the other case: the address is not valid, there
+is no vma that contains this address. In this case, the kernel jumps
+to the bad_area label.
+
+There it uses the address of the instruction that caused the exception
+(i.e. regs->eip) to find an address where the execution can continue
+(fixup). If this search is successful, the fault handler modifies the
+return address (again regs->eip) and returns. The execution will
+continue at the address in fixup.
+
+Where does fixup point to?
+
+Since we jump to the contents of fixup, fixup obviously points
+to executable code. This code is hidden inside the user access macros.
+I have picked the get_user() macro defined in arch/x86/include/asm/uaccess.h
+as an example. The definition is somewhat hard to follow, so let's peek at
+the code generated by the preprocessor and the compiler. I selected
+the get_user() call in drivers/char/sysrq.c for a detailed examination.
+
+The original code in sysrq.c line 587::
+
+        get_user(c, buf);
+
+The preprocessor output (edited to become somewhat readable)::
+
+  (
+    {
+      long __gu_err = - 14 , __gu_val = 0;
+      const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));
+      if (((((0 + current_set[0])->tss.segment) == 0x18 )  ||
+        (((sizeof(*(buf))) <= 0xC0000000UL) &&
+        ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
+        do {
+          __gu_err  = 0;
+          switch ((sizeof(*(buf)))) {
+            case 1:
+              __asm__ __volatile__(
+                "1:      mov" "b" " %2,%" "b" "1\n"
+                "2:\n"
+                ".section .fixup,\"ax\"\n"
+                "3:      movl %3,%0\n"
+                "        xor" "b" " %" "b" "1,%" "b" "1\n"
+                "        jmp 2b\n"
+                ".section __ex_table,\"a\"\n"
+                "        .align 4\n"
+                "        .long 1b,3b\n"
+                ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
+                              (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ;
+                break;
+            case 2:
+              __asm__ __volatile__(
+                "1:      mov" "w" " %2,%" "w" "1\n"
+                "2:\n"
+                ".section .fixup,\"ax\"\n"
+                "3:      movl %3,%0\n"
+                "        xor" "w" " %" "w" "1,%" "w" "1\n"
+                "        jmp 2b\n"
+                ".section __ex_table,\"a\"\n"
+                "        .align 4\n"
+                "        .long 1b,3b\n"
+                ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
+                              (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  ));
+                break;
+            case 4:
+              __asm__ __volatile__(
+                "1:      mov" "l" " %2,%" "" "1\n"
+                "2:\n"
+                ".section .fixup,\"ax\"\n"
+                "3:      movl %3,%0\n"
+                "        xor" "l" " %" "" "1,%" "" "1\n"
+                "        jmp 2b\n"
+                ".section __ex_table,\"a\"\n"
+                "        .align 4\n"        "        .long 1b,3b\n"
+                ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
+                              (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err));
+                break;
+            default:
+              (__gu_val) = __get_user_bad();
+          }
+        } while (0) ;
+      ((c)) = (__typeof__(*((buf))))__gu_val;
+      __gu_err;
+    }
+  );
+
+WOW! Black GCC/assembly magic. This is impossible to follow, so let's
+see what code gcc generates::
+
+ >         xorl %edx,%edx
+ >         movl current_set,%eax
+ >         cmpl $24,788(%eax)
+ >         je .L1424
+ >         cmpl $-1073741825,64(%esp)
+ >         ja .L1423
+ > .L1424:
+ >         movl %edx,%eax
+ >         movl 64(%esp),%ebx
+ > #APP
+ > 1:      movb (%ebx),%dl                /* this is the actual user access */
+ > 2:
+ > .section .fixup,"ax"
+ > 3:      movl $-14,%eax
+ >         xorb %dl,%dl
+ >         jmp 2b
+ > .section __ex_table,"a"
+ >         .align 4
+ >         .long 1b,3b
+ > .text
+ > #NO_APP
+ > .L1423:
+ >         movzbl %dl,%esi
+
+The optimizer does a good job and gives us something we can actually
+understand. Can we? The actual user access is quite obvious. Thanks
+to the unified address space we can just access the address in user
+memory. But what does the .section stuff do?????
+
+To understand this we have to look at the final kernel::
+
+ > objdump --section-headers vmlinux
+ >
+ > vmlinux:     file format elf32-i386
+ >
+ > Sections:
+ > Idx Name          Size      VMA       LMA       File off  Algn
+ >   0 .text         00098f40  c0100000  c0100000  00001000  2**4
+ >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
+ >   1 .fixup        000016bc  c0198f40  c0198f40  00099f40  2**0
+ >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
+ >   2 .rodata       0000f127  c019a5fc  c019a5fc  0009b5fc  2**2
+ >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
+ >   3 __ex_table    000015c0  c01a9724  c01a9724  000aa724  2**2
+ >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
+ >   4 .data         0000ea58  c01abcf0  c01abcf0  000abcf0  2**4
+ >                   CONTENTS, ALLOC, LOAD, DATA
+ >   5 .bss          00018e21  c01ba748  c01ba748  000ba748  2**2
+ >                   ALLOC
+ >   6 .comment      00000ec4  00000000  00000000  000ba748  2**0
+ >                   CONTENTS, READONLY
+ >   7 .note         00001068  00000ec4  00000ec4  000bb60c  2**0
+ >                   CONTENTS, READONLY
+
+There are obviously 2 non standard ELF sections in the generated object
+file. But first we want to find out what happened to our code in the
+final kernel executable::
+
+ > objdump --disassemble --section=.text vmlinux
+ >
+ > c017e785 <do_con_write+c1> xorl   %edx,%edx
+ > c017e787 <do_con_write+c3> movl   0xc01c7bec,%eax
+ > c017e78c <do_con_write+c8> cmpl   $0x18,0x314(%eax)
+ > c017e793 <do_con_write+cf> je     c017e79f <do_con_write+db>
+ > c017e795 <do_con_write+d1> cmpl   $0xbfffffff,0x40(%esp,1)
+ > c017e79d <do_con_write+d9> ja     c017e7a7 <do_con_write+e3>
+ > c017e79f <do_con_write+db> movl   %edx,%eax
+ > c017e7a1 <do_con_write+dd> movl   0x40(%esp,1),%ebx
+ > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
+ > c017e7a7 <do_con_write+e3> movzbl %dl,%esi
+
+The whole user memory access is reduced to 10 x86 machine instructions.
+The instructions bracketed in the .section directives are no longer
+in the normal execution path. They are located in a different section
+of the executable file::
+
+ > objdump --disassemble --section=.fixup vmlinux
+ >
+ > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
+ > c0199ffa <.fixup+10ba> xorb   %dl,%dl
+ > c0199ffc <.fixup+10bc> jmp    c017e7a7 <do_con_write+e3>
+
+And finally::
+
+ > objdump --full-contents --section=__ex_table vmlinux
+ >
+ >  c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0  ................
+ >  c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0  ................
+ >  c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0  ................
+
+or in human readable byte order::
+
+ >  c01aa7c4 c017c093 c0199fe0 c017c097 c017c099  ................
+ >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
+                               ^^^^^^^^^^^^^^^^^
+                               this is the interesting part!
+ >  c01aa7e4 c0180a08 c019a001 c0180a0a c019a004  ................
+
+What happened? The assembly directives::
+
+  .section .fixup,"ax"
+  .section __ex_table,"a"
+
+told the assembler to move the following code to the specified
+sections in the ELF object file. So the instructions::
+
+  3:      movl $-14,%eax
+          xorb %dl,%dl
+          jmp 2b
+
+ended up in the .fixup section of the object file and the addresses::
+
+        .long 1b,3b
+
+ended up in the __ex_table section of the object file. 1b and 3b
+are local labels. The local label 1b (1b stands for next label 1
+backward) is the address of the instruction that might fault, i.e.
+in our case the address of the label 1 is c017e7a5:
+the original assembly code: > 1:      movb (%ebx),%dl
+and linked in vmlinux     : > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
+
+The local label 3 (backwards again) is the address of the code to handle
+the fault, in our case the actual value is c0199ff5:
+the original assembly code: > 3:      movl $-14,%eax
+and linked in vmlinux     : > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
+
+If the fixup was able to handle the exception, control flow may be returned
+to the instruction after the one that triggered the fault, ie. local label 2b.
+
+The assembly code::
+
+ > .section __ex_table,"a"
+ >         .align 4
+ >         .long 1b,3b
+
+becomes the value pair::
+
+ >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
+                               ^this is ^this is
+                               1b       3b
+
+c017e7a5,c0199ff5 in the exception table of the kernel.
+
+So, what actually happens if a fault from kernel mode with no suitable
+vma occurs?
+
+#. access to invalid address::
+
+    > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
+#. MMU generates exception
+#. CPU calls exc_page_fault()
+#. exc_page_fault() calls do_user_addr_fault()
+#. do_user_addr_fault() calls kernelmode_fixup_or_oops()
+#. kernelmode_fixup_or_oops() calls fixup_exception() (regs->eip == c017e7a5);
+#. fixup_exception() calls search_exception_tables()
+#. search_exception_tables() looks up the address c017e7a5 in the
+   exception table (i.e. the contents of the ELF section __ex_table)
+   and returns the address of the associated fault handle code c0199ff5.
+#. fixup_exception() modifies its own return address to point to the fault
+   handle code and returns.
+#. execution continues in the fault handling code.
+#. a) EAX becomes -EFAULT (== -14)
+   b) DL  becomes zero (the value we "read" from user space)
+   c) execution continues at local label 2 (address of the
+      instruction immediately after the faulting user access).
+
+The steps 8a to 8c in a certain way emulate the faulting instruction.
+
+That's it, mostly. If you look at our example, you might ask why
+we set EAX to -EFAULT in the exception handler code. Well, the
+get_user() macro actually returns a value: 0, if the user access was
+successful, -EFAULT on failure. Our original code did not test this
+return value, however the inline assembly code in get_user() tries to
+return -EFAULT. GCC selected EAX to return this value.
+
+NOTE:
+Due to the way that the exception table is built and needs to be ordered,
+only use exceptions for code in the .text section.  Any other section
+will cause the exception table to not be sorted correctly, and the
+exceptions will fail.
+
+Things changed when 64-bit support was added to x86 Linux. Rather than
+double the size of the exception table by expanding the two entries
+from 32-bits to 64 bits, a clever trick was used to store addresses
+as relative offsets from the table itself. The assembly code changed
+from::
+
+    .long 1b,3b
+  to:
+          .long (from) - .
+          .long (to) - .
+
+and the C-code that uses these values converts back to absolute addresses
+like this::
+
+       ex_insn_addr(const struct exception_table_entry *x)
+       {
+               return (unsigned long)&x->insn + x->insn;
+       }
+
+In v4.6 the exception table entry was expanded with a new field "handler".
+This is also 32-bits wide and contains a third relative function
+pointer which points to one of:
+
+1) ``int ex_handler_default(const struct exception_table_entry *fixup)``
+     This is legacy case that just jumps to the fixup code
+
+2) ``int ex_handler_fault(const struct exception_table_entry *fixup)``
+     This case provides the fault number of the trap that occurred at
+     entry->insn. It is used to distinguish page faults from machine
+     check.
+
+More functions can easily be added.
+
+CONFIG_BUILDTIME_TABLE_SORT allows the __ex_table section to be sorted post
+link of the kernel image, via a host utility scripts/sorttable. It will set the
+symbol main_extable_sort_needed to 0, avoiding sorting the __ex_table section
+at boot time. With the exception table sorted, at runtime when an exception
+occurs we can quickly lookup the __ex_table entry via binary search.
+
+This is not just a boot time optimization, some architectures require this
+table to be sorted in order to handle exceptions relatively early in the boot
+process. For example, i386 makes use of this form of exception handling before
+paging support is even enabled!
diff --git a/Documentation/arch/x86/features.rst b/Documentation/arch/x86/features.rst
new file mode 100644 (file)
index 0000000..b663f15
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features x86
diff --git a/Documentation/arch/x86/i386/IO-APIC.rst b/Documentation/arch/x86/i386/IO-APIC.rst
new file mode 100644 (file)
index 0000000..ce4d8df
--- /dev/null
@@ -0,0 +1,123 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+IO-APIC
+=======
+
+:Author: Ingo Molnar <mingo@kernel.org>
+
+Most (all) Intel-MP compliant SMP boards have the so-called 'IO-APIC',
+which is an enhanced interrupt controller. It enables us to route
+hardware interrupts to multiple CPUs, or to CPU groups. Without an
+IO-APIC, interrupts from hardware will be delivered only to the
+CPU which boots the operating system (usually CPU#0).
+
+Linux supports all variants of compliant SMP boards, including ones with
+multiple IO-APICs. Multiple IO-APICs are used in high-end servers to
+distribute IRQ load further.
+
+There are (a few) known breakages in certain older boards, such bugs are
+usually worked around by the kernel. If your MP-compliant SMP board does
+not boot Linux, then consult the linux-smp mailing list archives first.
+
+If your box boots fine with enabled IO-APIC IRQs, then your
+/proc/interrupts will look like this one::
+
+  hell:~> cat /proc/interrupts
+             CPU0
+    0:    1360293    IO-APIC-edge  timer
+    1:          4    IO-APIC-edge  keyboard
+    2:          0          XT-PIC  cascade
+   13:          1          XT-PIC  fpu
+   14:       1448    IO-APIC-edge  ide0
+   16:      28232   IO-APIC-level  Intel EtherExpress Pro 10/100 Ethernet
+   17:      51304   IO-APIC-level  eth0
+  NMI:          0
+  ERR:          0
+  hell:~>
+
+Some interrupts are still listed as 'XT PIC', but this is not a problem;
+none of those IRQ sources is performance-critical.
+
+
+In the unlikely case that your board does not create a working mp-table,
+you can use the pirq= boot parameter to 'hand-construct' IRQ entries. This
+is non-trivial though and cannot be automated. One sample /etc/lilo.conf
+entry::
+
+       append="pirq=15,11,10"
+
+The actual numbers depend on your system, on your PCI cards and on their
+PCI slot position. Usually PCI slots are 'daisy chained' before they are
+connected to the PCI chipset IRQ routing facility (the incoming PIRQ1-4
+lines)::
+
+               ,-.        ,-.        ,-.        ,-.        ,-.
+     PIRQ4 ----| |-.    ,-| |-.    ,-| |-.    ,-| |--------| |
+               |S|  \  /  |S|  \  /  |S|  \  /  |S|        |S|
+     PIRQ3 ----|l|-. `/---|l|-. `/---|l|-. `/---|l|--------|l|
+               |o|  \/    |o|  \/    |o|  \/    |o|        |o|
+     PIRQ2 ----|t|-./`----|t|-./`----|t|-./`----|t|--------|t|
+               |1| /\     |2| /\     |3| /\     |4|        |5|
+     PIRQ1 ----| |-  `----| |-  `----| |-  `----| |--------| |
+               `-'        `-'        `-'        `-'        `-'
+
+Every PCI card emits a PCI IRQ, which can be INTA, INTB, INTC or INTD::
+
+                               ,-.
+                         INTD--| |
+                               |S|
+                         INTC--|l|
+                               |o|
+                         INTB--|t|
+                               |x|
+                         INTA--| |
+                               `-'
+
+These INTA-D PCI IRQs are always 'local to the card', their real meaning
+depends on which slot they are in. If you look at the daisy chaining diagram,
+a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ4 of
+the PCI chipset. Most cards issue INTA, this creates optimal distribution
+between the PIRQ lines. (distributing IRQ sources properly is not a
+necessity, PCI IRQs can be shared at will, but it's a good for performance
+to have non shared interrupts). Slot5 should be used for videocards, they
+do not use interrupts normally, thus they are not daisy chained either.
+
+so if you have your SCSI card (IRQ11) in Slot1, Tulip card (IRQ9) in
+Slot2, then you'll have to specify this pirq= line::
+
+       append="pirq=11,9"
+
+the following script tries to figure out such a default pirq= line from
+your PCI configuration::
+
+       echo -n pirq=; echo `scanpci | grep T_L | cut -c56-` | sed 's/ /,/g'
+
+note that this script won't work if you have skipped a few slots or if your
+board does not do default daisy-chaining. (or the IO-APIC has the PIRQ pins
+connected in some strange way). E.g. if in the above case you have your SCSI
+card (IRQ11) in Slot3, and have Slot1 empty::
+
+       append="pirq=0,9,11"
+
+[value '0' is a generic 'placeholder', reserved for empty (or non-IRQ emitting)
+slots.]
+
+Generally, it's always possible to find out the correct pirq= settings, just
+permute all IRQ numbers properly ... it will take some time though. An
+'incorrect' pirq line will cause the booting process to hang, or a device
+won't function properly (e.g. if it's inserted as a module).
+
+If you have 2 PCI buses, then you can use up to 8 pirq values, although such
+boards tend to have a good configuration.
+
+Be prepared that it might happen that you need some strange pirq line::
+
+       append="pirq=0,0,0,0,0,0,9,11"
+
+Use smart trial-and-error techniques to find out the correct pirq line ...
+
+Good luck and mail to linux-smp@vger.kernel.org or
+linux-kernel@vger.kernel.org if you have any problems that are not covered
+by this document.
+
diff --git a/Documentation/arch/x86/i386/index.rst b/Documentation/arch/x86/i386/index.rst
new file mode 100644 (file)
index 0000000..8747cf5
--- /dev/null
@@ -0,0 +1,10 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+i386 Support
+============
+
+.. toctree::
+   :maxdepth: 2
+
+   IO-APIC
diff --git a/Documentation/arch/x86/ifs.rst b/Documentation/arch/x86/ifs.rst
new file mode 100644 (file)
index 0000000..97abb69
--- /dev/null
@@ -0,0 +1,2 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. kernel-doc:: drivers/platform/x86/intel/ifs/ifs.h
diff --git a/Documentation/arch/x86/index.rst b/Documentation/arch/x86/index.rst
new file mode 100644 (file)
index 0000000..c73d133
--- /dev/null
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================
+x86-specific Documentation
+==========================
+
+.. toctree::
+   :maxdepth: 2
+   :numbered:
+
+   boot
+   booting-dt
+   cpuinfo
+   topology
+   exception-tables
+   kernel-stacks
+   entry_64
+   earlyprintk
+   orc-unwinder
+   zero-page
+   tlb
+   mtrr
+   pat
+   intel-hfi
+   iommu
+   intel_txt
+   amd-memory-encryption
+   amd_hsmp
+   tdx
+   pti
+   mds
+   microcode
+   resctrl
+   tsx_async_abort
+   buslock
+   usb-legacy-support
+   i386/index
+   x86_64/index
+   ifs
+   sva
+   sgx
+   features
+   elf_auxvec
+   xstate
diff --git a/Documentation/arch/x86/intel-hfi.rst b/Documentation/arch/x86/intel-hfi.rst
new file mode 100644 (file)
index 0000000..49dea58
--- /dev/null
@@ -0,0 +1,72 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============================================================
+Hardware-Feedback Interface for scheduling on Intel Hardware
+============================================================
+
+Overview
+--------
+
+Intel has described the Hardware Feedback Interface (HFI) in the Intel 64 and
+IA-32 Architectures Software Developer's Manual (Intel SDM) Volume 3 Section
+14.6 [1]_.
+
+The HFI gives the operating system a performance and energy efficiency
+capability data for each CPU in the system. Linux can use the information from
+the HFI to influence task placement decisions.
+
+The Hardware Feedback Interface
+-------------------------------
+
+The Hardware Feedback Interface provides to the operating system information
+about the performance and energy efficiency of each CPU in the system. Each
+capability is given as a unit-less quantity in the range [0-255]. Higher values
+indicate higher capability. Energy efficiency and performance are reported in
+separate capabilities. Even though on some systems these two metrics may be
+related, they are specified as independent capabilities in the Intel SDM.
+
+These capabilities may change at runtime as a result of changes in the
+operating conditions of the system or the action of external factors. The rate
+at which these capabilities are updated is specific to each processor model. On
+some models, capabilities are set at boot time and never change. On others,
+capabilities may change every tens of milliseconds. For instance, a remote
+mechanism may be used to lower Thermal Design Power. Such change can be
+reflected in the HFI. Likewise, if the system needs to be throttled due to
+excessive heat, the HFI may reflect reduced performance on specific CPUs.
+
+The kernel or a userspace policy daemon can use these capabilities to modify
+task placement decisions. For instance, if either the performance or energy
+capabilities of a given logical processor becomes zero, it is an indication that
+the hardware recommends to the operating system to not schedule any tasks on
+that processor for performance or energy efficiency reasons, respectively.
+
+Implementation details for Linux
+--------------------------------
+
+The infrastructure to handle thermal event interrupts has two parts. In the
+Local Vector Table of a CPU's local APIC, there exists a register for the
+Thermal Monitor Register. This register controls how interrupts are delivered
+to a CPU when the thermal monitor generates and interrupt. Further details
+can be found in the Intel SDM Vol. 3 Section 10.5 [1]_.
+
+The thermal monitor may generate interrupts per CPU or per package. The HFI
+generates package-level interrupts. This monitor is configured and initialized
+via a set of machine-specific registers. Specifically, the HFI interrupt and
+status are controlled via designated bits in the IA32_PACKAGE_THERM_INTERRUPT
+and IA32_PACKAGE_THERM_STATUS registers, respectively. There exists one HFI
+table per package. Further details can be found in the Intel SDM Vol. 3
+Section 14.9 [1]_.
+
+The hardware issues an HFI interrupt after updating the HFI table and is ready
+for the operating system to consume it. CPUs receive such interrupt via the
+thermal entry in the Local APIC's Local Vector Table.
+
+When servicing such interrupt, the HFI driver parses the updated table and
+relays the update to userspace using the thermal notification framework. Given
+that there may be many HFI updates every second, the updates relayed to
+userspace are throttled at a rate of CONFIG_HZ jiffies.
+
+References
+----------
+
+.. [1] https://www.intel.com/sdm
diff --git a/Documentation/arch/x86/intel_txt.rst b/Documentation/arch/x86/intel_txt.rst
new file mode 100644 (file)
index 0000000..d83c1a2
--- /dev/null
@@ -0,0 +1,227 @@
+=====================
+Intel(R) TXT Overview
+=====================
+
+Intel's technology for safer computing, Intel(R) Trusted Execution
+Technology (Intel(R) TXT), defines platform-level enhancements that
+provide the building blocks for creating trusted platforms.
+
+Intel TXT was formerly known by the code name LaGrande Technology (LT).
+
+Intel TXT in Brief:
+
+-  Provides dynamic root of trust for measurement (DRTM)
+-  Data protection in case of improper shutdown
+-  Measurement and verification of launched environment
+
+Intel TXT is part of the vPro(TM) brand and is also available some
+non-vPro systems.  It is currently available on desktop systems
+based on the Q35, X38, Q45, and Q43 Express chipsets (e.g. Dell
+Optiplex 755, HP dc7800, etc.) and mobile systems based on the GM45,
+PM45, and GS45 Express chipsets.
+
+For more information, see http://www.intel.com/technology/security/.
+This site also has a link to the Intel TXT MLE Developers Manual,
+which has been updated for the new released platforms.
+
+Intel TXT has been presented at various events over the past few
+years, some of which are:
+
+      - LinuxTAG 2008:
+          http://www.linuxtag.org/2008/en/conf/events/vp-donnerstag.html
+
+      - TRUST2008:
+          http://www.trust-conference.eu/downloads/Keynote-Speakers/
+          3_David-Grawrock_The-Front-Door-of-Trusted-Computing.pdf
+
+      - IDF, Shanghai:
+          http://www.prcidf.com.cn/index_en.html
+
+      - IDFs 2006, 2007
+         (I'm not sure if/where they are online)
+
+Trusted Boot Project Overview
+=============================
+
+Trusted Boot (tboot) is an open source, pre-kernel/VMM module that
+uses Intel TXT to perform a measured and verified launch of an OS
+kernel/VMM.
+
+It is hosted on SourceForge at http://sourceforge.net/projects/tboot.
+The mercurial source repo is available at http://www.bughost.org/
+repos.hg/tboot.hg.
+
+Tboot currently supports launching Xen (open source VMM/hypervisor
+w/ TXT support since v3.2), and now Linux kernels.
+
+
+Value Proposition for Linux or "Why should you care?"
+=====================================================
+
+While there are many products and technologies that attempt to
+measure or protect the integrity of a running kernel, they all
+assume the kernel is "good" to begin with.  The Integrity
+Measurement Architecture (IMA) and Linux Integrity Module interface
+are examples of such solutions.
+
+To get trust in the initial kernel without using Intel TXT, a
+static root of trust must be used.  This bases trust in BIOS
+starting at system reset and requires measurement of all code
+executed between system reset through the completion of the kernel
+boot as well as data objects used by that code.  In the case of a
+Linux kernel, this means all of BIOS, any option ROMs, the
+bootloader and the boot config.  In practice, this is a lot of
+code/data, much of which is subject to change from boot to boot
+(e.g. changing NICs may change option ROMs).  Without reference
+hashes, these measurement changes are difficult to assess or
+confirm as benign.  This process also does not provide DMA
+protection, memory configuration/alias checks and locks, crash
+protection, or policy support.
+
+By using the hardware-based root of trust that Intel TXT provides,
+many of these issues can be mitigated.  Specifically: many
+pre-launch components can be removed from the trust chain, DMA
+protection is provided to all launched components, a large number
+of platform configuration checks are performed and values locked,
+protection is provided for any data in the event of an improper
+shutdown, and there is support for policy-based execution/verification.
+This provides a more stable measurement and a higher assurance of
+system configuration and initial state than would be otherwise
+possible.  Since the tboot project is open source, source code for
+almost all parts of the trust chain is available (excepting SMM and
+Intel-provided firmware).
+
+How Does it Work?
+=================
+
+-  Tboot is an executable that is launched by the bootloader as
+   the "kernel" (the binary the bootloader executes).
+-  It performs all of the work necessary to determine if the
+   platform supports Intel TXT and, if so, executes the GETSEC[SENTER]
+   processor instruction that initiates the dynamic root of trust.
+
+   -  If tboot determines that the system does not support Intel TXT
+      or is not configured correctly (e.g. the SINIT AC Module was
+      incorrect), it will directly launch the kernel with no changes
+      to any state.
+   -  Tboot will output various information about its progress to the
+      terminal, serial port, and/or an in-memory log; the output
+      locations can be configured with a command line switch.
+
+-  The GETSEC[SENTER] instruction will return control to tboot and
+   tboot then verifies certain aspects of the environment (e.g. TPM NV
+   lock, e820 table does not have invalid entries, etc.).
+-  It will wake the APs from the special sleep state the GETSEC[SENTER]
+   instruction had put them in and place them into a wait-for-SIPI
+   state.
+
+   -  Because the processors will not respond to an INIT or SIPI when
+      in the TXT environment, it is necessary to create a small VT-x
+      guest for the APs.  When they run in this guest, they will
+      simply wait for the INIT-SIPI-SIPI sequence, which will cause
+      VMEXITs, and then disable VT and jump to the SIPI vector.  This
+      approach seemed like a better choice than having to insert
+      special code into the kernel's MP wakeup sequence.
+
+-  Tboot then applies an (optional) user-defined launch policy to
+   verify the kernel and initrd.
+
+   -  This policy is rooted in TPM NV and is described in the tboot
+      project.  The tboot project also contains code for tools to
+      create and provision the policy.
+   -  Policies are completely under user control and if not present
+      then any kernel will be launched.
+   -  Policy action is flexible and can include halting on failures
+      or simply logging them and continuing.
+
+-  Tboot adjusts the e820 table provided by the bootloader to reserve
+   its own location in memory as well as to reserve certain other
+   TXT-related regions.
+-  As part of its launch, tboot DMA protects all of RAM (using the
+   VT-d PMRs).  Thus, the kernel must be booted with 'intel_iommu=on'
+   in order to remove this blanket protection and use VT-d's
+   page-level protection.
+-  Tboot will populate a shared page with some data about itself and
+   pass this to the Linux kernel as it transfers control.
+
+   -  The location of the shared page is passed via the boot_params
+      struct as a physical address.
+
+-  The kernel will look for the tboot shared page address and, if it
+   exists, map it.
+-  As one of the checks/protections provided by TXT, it makes a copy
+   of the VT-d DMARs in a DMA-protected region of memory and verifies
+   them for correctness.  The VT-d code will detect if the kernel was
+   launched with tboot and use this copy instead of the one in the
+   ACPI table.
+-  At this point, tboot and TXT are out of the picture until a
+   shutdown (S<n>)
+-  In order to put a system into any of the sleep states after a TXT
+   launch, TXT must first be exited.  This is to prevent attacks that
+   attempt to crash the system to gain control on reboot and steal
+   data left in memory.
+
+   -  The kernel will perform all of its sleep preparation and
+      populate the shared page with the ACPI data needed to put the
+      platform in the desired sleep state.
+   -  Then the kernel jumps into tboot via the vector specified in the
+      shared page.
+   -  Tboot will clean up the environment and disable TXT, then use the
+      kernel-provided ACPI information to actually place the platform
+      into the desired sleep state.
+   -  In the case of S3, tboot will also register itself as the resume
+      vector.  This is necessary because it must re-establish the
+      measured environment upon resume.  Once the TXT environment
+      has been restored, it will restore the TPM PCRs and then
+      transfer control back to the kernel's S3 resume vector.
+      In order to preserve system integrity across S3, the kernel
+      provides tboot with a set of memory ranges (RAM and RESERVED_KERN
+      in the e820 table, but not any memory that BIOS might alter over
+      the S3 transition) that tboot will calculate a MAC (message
+      authentication code) over and then seal with the TPM. On resume
+      and once the measured environment has been re-established, tboot
+      will re-calculate the MAC and verify it against the sealed value.
+      Tboot's policy determines what happens if the verification fails.
+      Note that the c/s 194 of tboot which has the new MAC code supports
+      this.
+
+That's pretty much it for TXT support.
+
+
+Configuring the System
+======================
+
+This code works with 32bit, 32bit PAE, and 64bit (x86_64) kernels.
+
+In BIOS, the user must enable:  TPM, TXT, VT-x, VT-d.  Not all BIOSes
+allow these to be individually enabled/disabled and the screens in
+which to find them are BIOS-specific.
+
+grub.conf needs to be modified as follows::
+
+        title Linux 2.6.29-tip w/ tboot
+          root (hd0,0)
+                kernel /tboot.gz logging=serial,vga,memory
+                module /vmlinuz-2.6.29-tip intel_iommu=on ro
+                       root=LABEL=/ rhgb console=ttyS0,115200 3
+                module /initrd-2.6.29-tip.img
+                module /Q35_SINIT_17.BIN
+
+The kernel option for enabling Intel TXT support is found under the
+Security top-level menu and is called "Enable Intel(R) Trusted
+Execution Technology (TXT)".  It is considered EXPERIMENTAL and
+depends on the generic x86 support (to allow maximum flexibility in
+kernel build options), since the tboot code will detect whether the
+platform actually supports Intel TXT and thus whether any of the
+kernel code is executed.
+
+The Q35_SINIT_17.BIN file is what Intel TXT refers to as an
+Authenticated Code Module.  It is specific to the chipset in the
+system and can also be found on the Trusted Boot site.  It is an
+(unencrypted) module signed by Intel that is used as part of the
+DRTM process to verify and configure the system.  It is signed
+because it operates at a higher privilege level in the system than
+any other macrocode and its correct operation is critical to the
+establishment of the DRTM.  The process for determining the correct
+SINIT ACM for a system is documented in the SINIT-guide.txt file
+that is on the tboot SourceForge site under the SINIT ACM downloads.
diff --git a/Documentation/arch/x86/iommu.rst b/Documentation/arch/x86/iommu.rst
new file mode 100644 (file)
index 0000000..42c7a6f
--- /dev/null
@@ -0,0 +1,151 @@
+=================
+x86 IOMMU Support
+=================
+
+The architecture specs can be obtained from the below locations.
+
+- Intel: http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/vt-directed-io-spec.pdf
+- AMD: https://www.amd.com/system/files/TechDocs/48882_IOMMU.pdf
+
+This guide gives a quick cheat sheet for some basic understanding.
+
+Basic stuff
+-----------
+
+ACPI enumerates and lists the different IOMMUs on the platform, and
+device scope relationships between devices and which IOMMU controls
+them.
+
+Some ACPI Keywords:
+
+- DMAR - Intel DMA Remapping table
+- DRHD - Intel DMA Remapping Hardware Unit Definition
+- RMRR - Intel Reserved Memory Region Reporting Structure
+- IVRS - AMD I/O Virtualization Reporting Structure
+- IVDB - AMD I/O Virtualization Definition Block
+- IVHD - AMD I/O Virtualization Hardware Definition
+
+What is Intel RMRR?
+^^^^^^^^^^^^^^^^^^^
+
+There are some devices the BIOS controls, for e.g USB devices to perform
+PS2 emulation. The regions of memory used for these devices are marked
+reserved in the e820 map. When we turn on DMA translation, DMA to those
+regions will fail. Hence BIOS uses RMRR to specify these regions along with
+devices that need to access these regions. OS is expected to setup
+unity mappings for these regions for these devices to access these regions.
+
+What is AMD IVRS?
+^^^^^^^^^^^^^^^^^
+
+The architecture defines an ACPI-compatible data structure called an I/O
+Virtualization Reporting Structure (IVRS) that is used to convey information
+related to I/O virtualization to system software.  The IVRS describes the
+configuration and capabilities of the IOMMUs contained in the platform as
+well as information about the devices that each IOMMU virtualizes.
+
+The IVRS provides information about the following:
+
+- IOMMUs present in the platform including their capabilities and proper configuration
+- System I/O topology relevant to each IOMMU
+- Peripheral devices that cannot be otherwise enumerated
+- Memory regions used by SMI/SMM, platform firmware, and platform hardware. These are generally exclusion ranges to be configured by system software.
+
+How is an I/O Virtual Address (IOVA) generated?
+-----------------------------------------------
+
+Well behaved drivers call dma_map_*() calls before sending command to device
+that needs to perform DMA. Once DMA is completed and mapping is no longer
+required, driver performs dma_unmap_*() calls to unmap the region.
+
+Intel Specific Notes
+--------------------
+
+Graphics Problems?
+^^^^^^^^^^^^^^^^^^
+
+If you encounter issues with graphics devices, you can try adding
+option intel_iommu=igfx_off to turn off the integrated graphics engine.
+If this fixes anything, please ensure you file a bug reporting the problem.
+
+Some exceptions to IOVA
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff).
+The same is true for peer to peer transactions. Hence we reserve the
+address from PCI MMIO ranges so they are not allocated for IOVA addresses.
+
+AMD Specific Notes
+------------------
+
+Graphics Problems?
+^^^^^^^^^^^^^^^^^^
+
+If you encounter issues with integrated graphics devices, you can try adding
+option iommu=pt to the kernel command line use a 1:1 mapping for the IOMMU.  If
+this fixes anything, please ensure you file a bug reporting the problem.
+
+Fault reporting
+---------------
+When errors are reported, the IOMMU signals via an interrupt. The fault
+reason and device that caused it is printed on the console.
+
+
+Kernel Log Samples
+------------------
+
+Intel Boot Messages
+^^^^^^^^^^^^^^^^^^^
+
+Something like this gets printed indicating presence of DMAR tables
+in ACPI:
+
+::
+
+       ACPI: DMAR (v001 A M I  OEMDMAR  0x00000001 MSFT 0x00000097) @ 0x000000007f5b5ef0
+
+When DMAR is being processed and initialized by ACPI, prints DMAR locations
+and any RMRR's processed:
+
+::
+
+       ACPI DMAR:Host address width 36
+       ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000
+       ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000
+       ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000
+       ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff
+       ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff
+
+When DMAR is enabled for use, you will notice:
+
+::
+
+       PCI-DMA: Using DMAR IOMMU
+
+Intel Fault reporting
+^^^^^^^^^^^^^^^^^^^^^
+
+::
+
+       DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
+       DMAR:[fault reason 05] PTE Write access is not set
+       DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
+       DMAR:[fault reason 05] PTE Write access is not set
+
+AMD Boot Messages
+^^^^^^^^^^^^^^^^^
+
+Something like this gets printed indicating presence of the IOMMU:
+
+::
+
+       iommu: Default domain type: Translated
+       iommu: DMA domain TLB invalidation policy: lazy mode
+
+AMD Fault reporting
+^^^^^^^^^^^^^^^^^^^
+
+::
+
+       AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0007 address=0xffffc02000 flags=0x0000]
+       AMD-Vi: Event logged [IO_PAGE_FAULT device=07:00.0 domain=0x0007 address=0xffffc02000 flags=0x0000]
diff --git a/Documentation/arch/x86/kernel-stacks.rst b/Documentation/arch/x86/kernel-stacks.rst
new file mode 100644 (file)
index 0000000..6b0bcf0
--- /dev/null
@@ -0,0 +1,152 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+Kernel Stacks
+=============
+
+Kernel stacks on x86-64 bit
+===========================
+
+Most of the text from Keith Owens, hacked by AK
+
+x86_64 page size (PAGE_SIZE) is 4K.
+
+Like all other architectures, x86_64 has a kernel stack for every
+active thread.  These thread stacks are THREAD_SIZE (2*PAGE_SIZE) big.
+These stacks contain useful data as long as a thread is alive or a
+zombie. While the thread is in user space the kernel stack is empty
+except for the thread_info structure at the bottom.
+
+In addition to the per thread stacks, there are specialized stacks
+associated with each CPU.  These stacks are only used while the kernel
+is in control on that CPU; when a CPU returns to user space the
+specialized stacks contain no useful data.  The main CPU stacks are:
+
+* Interrupt stack.  IRQ_STACK_SIZE
+
+  Used for external hardware interrupts.  If this is the first external
+  hardware interrupt (i.e. not a nested hardware interrupt) then the
+  kernel switches from the current task to the interrupt stack.  Like
+  the split thread and interrupt stacks on i386, this gives more room
+  for kernel interrupt processing without having to increase the size
+  of every per thread stack.
+
+  The interrupt stack is also used when processing a softirq.
+
+Switching to the kernel interrupt stack is done by software based on a
+per CPU interrupt nest counter. This is needed because x86-64 "IST"
+hardware stacks cannot nest without races.
+
+x86_64 also has a feature which is not available on i386, the ability
+to automatically switch to a new stack for designated events such as
+double fault or NMI, which makes it easier to handle these unusual
+events on x86_64.  This feature is called the Interrupt Stack Table
+(IST).  There can be up to 7 IST entries per CPU. The IST code is an
+index into the Task State Segment (TSS). The IST entries in the TSS
+point to dedicated stacks; each stack can be a different size.
+
+An IST is selected by a non-zero value in the IST field of an
+interrupt-gate descriptor.  When an interrupt occurs and the hardware
+loads such a descriptor, the hardware automatically sets the new stack
+pointer based on the IST value, then invokes the interrupt handler.  If
+the interrupt came from user mode, then the interrupt handler prologue
+will switch back to the per-thread stack.  If software wants to allow
+nested IST interrupts then the handler must adjust the IST values on
+entry to and exit from the interrupt handler.  (This is occasionally
+done, e.g. for debug exceptions.)
+
+Events with different IST codes (i.e. with different stacks) can be
+nested.  For example, a debug interrupt can safely be interrupted by an
+NMI.  arch/x86_64/kernel/entry.S::paranoidentry adjusts the stack
+pointers on entry to and exit from all IST events, in theory allowing
+IST events with the same code to be nested.  However in most cases, the
+stack size allocated to an IST assumes no nesting for the same code.
+If that assumption is ever broken then the stacks will become corrupt.
+
+The currently assigned IST stacks are:
+
+* ESTACK_DF.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for interrupt 8 - Double Fault Exception (#DF).
+
+  Invoked when handling one exception causes another exception. Happens
+  when the kernel is very confused (e.g. kernel stack pointer corrupt).
+  Using a separate stack allows the kernel to recover from it well enough
+  in many cases to still output an oops.
+
+* ESTACK_NMI.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for non-maskable interrupts (NMI).
+
+  NMI can be delivered at any time, including when the kernel is in the
+  middle of switching stacks.  Using IST for NMI events avoids making
+  assumptions about the previous state of the kernel stack.
+
+* ESTACK_DB.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for hardware debug interrupts (interrupt 1) and for software
+  debug interrupts (INT3).
+
+  When debugging a kernel, debug interrupts (both hardware and
+  software) can occur at any time.  Using IST for these interrupts
+  avoids making assumptions about the previous state of the kernel
+  stack.
+
+  To handle nested #DB correctly there exist two instances of DB stacks. On
+  #DB entry the IST stackpointer for #DB is switched to the second instance
+  so a nested #DB starts from a clean stack. The nested #DB switches
+  the IST stackpointer to a guard hole to catch triple nesting.
+
+* ESTACK_MCE.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for interrupt 18 - Machine Check Exception (#MC).
+
+  MCE can be delivered at any time, including when the kernel is in the
+  middle of switching stacks.  Using IST for MCE events avoids making
+  assumptions about the previous state of the kernel stack.
+
+For more details see the Intel IA32 or AMD AMD64 architecture manuals.
+
+
+Printing backtraces on x86
+==========================
+
+The question about the '?' preceding function names in an x86 stacktrace
+keeps popping up, here's an indepth explanation. It helps if the reader
+stares at print_context_stack() and the whole machinery in and around
+arch/x86/kernel/dumpstack.c.
+
+Adapted from Ingo's mail, Message-ID: <20150521101614.GA10889@gmail.com>:
+
+We always scan the full kernel stack for return addresses stored on
+the kernel stack(s) [1]_, from stack top to stack bottom, and print out
+anything that 'looks like' a kernel text address.
+
+If it fits into the frame pointer chain, we print it without a question
+mark, knowing that it's part of the real backtrace.
+
+If the address does not fit into our expected frame pointer chain we
+still print it, but we print a '?'. It can mean two things:
+
+ - either the address is not part of the call chain: it's just stale
+   values on the kernel stack, from earlier function calls. This is
+   the common case.
+
+ - or it is part of the call chain, but the frame pointer was not set
+   up properly within the function, so we don't recognize it.
+
+This way we will always print out the real call chain (plus a few more
+entries), regardless of whether the frame pointer was set up correctly
+or not - but in most cases we'll get the call chain right as well. The
+entries printed are strictly in stack order, so you can deduce more
+information from that as well.
+
+The most important property of this method is that we _never_ lose
+information: we always strive to print _all_ addresses on the stack(s)
+that look like kernel text addresses, so if debug information is wrong,
+we still print out the real call chain as well - just with more question
+marks than ideal.
+
+.. [1] For things like IRQ and IST stacks, we also scan those stacks, in
+       the right order, and try to cross from one stack into another
+       reconstructing the call chain. This works most of the time.
diff --git a/Documentation/arch/x86/mds.rst b/Documentation/arch/x86/mds.rst
new file mode 100644 (file)
index 0000000..5d4330b
--- /dev/null
@@ -0,0 +1,193 @@
+Microarchitectural Data Sampling (MDS) mitigation
+=================================================
+
+.. _mds:
+
+Overview
+--------
+
+Microarchitectural Data Sampling (MDS) is a family of side channel attacks
+on internal buffers in Intel CPUs. The variants are:
+
+ - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126)
+ - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130)
+ - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127)
+ - Microarchitectural Data Sampling Uncacheable Memory (MDSUM) (CVE-2019-11091)
+
+MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a
+dependent load (store-to-load forwarding) as an optimization. The forward
+can also happen to a faulting or assisting load operation for a different
+memory address, which can be exploited under certain conditions. Store
+buffers are partitioned between Hyper-Threads so cross thread forwarding is
+not possible. But if a thread enters or exits a sleep state the store
+buffer is repartitioned which can expose data from one thread to the other.
+
+MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage
+L1 miss situations and to hold data which is returned or sent in response
+to a memory or I/O operation. Fill buffers can forward data to a load
+operation and also write data to the cache. When the fill buffer is
+deallocated it can retain the stale data of the preceding operations which
+can then be forwarded to a faulting or assisting load operation, which can
+be exploited under certain conditions. Fill buffers are shared between
+Hyper-Threads so cross thread leakage is possible.
+
+MLPDS leaks Load Port Data. Load ports are used to perform load operations
+from memory or I/O. The received data is then forwarded to the register
+file or a subsequent operation. In some implementations the Load Port can
+contain stale data from a previous operation which can be forwarded to
+faulting or assisting loads under certain conditions, which again can be
+exploited eventually. Load ports are shared between Hyper-Threads so cross
+thread leakage is possible.
+
+MDSUM is a special case of MSBDS, MFBDS and MLPDS. An uncacheable load from
+memory that takes a fault or assist can leave data in a microarchitectural
+structure that may later be observed using one of the same methods used by
+MSBDS, MFBDS or MLPDS.
+
+Exposure assumptions
+--------------------
+
+It is assumed that attack code resides in user space or in a guest with one
+exception. The rationale behind this assumption is that the code construct
+needed for exploiting MDS requires:
+
+ - to control the load to trigger a fault or assist
+
+ - to have a disclosure gadget which exposes the speculatively accessed
+   data for consumption through a side channel.
+
+ - to control the pointer through which the disclosure gadget exposes the
+   data
+
+The existence of such a construct in the kernel cannot be excluded with
+100% certainty, but the complexity involved makes it extremly unlikely.
+
+There is one exception, which is untrusted BPF. The functionality of
+untrusted BPF is limited, but it needs to be thoroughly investigated
+whether it can be used to create such a construct.
+
+
+Mitigation strategy
+-------------------
+
+All variants have the same mitigation strategy at least for the single CPU
+thread case (SMT off): Force the CPU to clear the affected buffers.
+
+This is achieved by using the otherwise unused and obsolete VERW
+instruction in combination with a microcode update. The microcode clears
+the affected CPU buffers when the VERW instruction is executed.
+
+For virtualization there are two ways to achieve CPU buffer
+clearing. Either the modified VERW instruction or via the L1D Flush
+command. The latter is issued when L1TF mitigation is enabled so the extra
+VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to
+be issued.
+
+If the VERW instruction with the supplied segment selector argument is
+executed on a CPU without the microcode update there is no side effect
+other than a small number of pointlessly wasted CPU cycles.
+
+This does not protect against cross Hyper-Thread attacks except for MSBDS
+which is only exploitable cross Hyper-thread when one of the Hyper-Threads
+enters a C-state.
+
+The kernel provides a function to invoke the buffer clearing:
+
+    mds_clear_cpu_buffers()
+
+The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state
+(idle) transitions.
+
+As a special quirk to address virtualization scenarios where the host has
+the microcode updated, but the hypervisor does not (yet) expose the
+MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the
+hope that it might actually clear the buffers. The state is reflected
+accordingly.
+
+According to current knowledge additional mitigations inside the kernel
+itself are not required because the necessary gadgets to expose the leaked
+data cannot be controlled in a way which allows exploitation from malicious
+user space or VM guests.
+
+Kernel internal mitigation modes
+--------------------------------
+
+ ======= ============================================================
+ off      Mitigation is disabled. Either the CPU is not affected or
+          mds=off is supplied on the kernel command line
+
+ full     Mitigation is enabled. CPU is affected and MD_CLEAR is
+          advertised in CPUID.
+
+ vmwerv          Mitigation is enabled. CPU is affected and MD_CLEAR is not
+         advertised in CPUID. That is mainly for virtualization
+         scenarios where the host has the updated microcode but the
+         hypervisor does not expose MD_CLEAR in CPUID. It's a best
+         effort approach without guarantee.
+ ======= ============================================================
+
+If the CPU is affected and mds=off is not supplied on the kernel command
+line then the kernel selects the appropriate mitigation mode depending on
+the availability of the MD_CLEAR CPUID bit.
+
+Mitigation points
+-----------------
+
+1. Return to user space
+^^^^^^^^^^^^^^^^^^^^^^^
+
+   When transitioning from kernel to user space the CPU buffers are flushed
+   on affected CPUs when the mitigation is not disabled on the kernel
+   command line. The migitation is enabled through the static key
+   mds_user_clear.
+
+   The mitigation is invoked in prepare_exit_to_usermode() which covers
+   all but one of the kernel to user space transitions.  The exception
+   is when we return from a Non Maskable Interrupt (NMI), which is
+   handled directly in do_nmi().
+
+   (The reason that NMI is special is that prepare_exit_to_usermode() can
+    enable IRQs.  In NMI context, NMIs are blocked, and we don't want to
+    enable IRQs with NMIs blocked.)
+
+
+2. C-State transition
+^^^^^^^^^^^^^^^^^^^^^
+
+   When a CPU goes idle and enters a C-State the CPU buffers need to be
+   cleared on affected CPUs when SMT is active. This addresses the
+   repartitioning of the store buffer when one of the Hyper-Threads enters
+   a C-State.
+
+   When SMT is inactive, i.e. either the CPU does not support it or all
+   sibling threads are offline CPU buffer clearing is not required.
+
+   The idle clearing is enabled on CPUs which are only affected by MSBDS
+   and not by any other MDS variant. The other MDS variants cannot be
+   protected against cross Hyper-Thread attacks because the Fill Buffer and
+   the Load Ports are shared. So on CPUs affected by other variants, the
+   idle clearing would be a window dressing exercise and is therefore not
+   activated.
+
+   The invocation is controlled by the static key mds_idle_clear which is
+   switched depending on the chosen mitigation mode and the SMT state of
+   the system.
+
+   The buffer clear is only invoked before entering the C-State to prevent
+   that stale data from the idling CPU from spilling to the Hyper-Thread
+   sibling after the store buffer got repartitioned and all entries are
+   available to the non idle sibling.
+
+   When coming out of idle the store buffer is partitioned again so each
+   sibling has half of it available. The back from idle CPU could be then
+   speculatively exposed to contents of the sibling. The buffers are
+   flushed either on exit to user space or on VMENTER so malicious code
+   in user space or the guest cannot speculatively access them.
+
+   The mitigation is hooked into all variants of halt()/mwait(), but does
+   not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver
+   has been superseded by the intel_idle driver around 2010 and is
+   preferred on all affected CPUs which are expected to gain the MD_CLEAR
+   functionality in microcode. Aside of that the IO-Port mechanism is a
+   legacy interface which is only used on older systems which are either
+   not affected or do not receive microcode updates anymore.
diff --git a/Documentation/arch/x86/microcode.rst b/Documentation/arch/x86/microcode.rst
new file mode 100644 (file)
index 0000000..b627c6f
--- /dev/null
@@ -0,0 +1,240 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================
+The Linux Microcode Loader
+==========================
+
+:Authors: - Fenghua Yu <fenghua.yu@intel.com>
+          - Borislav Petkov <bp@suse.de>
+         - Ashok Raj <ashok.raj@intel.com>
+
+The kernel has a x86 microcode loading facility which is supposed to
+provide microcode loading methods in the OS. Potential use cases are
+updating the microcode on platforms beyond the OEM End-Of-Life support,
+and updating the microcode on long-running systems without rebooting.
+
+The loader supports three loading methods:
+
+Early load microcode
+====================
+
+The kernel can update microcode very early during boot. Loading
+microcode early can fix CPU issues before they are observed during
+kernel boot time.
+
+The microcode is stored in an initrd file. During boot, it is read from
+it and loaded into the CPU cores.
+
+The format of the combined initrd image is microcode in (uncompressed)
+cpio format followed by the (possibly compressed) initrd image. The
+loader parses the combined initrd image during boot.
+
+The microcode files in cpio name space are:
+
+on Intel:
+  kernel/x86/microcode/GenuineIntel.bin
+on AMD  :
+  kernel/x86/microcode/AuthenticAMD.bin
+
+During BSP (BootStrapping Processor) boot (pre-SMP), the kernel
+scans the microcode file in the initrd. If microcode matching the
+CPU is found, it will be applied in the BSP and later on in all APs
+(Application Processors).
+
+The loader also saves the matching microcode for the CPU in memory.
+Thus, the cached microcode patch is applied when CPUs resume from a
+sleep state.
+
+Here's a crude example how to prepare an initrd with microcode (this is
+normally done automatically by the distribution, when recreating the
+initrd, so you don't really have to do it yourself. It is documented
+here for future reference only).
+::
+
+  #!/bin/bash
+
+  if [ -z "$1" ]; then
+      echo "You need to supply an initrd file"
+      exit 1
+  fi
+
+  INITRD="$1"
+
+  DSTDIR=kernel/x86/microcode
+  TMPDIR=/tmp/initrd
+
+  rm -rf $TMPDIR
+
+  mkdir $TMPDIR
+  cd $TMPDIR
+  mkdir -p $DSTDIR
+
+  if [ -d /lib/firmware/amd-ucode ]; then
+          cat /lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin
+  fi
+
+  if [ -d /lib/firmware/intel-ucode ]; then
+          cat /lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin
+  fi
+
+  find . | cpio -o -H newc >../ucode.cpio
+  cd ..
+  mv $INITRD $INITRD.orig
+  cat ucode.cpio $INITRD.orig > $INITRD
+
+  rm -rf $TMPDIR
+
+
+The system needs to have the microcode packages installed into
+/lib/firmware or you need to fixup the paths above if yours are
+somewhere else and/or you've downloaded them directly from the processor
+vendor's site.
+
+Late loading
+============
+
+You simply install the microcode packages your distro supplies and
+run::
+
+  # echo 1 > /sys/devices/system/cpu/microcode/reload
+
+as root.
+
+The loading mechanism looks for microcode blobs in
+/lib/firmware/{intel-ucode,amd-ucode}. The default distro installation
+packages already put them there.
+
+Since kernel 5.19, late loading is not enabled by default.
+
+The /dev/cpu/microcode method has been removed in 5.19.
+
+Why is late loading dangerous?
+==============================
+
+Synchronizing all CPUs
+----------------------
+
+The microcode engine which receives the microcode update is shared
+between the two logical threads in a SMT system. Therefore, when
+the update is executed on one SMT thread of the core, the sibling
+"automatically" gets the update.
+
+Since the microcode can "simulate" MSRs too, while the microcode update
+is in progress, those simulated MSRs transiently cease to exist. This
+can result in unpredictable results if the SMT sibling thread happens to
+be in the middle of an access to such an MSR. The usual observation is
+that such MSR accesses cause #GPs to be raised to signal that former are
+not present.
+
+The disappearing MSRs are just one common issue which is being observed.
+Any other instruction that's being patched and gets concurrently
+executed by the other SMT sibling, can also result in similar,
+unpredictable behavior.
+
+To eliminate this case, a stop_machine()-based CPU synchronization was
+introduced as a way to guarantee that all logical CPUs will not execute
+any code but just wait in a spin loop, polling an atomic variable.
+
+While this took care of device or external interrupts, IPIs including
+LVT ones, such as CMCI etc, it cannot address other special interrupts
+that can't be shut off. Those are Machine Check (#MC), System Management
+(#SMI) and Non-Maskable interrupts (#NMI).
+
+Machine Checks
+--------------
+
+Machine Checks (#MC) are non-maskable. There are two kinds of MCEs.
+Fatal un-recoverable MCEs and recoverable MCEs. While un-recoverable
+errors are fatal, recoverable errors can also happen in kernel context
+are also treated as fatal by the kernel.
+
+On certain Intel machines, MCEs are also broadcast to all threads in a
+system. If one thread is in the middle of executing WRMSR, a MCE will be
+taken at the end of the flow. Either way, they will wait for the thread
+performing the wrmsr(0x79) to rendezvous in the MCE handler and shutdown
+eventually if any of the threads in the system fail to check in to the
+MCE rendezvous.
+
+To be paranoid and get predictable behavior, the OS can choose to set
+MCG_STATUS.MCIP. Since MCEs can be at most one in a system, if an
+MCE was signaled, the above condition will promote to a system reset
+automatically. OS can turn off MCIP at the end of the update for that
+core.
+
+System Management Interrupt
+---------------------------
+
+SMIs are also broadcast to all CPUs in the platform. Microcode update
+requests exclusive access to the core before writing to MSR 0x79. So if
+it does happen such that, one thread is in WRMSR flow, and the 2nd got
+an SMI, that thread will be stopped in the first instruction in the SMI
+handler.
+
+Since the secondary thread is stopped in the first instruction in SMI,
+there is very little chance that it would be in the middle of executing
+an instruction being patched. Plus OS has no way to stop SMIs from
+happening.
+
+Non-Maskable Interrupts
+-----------------------
+
+When thread0 of a core is doing the microcode update, if thread1 is
+pulled into NMI, that can cause unpredictable behavior due to the
+reasons above.
+
+OS can choose a variety of methods to avoid running into this situation.
+
+
+Is the microcode suitable for late loading?
+-------------------------------------------
+
+Late loading is done when the system is fully operational and running
+real workloads. Late loading behavior depends on what the base patch on
+the CPU is before upgrading to the new patch.
+
+This is true for Intel CPUs.
+
+Consider, for example, a CPU has patch level 1 and the update is to
+patch level 3.
+
+Between patch1 and patch3, patch2 might have deprecated a software-visible
+feature.
+
+This is unacceptable if software is even potentially using that feature.
+For instance, say MSR_X is no longer available after an update,
+accessing that MSR will cause a #GP fault.
+
+Basically there is no way to declare a new microcode update suitable
+for late-loading. This is another one of the problems that caused late
+loading to be not enabled by default.
+
+Builtin microcode
+=================
+
+The loader supports also loading of a builtin microcode supplied through
+the regular builtin firmware method CONFIG_EXTRA_FIRMWARE. Only 64-bit is
+currently supported.
+
+Here's an example::
+
+  CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin"
+  CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"
+
+This basically means, you have the following tree structure locally::
+
+  /lib/firmware/
+  |-- amd-ucode
+  ...
+  |   |-- microcode_amd_fam15h.bin
+  ...
+  |-- intel-ucode
+  ...
+  |   |-- 06-3a-09
+  ...
+
+so that the build system can find those files and integrate them into
+the final kernel image. The early loader finds them and applies them.
+
+Needless to say, this method is not the most flexible one because it
+requires rebuilding the kernel each time updated microcode from the CPU
+vendor is available.
diff --git a/Documentation/arch/x86/mtrr.rst b/Documentation/arch/x86/mtrr.rst
new file mode 100644 (file)
index 0000000..f65ef03
--- /dev/null
@@ -0,0 +1,354 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================================
+MTRR (Memory Type Range Register) control
+=========================================
+
+:Authors: - Richard Gooch <rgooch@atnf.csiro.au> - 3 Jun 1999
+          - Luis R. Rodriguez <mcgrof@do-not-panic.com> - April 9, 2015
+
+
+Phasing out MTRR use
+====================
+
+MTRR use is replaced on modern x86 hardware with PAT. Direct MTRR use by
+drivers on Linux is now completely phased out, device drivers should use
+arch_phys_wc_add() in combination with ioremap_wc() to make MTRR effective on
+non-PAT systems while a no-op but equally effective on PAT enabled systems.
+
+Even if Linux does not use MTRRs directly, some x86 platform firmware may still
+set up MTRRs early before booting the OS. They do this as some platform
+firmware may still have implemented access to MTRRs which would be controlled
+and handled by the platform firmware directly. An example of platform use of
+MTRRs is through the use of SMI handlers, one case could be for fan control,
+the platform code would need uncachable access to some of its fan control
+registers. Such platform access does not need any Operating System MTRR code in
+place other than mtrr_type_lookup() to ensure any OS specific mapping requests
+are aligned with platform MTRR setup. If MTRRs are only set up by the platform
+firmware code though and the OS does not make any specific MTRR mapping
+requests mtrr_type_lookup() should always return MTRR_TYPE_INVALID.
+
+For details refer to Documentation/arch/x86/pat.rst.
+
+.. tip::
+  On Intel P6 family processors (Pentium Pro, Pentium II and later)
+  the Memory Type Range Registers (MTRRs) may be used to control
+  processor access to memory ranges. This is most useful when you have
+  a video (VGA) card on a PCI or AGP bus. Enabling write-combining
+  allows bus write transfers to be combined into a larger transfer
+  before bursting over the PCI/AGP bus. This can increase performance
+  of image write operations 2.5 times or more.
+
+  The Cyrix 6x86, 6x86MX and M II processors have Address Range
+  Registers (ARRs) which provide a similar functionality to MTRRs. For
+  these, the ARRs are used to emulate the MTRRs.
+
+  The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
+  MTRRs. These are supported.  The AMD Athlon family provide 8 Intel
+  style MTRRs.
+
+  The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
+  are supported.
+
+  The VIA Cyrix III and VIA C3 CPUs offer 8 Intel style MTRRs.
+
+  The CONFIG_MTRR option creates a /proc/mtrr file which may be used
+  to manipulate your MTRRs. Typically the X server should use
+  this. This should have a reasonably generic interface so that
+  similar control registers on other processors can be easily
+  supported.
+
+There are two interfaces to /proc/mtrr: one is an ASCII interface
+which allows you to read and write. The other is an ioctl()
+interface. The ASCII interface is meant for administration. The
+ioctl() interface is meant for C programs (i.e. the X server). The
+interfaces are described below, with sample commands and C code.
+
+
+Reading MTRRs from the shell
+============================
+::
+
+  % cat /proc/mtrr
+  reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
+  reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1
+
+Creating MTRRs from the C-shell::
+
+  # echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr
+
+or if you use bash::
+
+  # echo "base=0xf8000000 size=0x400000 type=write-combining" >| /proc/mtrr
+
+And the result thereof::
+
+  % cat /proc/mtrr
+  reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
+  reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1
+  reg02: base=0xf8000000 (3968MB), size=   4MB: write-combining, count=1
+
+This is for video RAM at base address 0xf8000000 and size 4 megabytes. To
+find out your base address, you need to look at the output of your X
+server, which tells you where the linear framebuffer address is. A
+typical line that you may get is::
+
+  (--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000
+
+Note that you should only use the value from the X server, as it may
+move the framebuffer base address, so the only value you can trust is
+that reported by the X server.
+
+To find out the size of your framebuffer (what, you don't actually
+know?), the following line will tell you::
+
+  (--) S3: videoram:  4096k
+
+That's 4 megabytes, which is 0x400000 bytes (in hexadecimal).
+A patch is being written for XFree86 which will make this automatic:
+in other words the X server will manipulate /proc/mtrr using the
+ioctl() interface, so users won't have to do anything. If you use a
+commercial X server, lobby your vendor to add support for MTRRs.
+
+
+Creating overlapping MTRRs
+==========================
+::
+
+  %echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr
+  %echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr
+
+And the results::
+
+  % cat /proc/mtrr
+  reg00: base=0x00000000 (   0MB), size=  64MB: write-back, count=1
+  reg01: base=0xfb000000 (4016MB), size=  16MB: write-combining, count=1
+  reg02: base=0xfb000000 (4016MB), size=   4kB: uncachable, count=1
+
+Some cards (especially Voodoo Graphics boards) need this 4 kB area
+excluded from the beginning of the region because it is used for
+registers.
+
+NOTE: You can only create type=uncachable region, if the first
+region that you created is type=write-combining.
+
+
+Removing MTRRs from the C-shel
+==============================
+::
+
+  % echo "disable=2" >! /proc/mtrr
+
+or using bash::
+
+  % echo "disable=2" >| /proc/mtrr
+
+
+Reading MTRRs from a C program using ioctl()'s
+==============================================
+::
+
+  /*  mtrr-show.c
+
+      Source file for mtrr-show (example program to show MTRRs using ioctl()'s)
+
+      Copyright (C) 1997-1998  Richard Gooch
+
+      This program is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published by
+      the Free Software Foundation; either version 2 of the License, or
+      (at your option) any later version.
+
+      This program is distributed in the hope that it will be useful,
+      but WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+      GNU General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with this program; if not, write to the Free Software
+      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+      Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
+      The postal address is:
+        Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
+  */
+
+  /*
+      This program will use an ioctl() on /proc/mtrr to show the current MTRR
+      settings. This is an alternative to reading /proc/mtrr.
+
+
+      Written by      Richard Gooch   17-DEC-1997
+
+      Last updated by Richard Gooch   2-MAY-1998
+
+
+  */
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  #include <sys/types.h>
+  #include <sys/stat.h>
+  #include <fcntl.h>
+  #include <sys/ioctl.h>
+  #include <errno.h>
+  #include <asm/mtrr.h>
+
+  #define TRUE 1
+  #define FALSE 0
+  #define ERRSTRING strerror (errno)
+
+  static char *mtrr_strings[MTRR_NUM_TYPES] =
+  {
+      "uncachable",               /* 0 */
+      "write-combining",          /* 1 */
+      "?",                        /* 2 */
+      "?",                        /* 3 */
+      "write-through",            /* 4 */
+      "write-protect",            /* 5 */
+      "write-back",               /* 6 */
+  };
+
+  int main ()
+  {
+      int fd;
+      struct mtrr_gentry gentry;
+
+      if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) == -1 )
+      {
+    if (errno == ENOENT)
+    {
+        fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
+        stderr);
+        exit (1);
+    }
+    fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
+    exit (2);
+      }
+      for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0;
+    ++gentry.regnum)
+      {
+    if (gentry.size < 1)
+    {
+        fprintf (stderr, "Register: %u disabled\n", gentry.regnum);
+        continue;
+    }
+    fprintf (stderr, "Register: %u base: 0x%lx size: 0x%lx type: %s\n",
+      gentry.regnum, gentry.base, gentry.size,
+      mtrr_strings[gentry.type]);
+      }
+      if (errno == EINVAL) exit (0);
+      fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
+      exit (3);
+  }   /*  End Function main  */
+
+
+Creating MTRRs from a C programme using ioctl()'s
+=================================================
+::
+
+  /*  mtrr-add.c
+
+      Source file for mtrr-add (example programme to add an MTRRs using ioctl())
+
+      Copyright (C) 1997-1998  Richard Gooch
+
+      This program is free software; you can redistribute it and/or modify
+      it under the terms of the GNU General Public License as published by
+      the Free Software Foundation; either version 2 of the License, or
+      (at your option) any later version.
+
+      This program is distributed in the hope that it will be useful,
+      but WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+      GNU General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with this program; if not, write to the Free Software
+      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+      Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
+      The postal address is:
+        Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
+  */
+
+  /*
+      This programme will use an ioctl() on /proc/mtrr to add an entry. The first
+      available mtrr is used. This is an alternative to writing /proc/mtrr.
+
+
+      Written by      Richard Gooch   17-DEC-1997
+
+      Last updated by Richard Gooch   2-MAY-1998
+
+
+  */
+  #include <stdio.h>
+  #include <string.h>
+  #include <stdlib.h>
+  #include <unistd.h>
+  #include <sys/types.h>
+  #include <sys/stat.h>
+  #include <fcntl.h>
+  #include <sys/ioctl.h>
+  #include <errno.h>
+  #include <asm/mtrr.h>
+
+  #define TRUE 1
+  #define FALSE 0
+  #define ERRSTRING strerror (errno)
+
+  static char *mtrr_strings[MTRR_NUM_TYPES] =
+  {
+      "uncachable",               /* 0 */
+      "write-combining",          /* 1 */
+      "?",                        /* 2 */
+      "?",                        /* 3 */
+      "write-through",            /* 4 */
+      "write-protect",            /* 5 */
+      "write-back",               /* 6 */
+  };
+
+  int main (int argc, char **argv)
+  {
+      int fd;
+      struct mtrr_sentry sentry;
+
+      if (argc != 4)
+      {
+    fprintf (stderr, "Usage:\tmtrr-add base size type\n");
+    exit (1);
+      }
+      sentry.base = strtoul (argv[1], NULL, 0);
+      sentry.size = strtoul (argv[2], NULL, 0);
+      for (sentry.type = 0; sentry.type < MTRR_NUM_TYPES; ++sentry.type)
+      {
+    if (strcmp (argv[3], mtrr_strings[sentry.type]) == 0) break;
+      }
+      if (sentry.type >= MTRR_NUM_TYPES)
+      {
+    fprintf (stderr, "Illegal type: \"%s\"\n", argv[3]);
+    exit (2);
+      }
+      if ( ( fd = open ("/proc/mtrr", O_WRONLY, 0) ) == -1 )
+      {
+    if (errno == ENOENT)
+    {
+        fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
+        stderr);
+        exit (3);
+    }
+    fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
+    exit (4);
+      }
+      if (ioctl (fd, MTRRIOC_ADD_ENTRY, &sentry) == -1)
+      {
+    fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
+    exit (5);
+      }
+      fprintf (stderr, "Sleeping for 5 seconds so you can see the new entry\n");
+      sleep (5);
+      close (fd);
+      fputs ("I've just closed /proc/mtrr so now the new entry should be gone\n",
+      stderr);
+  }   /*  End Function main  */
diff --git a/Documentation/arch/x86/orc-unwinder.rst b/Documentation/arch/x86/orc-unwinder.rst
new file mode 100644 (file)
index 0000000..cdb2570
--- /dev/null
@@ -0,0 +1,182 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+ORC unwinder
+============
+
+Overview
+========
+
+The kernel CONFIG_UNWINDER_ORC option enables the ORC unwinder, which is
+similar in concept to a DWARF unwinder.  The difference is that the
+format of the ORC data is much simpler than DWARF, which in turn allows
+the ORC unwinder to be much simpler and faster.
+
+The ORC data consists of unwind tables which are generated by objtool.
+They contain out-of-band data which is used by the in-kernel ORC
+unwinder.  Objtool generates the ORC data by first doing compile-time
+stack metadata validation (CONFIG_STACK_VALIDATION).  After analyzing
+all the code paths of a .o file, it determines information about the
+stack state at each instruction address in the file and outputs that
+information to the .orc_unwind and .orc_unwind_ip sections.
+
+The per-object ORC sections are combined at link time and are sorted and
+post-processed at boot time.  The unwinder uses the resulting data to
+correlate instruction addresses with their stack states at run time.
+
+
+ORC vs frame pointers
+=====================
+
+With frame pointers enabled, GCC adds instrumentation code to every
+function in the kernel.  The kernel's .text size increases by about
+3.2%, resulting in a broad kernel-wide slowdown.  Measurements by Mel
+Gorman [1]_ have shown a slowdown of 5-10% for some workloads.
+
+In contrast, the ORC unwinder has no effect on text size or runtime
+performance, because the debuginfo is out of band.  So if you disable
+frame pointers and enable the ORC unwinder, you get a nice performance
+improvement across the board, and still have reliable stack traces.
+
+Ingo Molnar says:
+
+  "Note that it's not just a performance improvement, but also an
+  instruction cache locality improvement: 3.2% .text savings almost
+  directly transform into a similarly sized reduction in cache
+  footprint. That can transform to even higher speedups for workloads
+  whose cache locality is borderline."
+
+Another benefit of ORC compared to frame pointers is that it can
+reliably unwind across interrupts and exceptions.  Frame pointer based
+unwinds can sometimes skip the caller of the interrupted function, if it
+was a leaf function or if the interrupt hit before the frame pointer was
+saved.
+
+The main disadvantage of the ORC unwinder compared to frame pointers is
+that it needs more memory to store the ORC unwind tables: roughly 2-4MB
+depending on the kernel config.
+
+
+ORC vs DWARF
+============
+
+ORC debuginfo's advantage over DWARF itself is that it's much simpler.
+It gets rid of the complex DWARF CFI state machine and also gets rid of
+the tracking of unnecessary registers.  This allows the unwinder to be
+much simpler, meaning fewer bugs, which is especially important for
+mission critical oops code.
+
+The simpler debuginfo format also enables the unwinder to be much faster
+than DWARF, which is important for perf and lockdep.  In a basic
+performance test by Jiri Slaby [2]_, the ORC unwinder was about 20x
+faster than an out-of-tree DWARF unwinder.  (Note: That measurement was
+taken before some performance tweaks were added, which doubled
+performance, so the speedup over DWARF may be closer to 40x.)
+
+The ORC data format does have a few downsides compared to DWARF.  ORC
+unwind tables take up ~50% more RAM (+1.3MB on an x86 defconfig kernel)
+than DWARF-based eh_frame tables.
+
+Another potential downside is that, as GCC evolves, it's conceivable
+that the ORC data may end up being *too* simple to describe the state of
+the stack for certain optimizations.  But IMO this is unlikely because
+GCC saves the frame pointer for any unusual stack adjustments it does,
+so I suspect we'll really only ever need to keep track of the stack
+pointer and the frame pointer between call frames.  But even if we do
+end up having to track all the registers DWARF tracks, at least we will
+still be able to control the format, e.g. no complex state machines.
+
+
+ORC unwind table generation
+===========================
+
+The ORC data is generated by objtool.  With the existing compile-time
+stack metadata validation feature, objtool already follows all code
+paths, and so it already has all the information it needs to be able to
+generate ORC data from scratch.  So it's an easy step to go from stack
+validation to ORC data generation.
+
+It should be possible to instead generate the ORC data with a simple
+tool which converts DWARF to ORC data.  However, such a solution would
+be incomplete due to the kernel's extensive use of asm, inline asm, and
+special sections like exception tables.
+
+That could be rectified by manually annotating those special code paths
+using GNU assembler .cfi annotations in .S files, and homegrown
+annotations for inline asm in .c files.  But asm annotations were tried
+in the past and were found to be unmaintainable.  They were often
+incorrect/incomplete and made the code harder to read and keep updated.
+And based on looking at glibc code, annotating inline asm in .c files
+might be even worse.
+
+Objtool still needs a few annotations, but only in code which does
+unusual things to the stack like entry code.  And even then, far fewer
+annotations are needed than what DWARF would need, so they're much more
+maintainable than DWARF CFI annotations.
+
+So the advantages of using objtool to generate ORC data are that it
+gives more accurate debuginfo, with very few annotations.  It also
+insulates the kernel from toolchain bugs which can be very painful to
+deal with in the kernel since we often have to workaround issues in
+older versions of the toolchain for years.
+
+The downside is that the unwinder now becomes dependent on objtool's
+ability to reverse engineer GCC code flow.  If GCC optimizations become
+too complicated for objtool to follow, the ORC data generation might
+stop working or become incomplete.  (It's worth noting that livepatch
+already has such a dependency on objtool's ability to follow GCC code
+flow.)
+
+If newer versions of GCC come up with some optimizations which break
+objtool, we may need to revisit the current implementation.  Some
+possible solutions would be asking GCC to make the optimizations more
+palatable, or having objtool use DWARF as an additional input, or
+creating a GCC plugin to assist objtool with its analysis.  But for now,
+objtool follows GCC code quite well.
+
+
+Unwinder implementation details
+===============================
+
+Objtool generates the ORC data by integrating with the compile-time
+stack metadata validation feature, which is described in detail in
+tools/objtool/Documentation/objtool.txt.  After analyzing all
+the code paths of a .o file, it creates an array of orc_entry structs,
+and a parallel array of instruction addresses associated with those
+structs, and writes them to the .orc_unwind and .orc_unwind_ip sections
+respectively.
+
+The ORC data is split into the two arrays for performance reasons, to
+make the searchable part of the data (.orc_unwind_ip) more compact.  The
+arrays are sorted in parallel at boot time.
+
+Performance is further improved by the use of a fast lookup table which
+is created at runtime.  The fast lookup table associates a given address
+with a range of indices for the .orc_unwind table, so that only a small
+subset of the table needs to be searched.
+
+
+Etymology
+=========
+
+Orcs, fearsome creatures of medieval folklore, are the Dwarves' natural
+enemies.  Similarly, the ORC unwinder was created in opposition to the
+complexity and slowness of DWARF.
+
+"Although Orcs rarely consider multiple solutions to a problem, they do
+excel at getting things done because they are creatures of action, not
+thought." [3]_  Similarly, unlike the esoteric DWARF unwinder, the
+veracious ORC unwinder wastes no time or siloconic effort decoding
+variable-length zero-extended unsigned-integer byte-coded
+state-machine-based debug information entries.
+
+Similar to how Orcs frequently unravel the well-intentioned plans of
+their adversaries, the ORC unwinder frequently unravels stacks with
+brutal, unyielding efficiency.
+
+ORC stands for Oops Rewind Capability.
+
+
+.. [1] https://lore.kernel.org/r/20170602104048.jkkzssljsompjdwy@suse.de
+.. [2] https://lore.kernel.org/r/d2ca5435-6386-29b8-db87-7f227c2b713a@suse.cz
+.. [3] http://dustin.wikidot.com/half-orcs-and-orcs
diff --git a/Documentation/arch/x86/pat.rst b/Documentation/arch/x86/pat.rst
new file mode 100644 (file)
index 0000000..5d90177
--- /dev/null
@@ -0,0 +1,240 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================
+PAT (Page Attribute Table)
+==========================
+
+x86 Page Attribute Table (PAT) allows for setting the memory attribute at the
+page level granularity. PAT is complementary to the MTRR settings which allows
+for setting of memory types over physical address ranges. However, PAT is
+more flexible than MTRR due to its capability to set attributes at page level
+and also due to the fact that there are no hardware limitations on number of
+such attribute settings allowed. Added flexibility comes with guidelines for
+not having memory type aliasing for the same physical memory with multiple
+virtual addresses.
+
+PAT allows for different types of memory attributes. The most commonly used
+ones that will be supported at this time are:
+
+===  ==============
+WB   Write-back
+UC   Uncached
+WC   Write-combined
+WT   Write-through
+UC-  Uncached Minus
+===  ==============
+
+
+PAT APIs
+========
+
+There are many different APIs in the kernel that allows setting of memory
+attributes at the page level. In order to avoid aliasing, these interfaces
+should be used thoughtfully. Below is a table of interfaces available,
+their intended usage and their memory attribute relationships. Internally,
+these APIs use a reserve_memtype()/free_memtype() interface on the physical
+address range to avoid any aliasing.
+
++------------------------+----------+--------------+------------------+
+| API                    |    RAM   |  ACPI,...    |  Reserved/Holes  |
++------------------------+----------+--------------+------------------+
+| ioremap                |    --    |    UC-       |       UC-        |
++------------------------+----------+--------------+------------------+
+| ioremap_cache          |    --    |    WB        |       WB         |
++------------------------+----------+--------------+------------------+
+| ioremap_uc             |    --    |    UC        |       UC         |
++------------------------+----------+--------------+------------------+
+| ioremap_wc             |    --    |    --        |       WC         |
++------------------------+----------+--------------+------------------+
+| ioremap_wt             |    --    |    --        |       WT         |
++------------------------+----------+--------------+------------------+
+| set_memory_uc,         |    UC-   |    --        |       --         |
+| set_memory_wb          |          |              |                  |
++------------------------+----------+--------------+------------------+
+| set_memory_wc,         |    WC    |    --        |       --         |
+| set_memory_wb          |          |              |                  |
++------------------------+----------+--------------+------------------+
+| set_memory_wt,         |    WT    |    --        |       --         |
+| set_memory_wb          |          |              |                  |
++------------------------+----------+--------------+------------------+
+| pci sysfs resource     |    --    |    --        |       UC-        |
++------------------------+----------+--------------+------------------+
+| pci sysfs resource_wc  |    --    |    --        |       WC         |
+| is IORESOURCE_PREFETCH |          |              |                  |
++------------------------+----------+--------------+------------------+
+| pci proc               |    --    |    --        |       UC-        |
+| !PCIIOC_WRITE_COMBINE  |          |              |                  |
++------------------------+----------+--------------+------------------+
+| pci proc               |    --    |    --        |       WC         |
+| PCIIOC_WRITE_COMBINE   |          |              |                  |
++------------------------+----------+--------------+------------------+
+| /dev/mem               |    --    |   WB/WC/UC-  |    WB/WC/UC-     |
+| read-write             |          |              |                  |
++------------------------+----------+--------------+------------------+
+| /dev/mem               |    --    |    UC-       |       UC-        |
+| mmap SYNC flag         |          |              |                  |
++------------------------+----------+--------------+------------------+
+| /dev/mem               |    --    |   WB/WC/UC-  |  WB/WC/UC-       |
+| mmap !SYNC flag        |          |              |                  |
+| and                    |          |(from existing|  (from existing  |
+| any alias to this area |          |alias)        |  alias)          |
++------------------------+----------+--------------+------------------+
+| /dev/mem               |    --    |    WB        |       WB         |
+| mmap !SYNC flag        |          |              |                  |
+| no alias to this area  |          |              |                  |
+| and                    |          |              |                  |
+| MTRR says WB           |          |              |                  |
++------------------------+----------+--------------+------------------+
+| /dev/mem               |    --    |    --        |       UC-        |
+| mmap !SYNC flag        |          |              |                  |
+| no alias to this area  |          |              |                  |
+| and                    |          |              |                  |
+| MTRR says !WB          |          |              |                  |
++------------------------+----------+--------------+------------------+
+
+
+Advanced APIs for drivers
+=========================
+
+A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range,
+vmf_insert_pfn.
+
+Drivers wanting to export some pages to userspace do it by using mmap
+interface and a combination of:
+
+  1) pgprot_noncached()
+  2) io_remap_pfn_range() or remap_pfn_range() or vmf_insert_pfn()
+
+With PAT support, a new API pgprot_writecombine is being added. So, drivers can
+continue to use the above sequence, with either pgprot_noncached() or
+pgprot_writecombine() in step 1, followed by step 2.
+
+In addition, step 2 internally tracks the region as UC or WC in memtype
+list in order to ensure no conflicting mapping.
+
+Note that this set of APIs only works with IO (non RAM) regions. If driver
+wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
+as step 0 above and also track the usage of those pages and use set_memory_wb()
+before the page is freed to free pool.
+
+MTRR effects on PAT / non-PAT systems
+=====================================
+
+The following table provides the effects of using write-combining MTRRs when
+using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
+mtrr_add() usage will be phased out in favor of arch_phys_wc_add() which will
+be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
+is made, should already have been ioremapped with WC attributes or PAT entries,
+this can be done by using ioremap_wc() / set_memory_wc().  Devices which
+combine areas of IO memory desired to remain uncacheable with areas where
+write-combining is desirable should consider use of ioremap_uc() followed by
+set_memory_wc() to white-list effective write-combined areas.  Such use is
+nevertheless discouraged as the effective memory type is considered
+implementation defined, yet this strategy can be used as last resort on devices
+with size-constrained regions where otherwise MTRR write-combining would
+otherwise not be effective.
+::
+
+  ====  =======  ===  =========================  =====================
+  MTRR  Non-PAT  PAT  Linux ioremap value        Effective memory type
+  ====  =======  ===  =========================  =====================
+        PAT                                        Non-PAT |  PAT
+        |PCD                                               |
+        ||PWT                                              |
+        |||                                                |
+  WC    000      WB   _PAGE_CACHE_MODE_WB             WC   |   WC
+  WC    001      WC   _PAGE_CACHE_MODE_WC             WC*  |   WC
+  WC    010      UC-  _PAGE_CACHE_MODE_UC_MINUS       WC*  |   UC
+  WC    011      UC   _PAGE_CACHE_MODE_UC             UC   |   UC
+  ====  =======  ===  =========================  =====================
+
+  (*) denotes implementation defined and is discouraged
+
+.. note:: -- in the above table mean "Not suggested usage for the API". Some
+  of the --'s are strictly enforced by the kernel. Some others are not really
+  enforced today, but may be enforced in future.
+
+For ioremap and pci access through /sys or /proc - The actual type returned
+can be more restrictive, in case of any existing aliasing for that address.
+For example: If there is an existing uncached mapping, a new ioremap_wc can
+return uncached mapping in place of write-combine requested.
+
+set_memory_[uc|wc|wt] and set_memory_wb should be used in pairs, where driver
+will first make a region uc, wc or wt and switch it back to wb after use.
+
+Over time writes to /proc/mtrr will be deprecated in favor of using PAT based
+interfaces. Users writing to /proc/mtrr are suggested to use above interfaces.
+
+Drivers should use ioremap_[uc|wc] to access PCI BARs with [uc|wc] access
+types.
+
+Drivers should use set_memory_[uc|wc|wt] to set access type for RAM ranges.
+
+
+PAT debugging
+=============
+
+With CONFIG_DEBUG_FS enabled, PAT memtype list can be examined by::
+
+  # mount -t debugfs debugfs /sys/kernel/debug
+  # cat /sys/kernel/debug/x86/pat_memtype_list
+  PAT memtype list:
+  uncached-minus @ 0x7fadf000-0x7fae0000
+  uncached-minus @ 0x7fb19000-0x7fb1a000
+  uncached-minus @ 0x7fb1a000-0x7fb1b000
+  uncached-minus @ 0x7fb1b000-0x7fb1c000
+  uncached-minus @ 0x7fb1c000-0x7fb1d000
+  uncached-minus @ 0x7fb1d000-0x7fb1e000
+  uncached-minus @ 0x7fb1e000-0x7fb25000
+  uncached-minus @ 0x7fb25000-0x7fb26000
+  uncached-minus @ 0x7fb26000-0x7fb27000
+  uncached-minus @ 0x7fb27000-0x7fb28000
+  uncached-minus @ 0x7fb28000-0x7fb2e000
+  uncached-minus @ 0x7fb2e000-0x7fb2f000
+  uncached-minus @ 0x7fb2f000-0x7fb30000
+  uncached-minus @ 0x7fb31000-0x7fb32000
+  uncached-minus @ 0x80000000-0x90000000
+
+This list shows physical address ranges and various PAT settings used to
+access those physical address ranges.
+
+Another, more verbose way of getting PAT related debug messages is with
+"debugpat" boot parameter. With this parameter, various debug messages are
+printed to dmesg log.
+
+PAT Initialization
+==================
+
+The following table describes how PAT is initialized under various
+configurations. The PAT MSR must be updated by Linux in order to support WC
+and WT attributes. Otherwise, the PAT MSR has the value programmed in it
+by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests.
+
+ ==== ===== ==========================  =========  =======
+ MTRR PAT   Call Sequence               PAT State  PAT MSR
+ ==== ===== ==========================  =========  =======
+ E    E     MTRR -> PAT init            Enabled    OS
+ E    D     MTRR -> PAT init            Disabled    -
+ D    E     MTRR -> PAT disable         Disabled   BIOS
+ D    D     MTRR -> PAT disable         Disabled    -
+ -    np/E  PAT  -> PAT disable         Disabled   BIOS
+ -    np/D  PAT  -> PAT disable         Disabled    -
+ E    !P/E  MTRR -> PAT init            Disabled   BIOS
+ D    !P/E  MTRR -> PAT disable         Disabled   BIOS
+ !M   !P/E  MTRR stub -> PAT disable    Disabled   BIOS
+ ==== ===== ==========================  =========  =======
+
+  Legend
+
+ ========= =======================================
+ E         Feature enabled in CPU
+ D        Feature disabled/unsupported in CPU
+ np       "nopat" boot option specified
+ !P       CONFIG_X86_PAT option unset
+ !M       CONFIG_MTRR option unset
+ Enabled   PAT state set to enabled
+ Disabled  PAT state set to disabled
+ OS        PAT initializes PAT MSR with OS setting
+ BIOS      PAT keeps PAT MSR with BIOS setting
+ ========= =======================================
+
diff --git a/Documentation/arch/x86/pti.rst b/Documentation/arch/x86/pti.rst
new file mode 100644 (file)
index 0000000..4b858a9
--- /dev/null
@@ -0,0 +1,195 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================
+Page Table Isolation (PTI)
+==========================
+
+Overview
+========
+
+Page Table Isolation (pti, previously known as KAISER [1]_) is a
+countermeasure against attacks on the shared user/kernel address
+space such as the "Meltdown" approach [2]_.
+
+To mitigate this class of attacks, we create an independent set of
+page tables for use only when running userspace applications.  When
+the kernel is entered via syscalls, interrupts or exceptions, the
+page tables are switched to the full "kernel" copy.  When the system
+switches back to user mode, the user copy is used again.
+
+The userspace page tables contain only a minimal amount of kernel
+data: only what is needed to enter/exit the kernel such as the
+entry/exit functions themselves and the interrupt descriptor table
+(IDT).  There are a few strictly unnecessary things that get mapped
+such as the first C function when entering an interrupt (see
+comments in pti.c).
+
+This approach helps to ensure that side-channel attacks leveraging
+the paging structures do not function when PTI is enabled.  It can be
+enabled by setting CONFIG_PAGE_TABLE_ISOLATION=y at compile time.
+Once enabled at compile-time, it can be disabled at boot with the
+'nopti' or 'pti=' kernel parameters (see kernel-parameters.txt).
+
+Page Table Management
+=====================
+
+When PTI is enabled, the kernel manages two sets of page tables.
+The first set is very similar to the single set which is present in
+kernels without PTI.  This includes a complete mapping of userspace
+that the kernel can use for things like copy_to_user().
+
+Although _complete_, the user portion of the kernel page tables is
+crippled by setting the NX bit in the top level.  This ensures
+that any missed kernel->user CR3 switch will immediately crash
+userspace upon executing its first instruction.
+
+The userspace page tables map only the kernel data needed to enter
+and exit the kernel.  This data is entirely contained in the 'struct
+cpu_entry_area' structure which is placed in the fixmap which gives
+each CPU's copy of the area a compile-time-fixed virtual address.
+
+For new userspace mappings, the kernel makes the entries in its
+page tables like normal.  The only difference is when the kernel
+makes entries in the top (PGD) level.  In addition to setting the
+entry in the main kernel PGD, a copy of the entry is made in the
+userspace page tables' PGD.
+
+This sharing at the PGD level also inherently shares all the lower
+layers of the page tables.  This leaves a single, shared set of
+userspace page tables to manage.  One PTE to lock, one set of
+accessed bits, dirty bits, etc...
+
+Overhead
+========
+
+Protection against side-channel attacks is important.  But,
+this protection comes at a cost:
+
+1. Increased Memory Use
+
+  a. Each process now needs an order-1 PGD instead of order-0.
+     (Consumes an additional 4k per process).
+  b. The 'cpu_entry_area' structure must be 2MB in size and 2MB
+     aligned so that it can be mapped by setting a single PMD
+     entry.  This consumes nearly 2MB of RAM once the kernel
+     is decompressed, but no space in the kernel image itself.
+
+2. Runtime Cost
+
+  a. CR3 manipulation to switch between the page table copies
+     must be done at interrupt, syscall, and exception entry
+     and exit (it can be skipped when the kernel is interrupted,
+     though.)  Moves to CR3 are on the order of a hundred
+     cycles, and are required at every entry and exit.
+  b. A "trampoline" must be used for SYSCALL entry.  This
+     trampoline depends on a smaller set of resources than the
+     non-PTI SYSCALL entry code, so requires mapping fewer
+     things into the userspace page tables.  The downside is
+     that stacks must be switched at entry time.
+  c. Global pages are disabled for all kernel structures not
+     mapped into both kernel and userspace page tables.  This
+     feature of the MMU allows different processes to share TLB
+     entries mapping the kernel.  Losing the feature means more
+     TLB misses after a context switch.  The actual loss of
+     performance is very small, however, never exceeding 1%.
+  d. Process Context IDentifiers (PCID) is a CPU feature that
+     allows us to skip flushing the entire TLB when switching page
+     tables by setting a special bit in CR3 when the page tables
+     are changed.  This makes switching the page tables (at context
+     switch, or kernel entry/exit) cheaper.  But, on systems with
+     PCID support, the context switch code must flush both the user
+     and kernel entries out of the TLB.  The user PCID TLB flush is
+     deferred until the exit to userspace, minimizing the cost.
+     See intel.com/sdm for the gory PCID/INVPCID details.
+  e. The userspace page tables must be populated for each new
+     process.  Even without PTI, the shared kernel mappings
+     are created by copying top-level (PGD) entries into each
+     new process.  But, with PTI, there are now *two* kernel
+     mappings: one in the kernel page tables that maps everything
+     and one for the entry/exit structures.  At fork(), we need to
+     copy both.
+  f. In addition to the fork()-time copying, there must also
+     be an update to the userspace PGD any time a set_pgd() is done
+     on a PGD used to map userspace.  This ensures that the kernel
+     and userspace copies always map the same userspace
+     memory.
+  g. On systems without PCID support, each CR3 write flushes
+     the entire TLB.  That means that each syscall, interrupt
+     or exception flushes the TLB.
+  h. INVPCID is a TLB-flushing instruction which allows flushing
+     of TLB entries for non-current PCIDs.  Some systems support
+     PCIDs, but do not support INVPCID.  On these systems, addresses
+     can only be flushed from the TLB for the current PCID.  When
+     flushing a kernel address, we need to flush all PCIDs, so a
+     single kernel address flush will require a TLB-flushing CR3
+     write upon the next use of every PCID.
+
+Possible Future Work
+====================
+1. We can be more careful about not actually writing to CR3
+   unless its value is actually changed.
+2. Allow PTI to be enabled/disabled at runtime in addition to the
+   boot-time switching.
+
+Testing
+========
+
+To test stability of PTI, the following test procedure is recommended,
+ideally doing all of these in parallel:
+
+1. Set CONFIG_DEBUG_ENTRY=y
+2. Run several copies of all of the tools/testing/selftests/x86/ tests
+   (excluding MPX and protection_keys) in a loop on multiple CPUs for
+   several minutes.  These tests frequently uncover corner cases in the
+   kernel entry code.  In general, old kernels might cause these tests
+   themselves to crash, but they should never crash the kernel.
+3. Run the 'perf' tool in a mode (top or record) that generates many
+   frequent performance monitoring non-maskable interrupts (see "NMI"
+   in /proc/interrupts).  This exercises the NMI entry/exit code which
+   is known to trigger bugs in code paths that did not expect to be
+   interrupted, including nested NMIs.  Using "-c" boosts the rate of
+   NMIs, and using two -c with separate counters encourages nested NMIs
+   and less deterministic behavior.
+   ::
+
+       while true; do perf record -c 10000 -e instructions,cycles -a sleep 10; done
+
+4. Launch a KVM virtual machine.
+5. Run 32-bit binaries on systems supporting the SYSCALL instruction.
+   This has been a lightly-tested code path and needs extra scrutiny.
+
+Debugging
+=========
+
+Bugs in PTI cause a few different signatures of crashes
+that are worth noting here.
+
+ * Failures of the selftests/x86 code.  Usually a bug in one of the
+   more obscure corners of entry_64.S
+ * Crashes in early boot, especially around CPU bringup.  Bugs
+   in the trampoline code or mappings cause these.
+ * Crashes at the first interrupt.  Caused by bugs in entry_64.S,
+   like screwing up a page table switch.  Also caused by
+   incorrectly mapping the IRQ handler entry code.
+ * Crashes at the first NMI.  The NMI code is separate from main
+   interrupt handlers and can have bugs that do not affect
+   normal interrupts.  Also caused by incorrectly mapping NMI
+   code.  NMIs that interrupt the entry code must be very
+   careful and can be the cause of crashes that show up when
+   running perf.
+ * Kernel crashes at the first exit to userspace.  entry_64.S
+   bugs, or failing to map some of the exit code.
+ * Crashes at first interrupt that interrupts userspace. The paths
+   in entry_64.S that return to userspace are sometimes separate
+   from the ones that return to the kernel.
+ * Double faults: overflowing the kernel stack because of page
+   faults upon page faults.  Caused by touching non-pti-mapped
+   data in the entry code, or forgetting to switch to kernel
+   CR3 before calling into C functions which are not pti-mapped.
+ * Userspace segfaults early in boot, sometimes manifesting
+   as mount(8) failing to mount the rootfs.  These have
+   tended to be TLB invalidation issues.  Usually invalidating
+   the wrong PCID, or otherwise missing an invalidation.
+
+.. [1] https://gruss.cc/files/kaiser.pdf
+.. [2] https://meltdownattack.com/meltdown.pdf
diff --git a/Documentation/arch/x86/resctrl.rst b/Documentation/arch/x86/resctrl.rst
new file mode 100644 (file)
index 0000000..387ccbc
--- /dev/null
@@ -0,0 +1,1447 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: <isonum.txt>
+
+===========================================
+User Interface for Resource Control feature
+===========================================
+
+:Copyright: |copy| 2016 Intel Corporation
+:Authors: - Fenghua Yu <fenghua.yu@intel.com>
+          - Tony Luck <tony.luck@intel.com>
+          - Vikas Shivappa <vikas.shivappa@intel.com>
+
+
+Intel refers to this feature as Intel Resource Director Technology(Intel(R) RDT).
+AMD refers to this feature as AMD Platform Quality of Service(AMD QoS).
+
+This feature is enabled by the CONFIG_X86_CPU_RESCTRL and the x86 /proc/cpuinfo
+flag bits:
+
+===============================================        ================================
+RDT (Resource Director Technology) Allocation  "rdt_a"
+CAT (Cache Allocation Technology)              "cat_l3", "cat_l2"
+CDP (Code and Data Prioritization)             "cdp_l3", "cdp_l2"
+CQM (Cache QoS Monitoring)                     "cqm_llc", "cqm_occup_llc"
+MBM (Memory Bandwidth Monitoring)              "cqm_mbm_total", "cqm_mbm_local"
+MBA (Memory Bandwidth Allocation)              "mba"
+SMBA (Slow Memory Bandwidth Allocation)         ""
+BMEC (Bandwidth Monitoring Event Configuration) ""
+===============================================        ================================
+
+Historically, new features were made visible by default in /proc/cpuinfo. This
+resulted in the feature flags becoming hard to parse by humans. Adding a new
+flag to /proc/cpuinfo should be avoided if user space can obtain information
+about the feature from resctrl's info directory.
+
+To use the feature mount the file system::
+
+ # mount -t resctrl resctrl [-o cdp[,cdpl2][,mba_MBps]] /sys/fs/resctrl
+
+mount options are:
+
+"cdp":
+       Enable code/data prioritization in L3 cache allocations.
+"cdpl2":
+       Enable code/data prioritization in L2 cache allocations.
+"mba_MBps":
+       Enable the MBA Software Controller(mba_sc) to specify MBA
+       bandwidth in MBps
+
+L2 and L3 CDP are controlled separately.
+
+RDT features are orthogonal. A particular system may support only
+monitoring, only control, or both monitoring and control.  Cache
+pseudo-locking is a unique way of using cache control to "pin" or
+"lock" data in the cache. Details can be found in
+"Cache Pseudo-Locking".
+
+
+The mount succeeds if either of allocation or monitoring is present, but
+only those files and directories supported by the system will be created.
+For more details on the behavior of the interface during monitoring
+and allocation, see the "Resource alloc and monitor groups" section.
+
+Info directory
+==============
+
+The 'info' directory contains information about the enabled
+resources. Each resource has its own subdirectory. The subdirectory
+names reflect the resource names.
+
+Each subdirectory contains the following files with respect to
+allocation:
+
+Cache resource(L3/L2)  subdirectory contains the following files
+related to allocation:
+
+"num_closids":
+               The number of CLOSIDs which are valid for this
+               resource. The kernel uses the smallest number of
+               CLOSIDs of all enabled resources as limit.
+"cbm_mask":
+               The bitmask which is valid for this resource.
+               This mask is equivalent to 100%.
+"min_cbm_bits":
+               The minimum number of consecutive bits which
+               must be set when writing a mask.
+
+"shareable_bits":
+               Bitmask of shareable resource with other executing
+               entities (e.g. I/O). User can use this when
+               setting up exclusive cache partitions. Note that
+               some platforms support devices that have their
+               own settings for cache use which can over-ride
+               these bits.
+"bit_usage":
+               Annotated capacity bitmasks showing how all
+               instances of the resource are used. The legend is:
+
+                       "0":
+                             Corresponding region is unused. When the system's
+                             resources have been allocated and a "0" is found
+                             in "bit_usage" it is a sign that resources are
+                             wasted.
+
+                       "H":
+                             Corresponding region is used by hardware only
+                             but available for software use. If a resource
+                             has bits set in "shareable_bits" but not all
+                             of these bits appear in the resource groups'
+                             schematas then the bits appearing in
+                             "shareable_bits" but no resource group will
+                             be marked as "H".
+                       "X":
+                             Corresponding region is available for sharing and
+                             used by hardware and software. These are the
+                             bits that appear in "shareable_bits" as
+                             well as a resource group's allocation.
+                       "S":
+                             Corresponding region is used by software
+                             and available for sharing.
+                       "E":
+                             Corresponding region is used exclusively by
+                             one resource group. No sharing allowed.
+                       "P":
+                             Corresponding region is pseudo-locked. No
+                             sharing allowed.
+
+Memory bandwidth(MB) subdirectory contains the following files
+with respect to allocation:
+
+"min_bandwidth":
+               The minimum memory bandwidth percentage which
+               user can request.
+
+"bandwidth_gran":
+               The granularity in which the memory bandwidth
+               percentage is allocated. The allocated
+               b/w percentage is rounded off to the next
+               control step available on the hardware. The
+               available bandwidth control steps are:
+               min_bandwidth + N * bandwidth_gran.
+
+"delay_linear":
+               Indicates if the delay scale is linear or
+               non-linear. This field is purely informational
+               only.
+
+"thread_throttle_mode":
+               Indicator on Intel systems of how tasks running on threads
+               of a physical core are throttled in cases where they
+               request different memory bandwidth percentages:
+
+               "max":
+                       the smallest percentage is applied
+                       to all threads
+               "per-thread":
+                       bandwidth percentages are directly applied to
+                       the threads running on the core
+
+If RDT monitoring is available there will be an "L3_MON" directory
+with the following files:
+
+"num_rmids":
+               The number of RMIDs available. This is the
+               upper bound for how many "CTRL_MON" + "MON"
+               groups can be created.
+
+"mon_features":
+               Lists the monitoring events if
+               monitoring is enabled for the resource.
+               Example::
+
+                       # cat /sys/fs/resctrl/info/L3_MON/mon_features
+                       llc_occupancy
+                       mbm_total_bytes
+                       mbm_local_bytes
+
+               If the system supports Bandwidth Monitoring Event
+               Configuration (BMEC), then the bandwidth events will
+               be configurable. The output will be::
+
+                       # cat /sys/fs/resctrl/info/L3_MON/mon_features
+                       llc_occupancy
+                       mbm_total_bytes
+                       mbm_total_bytes_config
+                       mbm_local_bytes
+                       mbm_local_bytes_config
+
+"mbm_total_bytes_config", "mbm_local_bytes_config":
+       Read/write files containing the configuration for the mbm_total_bytes
+       and mbm_local_bytes events, respectively, when the Bandwidth
+       Monitoring Event Configuration (BMEC) feature is supported.
+       The event configuration settings are domain specific and affect
+       all the CPUs in the domain. When either event configuration is
+       changed, the bandwidth counters for all RMIDs of both events
+       (mbm_total_bytes as well as mbm_local_bytes) are cleared for that
+       domain. The next read for every RMID will report "Unavailable"
+       and subsequent reads will report the valid value.
+
+       Following are the types of events supported:
+
+       ====    ========================================================
+       Bits    Description
+       ====    ========================================================
+       6       Dirty Victims from the QOS domain to all types of memory
+       5       Reads to slow memory in the non-local NUMA domain
+       4       Reads to slow memory in the local NUMA domain
+       3       Non-temporal writes to non-local NUMA domain
+       2       Non-temporal writes to local NUMA domain
+       1       Reads to memory in the non-local NUMA domain
+       0       Reads to memory in the local NUMA domain
+       ====    ========================================================
+
+       By default, the mbm_total_bytes configuration is set to 0x7f to count
+       all the event types and the mbm_local_bytes configuration is set to
+       0x15 to count all the local memory events.
+
+       Examples:
+
+       * To view the current configuration::
+         ::
+
+           # cat /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
+           0=0x7f;1=0x7f;2=0x7f;3=0x7f
+
+           # cat /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config
+           0=0x15;1=0x15;3=0x15;4=0x15
+
+       * To change the mbm_total_bytes to count only reads on domain 0,
+         the bits 0, 1, 4 and 5 needs to be set, which is 110011b in binary
+         (in hexadecimal 0x33):
+         ::
+
+           # echo  "0=0x33" > /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
+
+           # cat /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
+           0=0x33;1=0x7f;2=0x7f;3=0x7f
+
+       * To change the mbm_local_bytes to count all the slow memory reads on
+         domain 0 and 1, the bits 4 and 5 needs to be set, which is 110000b
+         in binary (in hexadecimal 0x30):
+         ::
+
+           # echo  "0=0x30;1=0x30" > /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config
+
+           # cat /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config
+           0=0x30;1=0x30;3=0x15;4=0x15
+
+"max_threshold_occupancy":
+               Read/write file provides the largest value (in
+               bytes) at which a previously used LLC_occupancy
+               counter can be considered for re-use.
+
+Finally, in the top level of the "info" directory there is a file
+named "last_cmd_status". This is reset with every "command" issued
+via the file system (making new directories or writing to any of the
+control files). If the command was successful, it will read as "ok".
+If the command failed, it will provide more information that can be
+conveyed in the error returns from file operations. E.g.
+::
+
+       # echo L3:0=f7 > schemata
+       bash: echo: write error: Invalid argument
+       # cat info/last_cmd_status
+       mask f7 has non-consecutive 1-bits
+
+Resource alloc and monitor groups
+=================================
+
+Resource groups are represented as directories in the resctrl file
+system.  The default group is the root directory which, immediately
+after mounting, owns all the tasks and cpus in the system and can make
+full use of all resources.
+
+On a system with RDT control features additional directories can be
+created in the root directory that specify different amounts of each
+resource (see "schemata" below). The root and these additional top level
+directories are referred to as "CTRL_MON" groups below.
+
+On a system with RDT monitoring the root directory and other top level
+directories contain a directory named "mon_groups" in which additional
+directories can be created to monitor subsets of tasks in the CTRL_MON
+group that is their ancestor. These are called "MON" groups in the rest
+of this document.
+
+Removing a directory will move all tasks and cpus owned by the group it
+represents to the parent. Removing one of the created CTRL_MON groups
+will automatically remove all MON groups below it.
+
+All groups contain the following files:
+
+"tasks":
+       Reading this file shows the list of all tasks that belong to
+       this group. Writing a task id to the file will add a task to the
+       group. If the group is a CTRL_MON group the task is removed from
+       whichever previous CTRL_MON group owned the task and also from
+       any MON group that owned the task. If the group is a MON group,
+       then the task must already belong to the CTRL_MON parent of this
+       group. The task is removed from any previous MON group.
+
+
+"cpus":
+       Reading this file shows a bitmask of the logical CPUs owned by
+       this group. Writing a mask to this file will add and remove
+       CPUs to/from this group. As with the tasks file a hierarchy is
+       maintained where MON groups may only include CPUs owned by the
+       parent CTRL_MON group.
+       When the resource group is in pseudo-locked mode this file will
+       only be readable, reflecting the CPUs associated with the
+       pseudo-locked region.
+
+
+"cpus_list":
+       Just like "cpus", only using ranges of CPUs instead of bitmasks.
+
+
+When control is enabled all CTRL_MON groups will also contain:
+
+"schemata":
+       A list of all the resources available to this group.
+       Each resource has its own line and format - see below for details.
+
+"size":
+       Mirrors the display of the "schemata" file to display the size in
+       bytes of each allocation instead of the bits representing the
+       allocation.
+
+"mode":
+       The "mode" of the resource group dictates the sharing of its
+       allocations. A "shareable" resource group allows sharing of its
+       allocations while an "exclusive" resource group does not. A
+       cache pseudo-locked region is created by first writing
+       "pseudo-locksetup" to the "mode" file before writing the cache
+       pseudo-locked region's schemata to the resource group's "schemata"
+       file. On successful pseudo-locked region creation the mode will
+       automatically change to "pseudo-locked".
+
+When monitoring is enabled all MON groups will also contain:
+
+"mon_data":
+       This contains a set of files organized by L3 domain and by
+       RDT event. E.g. on a system with two L3 domains there will
+       be subdirectories "mon_L3_00" and "mon_L3_01".  Each of these
+       directories have one file per event (e.g. "llc_occupancy",
+       "mbm_total_bytes", and "mbm_local_bytes"). In a MON group these
+       files provide a read out of the current value of the event for
+       all tasks in the group. In CTRL_MON groups these files provide
+       the sum for all tasks in the CTRL_MON group and all tasks in
+       MON groups. Please see example section for more details on usage.
+
+Resource allocation rules
+-------------------------
+
+When a task is running the following rules define which resources are
+available to it:
+
+1) If the task is a member of a non-default group, then the schemata
+   for that group is used.
+
+2) Else if the task belongs to the default group, but is running on a
+   CPU that is assigned to some specific group, then the schemata for the
+   CPU's group is used.
+
+3) Otherwise the schemata for the default group is used.
+
+Resource monitoring rules
+-------------------------
+1) If a task is a member of a MON group, or non-default CTRL_MON group
+   then RDT events for the task will be reported in that group.
+
+2) If a task is a member of the default CTRL_MON group, but is running
+   on a CPU that is assigned to some specific group, then the RDT events
+   for the task will be reported in that group.
+
+3) Otherwise RDT events for the task will be reported in the root level
+   "mon_data" group.
+
+
+Notes on cache occupancy monitoring and control
+===============================================
+When moving a task from one group to another you should remember that
+this only affects *new* cache allocations by the task. E.g. you may have
+a task in a monitor group showing 3 MB of cache occupancy. If you move
+to a new group and immediately check the occupancy of the old and new
+groups you will likely see that the old group is still showing 3 MB and
+the new group zero. When the task accesses locations still in cache from
+before the move, the h/w does not update any counters. On a busy system
+you will likely see the occupancy in the old group go down as cache lines
+are evicted and re-used while the occupancy in the new group rises as
+the task accesses memory and loads into the cache are counted based on
+membership in the new group.
+
+The same applies to cache allocation control. Moving a task to a group
+with a smaller cache partition will not evict any cache lines. The
+process may continue to use them from the old partition.
+
+Hardware uses CLOSid(Class of service ID) and an RMID(Resource monitoring ID)
+to identify a control group and a monitoring group respectively. Each of
+the resource groups are mapped to these IDs based on the kind of group. The
+number of CLOSid and RMID are limited by the hardware and hence the creation of
+a "CTRL_MON" directory may fail if we run out of either CLOSID or RMID
+and creation of "MON" group may fail if we run out of RMIDs.
+
+max_threshold_occupancy - generic concepts
+------------------------------------------
+
+Note that an RMID once freed may not be immediately available for use as
+the RMID is still tagged the cache lines of the previous user of RMID.
+Hence such RMIDs are placed on limbo list and checked back if the cache
+occupancy has gone down. If there is a time when system has a lot of
+limbo RMIDs but which are not ready to be used, user may see an -EBUSY
+during mkdir.
+
+max_threshold_occupancy is a user configurable value to determine the
+occupancy at which an RMID can be freed.
+
+Schemata files - general concepts
+---------------------------------
+Each line in the file describes one resource. The line starts with
+the name of the resource, followed by specific values to be applied
+in each of the instances of that resource on the system.
+
+Cache IDs
+---------
+On current generation systems there is one L3 cache per socket and L2
+caches are generally just shared by the hyperthreads on a core, but this
+isn't an architectural requirement. We could have multiple separate L3
+caches on a socket, multiple cores could share an L2 cache. So instead
+of using "socket" or "core" to define the set of logical cpus sharing
+a resource we use a "Cache ID". At a given cache level this will be a
+unique number across the whole system (but it isn't guaranteed to be a
+contiguous sequence, there may be gaps).  To find the ID for each logical
+CPU look in /sys/devices/system/cpu/cpu*/cache/index*/id
+
+Cache Bit Masks (CBM)
+---------------------
+For cache resources we describe the portion of the cache that is available
+for allocation using a bitmask. The maximum value of the mask is defined
+by each cpu model (and may be different for different cache levels). It
+is found using CPUID, but is also provided in the "info" directory of
+the resctrl file system in "info/{resource}/cbm_mask". Intel hardware
+requires that these masks have all the '1' bits in a contiguous block. So
+0x3, 0x6 and 0xC are legal 4-bit masks with two bits set, but 0x5, 0x9
+and 0xA are not.  On a system with a 20-bit mask each bit represents 5%
+of the capacity of the cache. You could partition the cache into four
+equal parts with masks: 0x1f, 0x3e0, 0x7c00, 0xf8000.
+
+Memory bandwidth Allocation and monitoring
+==========================================
+
+For Memory bandwidth resource, by default the user controls the resource
+by indicating the percentage of total memory bandwidth.
+
+The minimum bandwidth percentage value for each cpu model is predefined
+and can be looked up through "info/MB/min_bandwidth". The bandwidth
+granularity that is allocated is also dependent on the cpu model and can
+be looked up at "info/MB/bandwidth_gran". The available bandwidth
+control steps are: min_bw + N * bw_gran. Intermediate values are rounded
+to the next control step available on the hardware.
+
+The bandwidth throttling is a core specific mechanism on some of Intel
+SKUs. Using a high bandwidth and a low bandwidth setting on two threads
+sharing a core may result in both threads being throttled to use the
+low bandwidth (see "thread_throttle_mode").
+
+The fact that Memory bandwidth allocation(MBA) may be a core
+specific mechanism where as memory bandwidth monitoring(MBM) is done at
+the package level may lead to confusion when users try to apply control
+via the MBA and then monitor the bandwidth to see if the controls are
+effective. Below are such scenarios:
+
+1. User may *not* see increase in actual bandwidth when percentage
+   values are increased:
+
+This can occur when aggregate L2 external bandwidth is more than L3
+external bandwidth. Consider an SKL SKU with 24 cores on a package and
+where L2 external  is 10GBps (hence aggregate L2 external bandwidth is
+240GBps) and L3 external bandwidth is 100GBps. Now a workload with '20
+threads, having 50% bandwidth, each consuming 5GBps' consumes the max L3
+bandwidth of 100GBps although the percentage value specified is only 50%
+<< 100%. Hence increasing the bandwidth percentage will not yield any
+more bandwidth. This is because although the L2 external bandwidth still
+has capacity, the L3 external bandwidth is fully used. Also note that
+this would be dependent on number of cores the benchmark is run on.
+
+2. Same bandwidth percentage may mean different actual bandwidth
+   depending on # of threads:
+
+For the same SKU in #1, a 'single thread, with 10% bandwidth' and '4
+thread, with 10% bandwidth' can consume upto 10GBps and 40GBps although
+they have same percentage bandwidth of 10%. This is simply because as
+threads start using more cores in an rdtgroup, the actual bandwidth may
+increase or vary although user specified bandwidth percentage is same.
+
+In order to mitigate this and make the interface more user friendly,
+resctrl added support for specifying the bandwidth in MBps as well.  The
+kernel underneath would use a software feedback mechanism or a "Software
+Controller(mba_sc)" which reads the actual bandwidth using MBM counters
+and adjust the memory bandwidth percentages to ensure::
+
+       "actual bandwidth < user specified bandwidth".
+
+By default, the schemata would take the bandwidth percentage values
+where as user can switch to the "MBA software controller" mode using
+a mount option 'mba_MBps'. The schemata format is specified in the below
+sections.
+
+L3 schemata file details (code and data prioritization disabled)
+----------------------------------------------------------------
+With CDP disabled the L3 schemata format is::
+
+       L3:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+L3 schemata file details (CDP enabled via mount option to resctrl)
+------------------------------------------------------------------
+When CDP is enabled L3 control is split into two separate resources
+so you can specify independent masks for code and data like this::
+
+       L3DATA:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+       L3CODE:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+L2 schemata file details
+------------------------
+CDP is supported at L2 using the 'cdpl2' mount option. The schemata
+format is either::
+
+       L2:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+or
+
+       L2DATA:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+       L2CODE:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+
+Memory bandwidth Allocation (default mode)
+------------------------------------------
+
+Memory b/w domain is L3 cache.
+::
+
+       MB:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;...
+
+Memory bandwidth Allocation specified in MBps
+---------------------------------------------
+
+Memory bandwidth domain is L3 cache.
+::
+
+       MB:<cache_id0>=bw_MBps0;<cache_id1>=bw_MBps1;...
+
+Slow Memory Bandwidth Allocation (SMBA)
+---------------------------------------
+AMD hardware supports Slow Memory Bandwidth Allocation (SMBA).
+CXL.memory is the only supported "slow" memory device. With the
+support of SMBA, the hardware enables bandwidth allocation on
+the slow memory devices. If there are multiple such devices in
+the system, the throttling logic groups all the slow sources
+together and applies the limit on them as a whole.
+
+The presence of SMBA (with CXL.memory) is independent of slow memory
+devices presence. If there are no such devices on the system, then
+configuring SMBA will have no impact on the performance of the system.
+
+The bandwidth domain for slow memory is L3 cache. Its schemata file
+is formatted as:
+::
+
+       SMBA:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;...
+
+Reading/writing the schemata file
+---------------------------------
+Reading the schemata file will show the state of all resources
+on all domains. When writing you only need to specify those values
+which you wish to change.  E.g.
+::
+
+  # cat schemata
+  L3DATA:0=fffff;1=fffff;2=fffff;3=fffff
+  L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
+  # echo "L3DATA:2=3c0;" > schemata
+  # cat schemata
+  L3DATA:0=fffff;1=fffff;2=3c0;3=fffff
+  L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
+
+Reading/writing the schemata file (on AMD systems)
+--------------------------------------------------
+Reading the schemata file will show the current bandwidth limit on all
+domains. The allocated resources are in multiples of one eighth GB/s.
+When writing to the file, you need to specify what cache id you wish to
+configure the bandwidth limit.
+
+For example, to allocate 2GB/s limit on the first cache id:
+
+::
+
+  # cat schemata
+    MB:0=2048;1=2048;2=2048;3=2048
+    L3:0=ffff;1=ffff;2=ffff;3=ffff
+
+  # echo "MB:1=16" > schemata
+  # cat schemata
+    MB:0=2048;1=  16;2=2048;3=2048
+    L3:0=ffff;1=ffff;2=ffff;3=ffff
+
+Reading/writing the schemata file (on AMD systems) with SMBA feature
+--------------------------------------------------------------------
+Reading and writing the schemata file is the same as without SMBA in
+above section.
+
+For example, to allocate 8GB/s limit on the first cache id:
+
+::
+
+  # cat schemata
+    SMBA:0=2048;1=2048;2=2048;3=2048
+      MB:0=2048;1=2048;2=2048;3=2048
+      L3:0=ffff;1=ffff;2=ffff;3=ffff
+
+  # echo "SMBA:1=64" > schemata
+  # cat schemata
+    SMBA:0=2048;1=  64;2=2048;3=2048
+      MB:0=2048;1=2048;2=2048;3=2048
+      L3:0=ffff;1=ffff;2=ffff;3=ffff
+
+Cache Pseudo-Locking
+====================
+CAT enables a user to specify the amount of cache space that an
+application can fill. Cache pseudo-locking builds on the fact that a
+CPU can still read and write data pre-allocated outside its current
+allocated area on a cache hit. With cache pseudo-locking, data can be
+preloaded into a reserved portion of cache that no application can
+fill, and from that point on will only serve cache hits. The cache
+pseudo-locked memory is made accessible to user space where an
+application can map it into its virtual address space and thus have
+a region of memory with reduced average read latency.
+
+The creation of a cache pseudo-locked region is triggered by a request
+from the user to do so that is accompanied by a schemata of the region
+to be pseudo-locked. The cache pseudo-locked region is created as follows:
+
+- Create a CAT allocation CLOSNEW with a CBM matching the schemata
+  from the user of the cache region that will contain the pseudo-locked
+  memory. This region must not overlap with any current CAT allocation/CLOS
+  on the system and no future overlap with this cache region is allowed
+  while the pseudo-locked region exists.
+- Create a contiguous region of memory of the same size as the cache
+  region.
+- Flush the cache, disable hardware prefetchers, disable preemption.
+- Make CLOSNEW the active CLOS and touch the allocated memory to load
+  it into the cache.
+- Set the previous CLOS as active.
+- At this point the closid CLOSNEW can be released - the cache
+  pseudo-locked region is protected as long as its CBM does not appear in
+  any CAT allocation. Even though the cache pseudo-locked region will from
+  this point on not appear in any CBM of any CLOS an application running with
+  any CLOS will be able to access the memory in the pseudo-locked region since
+  the region continues to serve cache hits.
+- The contiguous region of memory loaded into the cache is exposed to
+  user-space as a character device.
+
+Cache pseudo-locking increases the probability that data will remain
+in the cache via carefully configuring the CAT feature and controlling
+application behavior. There is no guarantee that data is placed in
+cache. Instructions like INVD, WBINVD, CLFLUSH, etc. can still evict
+“locked” data from cache. Power management C-states may shrink or
+power off cache. Deeper C-states will automatically be restricted on
+pseudo-locked region creation.
+
+It is required that an application using a pseudo-locked region runs
+with affinity to the cores (or a subset of the cores) associated
+with the cache on which the pseudo-locked region resides. A sanity check
+within the code will not allow an application to map pseudo-locked memory
+unless it runs with affinity to cores associated with the cache on which the
+pseudo-locked region resides. The sanity check is only done during the
+initial mmap() handling, there is no enforcement afterwards and the
+application self needs to ensure it remains affine to the correct cores.
+
+Pseudo-locking is accomplished in two stages:
+
+1) During the first stage the system administrator allocates a portion
+   of cache that should be dedicated to pseudo-locking. At this time an
+   equivalent portion of memory is allocated, loaded into allocated
+   cache portion, and exposed as a character device.
+2) During the second stage a user-space application maps (mmap()) the
+   pseudo-locked memory into its address space.
+
+Cache Pseudo-Locking Interface
+------------------------------
+A pseudo-locked region is created using the resctrl interface as follows:
+
+1) Create a new resource group by creating a new directory in /sys/fs/resctrl.
+2) Change the new resource group's mode to "pseudo-locksetup" by writing
+   "pseudo-locksetup" to the "mode" file.
+3) Write the schemata of the pseudo-locked region to the "schemata" file. All
+   bits within the schemata should be "unused" according to the "bit_usage"
+   file.
+
+On successful pseudo-locked region creation the "mode" file will contain
+"pseudo-locked" and a new character device with the same name as the resource
+group will exist in /dev/pseudo_lock. This character device can be mmap()'ed
+by user space in order to obtain access to the pseudo-locked memory region.
+
+An example of cache pseudo-locked region creation and usage can be found below.
+
+Cache Pseudo-Locking Debugging Interface
+----------------------------------------
+The pseudo-locking debugging interface is enabled by default (if
+CONFIG_DEBUG_FS is enabled) and can be found in /sys/kernel/debug/resctrl.
+
+There is no explicit way for the kernel to test if a provided memory
+location is present in the cache. The pseudo-locking debugging interface uses
+the tracing infrastructure to provide two ways to measure cache residency of
+the pseudo-locked region:
+
+1) Memory access latency using the pseudo_lock_mem_latency tracepoint. Data
+   from these measurements are best visualized using a hist trigger (see
+   example below). In this test the pseudo-locked region is traversed at
+   a stride of 32 bytes while hardware prefetchers and preemption
+   are disabled. This also provides a substitute visualization of cache
+   hits and misses.
+2) Cache hit and miss measurements using model specific precision counters if
+   available. Depending on the levels of cache on the system the pseudo_lock_l2
+   and pseudo_lock_l3 tracepoints are available.
+
+When a pseudo-locked region is created a new debugfs directory is created for
+it in debugfs as /sys/kernel/debug/resctrl/<newdir>. A single
+write-only file, pseudo_lock_measure, is present in this directory. The
+measurement of the pseudo-locked region depends on the number written to this
+debugfs file:
+
+1:
+     writing "1" to the pseudo_lock_measure file will trigger the latency
+     measurement captured in the pseudo_lock_mem_latency tracepoint. See
+     example below.
+2:
+     writing "2" to the pseudo_lock_measure file will trigger the L2 cache
+     residency (cache hits and misses) measurement captured in the
+     pseudo_lock_l2 tracepoint. See example below.
+3:
+     writing "3" to the pseudo_lock_measure file will trigger the L3 cache
+     residency (cache hits and misses) measurement captured in the
+     pseudo_lock_l3 tracepoint.
+
+All measurements are recorded with the tracing infrastructure. This requires
+the relevant tracepoints to be enabled before the measurement is triggered.
+
+Example of latency debugging interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In this example a pseudo-locked region named "newlock" was created. Here is
+how we can measure the latency in cycles of reading from this region and
+visualize this data with a histogram that is available if CONFIG_HIST_TRIGGERS
+is set::
+
+  # :> /sys/kernel/tracing/trace
+  # echo 'hist:keys=latency' > /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/trigger
+  # echo 1 > /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/enable
+  # echo 1 > /sys/kernel/debug/resctrl/newlock/pseudo_lock_measure
+  # echo 0 > /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/enable
+  # cat /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/hist
+
+  # event histogram
+  #
+  # trigger info: hist:keys=latency:vals=hitcount:sort=hitcount:size=2048 [active]
+  #
+
+  { latency:        456 } hitcount:          1
+  { latency:         50 } hitcount:         83
+  { latency:         36 } hitcount:         96
+  { latency:         44 } hitcount:        174
+  { latency:         48 } hitcount:        195
+  { latency:         46 } hitcount:        262
+  { latency:         42 } hitcount:        693
+  { latency:         40 } hitcount:       3204
+  { latency:         38 } hitcount:       3484
+
+  Totals:
+      Hits: 8192
+      Entries: 9
+    Dropped: 0
+
+Example of cache hits/misses debugging
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In this example a pseudo-locked region named "newlock" was created on the L2
+cache of a platform. Here is how we can obtain details of the cache hits
+and misses using the platform's precision counters.
+::
+
+  # :> /sys/kernel/tracing/trace
+  # echo 1 > /sys/kernel/tracing/events/resctrl/pseudo_lock_l2/enable
+  # echo 2 > /sys/kernel/debug/resctrl/newlock/pseudo_lock_measure
+  # echo 0 > /sys/kernel/tracing/events/resctrl/pseudo_lock_l2/enable
+  # cat /sys/kernel/tracing/trace
+
+  # tracer: nop
+  #
+  #                              _-----=> irqs-off
+  #                             / _----=> need-resched
+  #                            | / _---=> hardirq/softirq
+  #                            || / _--=> preempt-depth
+  #                            ||| /     delay
+  #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+  #              | |       |   ||||       |         |
+  pseudo_lock_mea-1672  [002] ....  3132.860500: pseudo_lock_l2: hits=4097 miss=0
+
+
+Examples for RDT allocation usage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1) Example 1
+
+On a two socket machine (one L3 cache per socket) with just four bits
+for cache bit masks, minimum b/w of 10% with a memory bandwidth
+granularity of 10%.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+  # mkdir p0 p1
+  # echo "L3:0=3;1=c\nMB:0=50;1=50" > /sys/fs/resctrl/p0/schemata
+  # echo "L3:0=3;1=3\nMB:0=50;1=50" > /sys/fs/resctrl/p1/schemata
+
+The default resource group is unmodified, so we have access to all parts
+of all caches (its schemata file reads "L3:0=f;1=f").
+
+Tasks that are under the control of group "p0" may only allocate from the
+"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
+Tasks in group "p1" use the "lower" 50% of cache on both sockets.
+
+Similarly, tasks that are under the control of group "p0" may use a
+maximum memory b/w of 50% on socket0 and 50% on socket 1.
+Tasks in group "p1" may also use 50% memory b/w on both sockets.
+Note that unlike cache masks, memory b/w cannot specify whether these
+allocations can overlap or not. The allocations specifies the maximum
+b/w that the group may be able to use and the system admin can configure
+the b/w accordingly.
+
+If resctrl is using the software controller (mba_sc) then user can enter the
+max b/w in MB rather than the percentage values.
+::
+
+  # echo "L3:0=3;1=c\nMB:0=1024;1=500" > /sys/fs/resctrl/p0/schemata
+  # echo "L3:0=3;1=3\nMB:0=1024;1=500" > /sys/fs/resctrl/p1/schemata
+
+In the above example the tasks in "p1" and "p0" on socket 0 would use a max b/w
+of 1024MB where as on socket 1 they would use 500MB.
+
+2) Example 2
+
+Again two sockets, but this time with a more realistic 20-bit mask.
+
+Two real time tasks pid=1234 running on processor 0 and pid=5678 running on
+processor 1 on socket 0 on a 2-socket and dual core machine. To avoid noisy
+neighbors, each of the two real-time tasks exclusively occupies one quarter
+of L3 cache on socket 0.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+
+First we reset the schemata for the default group so that the "upper"
+50% of the L3 cache on socket 0 and 50% of memory b/w cannot be used by
+ordinary tasks::
+
+  # echo "L3:0=3ff;1=fffff\nMB:0=50;1=100" > schemata
+
+Next we make a resource group for our first real time task and give
+it access to the "top" 25% of the cache on socket 0.
+::
+
+  # mkdir p0
+  # echo "L3:0=f8000;1=fffff" > p0/schemata
+
+Finally we move our first real time task into this resource group. We
+also use taskset(1) to ensure the task always runs on a dedicated CPU
+on socket 0. Most uses of resource groups will also constrain which
+processors tasks run on.
+::
+
+  # echo 1234 > p0/tasks
+  # taskset -cp 1 1234
+
+Ditto for the second real time task (with the remaining 25% of cache)::
+
+  # mkdir p1
+  # echo "L3:0=7c00;1=fffff" > p1/schemata
+  # echo 5678 > p1/tasks
+  # taskset -cp 2 5678
+
+For the same 2 socket system with memory b/w resource and CAT L3 the
+schemata would look like(Assume min_bandwidth 10 and bandwidth_gran is
+10):
+
+For our first real time task this would request 20% memory b/w on socket 0.
+::
+
+  # echo -e "L3:0=f8000;1=fffff\nMB:0=20;1=100" > p0/schemata
+
+For our second real time task this would request an other 20% memory b/w
+on socket 0.
+::
+
+  # echo -e "L3:0=f8000;1=fffff\nMB:0=20;1=100" > p0/schemata
+
+3) Example 3
+
+A single socket system which has real-time tasks running on core 4-7 and
+non real-time workload assigned to core 0-3. The real-time tasks share text
+and data, so a per task association is not required and due to interaction
+with the kernel it's desired that the kernel on these cores shares L3 with
+the tasks.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+
+First we reset the schemata for the default group so that the "upper"
+50% of the L3 cache on socket 0, and 50% of memory bandwidth on socket 0
+cannot be used by ordinary tasks::
+
+  # echo "L3:0=3ff\nMB:0=50" > schemata
+
+Next we make a resource group for our real time cores and give it access
+to the "top" 50% of the cache on socket 0 and 50% of memory bandwidth on
+socket 0.
+::
+
+  # mkdir p0
+  # echo "L3:0=ffc00\nMB:0=50" > p0/schemata
+
+Finally we move core 4-7 over to the new group and make sure that the
+kernel and the tasks running there get 50% of the cache. They should
+also get 50% of memory bandwidth assuming that the cores 4-7 are SMT
+siblings and only the real time threads are scheduled on the cores 4-7.
+::
+
+  # echo F0 > p0/cpus
+
+4) Example 4
+
+The resource groups in previous examples were all in the default "shareable"
+mode allowing sharing of their cache allocations. If one resource group
+configures a cache allocation then nothing prevents another resource group
+to overlap with that allocation.
+
+In this example a new exclusive resource group will be created on a L2 CAT
+system with two L2 cache instances that can be configured with an 8-bit
+capacity bitmask. The new exclusive resource group will be configured to use
+25% of each cache instance.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl/
+  # cd /sys/fs/resctrl
+
+First, we observe that the default group is configured to allocate to all L2
+cache::
+
+  # cat schemata
+  L2:0=ff;1=ff
+
+We could attempt to create the new resource group at this point, but it will
+fail because of the overlap with the schemata of the default group::
+
+  # mkdir p0
+  # echo 'L2:0=0x3;1=0x3' > p0/schemata
+  # cat p0/mode
+  shareable
+  # echo exclusive > p0/mode
+  -sh: echo: write error: Invalid argument
+  # cat info/last_cmd_status
+  schemata overlaps
+
+To ensure that there is no overlap with another resource group the default
+resource group's schemata has to change, making it possible for the new
+resource group to become exclusive.
+::
+
+  # echo 'L2:0=0xfc;1=0xfc' > schemata
+  # echo exclusive > p0/mode
+  # grep . p0/*
+  p0/cpus:0
+  p0/mode:exclusive
+  p0/schemata:L2:0=03;1=03
+  p0/size:L2:0=262144;1=262144
+
+A new resource group will on creation not overlap with an exclusive resource
+group::
+
+  # mkdir p1
+  # grep . p1/*
+  p1/cpus:0
+  p1/mode:shareable
+  p1/schemata:L2:0=fc;1=fc
+  p1/size:L2:0=786432;1=786432
+
+The bit_usage will reflect how the cache is used::
+
+  # cat info/L2/bit_usage
+  0=SSSSSSEE;1=SSSSSSEE
+
+A resource group cannot be forced to overlap with an exclusive resource group::
+
+  # echo 'L2:0=0x1;1=0x1' > p1/schemata
+  -sh: echo: write error: Invalid argument
+  # cat info/last_cmd_status
+  overlaps with exclusive group
+
+Example of Cache Pseudo-Locking
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Lock portion of L2 cache from cache id 1 using CBM 0x3. Pseudo-locked
+region is exposed at /dev/pseudo_lock/newlock that can be provided to
+application for argument to mmap().
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl/
+  # cd /sys/fs/resctrl
+
+Ensure that there are bits available that can be pseudo-locked, since only
+unused bits can be pseudo-locked the bits to be pseudo-locked needs to be
+removed from the default resource group's schemata::
+
+  # cat info/L2/bit_usage
+  0=SSSSSSSS;1=SSSSSSSS
+  # echo 'L2:1=0xfc' > schemata
+  # cat info/L2/bit_usage
+  0=SSSSSSSS;1=SSSSSS00
+
+Create a new resource group that will be associated with the pseudo-locked
+region, indicate that it will be used for a pseudo-locked region, and
+configure the requested pseudo-locked region capacity bitmask::
+
+  # mkdir newlock
+  # echo pseudo-locksetup > newlock/mode
+  # echo 'L2:1=0x3' > newlock/schemata
+
+On success the resource group's mode will change to pseudo-locked, the
+bit_usage will reflect the pseudo-locked region, and the character device
+exposing the pseudo-locked region will exist::
+
+  # cat newlock/mode
+  pseudo-locked
+  # cat info/L2/bit_usage
+  0=SSSSSSSS;1=SSSSSSPP
+  # ls -l /dev/pseudo_lock/newlock
+  crw------- 1 root root 243, 0 Apr  3 05:01 /dev/pseudo_lock/newlock
+
+::
+
+  /*
+  * Example code to access one page of pseudo-locked cache region
+  * from user space.
+  */
+  #define _GNU_SOURCE
+  #include <fcntl.h>
+  #include <sched.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <unistd.h>
+  #include <sys/mman.h>
+
+  /*
+  * It is required that the application runs with affinity to only
+  * cores associated with the pseudo-locked region. Here the cpu
+  * is hardcoded for convenience of example.
+  */
+  static int cpuid = 2;
+
+  int main(int argc, char *argv[])
+  {
+    cpu_set_t cpuset;
+    long page_size;
+    void *mapping;
+    int dev_fd;
+    int ret;
+
+    page_size = sysconf(_SC_PAGESIZE);
+
+    CPU_ZERO(&cpuset);
+    CPU_SET(cpuid, &cpuset);
+    ret = sched_setaffinity(0, sizeof(cpuset), &cpuset);
+    if (ret < 0) {
+      perror("sched_setaffinity");
+      exit(EXIT_FAILURE);
+    }
+
+    dev_fd = open("/dev/pseudo_lock/newlock", O_RDWR);
+    if (dev_fd < 0) {
+      perror("open");
+      exit(EXIT_FAILURE);
+    }
+
+    mapping = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+            dev_fd, 0);
+    if (mapping == MAP_FAILED) {
+      perror("mmap");
+      close(dev_fd);
+      exit(EXIT_FAILURE);
+    }
+
+    /* Application interacts with pseudo-locked memory @mapping */
+
+    ret = munmap(mapping, page_size);
+    if (ret < 0) {
+      perror("munmap");
+      close(dev_fd);
+      exit(EXIT_FAILURE);
+    }
+
+    close(dev_fd);
+    exit(EXIT_SUCCESS);
+  }
+
+Locking between applications
+----------------------------
+
+Certain operations on the resctrl filesystem, composed of read/writes
+to/from multiple files, must be atomic.
+
+As an example, the allocation of an exclusive reservation of L3 cache
+involves:
+
+  1. Read the cbmmasks from each directory or the per-resource "bit_usage"
+  2. Find a contiguous set of bits in the global CBM bitmask that is clear
+     in any of the directory cbmmasks
+  3. Create a new directory
+  4. Set the bits found in step 2 to the new directory "schemata" file
+
+If two applications attempt to allocate space concurrently then they can
+end up allocating the same bits so the reservations are shared instead of
+exclusive.
+
+To coordinate atomic operations on the resctrlfs and to avoid the problem
+above, the following locking procedure is recommended:
+
+Locking is based on flock, which is available in libc and also as a shell
+script command
+
+Write lock:
+
+ A) Take flock(LOCK_EX) on /sys/fs/resctrl
+ B) Read/write the directory structure.
+ C) funlock
+
+Read lock:
+
+ A) Take flock(LOCK_SH) on /sys/fs/resctrl
+ B) If success read the directory structure.
+ C) funlock
+
+Example with bash::
+
+  # Atomically read directory structure
+  $ flock -s /sys/fs/resctrl/ find /sys/fs/resctrl
+
+  # Read directory contents and create new subdirectory
+
+  $ cat create-dir.sh
+  find /sys/fs/resctrl/ > output.txt
+  mask = function-of(output.txt)
+  mkdir /sys/fs/resctrl/newres/
+  echo mask > /sys/fs/resctrl/newres/schemata
+
+  $ flock /sys/fs/resctrl/ ./create-dir.sh
+
+Example with C::
+
+  /*
+  * Example code do take advisory locks
+  * before accessing resctrl filesystem
+  */
+  #include <sys/file.h>
+  #include <stdlib.h>
+
+  void resctrl_take_shared_lock(int fd)
+  {
+    int ret;
+
+    /* take shared lock on resctrl filesystem */
+    ret = flock(fd, LOCK_SH);
+    if (ret) {
+      perror("flock");
+      exit(-1);
+    }
+  }
+
+  void resctrl_take_exclusive_lock(int fd)
+  {
+    int ret;
+
+    /* release lock on resctrl filesystem */
+    ret = flock(fd, LOCK_EX);
+    if (ret) {
+      perror("flock");
+      exit(-1);
+    }
+  }
+
+  void resctrl_release_lock(int fd)
+  {
+    int ret;
+
+    /* take shared lock on resctrl filesystem */
+    ret = flock(fd, LOCK_UN);
+    if (ret) {
+      perror("flock");
+      exit(-1);
+    }
+  }
+
+  void main(void)
+  {
+    int fd, ret;
+
+    fd = open("/sys/fs/resctrl", O_DIRECTORY);
+    if (fd == -1) {
+      perror("open");
+      exit(-1);
+    }
+    resctrl_take_shared_lock(fd);
+    /* code to read directory contents */
+    resctrl_release_lock(fd);
+
+    resctrl_take_exclusive_lock(fd);
+    /* code to read and write directory contents */
+    resctrl_release_lock(fd);
+  }
+
+Examples for RDT Monitoring along with allocation usage
+=======================================================
+Reading monitored data
+----------------------
+Reading an event file (for ex: mon_data/mon_L3_00/llc_occupancy) would
+show the current snapshot of LLC occupancy of the corresponding MON
+group or CTRL_MON group.
+
+
+Example 1 (Monitor CTRL_MON group and subset of tasks in CTRL_MON group)
+------------------------------------------------------------------------
+On a two socket machine (one L3 cache per socket) with just four bits
+for cache bit masks::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+  # mkdir p0 p1
+  # echo "L3:0=3;1=c" > /sys/fs/resctrl/p0/schemata
+  # echo "L3:0=3;1=3" > /sys/fs/resctrl/p1/schemata
+  # echo 5678 > p1/tasks
+  # echo 5679 > p1/tasks
+
+The default resource group is unmodified, so we have access to all parts
+of all caches (its schemata file reads "L3:0=f;1=f").
+
+Tasks that are under the control of group "p0" may only allocate from the
+"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
+Tasks in group "p1" use the "lower" 50% of cache on both sockets.
+
+Create monitor groups and assign a subset of tasks to each monitor group.
+::
+
+  # cd /sys/fs/resctrl/p1/mon_groups
+  # mkdir m11 m12
+  # echo 5678 > m11/tasks
+  # echo 5679 > m12/tasks
+
+fetch data (data shown in bytes)
+::
+
+  # cat m11/mon_data/mon_L3_00/llc_occupancy
+  16234000
+  # cat m11/mon_data/mon_L3_01/llc_occupancy
+  14789000
+  # cat m12/mon_data/mon_L3_00/llc_occupancy
+  16789000
+
+The parent ctrl_mon group shows the aggregated data.
+::
+
+  # cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
+  31234000
+
+Example 2 (Monitor a task from its creation)
+--------------------------------------------
+On a two socket machine (one L3 cache per socket)::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+  # mkdir p0 p1
+
+An RMID is allocated to the group once its created and hence the <cmd>
+below is monitored from its creation.
+::
+
+  # echo $$ > /sys/fs/resctrl/p1/tasks
+  # <cmd>
+
+Fetch the data::
+
+  # cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
+  31789000
+
+Example 3 (Monitor without CAT support or before creating CAT groups)
+---------------------------------------------------------------------
+
+Assume a system like HSW has only CQM and no CAT support. In this case
+the resctrl will still mount but cannot create CTRL_MON directories.
+But user can create different MON groups within the root group thereby
+able to monitor all tasks including kernel threads.
+
+This can also be used to profile jobs cache size footprint before being
+able to allocate them to different allocation groups.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+  # mkdir mon_groups/m01
+  # mkdir mon_groups/m02
+
+  # echo 3478 > /sys/fs/resctrl/mon_groups/m01/tasks
+  # echo 2467 > /sys/fs/resctrl/mon_groups/m02/tasks
+
+Monitor the groups separately and also get per domain data. From the
+below its apparent that the tasks are mostly doing work on
+domain(socket) 0.
+::
+
+  # cat /sys/fs/resctrl/mon_groups/m01/mon_L3_00/llc_occupancy
+  31234000
+  # cat /sys/fs/resctrl/mon_groups/m01/mon_L3_01/llc_occupancy
+  34555
+  # cat /sys/fs/resctrl/mon_groups/m02/mon_L3_00/llc_occupancy
+  31234000
+  # cat /sys/fs/resctrl/mon_groups/m02/mon_L3_01/llc_occupancy
+  32789
+
+
+Example 4 (Monitor real time tasks)
+-----------------------------------
+
+A single socket system which has real time tasks running on cores 4-7
+and non real time tasks on other cpus. We want to monitor the cache
+occupancy of the real time threads on these cores.
+::
+
+  # mount -t resctrl resctrl /sys/fs/resctrl
+  # cd /sys/fs/resctrl
+  # mkdir p1
+
+Move the cpus 4-7 over to p1::
+
+  # echo f0 > p1/cpus
+
+View the llc occupancy snapshot::
+
+  # cat /sys/fs/resctrl/p1/mon_data/mon_L3_00/llc_occupancy
+  11234000
+
+Intel RDT Errata
+================
+
+Intel MBM Counters May Report System Memory Bandwidth Incorrectly
+-----------------------------------------------------------------
+
+Errata SKX99 for Skylake server and BDF102 for Broadwell server.
+
+Problem: Intel Memory Bandwidth Monitoring (MBM) counters track metrics
+according to the assigned Resource Monitor ID (RMID) for that logical
+core. The IA32_QM_CTR register (MSR 0xC8E), used to report these
+metrics, may report incorrect system bandwidth for certain RMID values.
+
+Implication: Due to the errata, system memory bandwidth may not match
+what is reported.
+
+Workaround: MBM total and local readings are corrected according to the
+following correction factor table:
+
++---------------+---------------+---------------+-----------------+
+|core count    |rmid count     |rmid threshold |correction factor|
++---------------+---------------+---------------+-----------------+
+|1             |8              |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|2             |16             |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|3             |24             |15             |0.969650         |
++---------------+---------------+---------------+-----------------+
+|4             |32             |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|6             |48             |31             |0.969650         |
++---------------+---------------+---------------+-----------------+
+|7             |56             |47             |1.142857         |
++---------------+---------------+---------------+-----------------+
+|8             |64             |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|9             |72             |63             |1.185115         |
++---------------+---------------+---------------+-----------------+
+|10            |80             |63             |1.066553         |
++---------------+---------------+---------------+-----------------+
+|11            |88             |79             |1.454545         |
++---------------+---------------+---------------+-----------------+
+|12            |96             |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|13            |104            |95             |1.230769         |
++---------------+---------------+---------------+-----------------+
+|14            |112            |95             |1.142857         |
++---------------+---------------+---------------+-----------------+
+|15            |120            |95             |1.066667         |
++---------------+---------------+---------------+-----------------+
+|16            |128            |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|17            |136            |127            |1.254863         |
++---------------+---------------+---------------+-----------------+
+|18            |144            |127            |1.185255         |
++---------------+---------------+---------------+-----------------+
+|19            |152            |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|20            |160            |127            |1.066667         |
++---------------+---------------+---------------+-----------------+
+|21            |168            |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|22            |176            |159            |1.454334         |
++---------------+---------------+---------------+-----------------+
+|23            |184            |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|24            |192            |127            |0.969744         |
++---------------+---------------+---------------+-----------------+
+|25            |200            |191            |1.280246         |
++---------------+---------------+---------------+-----------------+
+|26            |208            |191            |1.230921         |
++---------------+---------------+---------------+-----------------+
+|27            |216            |0              |1.000000         |
++---------------+---------------+---------------+-----------------+
+|28            |224            |191            |1.143118         |
++---------------+---------------+---------------+-----------------+
+
+If rmid > rmid threshold, MBM total and local values should be multiplied
+by the correction factor.
+
+See:
+
+1. Erratum SKX99 in Intel Xeon Processor Scalable Family Specification Update:
+http://web.archive.org/web/20200716124958/https://www.intel.com/content/www/us/en/processors/xeon/scalable/xeon-scalable-spec-update.html
+
+2. Erratum BDF102 in Intel Xeon E5-2600 v4 Processor Product Family Specification Update:
+http://web.archive.org/web/20191125200531/https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/xeon-e5-v4-spec-update.pdf
+
+3. The errata in Intel Resource Director Technology (Intel RDT) on 2nd Generation Intel Xeon Scalable Processors Reference Manual:
+https://software.intel.com/content/www/us/en/develop/articles/intel-resource-director-technology-rdt-reference-manual.html
+
+for further information.
diff --git a/Documentation/arch/x86/sgx.rst b/Documentation/arch/x86/sgx.rst
new file mode 100644 (file)
index 0000000..2bcbffa
--- /dev/null
@@ -0,0 +1,302 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================
+Software Guard eXtensions (SGX)
+===============================
+
+Overview
+========
+
+Software Guard eXtensions (SGX) hardware enables for user space applications
+to set aside private memory regions of code and data:
+
+* Privileged (ring-0) ENCLS functions orchestrate the construction of the
+  regions.
+* Unprivileged (ring-3) ENCLU functions allow an application to enter and
+  execute inside the regions.
+
+These memory regions are called enclaves. An enclave can be only entered at a
+fixed set of entry points. Each entry point can hold a single hardware thread
+at a time.  While the enclave is loaded from a regular binary file by using
+ENCLS functions, only the threads inside the enclave can access its memory. The
+region is denied from outside access by the CPU, and encrypted before it leaves
+from LLC.
+
+The support can be determined by
+
+       ``grep sgx /proc/cpuinfo``
+
+SGX must both be supported in the processor and enabled by the BIOS.  If SGX
+appears to be unsupported on a system which has hardware support, ensure
+support is enabled in the BIOS.  If a BIOS presents a choice between "Enabled"
+and "Software Enabled" modes for SGX, choose "Enabled".
+
+Enclave Page Cache
+==================
+
+SGX utilizes an *Enclave Page Cache (EPC)* to store pages that are associated
+with an enclave. It is contained in a BIOS-reserved region of physical memory.
+Unlike pages used for regular memory, pages can only be accessed from outside of
+the enclave during enclave construction with special, limited SGX instructions.
+
+Only a CPU executing inside an enclave can directly access enclave memory.
+However, a CPU executing inside an enclave may access normal memory outside the
+enclave.
+
+The kernel manages enclave memory similar to how it treats device memory.
+
+Enclave Page Types
+------------------
+
+**SGX Enclave Control Structure (SECS)**
+   Enclave's address range, attributes and other global data are defined
+   by this structure.
+
+**Regular (REG)**
+   Regular EPC pages contain the code and data of an enclave.
+
+**Thread Control Structure (TCS)**
+   Thread Control Structure pages define the entry points to an enclave and
+   track the execution state of an enclave thread.
+
+**Version Array (VA)**
+   Version Array pages contain 512 slots, each of which can contain a version
+   number for a page evicted from the EPC.
+
+Enclave Page Cache Map
+----------------------
+
+The processor tracks EPC pages in a hardware metadata structure called the
+*Enclave Page Cache Map (EPCM)*.  The EPCM contains an entry for each EPC page
+which describes the owning enclave, access rights and page type among the other
+things.
+
+EPCM permissions are separate from the normal page tables.  This prevents the
+kernel from, for instance, allowing writes to data which an enclave wishes to
+remain read-only.  EPCM permissions may only impose additional restrictions on
+top of normal x86 page permissions.
+
+For all intents and purposes, the SGX architecture allows the processor to
+invalidate all EPCM entries at will.  This requires that software be prepared to
+handle an EPCM fault at any time.  In practice, this can happen on events like
+power transitions when the ephemeral key that encrypts enclave memory is lost.
+
+Application interface
+=====================
+
+Enclave build functions
+-----------------------
+
+In addition to the traditional compiler and linker build process, SGX has a
+separate enclave “build” process.  Enclaves must be built before they can be
+executed (entered). The first step in building an enclave is opening the
+**/dev/sgx_enclave** device.  Since enclave memory is protected from direct
+access, special privileged instructions are then used to copy data into enclave
+pages and establish enclave page permissions.
+
+.. kernel-doc:: arch/x86/kernel/cpu/sgx/ioctl.c
+   :functions: sgx_ioc_enclave_create
+               sgx_ioc_enclave_add_pages
+               sgx_ioc_enclave_init
+               sgx_ioc_enclave_provision
+
+Enclave runtime management
+--------------------------
+
+Systems supporting SGX2 additionally support changes to initialized
+enclaves: modifying enclave page permissions and type, and dynamically
+adding and removing of enclave pages. When an enclave accesses an address
+within its address range that does not have a backing page then a new
+regular page will be dynamically added to the enclave. The enclave is
+still required to run EACCEPT on the new page before it can be used.
+
+.. kernel-doc:: arch/x86/kernel/cpu/sgx/ioctl.c
+   :functions: sgx_ioc_enclave_restrict_permissions
+               sgx_ioc_enclave_modify_types
+               sgx_ioc_enclave_remove_pages
+
+Enclave vDSO
+------------
+
+Entering an enclave can only be done through SGX-specific EENTER and ERESUME
+functions, and is a non-trivial process.  Because of the complexity of
+transitioning to and from an enclave, enclaves typically utilize a library to
+handle the actual transitions.  This is roughly analogous to how glibc
+implementations are used by most applications to wrap system calls.
+
+Another crucial characteristic of enclaves is that they can generate exceptions
+as part of their normal operation that need to be handled in the enclave or are
+unique to SGX.
+
+Instead of the traditional signal mechanism to handle these exceptions, SGX
+can leverage special exception fixup provided by the vDSO.  The kernel-provided
+vDSO function wraps low-level transitions to/from the enclave like EENTER and
+ERESUME.  The vDSO function intercepts exceptions that would otherwise generate
+a signal and return the fault information directly to its caller.  This avoids
+the need to juggle signal handlers.
+
+.. kernel-doc:: arch/x86/include/uapi/asm/sgx.h
+   :functions: vdso_sgx_enter_enclave_t
+
+ksgxd
+=====
+
+SGX support includes a kernel thread called *ksgxd*.
+
+EPC sanitization
+----------------
+
+ksgxd is started when SGX initializes.  Enclave memory is typically ready
+for use when the processor powers on or resets.  However, if SGX has been in
+use since the reset, enclave pages may be in an inconsistent state.  This might
+occur after a crash and kexec() cycle, for instance.  At boot, ksgxd
+reinitializes all enclave pages so that they can be allocated and re-used.
+
+The sanitization is done by going through EPC address space and applying the
+EREMOVE function to each physical page. Some enclave pages like SECS pages have
+hardware dependencies on other pages which prevents EREMOVE from functioning.
+Executing two EREMOVE passes removes the dependencies.
+
+Page reclaimer
+--------------
+
+Similar to the core kswapd, ksgxd, is responsible for managing the
+overcommitment of enclave memory.  If the system runs out of enclave memory,
+*ksgxd* “swaps” enclave memory to normal memory.
+
+Launch Control
+==============
+
+SGX provides a launch control mechanism. After all enclave pages have been
+copied, kernel executes EINIT function, which initializes the enclave. Only after
+this the CPU can execute inside the enclave.
+
+EINIT function takes an RSA-3072 signature of the enclave measurement.  The function
+checks that the measurement is correct and signature is signed with the key
+hashed to the four **IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}** MSRs representing the
+SHA256 of a public key.
+
+Those MSRs can be configured by the BIOS to be either readable or writable.
+Linux supports only writable configuration in order to give full control to the
+kernel on launch control policy. Before calling EINIT function, the driver sets
+the MSRs to match the enclave's signing key.
+
+Encryption engines
+==================
+
+In order to conceal the enclave data while it is out of the CPU package, the
+memory controller has an encryption engine to transparently encrypt and decrypt
+enclave memory.
+
+In CPUs prior to Ice Lake, the Memory Encryption Engine (MEE) is used to
+encrypt pages leaving the CPU caches. MEE uses a n-ary Merkle tree with root in
+SRAM to maintain integrity of the encrypted data. This provides integrity and
+anti-replay protection but does not scale to large memory sizes because the time
+required to update the Merkle tree grows logarithmically in relation to the
+memory size.
+
+CPUs starting from Icelake use Total Memory Encryption (TME) in the place of
+MEE. TME-based SGX implementations do not have an integrity Merkle tree, which
+means integrity and replay-attacks are not mitigated.  B, it includes
+additional changes to prevent cipher text from being returned and SW memory
+aliases from being created.
+
+DMA to enclave memory is blocked by range registers on both MEE and TME systems
+(SDM section 41.10).
+
+Usage Models
+============
+
+Shared Library
+--------------
+
+Sensitive data and the code that acts on it is partitioned from the application
+into a separate library. The library is then linked as a DSO which can be loaded
+into an enclave. The application can then make individual function calls into
+the enclave through special SGX instructions. A run-time within the enclave is
+configured to marshal function parameters into and out of the enclave and to
+call the correct library function.
+
+Application Container
+---------------------
+
+An application may be loaded into a container enclave which is specially
+configured with a library OS and run-time which permits the application to run.
+The enclave run-time and library OS work together to execute the application
+when a thread enters the enclave.
+
+Impact of Potential Kernel SGX Bugs
+===================================
+
+EPC leaks
+---------
+
+When EPC page leaks happen, a WARNING like this is shown in dmesg:
+
+"EREMOVE returned ... and an EPC page was leaked.  SGX may become unusable..."
+
+This is effectively a kernel use-after-free of an EPC page, and due
+to the way SGX works, the bug is detected at freeing. Rather than
+adding the page back to the pool of available EPC pages, the kernel
+intentionally leaks the page to avoid additional errors in the future.
+
+When this happens, the kernel will likely soon leak more EPC pages, and
+SGX will likely become unusable because the memory available to SGX is
+limited. However, while this may be fatal to SGX, the rest of the kernel
+is unlikely to be impacted and should continue to work.
+
+As a result, when this happpens, user should stop running any new
+SGX workloads, (or just any new workloads), and migrate all valuable
+workloads. Although a machine reboot can recover all EPC memory, the bug
+should be reported to Linux developers.
+
+
+Virtual EPC
+===========
+
+The implementation has also a virtual EPC driver to support SGX enclaves
+in guests. Unlike the SGX driver, an EPC page allocated by the virtual
+EPC driver doesn't have a specific enclave associated with it. This is
+because KVM doesn't track how a guest uses EPC pages.
+
+As a result, the SGX core page reclaimer doesn't support reclaiming EPC
+pages allocated to KVM guests through the virtual EPC driver. If the
+user wants to deploy SGX applications both on the host and in guests
+on the same machine, the user should reserve enough EPC (by taking out
+total virtual EPC size of all SGX VMs from the physical EPC size) for
+host SGX applications so they can run with acceptable performance.
+
+Architectural behavior is to restore all EPC pages to an uninitialized
+state also after a guest reboot.  Because this state can be reached only
+through the privileged ``ENCLS[EREMOVE]`` instruction, ``/dev/sgx_vepc``
+provides the ``SGX_IOC_VEPC_REMOVE_ALL`` ioctl to execute the instruction
+on all pages in the virtual EPC.
+
+``EREMOVE`` can fail for three reasons.  Userspace must pay attention
+to expected failures and handle them as follows:
+
+1. Page removal will always fail when any thread is running in the
+   enclave to which the page belongs.  In this case the ioctl will
+   return ``EBUSY`` independent of whether it has successfully removed
+   some pages; userspace can avoid these failures by preventing execution
+   of any vcpu which maps the virtual EPC.
+
+2. Page removal will cause a general protection fault if two calls to
+   ``EREMOVE`` happen concurrently for pages that refer to the same
+   "SECS" metadata pages.  This can happen if there are concurrent
+   invocations to ``SGX_IOC_VEPC_REMOVE_ALL``, or if a ``/dev/sgx_vepc``
+   file descriptor in the guest is closed at the same time as
+   ``SGX_IOC_VEPC_REMOVE_ALL``; it will also be reported as ``EBUSY``.
+   This can be avoided in userspace by serializing calls to the ioctl()
+   and to close(), but in general it should not be a problem.
+
+3. Finally, page removal will fail for SECS metadata pages which still
+   have child pages.  Child pages can be removed by executing
+   ``SGX_IOC_VEPC_REMOVE_ALL`` on all ``/dev/sgx_vepc`` file descriptors
+   mapped into the guest.  This means that the ioctl() must be called
+   twice: an initial set of calls to remove child pages and a subsequent
+   set of calls to remove SECS pages.  The second set of calls is only
+   required for those mappings that returned a nonzero value from the
+   first call.  It indicates a bug in the kernel or the userspace client
+   if any of the second round of ``SGX_IOC_VEPC_REMOVE_ALL`` calls has
+   a return code other than 0.
diff --git a/Documentation/arch/x86/sva.rst b/Documentation/arch/x86/sva.rst
new file mode 100644 (file)
index 0000000..2e9b8b0
--- /dev/null
@@ -0,0 +1,286 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================================
+Shared Virtual Addressing (SVA) with ENQCMD
+===========================================
+
+Background
+==========
+
+Shared Virtual Addressing (SVA) allows the processor and device to use the
+same virtual addresses avoiding the need for software to translate virtual
+addresses to physical addresses. SVA is what PCIe calls Shared Virtual
+Memory (SVM).
+
+In addition to the convenience of using application virtual addresses
+by the device, it also doesn't require pinning pages for DMA.
+PCIe Address Translation Services (ATS) along with Page Request Interface
+(PRI) allow devices to function much the same way as the CPU handling
+application page-faults. For more information please refer to the PCIe
+specification Chapter 10: ATS Specification.
+
+Use of SVA requires IOMMU support in the platform. IOMMU is also
+required to support the PCIe features ATS and PRI. ATS allows devices
+to cache translations for virtual addresses. The IOMMU driver uses the
+mmu_notifier() support to keep the device TLB cache and the CPU cache in
+sync. When an ATS lookup fails for a virtual address, the device should
+use the PRI in order to request the virtual address to be paged into the
+CPU page tables. The device must use ATS again in order the fetch the
+translation before use.
+
+Shared Hardware Workqueues
+==========================
+
+Unlike Single Root I/O Virtualization (SR-IOV), Scalable IOV (SIOV) permits
+the use of Shared Work Queues (SWQ) by both applications and Virtual
+Machines (VM's). This allows better hardware utilization vs. hard
+partitioning resources that could result in under utilization. In order to
+allow the hardware to distinguish the context for which work is being
+executed in the hardware by SWQ interface, SIOV uses Process Address Space
+ID (PASID), which is a 20-bit number defined by the PCIe SIG.
+
+PASID value is encoded in all transactions from the device. This allows the
+IOMMU to track I/O on a per-PASID granularity in addition to using the PCIe
+Resource Identifier (RID) which is the Bus/Device/Function.
+
+
+ENQCMD
+======
+
+ENQCMD is a new instruction on Intel platforms that atomically submits a
+work descriptor to a device. The descriptor includes the operation to be
+performed, virtual addresses of all parameters, virtual address of a completion
+record, and the PASID (process address space ID) of the current process.
+
+ENQCMD works with non-posted semantics and carries a status back if the
+command was accepted by hardware. This allows the submitter to know if the
+submission needs to be retried or other device specific mechanisms to
+implement fairness or ensure forward progress should be provided.
+
+ENQCMD is the glue that ensures applications can directly submit commands
+to the hardware and also permits hardware to be aware of application context
+to perform I/O operations via use of PASID.
+
+Process Address Space Tagging
+=============================
+
+A new thread-scoped MSR (IA32_PASID) provides the connection between
+user processes and the rest of the hardware. When an application first
+accesses an SVA-capable device, this MSR is initialized with a newly
+allocated PASID. The driver for the device calls an IOMMU-specific API
+that sets up the routing for DMA and page-requests.
+
+For example, the Intel Data Streaming Accelerator (DSA) uses
+iommu_sva_bind_device(), which will do the following:
+
+- Allocate the PASID, and program the process page-table (%cr3 register) in the
+  PASID context entries.
+- Register for mmu_notifier() to track any page-table invalidations to keep
+  the device TLB in sync. For example, when a page-table entry is invalidated,
+  the IOMMU propagates the invalidation to the device TLB. This will force any
+  future access by the device to this virtual address to participate in
+  ATS. If the IOMMU responds with proper response that a page is not
+  present, the device would request the page to be paged in via the PCIe PRI
+  protocol before performing I/O.
+
+This MSR is managed with the XSAVE feature set as "supervisor state" to
+ensure the MSR is updated during context switch.
+
+PASID Management
+================
+
+The kernel must allocate a PASID on behalf of each process which will use
+ENQCMD and program it into the new MSR to communicate the process identity to
+platform hardware.  ENQCMD uses the PASID stored in this MSR to tag requests
+from this process.  When a user submits a work descriptor to a device using the
+ENQCMD instruction, the PASID field in the descriptor is auto-filled with the
+value from MSR_IA32_PASID. Requests for DMA from the device are also tagged
+with the same PASID. The platform IOMMU uses the PASID in the transaction to
+perform address translation. The IOMMU APIs setup the corresponding PASID
+entry in IOMMU with the process address used by the CPU (e.g. %cr3 register in
+x86).
+
+The MSR must be configured on each logical CPU before any application
+thread can interact with a device. Threads that belong to the same
+process share the same page tables, thus the same MSR value.
+
+PASID Life Cycle Management
+===========================
+
+PASID is initialized as INVALID_IOASID (-1) when a process is created.
+
+Only processes that access SVA-capable devices need to have a PASID
+allocated. This allocation happens when a process opens/binds an SVA-capable
+device but finds no PASID for this process. Subsequent binds of the same, or
+other devices will share the same PASID.
+
+Although the PASID is allocated to the process by opening a device,
+it is not active in any of the threads of that process. It's loaded to the
+IA32_PASID MSR lazily when a thread tries to submit a work descriptor
+to a device using the ENQCMD.
+
+That first access will trigger a #GP fault because the IA32_PASID MSR
+has not been initialized with the PASID value assigned to the process
+when the device was opened. The Linux #GP handler notes that a PASID has
+been allocated for the process, and so initializes the IA32_PASID MSR
+and returns so that the ENQCMD instruction is re-executed.
+
+On fork(2) or exec(2) the PASID is removed from the process as it no
+longer has the same address space that it had when the device was opened.
+
+On clone(2) the new task shares the same address space, so will be
+able to use the PASID allocated to the process. The IA32_PASID is not
+preemptively initialized as the PASID value might not be allocated yet or
+the kernel does not know whether this thread is going to access the device
+and the cleared IA32_PASID MSR reduces context switch overhead by xstate
+init optimization. Since #GP faults have to be handled on any threads that
+were created before the PASID was assigned to the mm of the process, newly
+created threads might as well be treated in a consistent way.
+
+Due to complexity of freeing the PASID and clearing all IA32_PASID MSRs in
+all threads in unbind, free the PASID lazily only on mm exit.
+
+If a process does a close(2) of the device file descriptor and munmap(2)
+of the device MMIO portal, then the driver will unbind the device. The
+PASID is still marked VALID in the PASID_MSR for any threads in the
+process that accessed the device. But this is harmless as without the
+MMIO portal they cannot submit new work to the device.
+
+Relationships
+=============
+
+ * Each process has many threads, but only one PASID.
+ * Devices have a limited number (~10's to 1000's) of hardware workqueues.
+   The device driver manages allocating hardware workqueues.
+ * A single mmap() maps a single hardware workqueue as a "portal" and
+   each portal maps down to a single workqueue.
+ * For each device with which a process interacts, there must be
+   one or more mmap()'d portals.
+ * Many threads within a process can share a single portal to access
+   a single device.
+ * Multiple processes can separately mmap() the same portal, in
+   which case they still share one device hardware workqueue.
+ * The single process-wide PASID is used by all threads to interact
+   with all devices.  There is not, for instance, a PASID for each
+   thread or each thread<->device pair.
+
+FAQ
+===
+
+* What is SVA/SVM?
+
+Shared Virtual Addressing (SVA) permits I/O hardware and the processor to
+work in the same address space, i.e., to share it. Some call it Shared
+Virtual Memory (SVM), but Linux community wanted to avoid confusing it with
+POSIX Shared Memory and Secure Virtual Machines which were terms already in
+circulation.
+
+* What is a PASID?
+
+A Process Address Space ID (PASID) is a PCIe-defined Transaction Layer Packet
+(TLP) prefix. A PASID is a 20-bit number allocated and managed by the OS.
+PASID is included in all transactions between the platform and the device.
+
+* How are shared workqueues different?
+
+Traditionally, in order for userspace applications to interact with hardware,
+there is a separate hardware instance required per process. For example,
+consider doorbells as a mechanism of informing hardware about work to process.
+Each doorbell is required to be spaced 4k (or page-size) apart for process
+isolation. This requires hardware to provision that space and reserve it in
+MMIO. This doesn't scale as the number of threads becomes quite large. The
+hardware also manages the queue depth for Shared Work Queues (SWQ), and
+consumers don't need to track queue depth. If there is no space to accept
+a command, the device will return an error indicating retry.
+
+A user should check Deferrable Memory Write (DMWr) capability on the device
+and only submits ENQCMD when the device supports it. In the new DMWr PCIe
+terminology, devices need to support DMWr completer capability. In addition,
+it requires all switch ports to support DMWr routing and must be enabled by
+the PCIe subsystem, much like how PCIe atomic operations are managed for
+instance.
+
+SWQ allows hardware to provision just a single address in the device. When
+used with ENQCMD to submit work, the device can distinguish the process
+submitting the work since it will include the PASID assigned to that
+process. This helps the device scale to a large number of processes.
+
+* Is this the same as a user space device driver?
+
+Communicating with the device via the shared workqueue is much simpler
+than a full blown user space driver. The kernel driver does all the
+initialization of the hardware. User space only needs to worry about
+submitting work and processing completions.
+
+* Is this the same as SR-IOV?
+
+Single Root I/O Virtualization (SR-IOV) focuses on providing independent
+hardware interfaces for virtualizing hardware. Hence, it's required to be
+almost fully functional interface to software supporting the traditional
+BARs, space for interrupts via MSI-X, its own register layout.
+Virtual Functions (VFs) are assisted by the Physical Function (PF)
+driver.
+
+Scalable I/O Virtualization builds on the PASID concept to create device
+instances for virtualization. SIOV requires host software to assist in
+creating virtual devices; each virtual device is represented by a PASID
+along with the bus/device/function of the device.  This allows device
+hardware to optimize device resource creation and can grow dynamically on
+demand. SR-IOV creation and management is very static in nature. Consult
+references below for more details.
+
+* Why not just create a virtual function for each app?
+
+Creating PCIe SR-IOV type Virtual Functions (VF) is expensive. VFs require
+duplicated hardware for PCI config space and interrupts such as MSI-X.
+Resources such as interrupts have to be hard partitioned between VFs at
+creation time, and cannot scale dynamically on demand. The VFs are not
+completely independent from the Physical Function (PF). Most VFs require
+some communication and assistance from the PF driver. SIOV, in contrast,
+creates a software-defined device where all the configuration and control
+aspects are mediated via the slow path. The work submission and completion
+happen without any mediation.
+
+* Does this support virtualization?
+
+ENQCMD can be used from within a guest VM. In these cases, the VMM helps
+with setting up a translation table to translate from Guest PASID to Host
+PASID. Please consult the ENQCMD instruction set reference for more
+details.
+
+* Does memory need to be pinned?
+
+When devices support SVA along with platform hardware such as IOMMU
+supporting such devices, there is no need to pin memory for DMA purposes.
+Devices that support SVA also support other PCIe features that remove the
+pinning requirement for memory.
+
+Device TLB support - Device requests the IOMMU to lookup an address before
+use via Address Translation Service (ATS) requests.  If the mapping exists
+but there is no page allocated by the OS, IOMMU hardware returns that no
+mapping exists.
+
+Device requests the virtual address to be mapped via Page Request
+Interface (PRI). Once the OS has successfully completed the mapping, it
+returns the response back to the device. The device requests again for
+a translation and continues.
+
+IOMMU works with the OS in managing consistency of page-tables with the
+device. When removing pages, it interacts with the device to remove any
+device TLB entry that might have been cached before removing the mappings from
+the OS.
+
+References
+==========
+
+VT-D:
+https://01.org/blogs/ashokraj/2018/recent-enhancements-intel-virtualization-technology-directed-i/o-intel-vt-d
+
+SIOV:
+https://01.org/blogs/2019/assignable-interfaces-intel-scalable-i/o-virtualization-linux
+
+ENQCMD in ISE:
+https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
+
+DSA spec:
+https://software.intel.com/sites/default/files/341204-intel-data-streaming-accelerator-spec.pdf
diff --git a/Documentation/arch/x86/tdx.rst b/Documentation/arch/x86/tdx.rst
new file mode 100644 (file)
index 0000000..dc8d9fd
--- /dev/null
@@ -0,0 +1,261 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+Intel Trust Domain Extensions (TDX)
+=====================================
+
+Intel's Trust Domain Extensions (TDX) protect confidential guest VMs from
+the host and physical attacks by isolating the guest register state and by
+encrypting the guest memory. In TDX, a special module running in a special
+mode sits between the host and the guest and manages the guest/host
+separation.
+
+Since the host cannot directly access guest registers or memory, much
+normal functionality of a hypervisor must be moved into the guest. This is
+implemented using a Virtualization Exception (#VE) that is handled by the
+guest kernel. A #VE is handled entirely inside the guest kernel, but some
+require the hypervisor to be consulted.
+
+TDX includes new hypercall-like mechanisms for communicating from the
+guest to the hypervisor or the TDX module.
+
+New TDX Exceptions
+==================
+
+TDX guests behave differently from bare-metal and traditional VMX guests.
+In TDX guests, otherwise normal instructions or memory accesses can cause
+#VE or #GP exceptions.
+
+Instructions marked with an '*' conditionally cause exceptions.  The
+details for these instructions are discussed below.
+
+Instruction-based #VE
+---------------------
+
+- Port I/O (INS, OUTS, IN, OUT)
+- HLT
+- MONITOR, MWAIT
+- WBINVD, INVD
+- VMCALL
+- RDMSR*,WRMSR*
+- CPUID*
+
+Instruction-based #GP
+---------------------
+
+- All VMX instructions: INVEPT, INVVPID, VMCLEAR, VMFUNC, VMLAUNCH,
+  VMPTRLD, VMPTRST, VMREAD, VMRESUME, VMWRITE, VMXOFF, VMXON
+- ENCLS, ENCLU
+- GETSEC
+- RSM
+- ENQCMD
+- RDMSR*,WRMSR*
+
+RDMSR/WRMSR Behavior
+--------------------
+
+MSR access behavior falls into three categories:
+
+- #GP generated
+- #VE generated
+- "Just works"
+
+In general, the #GP MSRs should not be used in guests.  Their use likely
+indicates a bug in the guest.  The guest may try to handle the #GP with a
+hypercall but it is unlikely to succeed.
+
+The #VE MSRs are typically able to be handled by the hypervisor.  Guests
+can make a hypercall to the hypervisor to handle the #VE.
+
+The "just works" MSRs do not need any special guest handling.  They might
+be implemented by directly passing through the MSR to the hardware or by
+trapping and handling in the TDX module.  Other than possibly being slow,
+these MSRs appear to function just as they would on bare metal.
+
+CPUID Behavior
+--------------
+
+For some CPUID leaves and sub-leaves, the virtualized bit fields of CPUID
+return values (in guest EAX/EBX/ECX/EDX) are configurable by the
+hypervisor. For such cases, the Intel TDX module architecture defines two
+virtualization types:
+
+- Bit fields for which the hypervisor controls the value seen by the guest
+  TD.
+
+- Bit fields for which the hypervisor configures the value such that the
+  guest TD either sees their native value or a value of 0.  For these bit
+  fields, the hypervisor can mask off the native values, but it can not
+  turn *on* values.
+
+A #VE is generated for CPUID leaves and sub-leaves that the TDX module does
+not know how to handle. The guest kernel may ask the hypervisor for the
+value with a hypercall.
+
+#VE on Memory Accesses
+======================
+
+There are essentially two classes of TDX memory: private and shared.
+Private memory receives full TDX protections.  Its content is protected
+against access from the hypervisor.  Shared memory is expected to be
+shared between guest and hypervisor and does not receive full TDX
+protections.
+
+A TD guest is in control of whether its memory accesses are treated as
+private or shared.  It selects the behavior with a bit in its page table
+entries.  This helps ensure that a guest does not place sensitive
+information in shared memory, exposing it to the untrusted hypervisor.
+
+#VE on Shared Memory
+--------------------
+
+Access to shared mappings can cause a #VE.  The hypervisor ultimately
+controls whether a shared memory access causes a #VE, so the guest must be
+careful to only reference shared pages it can safely handle a #VE.  For
+instance, the guest should be careful not to access shared memory in the
+#VE handler before it reads the #VE info structure (TDG.VP.VEINFO.GET).
+
+Shared mapping content is entirely controlled by the hypervisor. The guest
+should only use shared mappings for communicating with the hypervisor.
+Shared mappings must never be used for sensitive memory content like kernel
+stacks.  A good rule of thumb is that hypervisor-shared memory should be
+treated the same as memory mapped to userspace.  Both the hypervisor and
+userspace are completely untrusted.
+
+MMIO for virtual devices is implemented as shared memory.  The guest must
+be careful not to access device MMIO regions unless it is also prepared to
+handle a #VE.
+
+#VE on Private Pages
+--------------------
+
+An access to private mappings can also cause a #VE.  Since all kernel
+memory is also private memory, the kernel might theoretically need to
+handle a #VE on arbitrary kernel memory accesses.  This is not feasible, so
+TDX guests ensure that all guest memory has been "accepted" before memory
+is used by the kernel.
+
+A modest amount of memory (typically 512M) is pre-accepted by the firmware
+before the kernel runs to ensure that the kernel can start up without
+being subjected to a #VE.
+
+The hypervisor is permitted to unilaterally move accepted pages to a
+"blocked" state. However, if it does this, page access will not generate a
+#VE.  It will, instead, cause a "TD Exit" where the hypervisor is required
+to handle the exception.
+
+Linux #VE handler
+=================
+
+Just like page faults or #GP's, #VE exceptions can be either handled or be
+fatal.  Typically, an unhandled userspace #VE results in a SIGSEGV.
+An unhandled kernel #VE results in an oops.
+
+Handling nested exceptions on x86 is typically nasty business.  A #VE
+could be interrupted by an NMI which triggers another #VE and hilarity
+ensues.  The TDX #VE architecture anticipated this scenario and includes a
+feature to make it slightly less nasty.
+
+During #VE handling, the TDX module ensures that all interrupts (including
+NMIs) are blocked.  The block remains in place until the guest makes a
+TDG.VP.VEINFO.GET TDCALL.  This allows the guest to control when interrupts
+or a new #VE can be delivered.
+
+However, the guest kernel must still be careful to avoid potential
+#VE-triggering actions (discussed above) while this block is in place.
+While the block is in place, any #VE is elevated to a double fault (#DF)
+which is not recoverable.
+
+MMIO handling
+=============
+
+In non-TDX VMs, MMIO is usually implemented by giving a guest access to a
+mapping which will cause a VMEXIT on access, and then the hypervisor
+emulates the access.  That is not possible in TDX guests because VMEXIT
+will expose the register state to the host. TDX guests don't trust the host
+and can't have their state exposed to the host.
+
+In TDX, MMIO regions typically trigger a #VE exception in the guest.  The
+guest #VE handler then emulates the MMIO instruction inside the guest and
+converts it into a controlled TDCALL to the host, rather than exposing
+guest state to the host.
+
+MMIO addresses on x86 are just special physical addresses. They can
+theoretically be accessed with any instruction that accesses memory.
+However, the kernel instruction decoding method is limited. It is only
+designed to decode instructions like those generated by io.h macros.
+
+MMIO access via other means (like structure overlays) may result in an
+oops.
+
+Shared Memory Conversions
+=========================
+
+All TDX guest memory starts out as private at boot.  This memory can not
+be accessed by the hypervisor.  However, some kernel users like device
+drivers might have a need to share data with the hypervisor.  To do this,
+memory must be converted between shared and private.  This can be
+accomplished using some existing memory encryption helpers:
+
+ * set_memory_decrypted() converts a range of pages to shared.
+ * set_memory_encrypted() converts memory back to private.
+
+Device drivers are the primary user of shared memory, but there's no need
+to touch every driver. DMA buffers and ioremap() do the conversions
+automatically.
+
+TDX uses SWIOTLB for most DMA allocations. The SWIOTLB buffer is
+converted to shared on boot.
+
+For coherent DMA allocation, the DMA buffer gets converted on the
+allocation. Check force_dma_unencrypted() for details.
+
+Attestation
+===========
+
+Attestation is used to verify the TDX guest trustworthiness to other
+entities before provisioning secrets to the guest. For example, a key
+server may want to use attestation to verify that the guest is the
+desired one before releasing the encryption keys to mount the encrypted
+rootfs or a secondary drive.
+
+The TDX module records the state of the TDX guest in various stages of
+the guest boot process using the build time measurement register (MRTD)
+and runtime measurement registers (RTMR). Measurements related to the
+guest initial configuration and firmware image are recorded in the MRTD
+register. Measurements related to initial state, kernel image, firmware
+image, command line options, initrd, ACPI tables, etc are recorded in
+RTMR registers. For more details, as an example, please refer to TDX
+Virtual Firmware design specification, section titled "TD Measurement".
+At TDX guest runtime, the attestation process is used to attest to these
+measurements.
+
+The attestation process consists of two steps: TDREPORT generation and
+Quote generation.
+
+TDX guest uses TDCALL[TDG.MR.REPORT] to get the TDREPORT (TDREPORT_STRUCT)
+from the TDX module. TDREPORT is a fixed-size data structure generated by
+the TDX module which contains guest-specific information (such as build
+and boot measurements), platform security version, and the MAC to protect
+the integrity of the TDREPORT. A user-provided 64-Byte REPORTDATA is used
+as input and included in the TDREPORT. Typically it can be some nonce
+provided by attestation service so the TDREPORT can be verified uniquely.
+More details about the TDREPORT can be found in Intel TDX Module
+specification, section titled "TDG.MR.REPORT Leaf".
+
+After getting the TDREPORT, the second step of the attestation process
+is to send it to the Quoting Enclave (QE) to generate the Quote. TDREPORT
+by design can only be verified on the local platform as the MAC key is
+bound to the platform. To support remote verification of the TDREPORT,
+TDX leverages Intel SGX Quoting Enclave to verify the TDREPORT locally
+and convert it to a remotely verifiable Quote. Method of sending TDREPORT
+to QE is implementation specific. Attestation software can choose
+whatever communication channel available (i.e. vsock or TCP/IP) to
+send the TDREPORT to QE and receive the Quote.
+
+References
+==========
+
+TDX reference material is collected here:
+
+https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html
diff --git a/Documentation/arch/x86/tlb.rst b/Documentation/arch/x86/tlb.rst
new file mode 100644 (file)
index 0000000..82ec58a
--- /dev/null
@@ -0,0 +1,83 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+The TLB
+=======
+
+When the kernel unmaps or modified the attributes of a range of
+memory, it has two choices:
+
+ 1. Flush the entire TLB with a two-instruction sequence.  This is
+    a quick operation, but it causes collateral damage: TLB entries
+    from areas other than the one we are trying to flush will be
+    destroyed and must be refilled later, at some cost.
+ 2. Use the invlpg instruction to invalidate a single page at a
+    time.  This could potentially cost many more instructions, but
+    it is a much more precise operation, causing no collateral
+    damage to other TLB entries.
+
+Which method to do depends on a few things:
+
+ 1. The size of the flush being performed.  A flush of the entire
+    address space is obviously better performed by flushing the
+    entire TLB than doing 2^48/PAGE_SIZE individual flushes.
+ 2. The contents of the TLB.  If the TLB is empty, then there will
+    be no collateral damage caused by doing the global flush, and
+    all of the individual flush will have ended up being wasted
+    work.
+ 3. The size of the TLB.  The larger the TLB, the more collateral
+    damage we do with a full flush.  So, the larger the TLB, the
+    more attractive an individual flush looks.  Data and
+    instructions have separate TLBs, as do different page sizes.
+ 4. The microarchitecture.  The TLB has become a multi-level
+    cache on modern CPUs, and the global flushes have become more
+    expensive relative to single-page flushes.
+
+There is obviously no way the kernel can know all these things,
+especially the contents of the TLB during a given flush.  The
+sizes of the flush will vary greatly depending on the workload as
+well.  There is essentially no "right" point to choose.
+
+You may be doing too many individual invalidations if you see the
+invlpg instruction (or instructions _near_ it) show up high in
+profiles.  If you believe that individual invalidations being
+called too often, you can lower the tunable::
+
+       /sys/kernel/debug/x86/tlb_single_page_flush_ceiling
+
+This will cause us to do the global flush for more cases.
+Lowering it to 0 will disable the use of the individual flushes.
+Setting it to 1 is a very conservative setting and it should
+never need to be 0 under normal circumstances.
+
+Despite the fact that a single individual flush on x86 is
+guaranteed to flush a full 2MB [1]_, hugetlbfs always uses the full
+flushes.  THP is treated exactly the same as normal memory.
+
+You might see invlpg inside of flush_tlb_mm_range() show up in
+profiles, or you can use the trace_tlb_flush() tracepoints. to
+determine how long the flush operations are taking.
+
+Essentially, you are balancing the cycles you spend doing invlpg
+with the cycles that you spend refilling the TLB later.
+
+You can measure how expensive TLB refills are by using
+performance counters and 'perf stat', like this::
+
+  perf stat -e
+    cpu/event=0x8,umask=0x84,name=dtlb_load_misses_walk_duration/,
+    cpu/event=0x8,umask=0x82,name=dtlb_load_misses_walk_completed/,
+    cpu/event=0x49,umask=0x4,name=dtlb_store_misses_walk_duration/,
+    cpu/event=0x49,umask=0x2,name=dtlb_store_misses_walk_completed/,
+    cpu/event=0x85,umask=0x4,name=itlb_misses_walk_duration/,
+    cpu/event=0x85,umask=0x2,name=itlb_misses_walk_completed/
+
+That works on an IvyBridge-era CPU (i5-3320M).  Different CPUs
+may have differently-named counters, but they should at least
+be there in some form.  You can use pmu-tools 'ocperf list'
+(https://github.com/andikleen/pmu-tools) to find the right
+counters for a given CPU.
+
+.. [1] A footnote in Intel's SDM "4.10.4.2 Recommended Invalidation"
+   says: "One execution of INVLPG is sufficient even for a page
+   with size greater than 4 KBytes."
diff --git a/Documentation/arch/x86/topology.rst b/Documentation/arch/x86/topology.rst
new file mode 100644 (file)
index 0000000..7f58010
--- /dev/null
@@ -0,0 +1,234 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+x86 Topology
+============
+
+This documents and clarifies the main aspects of x86 topology modelling and
+representation in the kernel. Update/change when doing changes to the
+respective code.
+
+The architecture-agnostic topology definitions are in
+Documentation/admin-guide/cputopology.rst. This file holds x86-specific
+differences/specialities which must not necessarily apply to the generic
+definitions. Thus, the way to read up on Linux topology on x86 is to start
+with the generic one and look at this one in parallel for the x86 specifics.
+
+Needless to say, code should use the generic functions - this file is *only*
+here to *document* the inner workings of x86 topology.
+
+Started by Thomas Gleixner <tglx@linutronix.de> and Borislav Petkov <bp@alien8.de>.
+
+The main aim of the topology facilities is to present adequate interfaces to
+code which needs to know/query/use the structure of the running system wrt
+threads, cores, packages, etc.
+
+The kernel does not care about the concept of physical sockets because a
+socket has no relevance to software. It's an electromechanical component. In
+the past a socket always contained a single package (see below), but with the
+advent of Multi Chip Modules (MCM) a socket can hold more than one package. So
+there might be still references to sockets in the code, but they are of
+historical nature and should be cleaned up.
+
+The topology of a system is described in the units of:
+
+    - packages
+    - cores
+    - threads
+
+Package
+=======
+Packages contain a number of cores plus shared resources, e.g. DRAM
+controller, shared caches etc.
+
+Modern systems may also use the term 'Die' for package.
+
+AMD nomenclature for package is 'Node'.
+
+Package-related topology information in the kernel:
+
+  - cpuinfo_x86.x86_max_cores:
+
+    The number of cores in a package. This information is retrieved via CPUID.
+
+  - cpuinfo_x86.x86_max_dies:
+
+    The number of dies in a package. This information is retrieved via CPUID.
+
+  - cpuinfo_x86.cpu_die_id:
+
+    The physical ID of the die. This information is retrieved via CPUID.
+
+  - cpuinfo_x86.phys_proc_id:
+
+    The physical ID of the package. This information is retrieved via CPUID
+    and deduced from the APIC IDs of the cores in the package.
+
+    Modern systems use this value for the socket. There may be multiple
+    packages within a socket. This value may differ from cpu_die_id.
+
+  - cpuinfo_x86.logical_proc_id:
+
+    The logical ID of the package. As we do not trust BIOSes to enumerate the
+    packages in a consistent way, we introduced the concept of logical package
+    ID so we can sanely calculate the number of maximum possible packages in
+    the system and have the packages enumerated linearly.
+
+  - topology_max_packages():
+
+    The maximum possible number of packages in the system. Helpful for per
+    package facilities to preallocate per package information.
+
+  - cpu_llc_id:
+
+    A per-CPU variable containing:
+
+      - On Intel, the first APIC ID of the list of CPUs sharing the Last Level
+        Cache
+
+      - On AMD, the Node ID or Core Complex ID containing the Last Level
+        Cache. In general, it is a number identifying an LLC uniquely on the
+        system.
+
+Cores
+=====
+A core consists of 1 or more threads. It does not matter whether the threads
+are SMT- or CMT-type threads.
+
+AMDs nomenclature for a CMT core is "Compute Unit". The kernel always uses
+"core".
+
+Core-related topology information in the kernel:
+
+  - smp_num_siblings:
+
+    The number of threads in a core. The number of threads in a package can be
+    calculated by::
+
+       threads_per_package = cpuinfo_x86.x86_max_cores * smp_num_siblings
+
+
+Threads
+=======
+A thread is a single scheduling unit. It's the equivalent to a logical Linux
+CPU.
+
+AMDs nomenclature for CMT threads is "Compute Unit Core". The kernel always
+uses "thread".
+
+Thread-related topology information in the kernel:
+
+  - topology_core_cpumask():
+
+    The cpumask contains all online threads in the package to which a thread
+    belongs.
+
+    The number of online threads is also printed in /proc/cpuinfo "siblings."
+
+  - topology_sibling_cpumask():
+
+    The cpumask contains all online threads in the core to which a thread
+    belongs.
+
+  - topology_logical_package_id():
+
+    The logical package ID to which a thread belongs.
+
+  - topology_physical_package_id():
+
+    The physical package ID to which a thread belongs.
+
+  - topology_core_id();
+
+    The ID of the core to which a thread belongs. It is also printed in /proc/cpuinfo
+    "core_id."
+
+
+
+System topology examples
+========================
+
+.. note::
+  The alternative Linux CPU enumeration depends on how the BIOS enumerates the
+  threads. Many BIOSes enumerate all threads 0 first and then all threads 1.
+  That has the "advantage" that the logical Linux CPU numbers of threads 0 stay
+  the same whether threads are enabled or not. That's merely an implementation
+  detail and has no practical impact.
+
+1) Single Package, Single Core::
+
+   [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+
+2) Single Package, Dual Core
+
+   a) One thread per core::
+
+       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+                   -> [core 1] -> [thread 0] -> Linux CPU 1
+
+   b) Two threads per core::
+
+       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+                               -> [thread 1] -> Linux CPU 1
+                   -> [core 1] -> [thread 0] -> Linux CPU 2
+                               -> [thread 1] -> Linux CPU 3
+
+      Alternative enumeration::
+
+       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+                               -> [thread 1] -> Linux CPU 2
+                   -> [core 1] -> [thread 0] -> Linux CPU 1
+                               -> [thread 1] -> Linux CPU 3
+
+      AMD nomenclature for CMT systems::
+
+       [node 0] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 0
+                                    -> [Compute Unit Core 1] -> Linux CPU 1
+                -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 2
+                                    -> [Compute Unit Core 1] -> Linux CPU 3
+
+4) Dual Package, Dual Core
+
+   a) One thread per core::
+
+       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+                   -> [core 1] -> [thread 0] -> Linux CPU 1
+
+       [package 1] -> [core 0] -> [thread 0] -> Linux CPU 2
+                   -> [core 1] -> [thread 0] -> Linux CPU 3
+
+   b) Two threads per core::
+
+       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+                               -> [thread 1] -> Linux CPU 1
+                   -> [core 1] -> [thread 0] -> Linux CPU 2
+                               -> [thread 1] -> Linux CPU 3
+
+       [package 1] -> [core 0] -> [thread 0] -> Linux CPU 4
+                               -> [thread 1] -> Linux CPU 5
+                   -> [core 1] -> [thread 0] -> Linux CPU 6
+                               -> [thread 1] -> Linux CPU 7
+
+      Alternative enumeration::
+
+       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
+                               -> [thread 1] -> Linux CPU 4
+                   -> [core 1] -> [thread 0] -> Linux CPU 1
+                               -> [thread 1] -> Linux CPU 5
+
+       [package 1] -> [core 0] -> [thread 0] -> Linux CPU 2
+                               -> [thread 1] -> Linux CPU 6
+                   -> [core 1] -> [thread 0] -> Linux CPU 3
+                               -> [thread 1] -> Linux CPU 7
+
+      AMD nomenclature for CMT systems::
+
+       [node 0] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 0
+                                    -> [Compute Unit Core 1] -> Linux CPU 1
+                -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 2
+                                    -> [Compute Unit Core 1] -> Linux CPU 3
+
+       [node 1] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 4
+                                    -> [Compute Unit Core 1] -> Linux CPU 5
+                -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 6
+                                    -> [Compute Unit Core 1] -> Linux CPU 7
diff --git a/Documentation/arch/x86/tsx_async_abort.rst b/Documentation/arch/x86/tsx_async_abort.rst
new file mode 100644 (file)
index 0000000..583ddc1
--- /dev/null
@@ -0,0 +1,117 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+TSX Async Abort (TAA) mitigation
+================================
+
+.. _tsx_async_abort:
+
+Overview
+--------
+
+TSX Async Abort (TAA) is a side channel attack on internal buffers in some
+Intel processors similar to Microachitectural Data Sampling (MDS).  In this
+case certain loads may speculatively pass invalid data to dependent operations
+when an asynchronous abort condition is pending in a Transactional
+Synchronization Extensions (TSX) transaction.  This includes loads with no
+fault or assist condition. Such loads may speculatively expose stale data from
+the same uarch data structures as in MDS, with same scope of exposure i.e.
+same-thread and cross-thread. This issue affects all current processors that
+support TSX.
+
+Mitigation strategy
+-------------------
+
+a) TSX disable - one of the mitigations is to disable TSX. A new MSR
+IA32_TSX_CTRL will be available in future and current processors after
+microcode update which can be used to disable TSX. In addition, it
+controls the enumeration of the TSX feature bits (RTM and HLE) in CPUID.
+
+b) Clear CPU buffers - similar to MDS, clearing the CPU buffers mitigates this
+vulnerability. More details on this approach can be found in
+:ref:`Documentation/admin-guide/hw-vuln/mds.rst <mds>`.
+
+Kernel internal mitigation modes
+--------------------------------
+
+ =============    ============================================================
+ off              Mitigation is disabled. Either the CPU is not affected or
+                  tsx_async_abort=off is supplied on the kernel command line.
+
+ tsx disabled     Mitigation is enabled. TSX feature is disabled by default at
+                  bootup on processors that support TSX control.
+
+ verw             Mitigation is enabled. CPU is affected and MD_CLEAR is
+                  advertised in CPUID.
+
+ ucode needed     Mitigation is enabled. CPU is affected and MD_CLEAR is not
+                  advertised in CPUID. That is mainly for virtualization
+                  scenarios where the host has the updated microcode but the
+                  hypervisor does not expose MD_CLEAR in CPUID. It's a best
+                  effort approach without guarantee.
+ =============    ============================================================
+
+If the CPU is affected and the "tsx_async_abort" kernel command line parameter is
+not provided then the kernel selects an appropriate mitigation depending on the
+status of RTM and MD_CLEAR CPUID bits.
+
+Below tables indicate the impact of tsx=on|off|auto cmdline options on state of
+TAA mitigation, VERW behavior and TSX feature for various combinations of
+MSR_IA32_ARCH_CAPABILITIES bits.
+
+1. "tsx=off"
+
+=========  =========  ============  ============  ==============  ===================  ======================
+MSR_IA32_ARCH_CAPABILITIES bits     Result with cmdline tsx=off
+----------------------------------  -------------------------------------------------------------------------
+TAA_NO     MDS_NO     TSX_CTRL_MSR  TSX state     VERW can clear  TAA mitigation       TAA mitigation
+                                    after bootup  CPU buffers     tsx_async_abort=off  tsx_async_abort=full
+=========  =========  ============  ============  ==============  ===================  ======================
+    0          0           0         HW default         Yes           Same as MDS           Same as MDS
+    0          0           1        Invalid case   Invalid case       Invalid case          Invalid case
+    0          1           0         HW default         No         Need ucode update     Need ucode update
+    0          1           1          Disabled          Yes           TSX disabled          TSX disabled
+    1          X           1          Disabled           X             None needed           None needed
+=========  =========  ============  ============  ==============  ===================  ======================
+
+2. "tsx=on"
+
+=========  =========  ============  ============  ==============  ===================  ======================
+MSR_IA32_ARCH_CAPABILITIES bits     Result with cmdline tsx=on
+----------------------------------  -------------------------------------------------------------------------
+TAA_NO     MDS_NO     TSX_CTRL_MSR  TSX state     VERW can clear  TAA mitigation       TAA mitigation
+                                    after bootup  CPU buffers     tsx_async_abort=off  tsx_async_abort=full
+=========  =========  ============  ============  ==============  ===================  ======================
+    0          0           0         HW default        Yes            Same as MDS          Same as MDS
+    0          0           1        Invalid case   Invalid case       Invalid case         Invalid case
+    0          1           0         HW default        No          Need ucode update     Need ucode update
+    0          1           1          Enabled          Yes               None              Same as MDS
+    1          X           1          Enabled          X              None needed          None needed
+=========  =========  ============  ============  ==============  ===================  ======================
+
+3. "tsx=auto"
+
+=========  =========  ============  ============  ==============  ===================  ======================
+MSR_IA32_ARCH_CAPABILITIES bits     Result with cmdline tsx=auto
+----------------------------------  -------------------------------------------------------------------------
+TAA_NO     MDS_NO     TSX_CTRL_MSR  TSX state     VERW can clear  TAA mitigation       TAA mitigation
+                                    after bootup  CPU buffers     tsx_async_abort=off  tsx_async_abort=full
+=========  =========  ============  ============  ==============  ===================  ======================
+    0          0           0         HW default    Yes                Same as MDS           Same as MDS
+    0          0           1        Invalid case  Invalid case        Invalid case          Invalid case
+    0          1           0         HW default    No              Need ucode update     Need ucode update
+    0          1           1          Disabled      Yes               TSX disabled          TSX disabled
+    1          X           1          Enabled       X                 None needed           None needed
+=========  =========  ============  ============  ==============  ===================  ======================
+
+In the tables, TSX_CTRL_MSR is a new bit in MSR_IA32_ARCH_CAPABILITIES that
+indicates whether MSR_IA32_TSX_CTRL is supported.
+
+There are two control bits in IA32_TSX_CTRL MSR:
+
+      Bit 0: When set it disables the Restricted Transactional Memory (RTM)
+             sub-feature of TSX (will force all transactions to abort on the
+             XBEGIN instruction).
+
+      Bit 1: When set it disables the enumeration of the RTM and HLE feature
+             (i.e. it will make CPUID(EAX=7).EBX{bit4} and
+             CPUID(EAX=7).EBX{bit11} read as 0).
diff --git a/Documentation/arch/x86/usb-legacy-support.rst b/Documentation/arch/x86/usb-legacy-support.rst
new file mode 100644 (file)
index 0000000..e01c08b
--- /dev/null
@@ -0,0 +1,50 @@
+
+.. SPDX-License-Identifier: GPL-2.0
+
+==================
+USB Legacy support
+==================
+
+:Author: Vojtech Pavlik <vojtech@suse.cz>, January 2004
+
+
+Also known as "USB Keyboard" or "USB Mouse support" in the BIOS Setup is a
+feature that allows one to use the USB mouse and keyboard as if they were
+their classic PS/2 counterparts.  This means one can use an USB keyboard to
+type in LILO for example.
+
+It has several drawbacks, though:
+
+1) On some machines, the emulated PS/2 mouse takes over even when no USB
+   mouse is present and a real PS/2 mouse is present.  In that case the extra
+   features (wheel, extra buttons, touchpad mode) of the real PS/2 mouse may
+   not be available.
+
+2) If CONFIG_HIGHMEM64G is enabled, the PS/2 mouse emulation can cause
+   system crashes, because the SMM BIOS is not expecting to be in PAE mode.
+   The Intel E7505 is a typical machine where this happens.
+
+3) If AMD64 64-bit mode is enabled, again system crashes often happen,
+   because the SMM BIOS isn't expecting the CPU to be in 64-bit mode.  The
+   BIOS manufacturers only test with Windows, and Windows doesn't do 64-bit
+   yet.
+
+Solutions:
+
+Problem 1)
+  can be solved by loading the USB drivers prior to loading the
+  PS/2 mouse driver. Since the PS/2 mouse driver is in 2.6 compiled into
+  the kernel unconditionally, this means the USB drivers need to be
+  compiled-in, too.
+
+Problem 2)
+  can currently only be solved by either disabling HIGHMEM64G
+  in the kernel config or USB Legacy support in the BIOS. A BIOS update
+  could help, but so far no such update exists.
+
+Problem 3)
+  is usually fixed by a BIOS update. Check the board
+  manufacturers web site. If an update is not available, disable USB
+  Legacy support in the BIOS. If this alone doesn't help, try also adding
+  idle=poll on the kernel command line. The BIOS may be entering the SMM
+  on the HLT instruction as well.
diff --git a/Documentation/arch/x86/x86_64/5level-paging.rst b/Documentation/arch/x86/x86_64/5level-paging.rst
new file mode 100644 (file)
index 0000000..71f882f
--- /dev/null
@@ -0,0 +1,67 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============
+5-level paging
+==============
+
+Overview
+========
+Original x86-64 was limited by 4-level paging to 256 TiB of virtual address
+space and 64 TiB of physical address space. We are already bumping into
+this limit: some vendors offer servers with 64 TiB of memory today.
+
+To overcome the limitation upcoming hardware will introduce support for
+5-level paging. It is a straight-forward extension of the current page
+table structure adding one more layer of translation.
+
+It bumps the limits to 128 PiB of virtual address space and 4 PiB of
+physical address space. This "ought to be enough for anybody" ©.
+
+QEMU 2.9 and later support 5-level paging.
+
+Virtual memory layout for 5-level paging is described in
+Documentation/arch/x86/x86_64/mm.rst
+
+
+Enabling 5-level paging
+=======================
+CONFIG_X86_5LEVEL=y enables the feature.
+
+Kernel with CONFIG_X86_5LEVEL=y still able to boot on 4-level hardware.
+In this case additional page table level -- p4d -- will be folded at
+runtime.
+
+User-space and large virtual address space
+==========================================
+On x86, 5-level paging enables 56-bit userspace virtual address space.
+Not all user space is ready to handle wide addresses. It's known that
+at least some JIT compilers use higher bits in pointers to encode their
+information. It collides with valid pointers with 5-level paging and
+leads to crashes.
+
+To mitigate this, we are not going to allocate virtual address space
+above 47-bit by default.
+
+But userspace can ask for allocation from full address space by
+specifying hint address (with or without MAP_FIXED) above 47-bits.
+
+If hint address set above 47-bit, but MAP_FIXED is not specified, we try
+to look for unmapped area by specified address. If it's already
+occupied, we look for unmapped area in *full* address space, rather than
+from 47-bit window.
+
+A high hint address would only affect the allocation in question, but not
+any future mmap()s.
+
+Specifying high hint address on older kernel or on machine without 5-level
+paging support is safe. The hint will be ignored and kernel will fall back
+to allocation from 47-bit address space.
+
+This approach helps to easily make application's memory allocator aware
+about large address space without manually tracking allocated virtual
+address space.
+
+One important case we need to handle here is interaction with MPX.
+MPX (without MAWA extension) cannot handle addresses above 47-bit, so we
+need to make sure that MPX cannot be enabled we already have VMA above
+the boundary and forbid creating such VMAs once MPX is enabled.
diff --git a/Documentation/arch/x86/x86_64/boot-options.rst b/Documentation/arch/x86/x86_64/boot-options.rst
new file mode 100644 (file)
index 0000000..137432d
--- /dev/null
@@ -0,0 +1,319 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================
+AMD64 Specific Boot Options
+===========================
+
+There are many others (usually documented in driver documentation), but
+only the AMD64 specific ones are listed here.
+
+Machine check
+=============
+Please see Documentation/arch/x86/x86_64/machinecheck.rst for sysfs runtime tunables.
+
+   mce=off
+               Disable machine check
+   mce=no_cmci
+               Disable CMCI(Corrected Machine Check Interrupt) that
+               Intel processor supports.  Usually this disablement is
+               not recommended, but it might be handy if your hardware
+               is misbehaving.
+               Note that you'll get more problems without CMCI than with
+               due to the shared banks, i.e. you might get duplicated
+               error logs.
+   mce=dont_log_ce
+               Don't make logs for corrected errors.  All events reported
+               as corrected are silently cleared by OS.
+               This option will be useful if you have no interest in any
+               of corrected errors.
+   mce=ignore_ce
+               Disable features for corrected errors, e.g. polling timer
+               and CMCI.  All events reported as corrected are not cleared
+               by OS and remained in its error banks.
+               Usually this disablement is not recommended, however if
+               there is an agent checking/clearing corrected errors
+               (e.g. BIOS or hardware monitoring applications), conflicting
+               with OS's error handling, and you cannot deactivate the agent,
+               then this option will be a help.
+   mce=no_lmce
+               Do not opt-in to Local MCE delivery. Use legacy method
+               to broadcast MCEs.
+   mce=bootlog
+               Enable logging of machine checks left over from booting.
+               Disabled by default on AMD Fam10h and older because some BIOS
+               leave bogus ones.
+               If your BIOS doesn't do that it's a good idea to enable though
+               to make sure you log even machine check events that result
+               in a reboot. On Intel systems it is enabled by default.
+   mce=nobootlog
+               Disable boot machine check logging.
+   mce=monarchtimeout (number)
+               monarchtimeout:
+               Sets the time in us to wait for other CPUs on machine checks. 0
+               to disable.
+   mce=bios_cmci_threshold
+               Don't overwrite the bios-set CMCI threshold. This boot option
+               prevents Linux from overwriting the CMCI threshold set by the
+               bios. Without this option, Linux always sets the CMCI
+               threshold to 1. Enabling this may make memory predictive failure
+               analysis less effective if the bios sets thresholds for memory
+               errors since we will not see details for all errors.
+   mce=recovery
+               Force-enable recoverable machine check code paths
+
+   nomce (for compatibility with i386)
+               same as mce=off
+
+   Everything else is in sysfs now.
+
+APICs
+=====
+
+   apic
+       Use IO-APIC. Default
+
+   noapic
+       Don't use the IO-APIC.
+
+   disableapic
+       Don't use the local APIC
+
+   nolapic
+     Don't use the local APIC (alias for i386 compatibility)
+
+   pirq=...
+       See Documentation/arch/x86/i386/IO-APIC.rst
+
+   noapictimer
+       Don't set up the APIC timer
+
+   no_timer_check
+       Don't check the IO-APIC timer. This can work around
+       problems with incorrect timer initialization on some boards.
+
+   apicpmtimer
+       Do APIC timer calibration using the pmtimer. Implies
+       apicmaintimer. Useful when your PIT timer is totally broken.
+
+Timing
+======
+
+  notsc
+    Deprecated, use tsc=unstable instead.
+
+  nohpet
+    Don't use the HPET timer.
+
+Idle loop
+=========
+
+  idle=poll
+    Don't do power saving in the idle loop using HLT, but poll for rescheduling
+    event. This will make the CPUs eat a lot more power, but may be useful
+    to get slightly better performance in multiprocessor benchmarks. It also
+    makes some profiling using performance counters more accurate.
+    Please note that on systems with MONITOR/MWAIT support (like Intel EM64T
+    CPUs) this option has no performance advantage over the normal idle loop.
+    It may also interact badly with hyperthreading.
+
+Rebooting
+=========
+
+   reboot=b[ios] | t[riple] | k[bd] | a[cpi] | e[fi] | p[ci] [, [w]arm | [c]old]
+      bios
+        Use the CPU reboot vector for warm reset
+      warm
+        Don't set the cold reboot flag
+      cold
+        Set the cold reboot flag
+      triple
+        Force a triple fault (init)
+      kbd
+        Use the keyboard controller. cold reset (default)
+      acpi
+        Use the ACPI RESET_REG in the FADT. If ACPI is not configured or
+        the ACPI reset does not work, the reboot path attempts the reset
+        using the keyboard controller.
+      efi
+        Use efi reset_system runtime service. If EFI is not configured or
+        the EFI reset does not work, the reboot path attempts the reset using
+        the keyboard controller.
+      pci
+        Use a write to the PCI config space register 0xcf9 to trigger reboot.
+
+   Using warm reset will be much faster especially on big memory
+   systems because the BIOS will not go through the memory check.
+   Disadvantage is that not all hardware will be completely reinitialized
+   on reboot so there may be boot problems on some systems.
+
+   reboot=force
+     Don't stop other CPUs on reboot. This can make reboot more reliable
+     in some cases.
+
+   reboot=default
+     There are some built-in platform specific "quirks" - you may see:
+     "reboot: <name> series board detected. Selecting <type> for reboots."
+     In the case where you think the quirk is in error (e.g. you have
+     newer BIOS, or newer board) using this option will ignore the built-in
+     quirk table, and use the generic default reboot actions.
+
+NUMA
+====
+
+  numa=off
+    Only set up a single NUMA node spanning all memory.
+
+  numa=noacpi
+    Don't parse the SRAT table for NUMA setup
+
+  numa=nohmat
+    Don't parse the HMAT table for NUMA setup, or soft-reserved memory
+    partitioning.
+
+  numa=fake=<size>[MG]
+    If given as a memory unit, fills all system RAM with nodes of
+    size interleaved over physical nodes.
+
+  numa=fake=<N>
+    If given as an integer, fills all system RAM with N fake nodes
+    interleaved over physical nodes.
+
+  numa=fake=<N>U
+    If given as an integer followed by 'U', it will divide each
+    physical node into N emulated nodes.
+
+ACPI
+====
+
+  acpi=off
+    Don't enable ACPI
+  acpi=ht
+    Use ACPI boot table parsing, but don't enable ACPI interpreter
+  acpi=force
+    Force ACPI on (currently not needed)
+  acpi=strict
+    Disable out of spec ACPI workarounds.
+  acpi_sci={edge,level,high,low}
+    Set up ACPI SCI interrupt.
+  acpi=noirq
+    Don't route interrupts
+  acpi=nocmcff
+    Disable firmware first mode for corrected errors. This
+    disables parsing the HEST CMC error source to check if
+    firmware has set the FF flag. This may result in
+    duplicate corrected error reports.
+
+PCI
+===
+
+  pci=off
+    Don't use PCI
+  pci=conf1
+    Use conf1 access.
+  pci=conf2
+    Use conf2 access.
+  pci=rom
+    Assign ROMs.
+  pci=assign-busses
+    Assign busses
+  pci=irqmask=MASK
+    Set PCI interrupt mask to MASK
+  pci=lastbus=NUMBER
+    Scan up to NUMBER busses, no matter what the mptable says.
+  pci=noacpi
+    Don't use ACPI to set up PCI interrupt routing.
+
+IOMMU (input/output memory management unit)
+===========================================
+Multiple x86-64 PCI-DMA mapping implementations exist, for example:
+
+   1. <kernel/dma/direct.c>: use no hardware/software IOMMU at all
+      (e.g. because you have < 3 GB memory).
+      Kernel boot message: "PCI-DMA: Disabling IOMMU"
+
+   2. <arch/x86/kernel/amd_gart_64.c>: AMD GART based hardware IOMMU.
+      Kernel boot message: "PCI-DMA: using GART IOMMU"
+
+   3. <arch/x86_64/kernel/pci-swiotlb.c> : Software IOMMU implementation. Used
+      e.g. if there is no hardware IOMMU in the system and it is need because
+      you have >3GB memory or told the kernel to us it (iommu=soft))
+      Kernel boot message: "PCI-DMA: Using software bounce buffering
+      for IO (SWIOTLB)"
+
+::
+
+  iommu=[<size>][,noagp][,off][,force][,noforce]
+  [,memaper[=<order>]][,merge][,fullflush][,nomerge]
+  [,noaperture]
+
+General iommu options:
+
+    off
+      Don't initialize and use any kind of IOMMU.
+    noforce
+      Don't force hardware IOMMU usage when it is not needed. (default).
+    force
+      Force the use of the hardware IOMMU even when it is
+      not actually needed (e.g. because < 3 GB memory).
+    soft
+      Use software bounce buffering (SWIOTLB) (default for
+      Intel machines). This can be used to prevent the usage
+      of an available hardware IOMMU.
+
+iommu options only relevant to the AMD GART hardware IOMMU:
+
+    <size>
+      Set the size of the remapping area in bytes.
+    allowed
+      Overwrite iommu off workarounds for specific chipsets.
+    fullflush
+      Flush IOMMU on each allocation (default).
+    nofullflush
+      Don't use IOMMU fullflush.
+    memaper[=<order>]
+      Allocate an own aperture over RAM with size 32MB<<order.
+      (default: order=1, i.e. 64MB)
+    merge
+      Do scatter-gather (SG) merging. Implies "force" (experimental).
+    nomerge
+      Don't do scatter-gather (SG) merging.
+    noaperture
+      Ask the IOMMU not to touch the aperture for AGP.
+    noagp
+      Don't initialize the AGP driver and use full aperture.
+    panic
+      Always panic when IOMMU overflows.
+
+iommu options only relevant to the software bounce buffering (SWIOTLB) IOMMU
+implementation:
+
+    swiotlb=<slots>[,force,noforce]
+      <slots>
+        Prereserve that many 2K slots for the software IO bounce buffering.
+      force
+        Force all IO through the software TLB.
+      noforce
+        Do not initialize the software TLB.
+
+
+Miscellaneous
+=============
+
+  nogbpages
+    Do not use GB pages for kernel direct mappings.
+  gbpages
+    Use GB pages for kernel direct mappings.
+
+
+AMD SEV (Secure Encrypted Virtualization)
+=========================================
+Options relating to AMD SEV, specified via the following format:
+
+::
+
+   sev=option1[,option2]
+
+The available options are:
+
+   debug
+     Enable debug messages.
diff --git a/Documentation/arch/x86/x86_64/cpu-hotplug-spec.rst b/Documentation/arch/x86/x86_64/cpu-hotplug-spec.rst
new file mode 100644 (file)
index 0000000..8d1c91f
--- /dev/null
@@ -0,0 +1,24 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================================
+Firmware support for CPU hotplug under Linux/x86-64
+===================================================
+
+Linux/x86-64 supports CPU hotplug now. For various reasons Linux wants to
+know in advance of boot time the maximum number of CPUs that could be plugged
+into the system. ACPI 3.0 currently has no official way to supply
+this information from the firmware to the operating system.
+
+In ACPI each CPU needs an LAPIC object in the MADT table (5.2.11.5 in the
+ACPI 3.0 specification).  ACPI already has the concept of disabled LAPIC
+objects by setting the Enabled bit in the LAPIC object to zero.
+
+For CPU hotplug Linux/x86-64 expects now that any possible future hotpluggable
+CPU is already available in the MADT. If the CPU is not available yet
+it should have its LAPIC Enabled bit set to 0. Linux will use the number
+of disabled LAPICs to compute the maximum number of future CPUs.
+
+In the worst case the user can overwrite this choice using a command line
+option (additional_cpus=...), but it is recommended to supply the correct
+number (or a reasonable approximation of it, with erring towards more not less)
+in the MADT to avoid manual configuration.
diff --git a/Documentation/arch/x86/x86_64/fake-numa-for-cpusets.rst b/Documentation/arch/x86/x86_64/fake-numa-for-cpusets.rst
new file mode 100644 (file)
index 0000000..ba74617
--- /dev/null
@@ -0,0 +1,78 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================
+Fake NUMA For CPUSets
+=====================
+
+:Author: David Rientjes <rientjes@cs.washington.edu>
+
+Using numa=fake and CPUSets for Resource Management
+
+This document describes how the numa=fake x86_64 command-line option can be used
+in conjunction with cpusets for coarse memory management.  Using this feature,
+you can create fake NUMA nodes that represent contiguous chunks of memory and
+assign them to cpusets and their attached tasks.  This is a way of limiting the
+amount of system memory that are available to a certain class of tasks.
+
+For more information on the features of cpusets, see
+Documentation/admin-guide/cgroup-v1/cpusets.rst.
+There are a number of different configurations you can use for your needs.  For
+more information on the numa=fake command line option and its various ways of
+configuring fake nodes, see Documentation/arch/x86/x86_64/boot-options.rst.
+
+For the purposes of this introduction, we'll assume a very primitive NUMA
+emulation setup of "numa=fake=4*512,".  This will split our system memory into
+four equal chunks of 512M each that we can now use to assign to cpusets.  As
+you become more familiar with using this combination for resource control,
+you'll determine a better setup to minimize the number of nodes you have to deal
+with.
+
+A machine may be split as follows with "numa=fake=4*512," as reported by dmesg::
+
+       Faking node 0 at 0000000000000000-0000000020000000 (512MB)
+       Faking node 1 at 0000000020000000-0000000040000000 (512MB)
+       Faking node 2 at 0000000040000000-0000000060000000 (512MB)
+       Faking node 3 at 0000000060000000-0000000080000000 (512MB)
+       ...
+       On node 0 totalpages: 130975
+       On node 1 totalpages: 131072
+       On node 2 totalpages: 131072
+       On node 3 totalpages: 131072
+
+Now following the instructions for mounting the cpusets filesystem from
+Documentation/admin-guide/cgroup-v1/cpusets.rst, you can assign fake nodes (i.e. contiguous memory
+address spaces) to individual cpusets::
+
+       [root@xroads /]# mkdir exampleset
+       [root@xroads /]# mount -t cpuset none exampleset
+       [root@xroads /]# mkdir exampleset/ddset
+       [root@xroads /]# cd exampleset/ddset
+       [root@xroads /exampleset/ddset]# echo 0-1 > cpus
+       [root@xroads /exampleset/ddset]# echo 0-1 > mems
+
+Now this cpuset, 'ddset', will only allowed access to fake nodes 0 and 1 for
+memory allocations (1G).
+
+You can now assign tasks to these cpusets to limit the memory resources
+available to them according to the fake nodes assigned as mems::
+
+       [root@xroads /exampleset/ddset]# echo $$ > tasks
+       [root@xroads /exampleset/ddset]# dd if=/dev/zero of=tmp bs=1024 count=1G
+       [1] 13425
+
+Notice the difference between the system memory usage as reported by
+/proc/meminfo between the restricted cpuset case above and the unrestricted
+case (i.e. running the same 'dd' command without assigning it to a fake NUMA
+cpuset):
+
+       ========        ============    ==========
+       Name            Unrestricted    Restricted
+       ========        ============    ==========
+       MemTotal        3091900 kB      3091900 kB
+       MemFree         42113 kB        1513236 kB
+       ========        ============    ==========
+
+This allows for coarse memory management for the tasks you assign to particular
+cpusets.  Since cpusets can form a hierarchy, you can create some pretty
+interesting combinations of use-cases for various classes of tasks for your
+memory management needs.
diff --git a/Documentation/arch/x86/x86_64/fsgs.rst b/Documentation/arch/x86/x86_64/fsgs.rst
new file mode 100644 (file)
index 0000000..50960e0
--- /dev/null
@@ -0,0 +1,199 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Using FS and GS segments in user space applications
+===================================================
+
+The x86 architecture supports segmentation. Instructions which access
+memory can use segment register based addressing mode. The following
+notation is used to address a byte within a segment:
+
+  Segment-register:Byte-address
+
+The segment base address is added to the Byte-address to compute the
+resulting virtual address which is accessed. This allows to access multiple
+instances of data with the identical Byte-address, i.e. the same code. The
+selection of a particular instance is purely based on the base-address in
+the segment register.
+
+In 32-bit mode the CPU provides 6 segments, which also support segment
+limits. The limits can be used to enforce address space protections.
+
+In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address is
+always 0 to provide a full 64bit address space. The FS and GS segments are
+still functional in 64-bit mode.
+
+Common FS and GS usage
+------------------------------
+
+The FS segment is commonly used to address Thread Local Storage (TLS). FS
+is usually managed by runtime code or a threading library. Variables
+declared with the '__thread' storage class specifier are instantiated per
+thread and the compiler emits the FS: address prefix for accesses to these
+variables. Each thread has its own FS base address so common code can be
+used without complex address offset calculations to access the per thread
+instances. Applications should not use FS for other purposes when they use
+runtimes or threading libraries which manage the per thread FS.
+
+The GS segment has no common use and can be used freely by
+applications. GCC and Clang support GS based addressing via address space
+identifiers.
+
+Reading and writing the FS/GS base address
+------------------------------------------
+
+There exist two mechanisms to read and write the FS/GS base address:
+
+ - the arch_prctl() system call
+
+ - the FSGSBASE instruction family
+
+Accessing FS/GS base with arch_prctl()
+--------------------------------------
+
+ The arch_prctl(2) based mechanism is available on all 64-bit CPUs and all
+ kernel versions.
+
+ Reading the base:
+
+   arch_prctl(ARCH_GET_FS, &fsbase);
+   arch_prctl(ARCH_GET_GS, &gsbase);
+
+ Writing the base:
+
+   arch_prctl(ARCH_SET_FS, fsbase);
+   arch_prctl(ARCH_SET_GS, gsbase);
+
+ The ARCH_SET_GS prctl may be disabled depending on kernel configuration
+ and security settings.
+
+Accessing FS/GS base with the FSGSBASE instructions
+---------------------------------------------------
+
+ With the Ivy Bridge CPU generation Intel introduced a new set of
+ instructions to access the FS and GS base registers directly from user
+ space. These instructions are also supported on AMD Family 17H CPUs. The
+ following instructions are available:
+
+  =============== ===========================
+  RDFSBASE %reg   Read the FS base register
+  RDGSBASE %reg   Read the GS base register
+  WRFSBASE %reg   Write the FS base register
+  WRGSBASE %reg   Write the GS base register
+  =============== ===========================
+
+ The instructions avoid the overhead of the arch_prctl() syscall and allow
+ more flexible usage of the FS/GS addressing modes in user space
+ applications. This does not prevent conflicts between threading libraries
+ and runtimes which utilize FS and applications which want to use it for
+ their own purpose.
+
+FSGSBASE instructions enablement
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ The instructions are enumerated in CPUID leaf 7, bit 0 of EBX. If
+ available /proc/cpuinfo shows 'fsgsbase' in the flag entry of the CPUs.
+
+ The availability of the instructions does not enable them
+ automatically. The kernel has to enable them explicitly in CR4. The
+ reason for this is that older kernels make assumptions about the values in
+ the GS register and enforce them when GS base is set via
+ arch_prctl(). Allowing user space to write arbitrary values to GS base
+ would violate these assumptions and cause malfunction.
+
+ On kernels which do not enable FSGSBASE the execution of the FSGSBASE
+ instructions will fault with a #UD exception.
+
+ The kernel provides reliable information about the enabled state in the
+ ELF AUX vector. If the HWCAP2_FSGSBASE bit is set in the AUX vector, the
+ kernel has FSGSBASE instructions enabled and applications can use them.
+ The following code example shows how this detection works::
+
+   #include <sys/auxv.h>
+   #include <elf.h>
+
+   /* Will be eventually in asm/hwcap.h */
+   #ifndef HWCAP2_FSGSBASE
+   #define HWCAP2_FSGSBASE        (1 << 1)
+   #endif
+
+   ....
+
+   unsigned val = getauxval(AT_HWCAP2);
+
+   if (val & HWCAP2_FSGSBASE)
+        printf("FSGSBASE enabled\n");
+
+FSGSBASE instructions compiler support
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+GCC version 4.6.4 and newer provide instrinsics for the FSGSBASE
+instructions. Clang 5 supports them as well.
+
+  =================== ===========================
+  _readfsbase_u64()   Read the FS base register
+  _readfsbase_u64()   Read the GS base register
+  _writefsbase_u64()  Write the FS base register
+  _writegsbase_u64()  Write the GS base register
+  =================== ===========================
+
+To utilize these instrinsics <immintrin.h> must be included in the source
+code and the compiler option -mfsgsbase has to be added.
+
+Compiler support for FS/GS based addressing
+-------------------------------------------
+
+GCC version 6 and newer provide support for FS/GS based addressing via
+Named Address Spaces. GCC implements the following address space
+identifiers for x86:
+
+  ========= ====================================
+  __seg_fs  Variable is addressed relative to FS
+  __seg_gs  Variable is addressed relative to GS
+  ========= ====================================
+
+The preprocessor symbols __SEG_FS and __SEG_GS are defined when these
+address spaces are supported. Code which implements fallback modes should
+check whether these symbols are defined. Usage example::
+
+  #ifdef __SEG_GS
+
+  long data0 = 0;
+  long data1 = 1;
+
+  long __seg_gs *ptr;
+
+  /* Check whether FSGSBASE is enabled by the kernel (HWCAP2_FSGSBASE) */
+  ....
+
+  /* Set GS base to point to data0 */
+  _writegsbase_u64(&data0);
+
+  /* Access offset 0 of GS */
+  ptr = 0;
+  printf("data0 = %ld\n", *ptr);
+
+  /* Set GS base to point to data1 */
+  _writegsbase_u64(&data1);
+  /* ptr still addresses offset 0! */
+  printf("data1 = %ld\n", *ptr);
+
+
+Clang does not provide the GCC address space identifiers, but it provides
+address spaces via an attribute based mechanism in Clang 2.6 and newer
+versions:
+
+ ==================================== =====================================
+  __attribute__((address_space(256))  Variable is addressed relative to GS
+  __attribute__((address_space(257))  Variable is addressed relative to FS
+ ==================================== =====================================
+
+FS/GS based addressing with inline assembly
+-------------------------------------------
+
+In case the compiler does not support address spaces, inline assembly can
+be used for FS/GS based addressing mode::
+
+       mov %fs:offset, %reg
+       mov %gs:offset, %reg
+
+       mov %reg, %fs:offset
+       mov %reg, %gs:offset
diff --git a/Documentation/arch/x86/x86_64/index.rst b/Documentation/arch/x86/x86_64/index.rst
new file mode 100644 (file)
index 0000000..a56070f
--- /dev/null
@@ -0,0 +1,17 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============
+x86_64 Support
+==============
+
+.. toctree::
+   :maxdepth: 2
+
+   boot-options
+   uefi
+   mm
+   5level-paging
+   fake-numa-for-cpusets
+   cpu-hotplug-spec
+   machinecheck
+   fsgs
diff --git a/Documentation/arch/x86/x86_64/machinecheck.rst b/Documentation/arch/x86/x86_64/machinecheck.rst
new file mode 100644 (file)
index 0000000..cea12ee
--- /dev/null
@@ -0,0 +1,33 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===============================================================
+Configurable sysfs parameters for the x86-64 machine check code
+===============================================================
+
+Machine checks report internal hardware error conditions detected
+by the CPU. Uncorrected errors typically cause a machine check
+(often with panic), corrected ones cause a machine check log entry.
+
+Machine checks are organized in banks (normally associated with
+a hardware subsystem) and subevents in a bank. The exact meaning
+of the banks and subevent is CPU specific.
+
+mcelog knows how to decode them.
+
+When you see the "Machine check errors logged" message in the system
+log then mcelog should run to collect and decode machine check entries
+from /dev/mcelog. Normally mcelog should be run regularly from a cronjob.
+
+Each CPU has a directory in /sys/devices/system/machinecheck/machinecheckN
+(N = CPU number).
+
+The directory contains some configurable entries. See
+Documentation/ABI/testing/sysfs-mce for more details.
+
+TBD document entries for AMD threshold interrupt configuration
+
+For more details about the x86 machine check architecture
+see the Intel and AMD architecture manuals from their developer websites.
+
+For more details about the architecture
+see http://one.firstfloor.org/~andi/mce.pdf
diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
new file mode 100644 (file)
index 0000000..35e5e18
--- /dev/null
@@ -0,0 +1,157 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+Memory Management
+=================
+
+Complete virtual memory map with 4-level page tables
+====================================================
+
+.. note::
+
+ - Negative addresses such as "-23 TB" are absolute addresses in bytes, counted down
+   from the top of the 64-bit address space. It's easier to understand the layout
+   when seen both in absolute addresses and in distance-from-top notation.
+
+   For example 0xffffe90000000000 == -23 TB, it's 23 TB lower than the top of the
+   64-bit address space (ffffffffffffffff).
+
+   Note that as we get closer to the top of the address space, the notation changes
+   from TB to GB and then MB/KB.
+
+ - "16M TB" might look weird at first sight, but it's an easier way to visualize size
+   notation than "16 EB", which few will recognize at first sight as 16 exabytes.
+   It also shows it nicely how incredibly large 64-bit address space is.
+
+::
+
+  ========================================================================================================================
+      Start addr    |   Offset   |     End addr     |  Size   | VM area description
+  ========================================================================================================================
+                    |            |                  |         |
+   0000000000000000 |    0       | 00007fffffffffff |  128 TB | user-space virtual memory, different per mm
+  __________________|____________|__________________|_________|___________________________________________________________
+                    |            |                  |         |
+   0000800000000000 | +128    TB | ffff7fffffffffff | ~16M TB | ... huge, almost 64 bits wide hole of non-canonical
+                    |            |                  |         |     virtual memory addresses up to the -128 TB
+                    |            |                  |         |     starting offset of kernel mappings.
+  __________________|____________|__________________|_________|___________________________________________________________
+                                                              |
+                                                              | Kernel-space virtual memory, shared between all processes:
+  ____________________________________________________________|___________________________________________________________
+                    |            |                  |         |
+   ffff800000000000 | -128    TB | ffff87ffffffffff |    8 TB | ... guard hole, also reserved for hypervisor
+   ffff880000000000 | -120    TB | ffff887fffffffff |  0.5 TB | LDT remap for PTI
+   ffff888000000000 | -119.5  TB | ffffc87fffffffff |   64 TB | direct mapping of all physical memory (page_offset_base)
+   ffffc88000000000 |  -55.5  TB | ffffc8ffffffffff |  0.5 TB | ... unused hole
+   ffffc90000000000 |  -55    TB | ffffe8ffffffffff |   32 TB | vmalloc/ioremap space (vmalloc_base)
+   ffffe90000000000 |  -23    TB | ffffe9ffffffffff |    1 TB | ... unused hole
+   ffffea0000000000 |  -22    TB | ffffeaffffffffff |    1 TB | virtual memory map (vmemmap_base)
+   ffffeb0000000000 |  -21    TB | ffffebffffffffff |    1 TB | ... unused hole
+   ffffec0000000000 |  -20    TB | fffffbffffffffff |   16 TB | KASAN shadow memory
+  __________________|____________|__________________|_________|____________________________________________________________
+                                                              |
+                                                              | Identical layout to the 56-bit one from here on:
+  ____________________________________________________________|____________________________________________________________
+                    |            |                  |         |
+   fffffc0000000000 |   -4    TB | fffffdffffffffff |    2 TB | ... unused hole
+                    |            |                  |         | vaddr_end for KASLR
+   fffffe0000000000 |   -2    TB | fffffe7fffffffff |  0.5 TB | cpu_entry_area mapping
+   fffffe8000000000 |   -1.5  TB | fffffeffffffffff |  0.5 TB | ... unused hole
+   ffffff0000000000 |   -1    TB | ffffff7fffffffff |  0.5 TB | %esp fixup stacks
+   ffffff8000000000 | -512    GB | ffffffeeffffffff |  444 GB | ... unused hole
+   ffffffef00000000 |  -68    GB | fffffffeffffffff |   64 GB | EFI region mapping space
+   ffffffff00000000 |   -4    GB | ffffffff7fffffff |    2 GB | ... unused hole
+   ffffffff80000000 |   -2    GB | ffffffff9fffffff |  512 MB | kernel text mapping, mapped to physical address 0
+   ffffffff80000000 |-2048    MB |                  |         |
+   ffffffffa0000000 |-1536    MB | fffffffffeffffff | 1520 MB | module mapping space
+   ffffffffff000000 |  -16    MB |                  |         |
+      FIXADDR_START | ~-11    MB | ffffffffff5fffff | ~0.5 MB | kernel-internal fixmap range, variable size and offset
+   ffffffffff600000 |  -10    MB | ffffffffff600fff |    4 kB | legacy vsyscall ABI
+   ffffffffffe00000 |   -2    MB | ffffffffffffffff |    2 MB | ... unused hole
+  __________________|____________|__________________|_________|___________________________________________________________
+
+
+Complete virtual memory map with 5-level page tables
+====================================================
+
+.. note::
+
+ - With 56-bit addresses, user-space memory gets expanded by a factor of 512x,
+   from 0.125 PB to 64 PB. All kernel mappings shift down to the -64 PB starting
+   offset and many of the regions expand to support the much larger physical
+   memory supported.
+
+::
+
+  ========================================================================================================================
+      Start addr    |   Offset   |     End addr     |  Size   | VM area description
+  ========================================================================================================================
+                    |            |                  |         |
+   0000000000000000 |    0       | 00ffffffffffffff |   64 PB | user-space virtual memory, different per mm
+  __________________|____________|__________________|_________|___________________________________________________________
+                    |            |                  |         |
+   0100000000000000 |  +64    PB | feffffffffffffff | ~16K PB | ... huge, still almost 64 bits wide hole of non-canonical
+                    |            |                  |         |     virtual memory addresses up to the -64 PB
+                    |            |                  |         |     starting offset of kernel mappings.
+  __________________|____________|__________________|_________|___________________________________________________________
+                                                              |
+                                                              | Kernel-space virtual memory, shared between all processes:
+  ____________________________________________________________|___________________________________________________________
+                    |            |                  |         |
+   ff00000000000000 |  -64    PB | ff0fffffffffffff |    4 PB | ... guard hole, also reserved for hypervisor
+   ff10000000000000 |  -60    PB | ff10ffffffffffff | 0.25 PB | LDT remap for PTI
+   ff11000000000000 |  -59.75 PB | ff90ffffffffffff |   32 PB | direct mapping of all physical memory (page_offset_base)
+   ff91000000000000 |  -27.75 PB | ff9fffffffffffff | 3.75 PB | ... unused hole
+   ffa0000000000000 |  -24    PB | ffd1ffffffffffff | 12.5 PB | vmalloc/ioremap space (vmalloc_base)
+   ffd2000000000000 |  -11.5  PB | ffd3ffffffffffff |  0.5 PB | ... unused hole
+   ffd4000000000000 |  -11    PB | ffd5ffffffffffff |  0.5 PB | virtual memory map (vmemmap_base)
+   ffd6000000000000 |  -10.5  PB | ffdeffffffffffff | 2.25 PB | ... unused hole
+   ffdf000000000000 |   -8.25 PB | fffffbffffffffff |   ~8 PB | KASAN shadow memory
+  __________________|____________|__________________|_________|____________________________________________________________
+                                                              |
+                                                              | Identical layout to the 47-bit one from here on:
+  ____________________________________________________________|____________________________________________________________
+                    |            |                  |         |
+   fffffc0000000000 |   -4    TB | fffffdffffffffff |    2 TB | ... unused hole
+                    |            |                  |         | vaddr_end for KASLR
+   fffffe0000000000 |   -2    TB | fffffe7fffffffff |  0.5 TB | cpu_entry_area mapping
+   fffffe8000000000 |   -1.5  TB | fffffeffffffffff |  0.5 TB | ... unused hole
+   ffffff0000000000 |   -1    TB | ffffff7fffffffff |  0.5 TB | %esp fixup stacks
+   ffffff8000000000 | -512    GB | ffffffeeffffffff |  444 GB | ... unused hole
+   ffffffef00000000 |  -68    GB | fffffffeffffffff |   64 GB | EFI region mapping space
+   ffffffff00000000 |   -4    GB | ffffffff7fffffff |    2 GB | ... unused hole
+   ffffffff80000000 |   -2    GB | ffffffff9fffffff |  512 MB | kernel text mapping, mapped to physical address 0
+   ffffffff80000000 |-2048    MB |                  |         |
+   ffffffffa0000000 |-1536    MB | fffffffffeffffff | 1520 MB | module mapping space
+   ffffffffff000000 |  -16    MB |                  |         |
+      FIXADDR_START | ~-11    MB | ffffffffff5fffff | ~0.5 MB | kernel-internal fixmap range, variable size and offset
+   ffffffffff600000 |  -10    MB | ffffffffff600fff |    4 kB | legacy vsyscall ABI
+   ffffffffffe00000 |   -2    MB | ffffffffffffffff |    2 MB | ... unused hole
+  __________________|____________|__________________|_________|___________________________________________________________
+
+Architecture defines a 64-bit virtual address. Implementations can support
+less. Currently supported are 48- and 57-bit virtual addresses. Bits 63
+through to the most-significant implemented bit are sign extended.
+This causes hole between user space and kernel addresses if you interpret them
+as unsigned.
+
+The direct mapping covers all memory in the system up to the highest
+memory address (this means in some cases it can also include PCI memory
+holes).
+
+We map EFI runtime services in the 'efi_pgd' PGD in a 64GB large virtual
+memory window (this size is arbitrary, it can be raised later if needed).
+The mappings are not part of any other kernel PGD and are only available
+during EFI runtime calls.
+
+Note that if CONFIG_RANDOMIZE_MEMORY is enabled, the direct mapping of all
+physical memory, vmalloc/ioremap space and virtual memory map are randomized.
+Their order is preserved but their base will be offset early at boot time.
+
+Be very careful vs. KASLR when changing anything here. The KASLR address
+range must not overlap with anything except the KASAN shadow area, which is
+correct as KASAN disables KASLR.
+
+For both 4- and 5-level layouts, the STACKLEAK_POISON value in the last 2MB
+hole: ffffffffffff4111
diff --git a/Documentation/arch/x86/x86_64/uefi.rst b/Documentation/arch/x86/x86_64/uefi.rst
new file mode 100644 (file)
index 0000000..fbc30c9
--- /dev/null
@@ -0,0 +1,58 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+General note on [U]EFI x86_64 support
+=====================================
+
+The nomenclature EFI and UEFI are used interchangeably in this document.
+
+Although the tools below are _not_ needed for building the kernel,
+the needed bootloader support and associated tools for x86_64 platforms
+with EFI firmware and specifications are listed below.
+
+1. UEFI specification:  http://www.uefi.org
+
+2. Booting Linux kernel on UEFI x86_64 platform requires bootloader
+   support. Elilo with x86_64 support can be used.
+
+3. x86_64 platform with EFI/UEFI firmware.
+
+Mechanics
+---------
+
+- Build the kernel with the following configuration::
+
+       CONFIG_FB_EFI=y
+       CONFIG_FRAMEBUFFER_CONSOLE=y
+
+  If EFI runtime services are expected, the following configuration should
+  be selected::
+
+       CONFIG_EFI=y
+       CONFIG_EFIVAR_FS=y or m         # optional
+
+- Create a VFAT partition on the disk
+- Copy the following to the VFAT partition:
+
+       elilo bootloader with x86_64 support, elilo configuration file,
+       kernel image built in first step and corresponding
+       initrd. Instructions on building elilo and its dependencies
+       can be found in the elilo sourceforge project.
+
+- Boot to EFI shell and invoke elilo choosing the kernel image built
+  in first step.
+- If some or all EFI runtime services don't work, you can try following
+  kernel command line parameters to turn off some or all EFI runtime
+  services.
+
+       noefi
+               turn off all EFI runtime services
+       reboot_type=k
+               turn off EFI reboot runtime service
+
+- If the EFI memory map has additional entries not in the E820 map,
+  you can include those entries in the kernels memory map of available
+  physical RAM by using the following kernel command line parameter.
+
+       add_efi_memmap
+               include EFI memory map of available physical RAM
diff --git a/Documentation/arch/x86/xstate.rst b/Documentation/arch/x86/xstate.rst
new file mode 100644 (file)
index 0000000..5cec7fb
--- /dev/null
@@ -0,0 +1,74 @@
+Using XSTATE features in user space applications
+================================================
+
+The x86 architecture supports floating-point extensions which are
+enumerated via CPUID. Applications consult CPUID and use XGETBV to
+evaluate which features have been enabled by the kernel XCR0.
+
+Up to AVX-512 and PKRU states, these features are automatically enabled by
+the kernel if available. Features like AMX TILE_DATA (XSTATE component 18)
+are enabled by XCR0 as well, but the first use of related instruction is
+trapped by the kernel because by default the required large XSTATE buffers
+are not allocated automatically.
+
+Using dynamically enabled XSTATE features in user space applications
+--------------------------------------------------------------------
+
+The kernel provides an arch_prctl(2) based mechanism for applications to
+request the usage of such features. The arch_prctl(2) options related to
+this are:
+
+-ARCH_GET_XCOMP_SUPP
+
+ arch_prctl(ARCH_GET_XCOMP_SUPP, &features);
+
+ ARCH_GET_XCOMP_SUPP stores the supported features in userspace storage of
+ type uint64_t. The second argument is a pointer to that storage.
+
+-ARCH_GET_XCOMP_PERM
+
+ arch_prctl(ARCH_GET_XCOMP_PERM, &features);
+
+ ARCH_GET_XCOMP_PERM stores the features for which the userspace process
+ has permission in userspace storage of type uint64_t. The second argument
+ is a pointer to that storage.
+
+-ARCH_REQ_XCOMP_PERM
+
+ arch_prctl(ARCH_REQ_XCOMP_PERM, feature_nr);
+
+ ARCH_REQ_XCOMP_PERM allows to request permission for a dynamically enabled
+ feature or a feature set. A feature set can be mapped to a facility, e.g.
+ AMX, and can require one or more XSTATE components to be enabled.
+
+ The feature argument is the number of the highest XSTATE component which
+ is required for a facility to work.
+
+When requesting permission for a feature, the kernel checks the
+availability. The kernel ensures that sigaltstacks in the process's tasks
+are large enough to accommodate the resulting large signal frame. It
+enforces this both during ARCH_REQ_XCOMP_SUPP and during any subsequent
+sigaltstack(2) calls. If an installed sigaltstack is smaller than the
+resulting sigframe size, ARCH_REQ_XCOMP_SUPP results in -ENOSUPP. Also,
+sigaltstack(2) results in -ENOMEM if the requested altstack is too small
+for the permitted features.
+
+Permission, when granted, is valid per process. Permissions are inherited
+on fork(2) and cleared on exec(3).
+
+The first use of an instruction related to a dynamically enabled feature is
+trapped by the kernel. The trap handler checks whether the process has
+permission to use the feature. If the process has no permission then the
+kernel sends SIGILL to the application. If the process has permission then
+the handler allocates a larger xstate buffer for the task so the large
+state can be context switched. In the unlikely cases that the allocation
+fails, the kernel sends SIGSEGV.
+
+Dynamic features in signal frames
+---------------------------------
+
+Dynamcally enabled features are not written to the signal frame upon signal
+entry if the feature is in its initial configuration.  This differs from
+non-dynamic features which are always written regardless of their
+configuration.  Signal handlers can examine the XSAVE buffer's XSTATE_BV
+field to determine if a features was written.
diff --git a/Documentation/arch/x86/zero-page.rst b/Documentation/arch/x86/zero-page.rst
new file mode 100644 (file)
index 0000000..45aa9cc
--- /dev/null
@@ -0,0 +1,47 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========
+Zero Page
+=========
+The additional fields in struct boot_params as a part of 32-bit boot
+protocol of kernel. These should be filled by bootloader or 16-bit
+real-mode setup code of the kernel. References/settings to it mainly
+are in::
+
+  arch/x86/include/uapi/asm/bootparam.h
+
+===========    =====   ======================= =================================================
+Offset/Size    Proto   Name                    Meaning
+
+000/040                ALL     screen_info             Text mode or frame buffer information
+                                               (struct screen_info)
+040/014                ALL     apm_bios_info           APM BIOS information (struct apm_bios_info)
+058/008                ALL     tboot_addr              Physical address of tboot shared page
+060/010                ALL     ist_info                Intel SpeedStep (IST) BIOS support information
+                                               (struct ist_info)
+070/008                ALL     acpi_rsdp_addr          Physical address of ACPI RSDP table
+080/010                ALL     hd0_info                hd0 disk parameter, OBSOLETE!!
+090/010                ALL     hd1_info                hd1 disk parameter, OBSOLETE!!
+0A0/010                ALL     sys_desc_table          System description table (struct sys_desc_table),
+                                               OBSOLETE!!
+0B0/010                ALL     olpc_ofw_header         OLPC's OpenFirmware CIF and friends
+0C0/004                ALL     ext_ramdisk_image       ramdisk_image high 32bits
+0C4/004                ALL     ext_ramdisk_size        ramdisk_size high 32bits
+0C8/004                ALL     ext_cmd_line_ptr        cmd_line_ptr high 32bits
+13C/004                ALL     cc_blob_address         Physical address of Confidential Computing blob
+140/080                ALL     edid_info               Video mode setup (struct edid_info)
+1C0/020                ALL     efi_info                EFI 32 information (struct efi_info)
+1E0/004                ALL     alt_mem_k               Alternative mem check, in KB
+1E4/004                ALL     scratch                 Scratch field for the kernel setup code
+1E8/001                ALL     e820_entries            Number of entries in e820_table (below)
+1E9/001                ALL     eddbuf_entries          Number of entries in eddbuf (below)
+1EA/001                ALL     edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
+                                               (below)
+1EB/001                ALL     kbd_status              Numlock is enabled
+1EC/001                ALL     secure_boot             Secure boot is enabled in the firmware
+1EF/001                ALL     sentinel                Used to detect broken bootloaders
+290/040                ALL     edd_mbr_sig_buffer      EDD MBR signatures
+2D0/A00                ALL     e820_table              E820 memory map table
+                                               (array of struct e820_entry)
+D00/1EC                ALL     eddbuf                  EDD data (array of struct edd_info)
+===========    =====   ======================= =================================================
diff --git a/Documentation/arch/xtensa/atomctl.rst b/Documentation/arch/xtensa/atomctl.rst
new file mode 100644 (file)
index 0000000..1ecbd0b
--- /dev/null
@@ -0,0 +1,51 @@
+===========================================
+Atomic Operation Control (ATOMCTL) Register
+===========================================
+
+We Have Atomic Operation Control (ATOMCTL) Register.
+This register determines the effect of using a S32C1I instruction
+with various combinations of:
+
+     1. With and without an Coherent Cache Controller which
+        can do Atomic Transactions to the memory internally.
+
+     2. With and without An Intelligent Memory Controller which
+        can do Atomic Transactions itself.
+
+The Core comes up with a default value of for the three types of cache ops::
+
+      0x28: (WB: Internal, WT: Internal, BY:Exception)
+
+On the FPGA Cards we typically simulate an Intelligent Memory controller
+which can implement  RCW transactions. For FPGA cards with an External
+Memory controller we let it to the atomic operations internally while
+doing a Cached (WB) transaction and use the Memory RCW for un-cached
+operations.
+
+For systems without an coherent cache controller, non-MX, we always
+use the memory controllers RCW, thought non-MX controlers likely
+support the Internal Operation.
+
+CUSTOMER-WARNING:
+   Virtually all customers buy their memory controllers from vendors that
+   don't support atomic RCW memory transactions and will likely want to
+   configure this register to not use RCW.
+
+Developers might find using RCW in Bypass mode convenient when testing
+with the cache being bypassed; for example studying cache alias problems.
+
+See Section 4.3.12.4 of ISA; Bits::
+
+                             WB     WT      BY
+                           5   4 | 3   2 | 1   0
+
+=========    ==================      ==================      ===============
+  2 Bit
+  Field
+  Values     WB - Write Back         WT - Write Thru         BY - Bypass
+=========    ==================      ==================      ===============
+    0        Exception               Exception               Exception
+    1        RCW Transaction         RCW Transaction         RCW Transaction
+    2        Internal Operation      Internal Operation      Reserved
+    3        Reserved                Reserved                Reserved
+=========    ==================      ==================      ===============
diff --git a/Documentation/arch/xtensa/booting.rst b/Documentation/arch/xtensa/booting.rst
new file mode 100644 (file)
index 0000000..e1b8370
--- /dev/null
@@ -0,0 +1,22 @@
+=====================================
+Passing boot parameters to the kernel
+=====================================
+
+Boot parameters are represented as a TLV list in the memory. Please see
+arch/xtensa/include/asm/bootparam.h for definition of the bp_tag structure and
+tag value constants. First entry in the list must have type BP_TAG_FIRST, last
+entry must have type BP_TAG_LAST. The address of the first list entry is
+passed to the kernel in the register a2. The address type depends on MMU type:
+
+- For configurations without MMU, with region protection or with MPU the
+  address must be the physical address.
+- For configurations with region translarion MMU or with MMUv3 and CONFIG_MMU=n
+  the address must be a valid address in the current mapping. The kernel will
+  not change the mapping on its own.
+- For configurations with MMUv2 the address must be a virtual address in the
+  default virtual mapping (0xd0000000..0xffffffff).
+- For configurations with MMUv3 and CONFIG_MMU=y the address may be either a
+  virtual or physical address. In either case it must be within the default
+  virtual mapping. It is considered physical if it is within the range of
+  physical addresses covered by the default KSEG mapping (XCHAL_KSEG_PADDR..
+  XCHAL_KSEG_PADDR + XCHAL_KSEG_SIZE), otherwise it is considered virtual.
diff --git a/Documentation/arch/xtensa/features.rst b/Documentation/arch/xtensa/features.rst
new file mode 100644 (file)
index 0000000..6b92c7b
--- /dev/null
@@ -0,0 +1,3 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. kernel-feat:: $srctree/Documentation/features xtensa
diff --git a/Documentation/arch/xtensa/index.rst b/Documentation/arch/xtensa/index.rst
new file mode 100644 (file)
index 0000000..6995244
--- /dev/null
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================
+Xtensa Architecture
+===================
+
+.. toctree::
+   :maxdepth: 1
+
+   atomctl
+   booting
+   mmu
+
+   features
diff --git a/Documentation/arch/xtensa/mmu.rst b/Documentation/arch/xtensa/mmu.rst
new file mode 100644 (file)
index 0000000..450573a
--- /dev/null
@@ -0,0 +1,198 @@
+=============================
+MMUv3 initialization sequence
+=============================
+
+The code in the initialize_mmu macro sets up MMUv3 memory mapping
+identically to MMUv2 fixed memory mapping. Depending on
+CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX symbol this code is
+located in addresses it was linked for (symbol undefined), or not
+(symbol defined), so it needs to be position-independent.
+
+The code has the following assumptions:
+
+  - This code fragment is run only on an MMU v3.
+  - TLBs are in their reset state.
+  - ITLBCFG and DTLBCFG are zero (reset state).
+  - RASID is 0x04030201 (reset state).
+  - PS.RING is zero (reset state).
+  - LITBASE is zero (reset state, PC-relative literals); required to be PIC.
+
+TLB setup proceeds along the following steps.
+
+  Legend:
+
+    - VA = virtual address (two upper nibbles of it);
+    - PA = physical address (two upper nibbles of it);
+    - pc = physical range that contains this code;
+
+After step 2, we jump to virtual address in the range 0x40000000..0x5fffffff
+or 0x00000000..0x1fffffff, depending on whether the kernel was loaded below
+0x40000000 or above. That address corresponds to next instruction to execute
+in this code. After step 4, we jump to intended (linked) address of this code.
+The scheme below assumes that the kernel is loaded below 0x40000000.
+
+ ====== =====  =====  =====  =====   ====== =====  =====
+ -      Step0  Step1  Step2  Step3          Step4  Step5
+
+   VA      PA     PA     PA     PA     VA      PA     PA
+ ====== =====  =====  =====  =====   ====== =====  =====
+ E0..FF -> E0  -> E0  -> E0          F0..FF -> F0  -> F0
+ C0..DF -> C0  -> C0  -> C0          E0..EF -> F0  -> F0
+ A0..BF -> A0  -> A0  -> A0          D8..DF -> 00  -> 00
+ 80..9F -> 80  -> 80  -> 80          D0..D7 -> 00  -> 00
+ 60..7F -> 60  -> 60  -> 60
+ 40..5F -> 40         -> pc  -> pc   40..5F -> pc
+ 20..3F -> 20  -> 20  -> 20
+ 00..1F -> 00  -> 00  -> 00
+ ====== =====  =====  =====  =====   ====== =====  =====
+
+The default location of IO peripherals is above 0xf0000000. This may be changed
+using a "ranges" property in a device tree simple-bus node. See the Devicetree
+Specification, section 4.5 for details on the syntax and semantics of
+simple-bus nodes. The following limitations apply:
+
+1. Only top level simple-bus nodes are considered
+
+2. Only one (first) simple-bus node is considered
+
+3. Empty "ranges" properties are not supported
+
+4. Only the first triplet in the "ranges" property is considered
+
+5. The parent-bus-address value is rounded down to the nearest 256MB boundary
+
+6. The IO area covers the entire 256MB segment of parent-bus-address; the
+   "ranges" triplet length field is ignored
+
+
+MMUv3 address space layouts.
+============================
+
+Default MMUv2-compatible layout::
+
+                        Symbol                   VADDR       Size
+  +------------------+
+  | Userspace        |                           0x00000000  TASK_SIZE
+  +------------------+                           0x40000000
+  +------------------+
+  | Page table       |  XCHAL_PAGE_TABLE_VADDR   0x80000000  XCHAL_PAGE_TABLE_SIZE
+  +------------------+
+  | KASAN shadow map |  KASAN_SHADOW_START       0x80400000  KASAN_SHADOW_SIZE
+  +------------------+                           0x8e400000
+  +------------------+
+  | VMALLOC area     |  VMALLOC_START            0xc0000000  128MB - 64KB
+  +------------------+  VMALLOC_END
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0xc8000000  DCACHE_WAY_SIZE
+  | remap area 1     |
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
+  | remap area 2     |
+  +------------------+
+  +------------------+
+  | KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
+  |                  |                                       DCACHE_N_COLORS *
+  |                  |                                       PAGE_SIZE
+  |                  |                                       (4MB * DCACHE_N_COLORS)
+  +------------------+
+  | Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
+  |                  |                                       NR_CPUS *
+  |                  |                                       DCACHE_N_COLORS *
+  |                  |                                       PAGE_SIZE
+  +------------------+  FIXADDR_TOP              0xcffff000
+  +------------------+
+  | Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xd0000000  128MB
+  +------------------+
+  | Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xd8000000  128MB
+  +------------------+
+  | Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
+  +------------------+
+  | Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
+  +------------------+
+
+
+256MB cached + 256MB uncached layout::
+
+                        Symbol                   VADDR       Size
+  +------------------+
+  | Userspace        |                           0x00000000  TASK_SIZE
+  +------------------+                           0x40000000
+  +------------------+
+  | Page table       |  XCHAL_PAGE_TABLE_VADDR   0x80000000  XCHAL_PAGE_TABLE_SIZE
+  +------------------+
+  | KASAN shadow map |  KASAN_SHADOW_START       0x80400000  KASAN_SHADOW_SIZE
+  +------------------+                           0x8e400000
+  +------------------+
+  | VMALLOC area     |  VMALLOC_START            0xa0000000  128MB - 64KB
+  +------------------+  VMALLOC_END
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0xa8000000  DCACHE_WAY_SIZE
+  | remap area 1     |
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
+  | remap area 2     |
+  +------------------+
+  +------------------+
+  | KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
+  |                  |                                       DCACHE_N_COLORS *
+  |                  |                                       PAGE_SIZE
+  |                  |                                       (4MB * DCACHE_N_COLORS)
+  +------------------+
+  | Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
+  |                  |                                       NR_CPUS *
+  |                  |                                       DCACHE_N_COLORS *
+  |                  |                                       PAGE_SIZE
+  +------------------+  FIXADDR_TOP              0xaffff000
+  +------------------+
+  | Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xb0000000  256MB
+  +------------------+
+  | Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xc0000000  256MB
+  +------------------+
+  +------------------+
+  | Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
+  +------------------+
+  | Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
+  +------------------+
+
+
+512MB cached + 512MB uncached layout::
+
+                        Symbol                   VADDR       Size
+  +------------------+
+  | Userspace        |                           0x00000000  TASK_SIZE
+  +------------------+                           0x40000000
+  +------------------+
+  | Page table       |  XCHAL_PAGE_TABLE_VADDR   0x80000000  XCHAL_PAGE_TABLE_SIZE
+  +------------------+
+  | KASAN shadow map |  KASAN_SHADOW_START       0x80400000  KASAN_SHADOW_SIZE
+  +------------------+                           0x8e400000
+  +------------------+
+  | VMALLOC area     |  VMALLOC_START            0x90000000  128MB - 64KB
+  +------------------+  VMALLOC_END
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0x98000000  DCACHE_WAY_SIZE
+  | remap area 1     |
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
+  | remap area 2     |
+  +------------------+
+  +------------------+
+  | KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
+  |                  |                                       DCACHE_N_COLORS *
+  |                  |                                       PAGE_SIZE
+  |                  |                                       (4MB * DCACHE_N_COLORS)
+  +------------------+
+  | Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
+  |                  |                                       NR_CPUS *
+  |                  |                                       DCACHE_N_COLORS *
+  |                  |                                       PAGE_SIZE
+  +------------------+  FIXADDR_TOP              0x9ffff000
+  +------------------+
+  | Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xa0000000  512MB
+  +------------------+
+  | Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xc0000000  512MB
+  +------------------+
+  | Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
+  +------------------+
+  | Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
+  +------------------+
index 056ac11372af290f7a823a05853d149f05831b47..fd43502ae9246f91c32a4bad4f92851894789d27 100644 (file)
@@ -70,11 +70,9 @@ SoC-specific documents
 
    spear/overview
 
-   sti/stih416-overview
    sti/stih407-overview
    sti/stih418-overview
    sti/overview
-   sti/stih415-overview
 
    vfp/release-notes
 
index 70743617a74fa9b358cfd69995311fe4d24ab6b0..ae16aced800f4949c651b030737566e0bde726e4 100644 (file)
@@ -7,22 +7,18 @@ Introduction
 
   The ST Microelectronics Multimedia and Application Processors range of
   CortexA9 System-on-Chip are supported by the 'STi' platform of
-  ARM Linux. Currently STiH415, STiH416 SOCs are supported with both
-  B2000 and B2020 Reference boards.
+  ARM Linux. Currently STiH407, STiH410 and STiH418 are supported.
 
 
 configuration
 -------------
 
-  A generic configuration is provided for both STiH415/416, and can be used as the
-  default by::
-
-       make stih41x_defconfig
+  The configuration for the STi platform is supported via the multi_v7_defconfig.
 
 Layout
 ------
 
-  All the files for multiple machine families (STiH415, STiH416, and STiG125)
+  All the files for multiple machine families (STiH407, STiH410, and STiH418)
   are located in the platform code contained in arch/arm/mach-sti
 
   There is a generic board board-dt.c in the mach folder which support
diff --git a/Documentation/arm/sti/stih415-overview.rst b/Documentation/arm/sti/stih415-overview.rst
deleted file mode 100644 (file)
index b67452d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-================
-STiH415 Overview
-================
-
-Introduction
-------------
-
-    The STiH415 is the next generation of HD, AVC set-top box processors
-    for satellite, cable, terrestrial and IP-STB markets.
-
-    Features:
-
-    - ARM Cortex-A9 1.0 GHz, dual-core CPU
-    - SATA2x2,USB 2.0x3, PCIe, Gbit Ethernet MACx2
diff --git a/Documentation/arm/sti/stih416-overview.rst b/Documentation/arm/sti/stih416-overview.rst
deleted file mode 100644 (file)
index 93f17d7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-================
-STiH416 Overview
-================
-
-Introduction
-------------
-
-    The STiH416 is the next generation of HD, AVC set-top box processors
-    for satellite, cable, terrestrial and IP-STB markets.
-
-    Features
-    - ARM Cortex-A9 1.2 GHz dual core CPU
-    - SATA2x2,USB 2.0x3, PCIe, Gbit Ethernet MACx2
index ec5f889d76819fd2fae733997d61ff1c33114ace..9e311bc43e05eaac3c36ffb50edb6750a14a6bbe 100644 (file)
@@ -172,6 +172,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | NVIDIA         | Carmel Core     | N/A             | NVIDIA_CARMEL_CNP_ERRATUM   |
 +----------------+-----------------+-----------------+-----------------------------+
+| NVIDIA         | T241 GICv3/4.x  | T241-FABRIC-4   | N/A                         |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
 +----------------+-----------------+-----------------+-----------------------------+
@@ -205,6 +207,9 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | Qualcomm Tech. | Kryo4xx Gold    | N/A             | ARM64_ERRATUM_1286807       |
 +----------------+-----------------+-----------------+-----------------------------+
++----------------+-----------------+-----------------+-----------------------------+
+| Rockchip       | RK3588          | #3588001        | ROCKCHIP_ERRATUM_3588001    |
++----------------+-----------------+-----------------+-----------------------------+
 
 +----------------+-----------------+-----------------+-----------------------------+
 | Fujitsu        | A64FX           | E#010001        | FUJITSU_ERRATUM_010001      |
index db16814f182fc52563fc014b400053bcbc975a11..37314afd1ac8aa6aed755612b45c5e9ad0ecabd0 100644 (file)
@@ -343,9 +343,10 @@ sys.stderr.write("Using %s theme\n" % html_theme)
 # so a file named "default.css" will overwrite the builtin "default.css".
 html_static_path = ['sphinx-static']
 
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-html_use_smartypants = False
+# If true, Docutils "smart quotes" will be used to convert quotes and dashes
+# to typographically correct entities.  This will convert "--" to "—",
+# which is not always what we want, so disable it.
+smartquotes = False
 
 # Custom sidebar templates, maps document names to template names.
 # Note that the RTD theme ignores this
index bc514ed598870c69406663b505642987052bb632..11c96d3f9ad6d78bf212fa6224540b99f8012f3b 100644 (file)
@@ -44,7 +44,7 @@ information. In particular, on properly annotated objects, ``objtool`` can be
 run to check and fix the object if needed. Currently, ``objtool`` can report
 missing frame pointer setup/destruction in functions. It can also
 automatically generate annotations for the ORC unwinder
-(Documentation/x86/orc-unwinder.rst)
+(Documentation/arch/x86/orc-unwinder.rst)
 for most code. Both of these are especially important to support reliable
 stack traces which are in turn necessary for kernel live patching
 (Documentation/livepatch/livepatch.rst).
index 828846804e25a246d422f9df28d9df5b184f5c08..72f6cdb6be1c012f7d2b4da987cf341b5bfaad55 100644 (file)
@@ -185,7 +185,7 @@ device struct of your device is embedded in the bus-specific device struct of
 your device.  For example, &pdev->dev is a pointer to the device struct of a
 PCI device (pdev is a pointer to the PCI device struct of your device).
 
-These calls usually return zero to indicated your device can perform DMA
+These calls usually return zero to indicate your device can perform DMA
 properly on the machine given the address mask you provided, but they might
 return an error if the mask is too small to be supportable on the given
 system.  If it returns non-zero, your device cannot perform DMA properly on
index 5483fd39ef2956d51750e6ef2bce37b96f7defc1..2cb00b53339fe9830a41867becc9beb4650f216a 100644 (file)
@@ -227,7 +227,7 @@ Testing with kmemleak-test
 --------------------------
 
 To check if you have all set up to use kmemleak, you can use the kmemleak-test
-module, a module that deliberately leaks memory. Set CONFIG_DEBUG_KMEMLEAK_TEST
+module, a module that deliberately leaks memory. Set CONFIG_SAMPLE_KMEMLEAK
 as module (it can't be used as built-in) and boot the kernel with kmemleak
 enabled. Load the module and perform a scan with::
 
index 1748f1605cc701b55ac97687c27c23e0e6716465..7dff32f373cb93cf55ca665d2ddfcecb942d7fff 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/arm/amlogic/amlogic,meson-gx-ao-secure.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/arm/amlogic/amlogic,meson-gx-ao-secure.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Meson Firmware registers Interface
 
index eee7cda9f91b670cfa404a26f64f4d266b9512cc..09b27e98d4c9797a24745a2f60c1aa8821b13165 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/arm/amlogic/amlogic,meson-mx-secbus2.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/arm/amlogic/amlogic,meson-mx-secbus2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Meson8/Meson8b/Meson8m2 SECBUS2 register interface
 
index d4dc0749f9fd1f257c05854fcc91a49498fd7102..5d033570b57bcf1b6a2b3b933c041922132d61a3 100644 (file)
@@ -28,7 +28,8 @@ properties:
     maxItems: 1
     description: |
       This interrupt which is used to signal an event by the secure world
-      software is expected to be edge-triggered.
+      software is expected to be either a per-cpu interrupt or an
+      edge-triggered peripheral interrupt.
 
   method:
     enum: [smc, hvc]
index 38efcad56dbdee6d1df0aa5c2abfe69bd37aee53..02cc6894eb135fc9a4195201515dcec642987d6d 100644 (file)
@@ -7,8 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Last Level Cache Controller
 
 maintainers:
-  - Rishabh Bhatnagar <rishabhb@codeaurora.org>
-  - Sai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
+  - Bjorn Andersson <andersson@kernel.org>
 
 description: |
   LLCC (Last Level Cache Controller) provides last level of cache memory in SoC,
@@ -27,6 +26,7 @@ properties:
       - qcom,sc8280xp-llcc
       - qcom,sdm845-llcc
       - qcom,sm6350-llcc
+      - qcom,sm7150-llcc
       - qcom,sm8150-llcc
       - qcom,sm8250-llcc
       - qcom,sm8350-llcc
@@ -34,14 +34,12 @@ properties:
       - qcom,sm8550-llcc
 
   reg:
-    items:
-      - description: LLCC base register region
-      - description: LLCC broadcast base register region
+    minItems: 2
+    maxItems: 9
 
   reg-names:
-    items:
-      - const: llcc_base
-      - const: llcc_broadcast_base
+    minItems: 2
+    maxItems: 9
 
   interrupts:
     maxItems: 1
@@ -51,15 +49,120 @@ required:
   - reg
   - reg-names
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sc7180-llcc
+              - qcom,sm6350-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc_broadcast_base
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sc7280-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC1 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc1_base
+            - const: llcc_broadcast_base
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sc8180x-llcc
+              - qcom,sc8280xp-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC1 base register region
+            - description: LLCC2 base register region
+            - description: LLCC3 base register region
+            - description: LLCC4 base register region
+            - description: LLCC5 base register region
+            - description: LLCC6 base register region
+            - description: LLCC7 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc1_base
+            - const: llcc2_base
+            - const: llcc3_base
+            - const: llcc4_base
+            - const: llcc5_base
+            - const: llcc6_base
+            - const: llcc7_base
+            - const: llcc_broadcast_base
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,sdm845-llcc
+              - qcom,sm8150-llcc
+              - qcom,sm8250-llcc
+              - qcom,sm8350-llcc
+              - qcom,sm8450-llcc
+    then:
+      properties:
+        reg:
+          items:
+            - description: LLCC0 base register region
+            - description: LLCC1 base register region
+            - description: LLCC2 base register region
+            - description: LLCC3 base register region
+            - description: LLCC broadcast base register region
+        reg-names:
+          items:
+            - const: llcc0_base
+            - const: llcc1_base
+            - const: llcc2_base
+            - const: llcc3_base
+            - const: llcc_broadcast_base
+
 additionalProperties: false
 
 examples:
   - |
     #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-    system-cache-controller@1100000 {
-      compatible = "qcom,sdm845-llcc";
-      reg = <0x1100000 0x200000>, <0x1300000 0x50000> ;
-      reg-names = "llcc_base", "llcc_broadcast_base";
-      interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        system-cache-controller@1100000 {
+            compatible = "qcom,sdm845-llcc";
+            reg = <0 0x01100000 0 0x50000>, <0 0x01180000 0 0x50000>,
+                <0 0x01200000 0 0x50000>, <0 0x01280000 0 0x50000>,
+                <0 0x01300000 0 0x50000>;
+            reg-names = "llcc0_base", "llcc1_base", "llcc2_base",
+                "llcc3_base", "llcc_broadcast_base";
+            interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
+        };
     };
diff --git a/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml b/Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml
new file mode 100644 (file)
index 0000000..92e1d76
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/crypto/qcom,inline-crypto-engine.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. (QTI) Inline Crypto Engine
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - qcom,sm8550-inline-crypto-engine
+      - const: qcom,inline-crypto-engine
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,sm8550-gcc.h>
+
+    crypto@1d88000 {
+      compatible = "qcom,sm8550-inline-crypto-engine",
+                   "qcom,inline-crypto-engine";
+      reg = <0x01d88000 0x8000>;
+      clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+    };
+...
index 2f7c51c75e85ae8d0c75bb4efe91c7df4ff6ec5a..5824c43e9893133f8a38cbf9bfb56e71eb768f48 100644 (file)
@@ -56,17 +56,38 @@ properties:
     description:
       Specifies the mailboxes used to communicate with SCMI compliant
       firmware.
-    items:
-      - const: tx
-      - const: rx
+    oneOf:
+      - items:
+          - const: tx
+          - const: rx
+        minItems: 1
+      - items:
+          - const: tx
+          - const: tx_reply
+          - const: rx
+        minItems: 2
 
   mboxes:
     description:
       List of phandle and mailbox channel specifiers. It should contain
-      exactly one or two mailboxes, one for transmitting messages("tx")
-      and another optional for receiving the notifications("rx") if supported.
+      exactly one, two or three mailboxes; the first one or two for transmitting
+      messages ("tx") and another optional ("rx") for receiving notifications
+      and delayed responses, if supported by the platform.
+      The number of mailboxes needed for transmitting messages depends on the
+      type of channels exposed by the specific underlying mailbox controller;
+      one single channel descriptor is enough if such channel is bidirectional,
+      while two channel descriptors are needed to represent the SCMI ("tx")
+      channel if the underlying mailbox channels are of unidirectional type.
+      The effective combination in numbers of mboxes and shmem descriptors let
+      the SCMI subsystem determine unambiguosly which type of SCMI channels are
+      made available by the underlying mailbox controller and how to use them.
+       1 mbox / 1 shmem => SCMI TX over 1 mailbox bidirectional channel
+       2 mbox / 2 shmem => SCMI TX and RX over 2 mailbox bidirectional channels
+       2 mbox / 1 shmem => SCMI TX over 2 mailbox unidirectional channels
+       3 mbox / 2 shmem => SCMI TX and RX over 3 mailbox unidirectional channels
+      Any other combination of mboxes and shmem is invalid.
     minItems: 1
-    maxItems: 2
+    maxItems: 3
 
   shmem:
     description:
@@ -228,13 +249,20 @@ $defs:
         maxItems: 1
 
       mbox-names:
-        items:
-          - const: tx
-          - const: rx
+        oneOf:
+          - items:
+              - const: tx
+              - const: rx
+            minItems: 1
+          - items:
+              - const: tx
+              - const: tx_reply
+              - const: rx
+            minItems: 2
 
       mboxes:
         minItems: 1
-        maxItems: 2
+        maxItems: 3
 
       shmem:
         minItems: 1
index a66e99812b1fc36cc6205e6546ac41e16cd6f6b2..367d04ad19236242d4c05bc88a43931964588cc6 100644 (file)
@@ -24,9 +24,11 @@ properties:
           - qcom,scm-apq8064
           - qcom,scm-apq8084
           - qcom,scm-ipq4019
+          - qcom,scm-ipq5332
           - qcom,scm-ipq6018
           - qcom,scm-ipq806x
           - qcom,scm-ipq8074
+          - qcom,scm-ipq9574
           - qcom,scm-mdm9607
           - qcom,scm-msm8226
           - qcom,scm-msm8660
@@ -38,10 +40,12 @@ properties:
           - qcom,scm-msm8994
           - qcom,scm-msm8996
           - qcom,scm-msm8998
+          - qcom,scm-qcm2290
           - qcom,scm-qdu1000
           - qcom,scm-sa8775p
           - qcom,scm-sc7180
           - qcom,scm-sc7280
+          - qcom,scm-sc8180x
           - qcom,scm-sc8280xp
           - qcom,scm-sdm670
           - qcom,scm-sdm845
@@ -107,6 +111,7 @@ allOf:
               - qcom,scm-msm8960
               - qcom,scm-msm8974
               - qcom,scm-msm8976
+              - qcom,scm-qcm2290
               - qcom,scm-sm6375
     then:
       required:
@@ -125,6 +130,7 @@ allOf:
               - qcom,scm-apq8064
               - qcom,scm-msm8660
               - qcom,scm-msm8960
+              - qcom,scm-qcm2290
               - qcom,scm-sm6375
     then:
       properties:
@@ -166,6 +172,7 @@ allOf:
           compatible:
             contains:
               enum:
+                - qcom,scm-qdu1000
                 - qcom,scm-sm8450
                 - qcom,scm-sm8550
     then:
diff --git a/Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml b/Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml
deleted file mode 100644 (file)
index 2a1cf88..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/interrupt-controller/loongarch,cpu-interrupt-controller.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: LoongArch CPU Interrupt Controller
-
-maintainers:
-  - Liu Peibao <liupeibao@loongson.cn>
-
-properties:
-  compatible:
-    const: loongarch,cpu-interrupt-controller
-
-  '#interrupt-cells':
-    const: 1
-
-  interrupt-controller: true
-
-additionalProperties: false
-
-required:
-  - compatible
-  - '#interrupt-cells'
-  - interrupt-controller
-
-examples:
-  - |
-    interrupt-controller {
-      compatible = "loongarch,cpu-interrupt-controller";
-      #interrupt-cells = <1>;
-      interrupt-controller;
-    };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/loongson,cpu-interrupt-controller.yaml b/Documentation/devicetree/bindings/interrupt-controller/loongson,cpu-interrupt-controller.yaml
new file mode 100644 (file)
index 0000000..adf9899
--- /dev/null
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/loongson,cpu-interrupt-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LoongArch CPU Interrupt Controller
+
+maintainers:
+  - Liu Peibao <liupeibao@loongson.cn>
+
+properties:
+  compatible:
+    const: loongson,cpu-interrupt-controller
+
+  '#interrupt-cells':
+    const: 1
+
+  interrupt-controller: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - '#interrupt-cells'
+  - interrupt-controller
+
+examples:
+  - |
+    interrupt-controller {
+      compatible = "loongson,cpu-interrupt-controller";
+      #interrupt-cells = <1>;
+      interrupt-controller;
+    };
index a8fda30cccbb5b605f929230715be90021d77505..2f36ac23604c50b1e9838c6a3d8b10bdc873bdac 100644 (file)
@@ -43,6 +43,7 @@ properties:
           - mediatek,mt8195-smi-common-vdo
           - mediatek,mt8195-smi-common-vpp
           - mediatek,mt8195-smi-sub-common
+          - mediatek,mt8365-smi-common
 
       - description: for mt7623
         items:
@@ -133,6 +134,7 @@ allOf:
             - mediatek,mt8192-smi-common
             - mediatek,mt8195-smi-common-vdo
             - mediatek,mt8195-smi-common-vpp
+            - mediatek,mt8365-smi-common
 
     then:
       properties:
index 5f4ac3609887f2975b5ed8cf0d6fb73da114aed7..aee7f6cf13003586c4a0d26912bde4f2a96b0067 100644 (file)
@@ -34,6 +34,10 @@ properties:
           - const: mediatek,mt7623-smi-larb
           - const: mediatek,mt2701-smi-larb
 
+      - items:
+          - const: mediatek,mt8365-smi-larb
+          - const: mediatek,mt8186-smi-larb
+
   reg:
     maxItems: 1
 
index 7056ccb7eb304cce9d0654a92833ec023ab480b1..8e3822314b25ac59dc9a9c56dadcfb38e39bbd41 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/memory-controllers/renesas,dbsc.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/memory-controllers/renesas,dbsc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Renesas DDR Bus Controllers
 
index 30a403b1b79a2c73508259d296f94871f8dd5deb..56e62cd0b36abd7a89b1ad3a57c9e4f41a92f445 100644 (file)
@@ -20,7 +20,7 @@ description: |
   - if it contains "cfi-flash", then HyperFlash is used.
 
 allOf:
-  - $ref: "/schemas/spi/spi-controller.yaml#"
+  - $ref: /schemas/spi/spi-controller.yaml#
 
 properties:
   compatible:
index 098348b2b815eab70a680e8701c37bea1e75f2c8..783ac984d89849e6683c87a77123156a57a9c63e 100644 (file)
@@ -42,7 +42,7 @@ properties:
     maxItems: 8
 
   devfreq-events:
-    $ref: '/schemas/types.yaml#/definitions/phandle-array'
+    $ref: /schemas/types.yaml#/definitions/phandle-array
     minItems: 1
     maxItems: 16
     items:
@@ -50,7 +50,7 @@ properties:
     description: phandles of the PPMU events used by the controller.
 
   device-handle:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
+    $ref: /schemas/types.yaml#/definitions/phandle
     description: |
       phandle of the connected DRAM memory device. For more information please
       refer to jedec,lpddr3.yaml.
@@ -73,7 +73,7 @@ properties:
       - description: registers of DREX1
 
   samsung,syscon-clk:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
+    $ref: /schemas/types.yaml#/definitions/phandle
     description: |
       Phandle of the clock register set used by the controller, these registers
       are used for enabling a 'pause' feature and are not exposed by clock
index 3fe981b14e2cb7d3380c19de4b56fc12bf99b00e..54736362378eb5975712fccb9a6f73c058741533 100644 (file)
@@ -76,6 +76,13 @@ properties:
       If "broken-flash-reset" is present then having this property does not
       make any difference.
 
+  spi-cpol: true
+  spi-cpha: true
+
+dependencies:
+  spi-cpol: [ spi-cpha ]
+  spi-cpha: [ spi-cpol ]
+
 unevaluatedProperties: false
 
 examples:
index 5e90051ed314ae1c1f8f60db6e3ead4e5aa99d3f..8f60a9113e7a28ab7628e036d4d2445102868d1e 100644 (file)
@@ -96,9 +96,11 @@ $defs:
           2: Lower Slew rate (slower edges)
           3: Reserved (No adjustments)
 
+      bias-bus-hold: true
       bias-pull-down: true
       bias-pull-up: true
       bias-disable: true
+      input-enable: true
       output-high: true
       output-low: true
 
index 1989bd67d04e8ad923fc45b25e5dec533dc096a1..54e4f41be9b4261ba877d9b2066a632b32a3d979 100644 (file)
@@ -92,7 +92,7 @@ properties:
           - description: Error interrupt
           - description: Receive buffer full interrupt
           - description: Transmit buffer empty interrupt
-          - description: Transmit End interrupt
+          - description: Break interrupt
       - items:
           - description: Error interrupt
           - description: Receive buffer full interrupt
@@ -107,7 +107,7 @@ properties:
           - const: eri
           - const: rxi
           - const: txi
-          - const: tei
+          - const: bri
       - items:
           - const: eri
           - const: rxi
index c3c59909635310d6a72a09b57f26c23412c10a0e..cd06865e1f2a81dee979a20a37e02583afae134c 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2019 BayLibre, SAS
 %YAML 1.2
 ---
-$id: "http://devicetree.org/schemas/soc/amlogic/amlogic,canvas.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/soc/amlogic/amlogic,canvas.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Amlogic Canvas Video Lookup Table
 
diff --git a/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml b/Documentation/devicetree/bindings/soc/amlogic/amlogic,meson-gx-clk-measure.yaml
new file mode 100644 (file)
index 0000000..77c2811
--- /dev/null
@@ -0,0 +1,40 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/amlogic/amlogic,meson-gx-clk-measure.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Internal Clock Measurer
+
+description:
+  The Amlogic SoCs contains an IP to measure the internal clocks.
+  The precision is multiple of MHz, useful to debug the clock states.
+
+maintainers:
+  - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,meson-gx-clk-measure
+      - amlogic,meson8-clk-measure
+      - amlogic,meson8b-clk-measure
+      - amlogic,meson-axg-clk-measure
+      - amlogic,meson-g12a-clk-measure
+      - amlogic,meson-sm1-clk-measure
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    clock-measure@8758 {
+        compatible = "amlogic,meson-gx-clk-measure";
+        reg = <0x8758 0x10>;
+    };
diff --git a/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt b/Documentation/devicetree/bindings/soc/amlogic/clk-measure.txt
deleted file mode 100644 (file)
index 3dd563c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Amlogic Internal Clock Measurer
-===============================
-
-The Amlogic SoCs contains an IP to measure the internal clocks.
-The precision is multiple of MHz, useful to debug the clock states.
-
-Required properties:
-- compatible: Shall contain one of the following :
-                       "amlogic,meson-gx-clk-measure" for GX SoCs
-                       "amlogic,meson8-clk-measure" for Meson8 SoCs
-                       "amlogic,meson8b-clk-measure" for Meson8b SoCs
-                       "amlogic,meson-axg-clk-measure" for AXG SoCs
-                       "amlogic,meson-g12a-clk-measure" for G12a SoCs
-                       "amlogic,meson-sm1-clk-measure" for SM1 SoCs
-- reg: base address and size of the Clock Measurer register space.
-
-Example:
-       clock-measure@8758 {
-               compatible = "amlogic,meson-gx-clk-measure";
-               reg = <0x0 0x8758 0x0 0x10>;
-       };
index 15c133cac3157d971d54677b6f728b4bd2d94e13..ba2014a8725c3630d1935fa5c7f47f036e0b7cdb 100644 (file)
@@ -35,6 +35,8 @@ properties:
       - mediatek,mt8188-disp-mutex
       - mediatek,mt8192-disp-mutex
       - mediatek,mt8195-disp-mutex
+      - mediatek,mt8195-vpp-mutex
+      - mediatek,mt8365-disp-mutex
 
   reg:
     maxItems: 1
@@ -70,12 +72,30 @@ properties:
       4 arguments defined in this property. Each GCE subsys id is mapping to
       a client defined in the header include/dt-bindings/gce/<chip>-gce.h.
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - mediatek,mt2701-disp-mutex
+              - mediatek,mt2712-disp-mutex
+              - mediatek,mt6795-disp-mutex
+              - mediatek,mt8173-disp-mutex
+              - mediatek,mt8186-disp-mutex
+              - mediatek,mt8186-mdp3-mutex
+              - mediatek,mt8192-disp-mutex
+              - mediatek,mt8195-disp-mutex
+    then:
+      required:
+        - clocks
+
+
 required:
   - compatible
   - reg
   - interrupts
   - power-domains
-  - clocks
 
 additionalProperties: false
 
index ab607efbb64c1218dd75cfd5edc0fc5217dcc7de..798f15588ee259dd60e39077c99cd9f2b9c9fff3 100644 (file)
@@ -25,6 +25,7 @@ properties:
   compatible:
     items:
       - enum:
+          - qcom,qdu1000-aoss-qmp
           - qcom,sc7180-aoss-qmp
           - qcom,sc7280-aoss-qmp
           - qcom,sc8180x-aoss-qmp
index 6026c21736d880e4685ff0b227fd66c8b2c64cb7..4502458b066907af5b7411cdf23fe7cd6fbe09ea 100644 (file)
@@ -62,7 +62,14 @@ properties:
     maxItems: 1
 
   qcom,intents:
-    $ref: /schemas/types.yaml#/definitions/uint32-array
+    $ref: /schemas/types.yaml#/definitions/uint32-matrix
+    minItems: 1
+    maxItems: 32
+    items:
+      items:
+        - description: size of each intent to preallocate
+        - description: amount of intents to preallocate
+          minimum: 1
     description:
       List of (size, amount) pairs describing what intents should be
       preallocated for this virtual channel. This can be used to tweak the
index cf863683c21a8595a781c872f68af94396f34980..6440dc801387db748150fe8dc50e9e1d0db20464 100644 (file)
@@ -25,6 +25,8 @@ properties:
           - qcom,sc8180x-pmic-glink
           - qcom,sc8280xp-pmic-glink
           - qcom,sm8350-pmic-glink
+          - qcom,sm8450-pmic-glink
+          - qcom,sm8550-pmic-glink
       - const: qcom,pmic-glink
 
   '#address-cells':
index 16fd67c0bd1fd60cc919cdccd88e82a19e371f5c..94765fbc868e234a1926b1ae30ce1fbe73df6042 100644 (file)
@@ -33,6 +33,7 @@ properties:
     enum:
       - qcom,rpm-apq8084
       - qcom,rpm-ipq6018
+      - qcom,rpm-ipq9574
       - qcom,rpm-msm8226
       - qcom,rpm-msm8909
       - qcom,rpm-msm8916
@@ -40,6 +41,7 @@ properties:
       - qcom,rpm-msm8953
       - qcom,rpm-msm8974
       - qcom,rpm-msm8976
+      - qcom,rpm-msm8994
       - qcom,rpm-msm8996
       - qcom,rpm-msm8998
       - qcom,rpm-sdm660
@@ -84,6 +86,7 @@ if:
           - qcom,rpm-msm8974
           - qcom,rpm-msm8976
           - qcom,rpm-msm8953
+          - qcom,rpm-msm8994
 then:
   properties:
     qcom,glink-channels: false
index ba694ce4a037ca188e632bcca62e9d15faaf51a8..0548e8e0d30be616f994dbe10ab7363d3bde9970 100644 (file)
@@ -26,6 +26,7 @@ properties:
           - qcom,sdm845-imem
           - qcom,sdx55-imem
           - qcom,sdx65-imem
+          - qcom,sm6375-imem
           - qcom,sm8450-imem
       - const: syscon
       - const: simple-mfd
index 3cad45d14187243e71a584cb82daa8a5adb8f678..93bab5336dfda06069eea700d2830089bf3bce03 100644 (file)
@@ -258,6 +258,11 @@ clocks properly but rely on them being on from the bootloader, bypassing
 the disabling means that the driver will remain functional while the issues
 are sorted out.
 
+You can see which clocks have been disabled by booting your kernel with these
+parameters::
+
+ tp_printk trace_event=clk:clk_disable
+
 To bypass this disabling, include "clk_ignore_unused" in the bootargs to the
 kernel.
 
index 4d2baac0311c8b0a206396370de20b3a07b6778f..2c7abd234f4e2480de17eec155191ddeb6b69fbe 100644 (file)
@@ -410,7 +410,7 @@ ioremap_uc()
 
 ioremap_uc() behaves like ioremap() except that on the x86 architecture without
 'PAT' mode, it marks memory as uncached even when the MTRR has designated
-it as cacheable, see Documentation/x86/pat.rst.
+it as cacheable, see Documentation/arch/x86/pat.rst.
 
 Portable drivers should avoid the use of ioremap_uc().
 
index a360f1009fa342e57f672159120c1ae5c902bfd2..d7cb1e8f00761f600a05ad8c373e7a88b2fd8e79 100644 (file)
@@ -22,5 +22,10 @@ can use the file:
 
 * /sys/module/firmware_class/parameters/path
 
-You would echo into it your custom path and firmware requested will be
-searched for there first.
+You would echo into it your custom path and firmware requested will be searched
+for there first. Be aware that newline characters will be taken into account
+and may not produce the intended effects. For instance you might want to use:
+
+echo -n /path/to/script > /sys/module/firmware_class/parameters/path
+
+to ensure that your script is being used.
index 50b690f7f66392d5131a2410717caa0cc44cd53e..68abc089d6ddd173013b115ff65df1e84b292706 100644 (file)
@@ -242,7 +242,7 @@ group and can access them as follows::
 VFIO User API
 -------------------------------------------------------------------------------
 
-Please see include/linux/vfio.h for complete API documentation.
+Please see include/uapi/linux/vfio.h for complete API documentation.
 
 VFIO bus driver API
 -------------------------------------------------------------------------------
index a43aacf1494e778585aea093fb4c099dc4459be7..4654ee57c1d5e4ef5d59d9b34cea5651434c5b34 100644 (file)
@@ -40,8 +40,8 @@ Here are the main features of EROFS:
  - Support multiple devices to refer to external blobs, which can be used
    for container images;
 
- - 4KiB block size and 32-bit block addresses for each device, therefore
-   16TiB address space at most for now;
+ - 32-bit block addresses for each device, therefore 16TiB address space at
+   most with 4KiB block size for now;
 
  - Two inode layouts for different requirements:
 
index b9b31066aef2ce828f0b3288c78ced482a23b85b..ad6d216405768ea46aa28e069de233516187274a 100644 (file)
@@ -241,7 +241,7 @@ according to the filesystem's idmapping as this would give the wrong owner if
 the caller is using an idmapping.
 
 So the kernel will map the id back up in the idmapping of the caller. Let's
-assume the caller has the slighly unconventional idmapping
+assume the caller has the somewhat unconventional idmapping
 ``u3000:k20000:r10000`` then ``k21000`` would map back up to ``u4000``.
 Consequently the user would see that this file is owned by ``u4000``.
 
@@ -320,6 +320,10 @@ and equally wrong::
  from_kuid(u20000:k0:r10000, u1000) = k21000
                              ~~~~~
 
+Since userspace ids have type ``uid_t`` and ``gid_t`` and kernel ids have type
+``kuid_t`` and ``kgid_t`` the compiler will throw an error when they are
+conflated. So the two examples above would cause a compilation failure.
+
 Idmappings when creating filesystem objects
 -------------------------------------------
 
@@ -623,42 +627,105 @@ privileged users in the initial user namespace.
 However, it is perfectly possible to combine idmapped mounts with filesystems
 mountable inside user namespaces. We will touch on this further below.
 
+Filesystem types vs idmapped mount types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+With the introduction of idmapped mounts we need to distinguish between
+filesystem ownership and mount ownership of a VFS object such as an inode. The
+owner of a inode might be different when looked at from a filesystem
+perspective than when looked at from an idmapped mount. Such fundamental
+conceptual distinctions should almost always be clearly expressed in the code.
+So, to distinguish idmapped mount ownership from filesystem ownership separate
+types have been introduced.
+
+If a uid or gid has been generated using the filesystem or caller's idmapping
+then we will use the ``kuid_t`` and ``kgid_t`` types. However, if a uid or gid
+has been generated using a mount idmapping then we will be using the dedicated
+``vfsuid_t`` and ``vfsgid_t`` types.
+
+All VFS helpers that generate or take uids and gids as arguments use the
+``vfsuid_t`` and ``vfsgid_t`` types and we will be able to rely on the compiler
+to catch errors that originate from conflating filesystem and VFS uids and gids.
+
+The ``vfsuid_t`` and ``vfsgid_t`` types are often mapped from and to ``kuid_t``
+and ``kgid_t`` types similar how ``kuid_t`` and ``kgid_t`` types are mapped
+from and to ``uid_t`` and ``gid_t`` types::
+
+ uid_t <--> kuid_t <--> vfsuid_t
+ gid_t <--> kgid_t <--> vfsgid_t
+
+Whenever we report ownership based on a ``vfsuid_t`` or ``vfsgid_t`` type,
+e.g., during ``stat()``, or store ownership information in a shared VFS object
+based on a ``vfsuid_t`` or ``vfsgid_t`` type, e.g., during ``chown()`` we can
+use the ``vfsuid_into_kuid()`` and ``vfsgid_into_kgid()`` helpers.
+
+To illustrate why this helper currently exists, consider what happens when we
+change ownership of an inode from an idmapped mount. After we generated
+a ``vfsuid_t`` or ``vfsgid_t`` based on the mount idmapping we later commit to
+this ``vfsuid_t`` or ``vfsgid_t`` to become the new filesytem wide ownership.
+Thus, we are turning the ``vfsuid_t`` or ``vfsgid_t`` into a global ``kuid_t``
+or ``kgid_t``. And this can be done by using ``vfsuid_into_kuid()`` and
+``vfsgid_into_kgid()``.
+
+Note, whenever a shared VFS object, e.g., a cached ``struct inode`` or a cached
+``struct posix_acl``, stores ownership information a filesystem or "global"
+``kuid_t`` and ``kgid_t`` must be used. Ownership expressed via ``vfsuid_t``
+and ``vfsgid_t`` is specific to an idmapped mount.
+
+We already noted that ``vfsuid_t`` and ``vfsgid_t`` types are generated based
+on mount idmappings whereas ``kuid_t`` and ``kgid_t`` types are generated based
+on filesystem idmappings. To prevent abusing filesystem idmappings to generate
+``vfsuid_t`` or ``vfsgid_t`` types or mount idmappings to generate ``kuid_t``
+or ``kgid_t`` types filesystem idmappings and mount idmappings are different
+types as well.
+
+All helpers that map to or from ``vfsuid_t`` and ``vfsgid_t`` types require
+a mount idmapping to be passed which is of type ``struct mnt_idmap``. Passing
+a filesystem or caller idmapping will cause a compilation error.
+
+Similar to how we prefix all userspace ids in this document with ``u`` and all
+kernel ids with ``k`` we will prefix all VFS ids with ``v``. So a mount
+idmapping will be written as: ``u0:v10000:r10000``.
+
 Remapping helpers
 ~~~~~~~~~~~~~~~~~
 
 Idmapping functions were added that translate between idmappings. They make use
-of the remapping algorithm we've introduced earlier. We're going to look at
-two:
+of the remapping algorithm we've introduced earlier. We're going to look at:
 
-- ``i_uid_into_mnt()`` and ``i_gid_into_mnt()``
+- ``i_uid_into_vfsuid()`` and ``i_gid_into_vfsgid()``
 
-  The ``i_*id_into_mnt()`` functions translate filesystem's kernel ids into
-  kernel ids in the mount's idmapping::
+  The ``i_*id_into_vfs*id()`` functions translate filesystem's kernel ids into
+  VFS ids in the mount's idmapping::
 
    /* Map the filesystem's kernel id up into a userspace id in the filesystem's idmapping. */
    from_kuid(filesystem, kid) = uid
 
-   /* Map the filesystem's userspace id down ito a kernel id in the mount's idmapping. */
+   /* Map the filesystem's userspace id down ito a VFS id in the mount's idmapping. */
    make_kuid(mount, uid) = kuid
 
 - ``mapped_fsuid()`` and ``mapped_fsgid()``
 
   The ``mapped_fs*id()`` functions translate the caller's kernel ids into
   kernel ids in the filesystem's idmapping. This translation is achieved by
-  remapping the caller's kernel ids using the mount's idmapping::
+  remapping the caller's VFS ids using the mount's idmapping::
 
-   /* Map the caller's kernel id up into a userspace id in the mount's idmapping. */
+   /* Map the caller's VFS id up into a userspace id in the mount's idmapping. */
    from_kuid(mount, kid) = uid
 
    /* Map the mount's userspace id down into a kernel id in the filesystem's idmapping. */
    make_kuid(filesystem, uid) = kuid
 
+- ``vfsuid_into_kuid()`` and ``vfsgid_into_kgid()``
+
+   Whenever
+
 Note that these two functions invert each other. Consider the following
 idmappings::
 
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k20000:r10000
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 Assume a file owned by ``u1000`` is read from disk. The filesystem maps this id
 to ``k21000`` according to its idmapping. This is what is stored in the
@@ -669,20 +736,21 @@ would usually simply use the crossmapping algorithm and map the filesystem's
 kernel id up to a userspace id in the caller's idmapping.
 
 But when the caller is accessing the file on an idmapped mount the kernel will
-first call ``i_uid_into_mnt()`` thereby translating the filesystem's kernel id
-into a kernel id in the mount's idmapping::
+first call ``i_uid_into_vfsuid()`` thereby translating the filesystem's kernel
+id into a VFS id in the mount's idmapping::
 
- i_uid_into_mnt(k21000):
+ i_uid_into_vfsuid(k21000):
    /* Map the filesystem's kernel id up into a userspace id. */
    from_kuid(u0:k20000:r10000, k21000) = u1000
 
-   /* Map the filesystem's userspace id down ito a kernel id in the mount's idmapping. */
-   make_kuid(u0:k10000:r10000, u1000) = k11000
+   /* Map the filesystem's userspace id down into a VFS id in the mount's idmapping. */
+   make_kuid(u0:v10000:r10000, u1000) = v11000
 
 Finally, when the kernel reports the owner to the caller it will turn the
-kernel id in the mount's idmapping into a userspace id in the caller's
+VFS id in the mount's idmapping into a userspace id in the caller's
 idmapping::
 
+  k11000 = vfsuid_into_kuid(v11000)
   from_kuid(u0:k10000:r10000, k11000) = u1000
 
 We can test whether this algorithm really works by verifying what happens when
@@ -696,18 +764,19 @@ fails.
 
 But when the caller is accessing the file on an idmapped mount the kernel will
 first call ``mapped_fs*id()`` thereby translating the caller's kernel id into
-a kernel id according to the mount's idmapping::
+a VFS id according to the mount's idmapping::
 
  mapped_fsuid(k11000):
     /* Map the caller's kernel id up into a userspace id in the mount's idmapping. */
     from_kuid(u0:k10000:r10000, k11000) = u1000
 
     /* Map the mount's userspace id down into a kernel id in the filesystem's idmapping. */
-    make_kuid(u0:k20000:r10000, u1000) = k21000
+    make_kuid(u0:v20000:r10000, u1000) = v21000
 
-When finally writing to disk the kernel will then map ``k21000`` up into a
+When finally writing to disk the kernel will then map ``v21000`` up into a
 userspace id in the filesystem's idmapping::
 
+   k21000 = vfsuid_into_kuid(v21000)
    from_kuid(u0:k20000:r10000, k21000) = u1000
 
 As we can see, we end up with an invertible and therefore information
@@ -725,7 +794,7 @@ Example 2 reconsidered
  caller id:            u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k20000:r10000
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 When the caller is using a non-initial idmapping the common case is to attach
 the same idmapping to the mount. We now perform three steps:
@@ -734,12 +803,12 @@ the same idmapping to the mount. We now perform three steps:
 
     make_kuid(u0:k10000:r10000, u1000) = k11000
 
-2. Translate the caller's kernel id into a kernel id in the filesystem's
+2. Translate the caller's VFS id into a kernel id in the filesystem's
    idmapping::
 
-    mapped_fsuid(k11000):
-      /* Map the kernel id up into a userspace id in the mount's idmapping. */
-      from_kuid(u0:k10000:r10000, k11000) = u1000
+    mapped_fsuid(v11000):
+      /* Map the VFS id up into a userspace id in the mount's idmapping. */
+      from_kuid(u0:v10000:r10000, v11000) = u1000
 
       /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
       make_kuid(u0:k20000:r10000, u1000) = k21000
@@ -759,7 +828,7 @@ Example 3 reconsidered
  caller id:            u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 The same translation algorithm works with the third example.
 
@@ -767,12 +836,12 @@ The same translation algorithm works with the third example.
 
     make_kuid(u0:k10000:r10000, u1000) = k11000
 
-2. Translate the caller's kernel id into a kernel id in the filesystem's
+2. Translate the caller's VFS id into a kernel id in the filesystem's
    idmapping::
 
-    mapped_fsuid(k11000):
-       /* Map the kernel id up into a userspace id in the mount's idmapping. */
-       from_kuid(u0:k10000:r10000, k11000) = u1000
+    mapped_fsuid(v11000):
+       /* Map the VFS id up into a userspace id in the mount's idmapping. */
+       from_kuid(u0:v10000:r10000, v11000) = u1000
 
        /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
        make_kuid(u0:k0:r4294967295, u1000) = k1000
@@ -792,7 +861,7 @@ Example 4 reconsidered
  file id:              u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 In order to report ownership to userspace the kernel now does three steps using
 the translation algorithm we introduced earlier:
@@ -802,17 +871,18 @@ the translation algorithm we introduced earlier:
 
     make_kuid(u0:k0:r4294967295, u1000) = k1000
 
-2. Translate the kernel id into a kernel id in the mount's idmapping::
+2. Translate the kernel id into a VFS id in the mount's idmapping::
 
-    i_uid_into_mnt(k1000):
+    i_uid_into_vfsuid(k1000):
       /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
       from_kuid(u0:k0:r4294967295, k1000) = u1000
 
-      /* Map the userspace id down into a kernel id in the mounts's idmapping. */
-      make_kuid(u0:k10000:r10000, u1000) = k11000
+      /* Map the userspace id down into a VFS id in the mounts's idmapping. */
+      make_kuid(u0:v10000:r10000, u1000) = v11000
 
-3. Map the kernel id up into a userspace id in the caller's idmapping::
+3. Map the VFS id up into a userspace id in the caller's idmapping::
 
+    k11000 = vfsuid_into_kuid(v11000)
     from_kuid(u0:k10000:r10000, k11000) = u1000
 
 Earlier, the caller's kernel id couldn't be crossmapped in the filesystems's
@@ -828,7 +898,7 @@ Example 5 reconsidered
  file id:              u1000
  caller idmapping:     u0:k10000:r10000
  filesystem idmapping: u0:k20000:r10000
- mount idmapping:      u0:k10000:r10000
+ mount idmapping:      u0:v10000:r10000
 
 Again, in order to report ownership to userspace the kernel now does three
 steps using the translation algorithm we introduced earlier:
@@ -838,17 +908,18 @@ steps using the translation algorithm we introduced earlier:
 
     make_kuid(u0:k20000:r10000, u1000) = k21000
 
-2. Translate the kernel id into a kernel id in the mount's idmapping::
+2. Translate the kernel id into a VFS id in the mount's idmapping::
 
-    i_uid_into_mnt(k21000):
+    i_uid_into_vfsuid(k21000):
       /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
       from_kuid(u0:k20000:r10000, k21000) = u1000
 
-      /* Map the userspace id down into a kernel id in the mounts's idmapping. */
-      make_kuid(u0:k10000:r10000, u1000) = k11000
+      /* Map the userspace id down into a VFS id in the mounts's idmapping. */
+      make_kuid(u0:v10000:r10000, u1000) = v11000
 
-3. Map the kernel id up into a userspace id in the caller's idmapping::
+3. Map the VFS id up into a userspace id in the caller's idmapping::
 
+    k11000 = vfsuid_into_kuid(v11000)
     from_kuid(u0:k10000:r10000, k11000) = u1000
 
 Earlier, the file's kernel id couldn't be crossmapped in the filesystems's
@@ -899,23 +970,23 @@ from above:::
  caller id:            u1125
  caller idmapping:     u0:k0:r4294967295
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u1000:k1125:r1
+ mount idmapping:      u1000:v1125:r1
 
 1. Map the caller's userspace ids into kernel ids in the caller's idmapping::
 
     make_kuid(u0:k0:r4294967295, u1125) = k1125
 
-2. Translate the caller's kernel id into a kernel id in the filesystem's
+2. Translate the caller's VFS id into a kernel id in the filesystem's
    idmapping::
 
-    mapped_fsuid(k1125):
-      /* Map the kernel id up into a userspace id in the mount's idmapping. */
-      from_kuid(u1000:k1125:r1, k1125) = u1000
+    mapped_fsuid(v1125):
+      /* Map the VFS id up into a userspace id in the mount's idmapping. */
+      from_kuid(u1000:v1125:r1, v1125) = u1000
 
       /* Map the userspace id down into a kernel id in the filesystem's idmapping. */
       make_kuid(u0:k0:r4294967295, u1000) = k1000
 
-2. Verify that the caller's kernel ids can be mapped to userspace ids in the
+2. Verify that the caller's filesystem ids can be mapped to userspace ids in the
    filesystem's idmapping::
 
     from_kuid(u0:k0:r4294967295, k1000) = u1000
@@ -930,24 +1001,25 @@ on their work computer:
  file id:              u1000
  caller idmapping:     u0:k0:r4294967295
  filesystem idmapping: u0:k0:r4294967295
- mount idmapping:      u1000:k1125:r1
+ mount idmapping:      u1000:v1125:r1
 
 1. Map the userspace id on disk down into a kernel id in the filesystem's
    idmapping::
 
     make_kuid(u0:k0:r4294967295, u1000) = k1000
 
-2. Translate the kernel id into a kernel id in the mount's idmapping::
+2. Translate the kernel id into a VFS id in the mount's idmapping::
 
-    i_uid_into_mnt(k1000):
+    i_uid_into_vfsuid(k1000):
       /* Map the kernel id up into a userspace id in the filesystem's idmapping. */
       from_kuid(u0:k0:r4294967295, k1000) = u1000
 
-      /* Map the userspace id down into a kernel id in the mounts's idmapping. */
-      make_kuid(u1000:k1125:r1, u1000) = k1125
+      /* Map the userspace id down into a VFS id in the mounts's idmapping. */
+      make_kuid(u1000:v1125:r1, u1000) = v1125
 
-3. Map the kernel id up into a userspace id in the caller's idmapping::
+3. Map the VFS id up into a userspace id in the caller's idmapping::
 
+    k1125 = vfsuid_into_kuid(v1125)
     from_kuid(u0:k0:r4294967295, k1125) = u1125
 
 So ultimately the caller will be reported that the file belongs to ``u1125``
index 63204d2094fdf4c75ffc5c4131304f960959bdcb..9aaf6ef75eb53b1ef25f20a0641479c48823183e 100644 (file)
@@ -79,7 +79,6 @@ context.  This is represented by the fs_context structure::
                unsigned int            sb_flags;
                unsigned int            sb_flags_mask;
                unsigned int            s_iflags;
-               unsigned int            lsm_flags;
                enum fs_context_purpose purpose:8;
                ...
        };
index 9d5fd9424e8bbdc7dfa6567908282612d4d26ec0..59db0bed35e12c37786ef21c2cd42bce701bdc83 100644 (file)
@@ -85,7 +85,7 @@ contact Bodo  Bauer  at  bb@ricochet.net.  We'll  be happy to add them to this
 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
@@ -232,7 +232,7 @@ asynchronous manner and the value may not be very precise. To see a precise
 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
@@ -305,7 +305,7 @@ It's slow but very precise.
  ==========================  ===================================================
 
 
-.. 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
@@ -323,7 +323,7 @@ It's slow but very precise.
  ======== ===============================      ==============================
 
 
-.. 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
@@ -1321,9 +1321,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:
@@ -1449,16 +1449,18 @@ Various pieces   of  information about  kernel activity  are  available in the
 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
@@ -1520,8 +1522,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>
 
@@ -1601,12 +1603,12 @@ can inadvertently  disrupt  your  system,  it  is  advisable  to  read  both
 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
 -------
index c53f30251a660c8b143e32bac800420fb9afe057..769be5230210769b454f14cbdf640301dd034121 100644 (file)
@@ -107,7 +107,7 @@ file /proc/filesystems.
 struct file_system_type
 -----------------------
 
-This describes the filesystem.  As of kernel 2.6.39, the following
+This describes the filesystem.  The following
 members are defined:
 
 .. code-block:: c
@@ -115,14 +115,24 @@ members are defined:
        struct file_system_type {
                const char *name;
                int fs_flags;
+               int (*init_fs_context)(struct fs_context *);
+               const struct fs_parameter_spec *parameters;
                struct dentry *(*mount) (struct file_system_type *, int,
-                                        const char *, void *);
+                       const char *, void *);
                void (*kill_sb) (struct super_block *);
                struct module *owner;
                struct file_system_type * next;
-               struct list_head fs_supers;
+               struct hlist_head fs_supers;
+
                struct lock_class_key s_lock_key;
                struct lock_class_key s_umount_key;
+               struct lock_class_key s_vfs_rename_key;
+               struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];
+
+               struct lock_class_key i_lock_key;
+               struct lock_class_key i_mutex_key;
+               struct lock_class_key invalidate_lock_key;
+               struct lock_class_key i_mutex_dir_key;
        };
 
 ``name``
@@ -132,6 +142,15 @@ members are defined:
 ``fs_flags``
        various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
 
+``init_fs_context``
+       Initializes 'struct fs_context' ->ops and ->fs_private fields with
+       filesystem-specific data.
+
+``parameters``
+       Pointer to the array of filesystem parameters descriptors
+       'struct fs_parameter_spec'.
+       More info in Documentation/filesystems/mount_api.rst.
+
 ``mount``
        the method to call when a new instance of this filesystem should
        be mounted
@@ -148,7 +167,11 @@ members are defined:
 ``next``
        for internal VFS use: you should initialize this to NULL
 
-  s_lock_key, s_umount_key: lockdep-specific
+``fs_supers``
+       for internal VFS use: hlist of filesystem instances (superblocks)
+
+  s_lock_key, s_umount_key, s_vfs_rename_key, s_writers_key,
+  i_lock_key, i_mutex_key, invalidate_lock_key, i_mutex_dir_key: lockdep-specific
 
 The mount() method has the following arguments:
 
@@ -222,33 +245,42 @@ struct super_operations
 -----------------------
 
 This describes how the VFS can manipulate the superblock of your
-filesystem.  As of kernel 2.6.22, the following members are defined:
+filesystem.  The following members are defined:
 
 .. code-block:: c
 
        struct super_operations {
                struct inode *(*alloc_inode)(struct super_block *sb);
                void (*destroy_inode)(struct inode *);
+               void (*free_inode)(struct inode *);
 
                void (*dirty_inode) (struct inode *, int flags);
-               int (*write_inode) (struct inode *, int);
-               void (*drop_inode) (struct inode *);
-               void (*delete_inode) (struct inode *);
+               int (*write_inode) (struct inode *, struct writeback_control *wbc);
+               int (*drop_inode) (struct inode *);
+               void (*evict_inode) (struct inode *);
                void (*put_super) (struct super_block *);
                int (*sync_fs)(struct super_block *sb, int wait);
+               int (*freeze_super) (struct super_block *);
                int (*freeze_fs) (struct super_block *);
+               int (*thaw_super) (struct super_block *);
                int (*unfreeze_fs) (struct super_block *);
                int (*statfs) (struct dentry *, struct kstatfs *);
                int (*remount_fs) (struct super_block *, int *, char *);
-               void (*clear_inode) (struct inode *);
                void (*umount_begin) (struct super_block *);
 
                int (*show_options)(struct seq_file *, struct dentry *);
+               int (*show_devname)(struct seq_file *, struct dentry *);
+               int (*show_path)(struct seq_file *, struct dentry *);
+               int (*show_stats)(struct seq_file *, struct dentry *);
 
                ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
                ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
-               int (*nr_cached_objects)(struct super_block *);
-               void (*free_cached_objects)(struct super_block *, int);
+               struct dquot **(*get_dquots)(struct inode *);
+
+               long (*nr_cached_objects)(struct super_block *,
+                                       struct shrink_control *);
+               long (*free_cached_objects)(struct super_block *,
+                                       struct shrink_control *);
        };
 
 All methods are called without any locks being held, unless otherwise
@@ -269,6 +301,11 @@ or bottom half).
        ->alloc_inode was defined and simply undoes anything done by
        ->alloc_inode.
 
+``free_inode``
+       this method is called from RCU callback. If you use call_rcu()
+       in ->destroy_inode to free 'struct inode' memory, then it's
+       better to release memory in this method.
+
 ``dirty_inode``
        this method is called by the VFS when an inode is marked dirty.
        This is specifically for the inode itself being marked dirty,
@@ -296,8 +333,12 @@ or bottom half).
        practice of using "force_delete" in the put_inode() case, but
        does not have the races that the "force_delete()" approach had.
 
-``delete_inode``
-       called when the VFS wants to delete an inode
+``evict_inode``
+       called when the VFS wants to evict an inode. Caller does
+       *not* evict the pagecache or inode-associated metadata buffers;
+       the method has to use truncate_inode_pages_final() to get rid
+       of those. Caller makes sure async writeback cannot be running for
+       the inode while (or after) ->evict_inode() is called. Optional.
 
 ``put_super``
        called when the VFS wishes to free the superblock
@@ -308,14 +349,25 @@ or bottom half).
        superblock.  The second parameter indicates whether the method
        should wait until the write out has been completed.  Optional.
 
+``freeze_super``
+       Called instead of ->freeze_fs callback if provided.
+       Main difference is that ->freeze_super is called without taking
+       down_write(&sb->s_umount). If filesystem implements it and wants
+       ->freeze_fs to be called too, then it has to call ->freeze_fs
+       explicitly from this callback. Optional.
+
 ``freeze_fs``
        called when VFS is locking a filesystem and forcing it into a
        consistent state.  This method is currently used by the Logical
-       Volume Manager (LVM).
+       Volume Manager (LVM) and ioctl(FIFREEZE). Optional.
+
+``thaw_super``
+       called when VFS is unlocking a filesystem and making it writable
+       again after ->freeze_super. Optional.
 
 ``unfreeze_fs``
        called when VFS is unlocking a filesystem and making it writable
-       again.
+       again after ->freeze_fs. Optional.
 
 ``statfs``
        called when the VFS needs to get filesystem statistics.
@@ -324,22 +376,37 @@ or bottom half).
        called when the filesystem is remounted.  This is called with
        the kernel lock held
 
-``clear_inode``
-       called then the VFS clears the inode.  Optional
-
 ``umount_begin``
        called when the VFS is unmounting a filesystem.
 
 ``show_options``
-       called by the VFS to show mount options for /proc/<pid>/mounts.
+       called by the VFS to show mount options for /proc/<pid>/mounts
+       and /proc/<pid>/mountinfo.
        (see "Mount Options" section)
 
+``show_devname``
+       Optional. Called by the VFS to show device name for
+       /proc/<pid>/{mounts,mountinfo,mountstats}. If not provided then
+       '(struct mount).mnt_devname' will be used.
+
+``show_path``
+       Optional. Called by the VFS (for /proc/<pid>/mountinfo) to show
+       the mount root dentry path relative to the filesystem root.
+
+``show_stats``
+       Optional. Called by the VFS (for /proc/<pid>/mountstats) to show
+       filesystem-specific mount statistics.
+
 ``quota_read``
        called by the VFS to read from filesystem quota file.
 
 ``quota_write``
        called by the VFS to write to filesystem quota file.
 
+``get_dquots``
+       called by quota to get 'struct dquot' array for a particular inode.
+       Optional.
+
 ``nr_cached_objects``
        called by the sb cache shrinking function for the filesystem to
        return the number of freeable cached objects it contains.
@@ -1222,7 +1289,7 @@ defined:
        return
        -ECHILD and it will be called again in ref-walk mode.
 
-``_weak_revalidate``
+``d_weak_revalidate``
        called when the VFS needs to revalidate a "jumped" dentry.  This
        is called when a path-walk ends at dentry that was not acquired
        by doing a lookup in the parent directory.  This includes "/",
index b9dc0c603f3672789a462945fad841d95d5b8307..56d9913a3370c47b2c10ebe0f8df58c6c6b4c674 100644 (file)
@@ -19,7 +19,7 @@ possible we decided to do following:
     platform devices.
 
   - Devices behind real busses where there is a connector resource
-    are represented as struct spi_device or struct i2c_device. Note
+    are represented as struct spi_device or struct i2c_client. Note
     that standard UARTs are not busses so there is no struct uart_device,
     although some of them may be represented by struct serdev_device.
 
diff --git a/Documentation/ia64/aliasing.rst b/Documentation/ia64/aliasing.rst
deleted file mode 100644 (file)
index 36a1e1d..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-==================================
-Memory Attribute Aliasing on IA-64
-==================================
-
-Bjorn Helgaas <bjorn.helgaas@hp.com>
-
-May 4, 2006
-
-
-Memory Attributes
-=================
-
-    Itanium supports several attributes for virtual memory references.
-    The attribute is part of the virtual translation, i.e., it is
-    contained in the TLB entry.  The ones of most interest to the Linux
-    kernel are:
-
-       ==              ======================
-        WB             Write-back (cacheable)
-       UC              Uncacheable
-       WC              Write-coalescing
-       ==              ======================
-
-    System memory typically uses the WB attribute.  The UC attribute is
-    used for memory-mapped I/O devices.  The WC attribute is uncacheable
-    like UC is, but writes may be delayed and combined to increase
-    performance for things like frame buffers.
-
-    The Itanium architecture requires that we avoid accessing the same
-    page with both a cacheable mapping and an uncacheable mapping[1].
-
-    The design of the chipset determines which attributes are supported
-    on which regions of the address space.  For example, some chipsets
-    support either WB or UC access to main memory, while others support
-    only WB access.
-
-Memory Map
-==========
-
-    Platform firmware describes the physical memory map and the
-    supported attributes for each region.  At boot-time, the kernel uses
-    the EFI GetMemoryMap() interface.  ACPI can also describe memory
-    devices and the attributes they support, but Linux/ia64 currently
-    doesn't use this information.
-
-    The kernel uses the efi_memmap table returned from GetMemoryMap() to
-    learn the attributes supported by each region of physical address
-    space.  Unfortunately, this table does not completely describe the
-    address space because some machines omit some or all of the MMIO
-    regions from the map.
-
-    The kernel maintains another table, kern_memmap, which describes the
-    memory Linux is actually using and the attribute for each region.
-    This contains only system memory; it does not contain MMIO space.
-
-    The kern_memmap table typically contains only a subset of the system
-    memory described by the efi_memmap.  Linux/ia64 can't use all memory
-    in the system because of constraints imposed by the identity mapping
-    scheme.
-
-    The efi_memmap table is preserved unmodified because the original
-    boot-time information is required for kexec.
-
-Kernel Identity Mappings
-========================
-
-    Linux/ia64 identity mappings are done with large pages, currently
-    either 16MB or 64MB, referred to as "granules."  Cacheable mappings
-    are speculative[2], so the processor can read any location in the
-    page at any time, independent of the programmer's intentions.  This
-    means that to avoid attribute aliasing, Linux can create a cacheable
-    identity mapping only when the entire granule supports cacheable
-    access.
-
-    Therefore, kern_memmap contains only full granule-sized regions that
-    can referenced safely by an identity mapping.
-
-    Uncacheable mappings are not speculative, so the processor will
-    generate UC accesses only to locations explicitly referenced by
-    software.  This allows UC identity mappings to cover granules that
-    are only partially populated, or populated with a combination of UC
-    and WB regions.
-
-User Mappings
-=============
-
-    User mappings are typically done with 16K or 64K pages.  The smaller
-    page size allows more flexibility because only 16K or 64K has to be
-    homogeneous with respect to memory attributes.
-
-Potential Attribute Aliasing Cases
-==================================
-
-    There are several ways the kernel creates new mappings:
-
-mmap of /dev/mem
-----------------
-
-       This uses remap_pfn_range(), which creates user mappings.  These
-       mappings may be either WB or UC.  If the region being mapped
-       happens to be in kern_memmap, meaning that it may also be mapped
-       by a kernel identity mapping, the user mapping must use the same
-       attribute as the kernel mapping.
-
-       If the region is not in kern_memmap, the user mapping should use
-       an attribute reported as being supported in the EFI memory map.
-
-       Since the EFI memory map does not describe MMIO on some
-       machines, this should use an uncacheable mapping as a fallback.
-
-mmap of /sys/class/pci_bus/.../legacy_mem
------------------------------------------
-
-       This is very similar to mmap of /dev/mem, except that legacy_mem
-       only allows mmap of the one megabyte "legacy MMIO" area for a
-       specific PCI bus.  Typically this is the first megabyte of
-       physical address space, but it may be different on machines with
-       several VGA devices.
-
-       "X" uses this to access VGA frame buffers.  Using legacy_mem
-       rather than /dev/mem allows multiple instances of X to talk to
-       different VGA cards.
-
-       The /dev/mem mmap constraints apply.
-
-mmap of /proc/bus/pci/.../??.?
-------------------------------
-
-       This is an MMIO mmap of PCI functions, which additionally may or
-       may not be requested as using the WC attribute.
-
-       If WC is requested, and the region in kern_memmap is either WC
-       or UC, and the EFI memory map designates the region as WC, then
-       the WC mapping is allowed.
-
-       Otherwise, the user mapping must use the same attribute as the
-       kernel mapping.
-
-read/write of /dev/mem
-----------------------
-
-       This uses copy_from_user(), which implicitly uses a kernel
-       identity mapping.  This is obviously safe for things in
-       kern_memmap.
-
-       There may be corner cases of things that are not in kern_memmap,
-       but could be accessed this way.  For example, registers in MMIO
-       space are not in kern_memmap, but could be accessed with a UC
-       mapping.  This would not cause attribute aliasing.  But
-       registers typically can be accessed only with four-byte or
-       eight-byte accesses, and the copy_from_user() path doesn't allow
-       any control over the access size, so this would be dangerous.
-
-ioremap()
----------
-
-       This returns a mapping for use inside the kernel.
-
-       If the region is in kern_memmap, we should use the attribute
-       specified there.
-
-       If the EFI memory map reports that the entire granule supports
-       WB, we should use that (granules that are partially reserved
-       or occupied by firmware do not appear in kern_memmap).
-
-       If the granule contains non-WB memory, but we can cover the
-       region safely with kernel page table mappings, we can use
-       ioremap_page_range() as most other architectures do.
-
-       Failing all of the above, we have to fall back to a UC mapping.
-
-Past Problem Cases
-==================
-
-mmap of various MMIO regions from /dev/mem by "X" on Intel platforms
---------------------------------------------------------------------
-
-      The EFI memory map may not report these MMIO regions.
-
-      These must be allowed so that X will work.  This means that
-      when the EFI memory map is incomplete, every /dev/mem mmap must
-      succeed.  It may create either WB or UC user mappings, depending
-      on whether the region is in kern_memmap or the EFI memory map.
-
-mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
-----------------------------------------------------------------------
-
-      The EFI memory map reports the following attributes:
-
-        =============== ======= ==================
-        0x00000-0x9FFFF WB only
-        0xA0000-0xBFFFF UC only (VGA frame buffer)
-        0xC0000-0xFFFFF WB only
-        =============== ======= ==================
-
-      This mmap is done with user pages, not kernel identity mappings,
-      so it is safe to use WB mappings.
-
-      The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
-      which uses a granule-sized UC mapping.  This granule will cover some
-      WB-only memory, but since UC is non-speculative, the processor will
-      never generate an uncacheable reference to the WB-only areas unless
-      the driver explicitly touches them.
-
-mmap of 0x0-0xFFFFF legacy_mem by "X"
--------------------------------------
-
-      If the EFI memory map reports that the entire range supports the
-      same attributes, we can allow the mmap (and we will prefer WB if
-      supported, as is the case with HP sx[12]000 machines with VGA
-      disabled).
-
-      If EFI reports the range as partly WB and partly UC (as on sx[12]000
-      machines with VGA enabled), we must fail the mmap because there's no
-      safe attribute to use.
-
-      If EFI reports some of the range but not all (as on Intel firmware
-      that doesn't report the VGA frame buffer at all), we should fail the
-      mmap and force the user to map just the specific region of interest.
-
-mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
-------------------------------------------------------------------------
-
-      The EFI memory map reports the following attributes::
-
-        0x00000-0xFFFFF WB only (no VGA MMIO hole)
-
-      This is a special case of the previous case, and the mmap should
-      fail for the same reason as above.
-
-read of /sys/devices/.../rom
-----------------------------
-
-      For VGA devices, this may cause an ioremap() of 0xC0000.  This
-      used to be done with a UC mapping, because the VGA frame buffer
-      at 0xA0000 prevents use of a WB granule.  The UC mapping causes
-      an MCA on HP sx[12]000 chipsets.
-
-      We should use WB page table mappings to avoid covering the VGA
-      frame buffer.
-
-Notes
-=====
-
-    [1] SDM rev 2.2, vol 2, sec 4.4.1.
-    [2] SDM rev 2.2, vol 2, sec 4.4.6.
diff --git a/Documentation/ia64/efirtc.rst b/Documentation/ia64/efirtc.rst
deleted file mode 100644 (file)
index fd83284..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-==========================
-EFI Real Time Clock driver
-==========================
-
-S. Eranian <eranian@hpl.hp.com>
-
-March 2000
-
-1. Introduction
-===============
-
-This document describes the efirtc.c driver has provided for
-the IA-64 platform.
-
-The purpose of this driver is to supply an API for kernel and user applications
-to get access to the Time Service offered by EFI version 0.92.
-
-EFI provides 4 calls one can make once the OS is booted: GetTime(),
-SetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this
-driver. We describe those calls as well the design of the driver in the
-following sections.
-
-2. Design Decisions
-===================
-
-The original ideas was to provide a very simple driver to get access to,
-at first, the time of day service. This is required in order to access, in a
-portable way, the CMOS clock. A program like /sbin/hwclock uses such a clock
-to initialize the system view of the time during boot.
-
-Because we wanted to minimize the impact on existing user-level apps using
-the CMOS clock, we decided to expose an API that was very similar to the one
-used today with the legacy RTC driver (driver/char/rtc.c). However, because
-EFI provides a simpler services, not all ioctl() are available. Also
-new ioctl()s have been introduced for things that EFI provides but not the
-legacy.
-
-EFI uses a slightly different way of representing the time, noticeably
-the reference date is different. Year is the using the full 4-digit format.
-The Epoch is January 1st 1998. For backward compatibility reasons we don't
-expose this new way of representing time. Instead we use something very
-similar to the struct tm, i.e. struct rtc_time, as used by hwclock.
-One of the reasons for doing it this way is to allow for EFI to still evolve
-without necessarily impacting any of the user applications. The decoupling
-enables flexibility and permits writing wrapper code is ncase things change.
-
-The driver exposes two interfaces, one via the device file and a set of
-ioctl()s. The other is read-only via the /proc filesystem.
-
-As of today we don't offer a /proc/sys interface.
-
-To allow for a uniform interface between the legacy RTC and EFI time service,
-we have created the include/linux/rtc.h header file to contain only the
-"public" API of the two drivers.  The specifics of the legacy RTC are still
-in include/linux/mc146818rtc.h.
-
-
-3. Time of day service
-======================
-
-The part of the driver gives access to the time of day service of EFI.
-Two ioctl()s, compatible with the legacy RTC calls:
-
-       Read the CMOS clock::
-
-               ioctl(d, RTC_RD_TIME, &rtc);
-
-       Write the CMOS clock::
-
-               ioctl(d, RTC_SET_TIME, &rtc);
-
-The rtc is a pointer to a data structure defined in rtc.h which is close
-to a struct tm::
-
-  struct rtc_time {
-          int tm_sec;
-          int tm_min;
-          int tm_hour;
-          int tm_mday;
-          int tm_mon;
-          int tm_year;
-          int tm_wday;
-          int tm_yday;
-          int tm_isdst;
-  };
-
-The driver takes care of converting back an forth between the EFI time and
-this format.
-
-Those two ioctl()s can be exercised with the hwclock command:
-
-For reading::
-
-       # /sbin/hwclock --show
-       Mon Mar  6 15:32:32 2000  -0.910248 seconds
-
-For setting::
-
-       # /sbin/hwclock --systohc
-
-Root privileges are required to be able to set the time of day.
-
-4. Wakeup Alarm service
-=======================
-
-EFI provides an API by which one can program when a machine should wakeup,
-i.e. reboot. This is very different from the alarm provided by the legacy
-RTC which is some kind of interval timer alarm. For this reason we don't use
-the same ioctl()s to get access to the service. Instead we have
-introduced 2 news ioctl()s to the interface of an RTC.
-
-We have added 2 new ioctl()s that are specific to the EFI driver:
-
-       Read the current state of the alarm::
-
-               ioctl(d, RTC_WKALM_RD, &wkt)
-
-       Set the alarm or change its status::
-
-               ioctl(d, RTC_WKALM_SET, &wkt)
-
-The wkt structure encapsulates a struct rtc_time + 2 extra fields to get
-status information::
-
-  struct rtc_wkalrm {
-
-          unsigned char enabled; /* =1 if alarm is enabled */
-          unsigned char pending; /* =1 if alarm is pending  */
-
-          struct rtc_time time;
-  }
-
-As of today, none of the existing user-level apps supports this feature.
-However writing such a program should be hard by simply using those two
-ioctl().
-
-Root privileges are required to be able to set the alarm.
-
-5. References
-=============
-
-Checkout the following Web site for more information on EFI:
-
-http://developer.intel.com/technology/efi/
diff --git a/Documentation/ia64/err_inject.rst b/Documentation/ia64/err_inject.rst
deleted file mode 100644 (file)
index 900f71e..0000000
+++ /dev/null
@@ -1,1067 +0,0 @@
-========================================
-IPF Machine Check (MC) error inject tool
-========================================
-
-IPF Machine Check (MC) error inject tool is used to inject MC
-errors from Linux. The tool is a test bed for IPF MC work flow including
-hardware correctable error handling, OS recoverable error handling, MC
-event logging, etc.
-
-The tool includes two parts: a kernel driver and a user application
-sample. The driver provides interface to PAL to inject error
-and query error injection capabilities. The driver code is in
-arch/ia64/kernel/err_inject.c. The application sample (shown below)
-provides a combination of various errors and calls the driver's interface
-(sysfs interface) to inject errors or query error injection capabilities.
-
-The tool can be used to test Intel IPF machine MC handling capabilities.
-It's especially useful for people who can not access hardware MC injection
-tool to inject error. It's also very useful to integrate with other
-software test suits to do stressful testing on IPF.
-
-Below is a sample application as part of the whole tool. The sample
-can be used as a working test tool. Or it can be expanded to include
-more features. It also can be a integrated into a library or other user
-application to have more thorough test.
-
-The sample application takes err.conf as error configuration input. GCC
-compiles the code. After you install err_inject driver, you can run
-this sample application to inject errors.
-
-Errata: Itanium 2 Processors Specification Update lists some errata against
-the pal_mc_error_inject PAL procedure. The following err.conf has been tested
-on latest Montecito PAL.
-
-err.conf::
-
-  #This is configuration file for err_inject_tool.
-  #The format of the each line is:
-  #cpu, loop, interval, err_type_info, err_struct_info, err_data_buffer
-  #where
-  #    cpu: logical cpu number the error will be inject in.
-  #    loop: times the error will be injected.
-  #    interval: In second. every so often one error is injected.
-  #    err_type_info, err_struct_info: PAL parameters.
-  #
-  #Note: All values are hex w/o or w/ 0x prefix.
-
-
-  #On cpu2, inject only total 0x10 errors, interval 5 seconds
-  #corrected, data cache, hier-2, physical addr(assigned by tool code).
-  #working on Montecito latest PAL.
-  2, 10, 5, 4101, 95
-
-  #On cpu4, inject and consume total 0x10 errors, interval 5 seconds
-  #corrected, data cache, hier-2, physical addr(assigned by tool code).
-  #working on Montecito latest PAL.
-  4, 10, 5, 4109, 95
-
-  #On cpu15, inject and consume total 0x10 errors, interval 5 seconds
-  #recoverable, DTR0, hier-2.
-  #working on Montecito latest PAL.
-  0xf, 0x10, 5, 4249, 15
-
-The sample application source code:
-
-err_injection_tool.c::
-
-  /*
-   * This program is free software; you can redistribute it and/or modify
-   * it under the terms of the GNU General Public License as published by
-   * the Free Software Foundation; either version 2 of the License, or
-   * (at your option) any later version.
-   *
-   * This program is distributed in the hope that it will be useful, but
-   * WITHOUT ANY WARRANTY; without even the implied warranty of
-   * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
-   * NON INFRINGEMENT.  See the GNU General Public License for more
-   * details.
-   *
-   * You should have received a copy of the GNU General Public License
-   * along with this program; if not, write to the Free Software
-   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-   *
-   * Copyright (C) 2006 Intel Co
-   *   Fenghua Yu <fenghua.yu@intel.com>
-   *
-   */
-  #include <sys/types.h>
-  #include <sys/stat.h>
-  #include <fcntl.h>
-  #include <stdio.h>
-  #include <sched.h>
-  #include <unistd.h>
-  #include <stdlib.h>
-  #include <stdarg.h>
-  #include <string.h>
-  #include <errno.h>
-  #include <time.h>
-  #include <sys/ipc.h>
-  #include <sys/sem.h>
-  #include <sys/wait.h>
-  #include <sys/mman.h>
-  #include <sys/shm.h>
-
-  #define MAX_FN_SIZE          256
-  #define MAX_BUF_SIZE                 256
-  #define DATA_BUF_SIZE                256
-  #define NR_CPUS              512
-  #define MAX_TASK_NUM         2048
-  #define MIN_INTERVAL         5       // seconds
-  #define      ERR_DATA_BUFFER_SIZE    3       // Three 8-byte.
-  #define PARA_FIELD_NUM               5
-  #define MASK_SIZE            (NR_CPUS/64)
-  #define PATH_FORMAT "/sys/devices/system/cpu/cpu%d/err_inject/"
-
-  int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);
-
-  int verbose;
-  #define vbprintf if (verbose) printf
-
-  int log_info(int cpu, const char *fmt, ...)
-  {
-       FILE *log;
-       char fn[MAX_FN_SIZE];
-       char buf[MAX_BUF_SIZE];
-       va_list args;
-
-       sprintf(fn, "%d.log", cpu);
-       log=fopen(fn, "a+");
-       if (log==NULL) {
-               perror("Error open:");
-               return -1;
-       }
-
-       va_start(args, fmt);
-       vprintf(fmt, args);
-       memset(buf, 0, MAX_BUF_SIZE);
-       vsprintf(buf, fmt, args);
-       va_end(args);
-
-       fwrite(buf, sizeof(buf), 1, log);
-       fclose(log);
-
-       return 0;
-  }
-
-  typedef unsigned long u64;
-  typedef unsigned int  u32;
-
-  typedef union err_type_info_u {
-       struct {
-               u64     mode            : 3,    /* 0-2 */
-                       err_inj         : 3,    /* 3-5 */
-                       err_sev         : 2,    /* 6-7 */
-                       err_struct      : 5,    /* 8-12 */
-                       struct_hier     : 3,    /* 13-15 */
-                       reserved        : 48;   /* 16-63 */
-       } err_type_info_u;
-       u64     err_type_info;
-  } err_type_info_t;
-
-  typedef union err_struct_info_u {
-       struct {
-               u64     siv             : 1,    /* 0     */
-                       c_t             : 2,    /* 1-2   */
-                       cl_p            : 3,    /* 3-5   */
-                       cl_id           : 3,    /* 6-8   */
-                       cl_dp           : 1,    /* 9     */
-                       reserved1       : 22,   /* 10-31 */
-                       tiv             : 1,    /* 32    */
-                       trigger         : 4,    /* 33-36 */
-                       trigger_pl      : 3,    /* 37-39 */
-                       reserved2       : 24;   /* 40-63 */
-       } err_struct_info_cache;
-       struct {
-               u64     siv             : 1,    /* 0     */
-                       tt              : 2,    /* 1-2   */
-                       tc_tr           : 2,    /* 3-4   */
-                       tr_slot         : 8,    /* 5-12  */
-                       reserved1       : 19,   /* 13-31 */
-                       tiv             : 1,    /* 32    */
-                       trigger         : 4,    /* 33-36 */
-                       trigger_pl      : 3,    /* 37-39 */
-                       reserved2       : 24;   /* 40-63 */
-       } err_struct_info_tlb;
-       struct {
-               u64     siv             : 1,    /* 0     */
-                       regfile_id      : 4,    /* 1-4   */
-                       reg_num         : 7,    /* 5-11  */
-                       reserved1       : 20,   /* 12-31 */
-                       tiv             : 1,    /* 32    */
-                       trigger         : 4,    /* 33-36 */
-                       trigger_pl      : 3,    /* 37-39 */
-                       reserved2       : 24;   /* 40-63 */
-       } err_struct_info_register;
-       struct {
-               u64     reserved;
-       } err_struct_info_bus_processor_interconnect;
-       u64     err_struct_info;
-  } err_struct_info_t;
-
-  typedef union err_data_buffer_u {
-       struct {
-               u64     trigger_addr;           /* 0-63         */
-               u64     inj_addr;               /* 64-127       */
-               u64     way             : 5,    /* 128-132      */
-                       index           : 20,   /* 133-152      */
-                                       : 39;   /* 153-191      */
-       } err_data_buffer_cache;
-       struct {
-               u64     trigger_addr;           /* 0-63         */
-               u64     inj_addr;               /* 64-127       */
-               u64     way             : 5,    /* 128-132      */
-                       index           : 20,   /* 133-152      */
-                       reserved        : 39;   /* 153-191      */
-       } err_data_buffer_tlb;
-       struct {
-               u64     trigger_addr;           /* 0-63         */
-       } err_data_buffer_register;
-       struct {
-               u64     reserved;               /* 0-63         */
-       } err_data_buffer_bus_processor_interconnect;
-       u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
-  } err_data_buffer_t;
-
-  typedef union capabilities_u {
-       struct {
-               u64     i               : 1,
-                       d               : 1,
-                       rv              : 1,
-                       tag             : 1,
-                       data            : 1,
-                       mesi            : 1,
-                       dp              : 1,
-                       reserved1       : 3,
-                       pa              : 1,
-                       va              : 1,
-                       wi              : 1,
-                       reserved2       : 20,
-                       trigger         : 1,
-                       trigger_pl      : 1,
-                       reserved3       : 30;
-       } capabilities_cache;
-       struct {
-               u64     d               : 1,
-                       i               : 1,
-                       rv              : 1,
-                       tc              : 1,
-                       tr              : 1,
-                       reserved1       : 27,
-                       trigger         : 1,
-                       trigger_pl      : 1,
-                       reserved2       : 30;
-       } capabilities_tlb;
-       struct {
-               u64     gr_b0           : 1,
-                       gr_b1           : 1,
-                       fr              : 1,
-                       br              : 1,
-                       pr              : 1,
-                       ar              : 1,
-                       cr              : 1,
-                       rr              : 1,
-                       pkr             : 1,
-                       dbr             : 1,
-                       ibr             : 1,
-                       pmc             : 1,
-                       pmd             : 1,
-                       reserved1       : 3,
-                       regnum          : 1,
-                       reserved2       : 15,
-                       trigger         : 1,
-                       trigger_pl      : 1,
-                       reserved3       : 30;
-       } capabilities_register;
-       struct {
-               u64     reserved;
-       } capabilities_bus_processor_interconnect;
-  } capabilities_t;
-
-  typedef struct resources_s {
-       u64     ibr0            : 1,
-               ibr2            : 1,
-               ibr4            : 1,
-               ibr6            : 1,
-               dbr0            : 1,
-               dbr2            : 1,
-               dbr4            : 1,
-               dbr6            : 1,
-               reserved        : 48;
-  } resources_t;
-
-
-  long get_page_size(void)
-  {
-       long page_size=sysconf(_SC_PAGESIZE);
-       return page_size;
-  }
-
-  #define PAGE_SIZE (get_page_size()==-1?0x4000:get_page_size())
-  #define SHM_SIZE (2*PAGE_SIZE*NR_CPUS)
-  #define SHM_VA 0x2000000100000000
-
-  int shmid;
-  void *shmaddr;
-
-  int create_shm(void)
-  {
-       key_t key;
-       char fn[MAX_FN_SIZE];
-
-       /* cpu0 is always existing */
-       sprintf(fn, PATH_FORMAT, 0);
-       if ((key = ftok(fn, 's')) == -1) {
-               perror("ftok");
-               return -1;
-       }
-
-       shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
-       if (shmid == -1) {
-               if (errno==EEXIST) {
-                       shmid = shmget(key, SHM_SIZE, 0);
-                       if (shmid == -1) {
-                               perror("shmget");
-                               return -1;
-                       }
-               }
-               else {
-                       perror("shmget");
-                       return -1;
-               }
-       }
-       vbprintf("shmid=%d", shmid);
-
-       /* connect to the segment: */
-       shmaddr = shmat(shmid, (void *)SHM_VA, 0);
-       if (shmaddr == (void*)-1) {
-               perror("shmat");
-               return -1;
-       }
-
-       memset(shmaddr, 0, SHM_SIZE);
-       mlock(shmaddr, SHM_SIZE);
-
-       return 0;
-  }
-
-  int free_shm()
-  {
-       munlock(shmaddr, SHM_SIZE);
-          shmdt(shmaddr);
-       semctl(shmid, 0, IPC_RMID);
-
-       return 0;
-  }
-
-  #ifdef _SEM_SEMUN_UNDEFINED
-  union semun
-  {
-       int val;
-       struct semid_ds *buf;
-       unsigned short int *array;
-       struct seminfo *__buf;
-  };
-  #endif
-
-  u32 mode=1; /* 1: physical mode; 2: virtual mode. */
-  int one_lock=1;
-  key_t key[NR_CPUS];
-  int semid[NR_CPUS];
-
-  int create_sem(int cpu)
-  {
-       union semun arg;
-       char fn[MAX_FN_SIZE];
-       int sid;
-
-       sprintf(fn, PATH_FORMAT, cpu);
-       sprintf(fn, "%s/%s", fn, "err_type_info");
-       if ((key[cpu] = ftok(fn, 'e')) == -1) {
-               perror("ftok");
-               return -1;
-       }
-
-       if (semid[cpu]!=0)
-               return 0;
-
-       /* clear old semaphore */
-       if ((sid = semget(key[cpu], 1, 0)) != -1)
-               semctl(sid, 0, IPC_RMID);
-
-       /* get one semaphore */
-       if ((semid[cpu] = semget(key[cpu], 1, IPC_CREAT | IPC_EXCL)) == -1) {
-               perror("semget");
-               printf("Please remove semaphore with key=0x%lx, then run the tool.\n",
-                       (u64)key[cpu]);
-               return -1;
-       }
-
-       vbprintf("semid[%d]=0x%lx, key[%d]=%lx\n",cpu,(u64)semid[cpu],cpu,
-               (u64)key[cpu]);
-       /* initialize the semaphore to 1: */
-       arg.val = 1;
-       if (semctl(semid[cpu], 0, SETVAL, arg) == -1) {
-               perror("semctl");
-               return -1;
-       }
-
-       return 0;
-  }
-
-  static int lock(int cpu)
-  {
-       struct sembuf lock;
-
-       lock.sem_num = cpu;
-       lock.sem_op = 1;
-       semop(semid[cpu], &lock, 1);
-
-          return 0;
-  }
-
-  static int unlock(int cpu)
-  {
-       struct sembuf unlock;
-
-       unlock.sem_num = cpu;
-       unlock.sem_op = -1;
-       semop(semid[cpu], &unlock, 1);
-
-          return 0;
-  }
-
-  void free_sem(int cpu)
-  {
-       semctl(semid[cpu], 0, IPC_RMID);
-  }
-
-  int wr_multi(char *fn, unsigned long *data, int size)
-  {
-       int fd;
-       char buf[MAX_BUF_SIZE];
-       int ret;
-
-       if (size==1)
-               sprintf(buf, "%lx", *data);
-       else if (size==3)
-               sprintf(buf, "%lx,%lx,%lx", data[0], data[1], data[2]);
-       else {
-               fprintf(stderr,"write to file with wrong size!\n");
-               return -1;
-       }
-
-       fd=open(fn, O_RDWR);
-       if (!fd) {
-               perror("Error:");
-               return -1;
-       }
-       ret=write(fd, buf, sizeof(buf));
-       close(fd);
-       return ret;
-  }
-
-  int wr(char *fn, unsigned long data)
-  {
-       return wr_multi(fn, &data, 1);
-  }
-
-  int rd(char *fn, unsigned long *data)
-  {
-       int fd;
-       char buf[MAX_BUF_SIZE];
-
-       fd=open(fn, O_RDONLY);
-       if (fd<0) {
-               perror("Error:");
-               return -1;
-       }
-       read(fd, buf, MAX_BUF_SIZE);
-       *data=strtoul(buf, NULL, 16);
-       close(fd);
-       return 0;
-  }
-
-  int rd_status(char *path, int *status)
-  {
-       char fn[MAX_FN_SIZE];
-       sprintf(fn, "%s/status", path);
-       if (rd(fn, (u64*)status)<0) {
-               perror("status reading error.\n");
-               return -1;
-       }
-
-       return 0;
-  }
-
-  int rd_capabilities(char *path, u64 *capabilities)
-  {
-       char fn[MAX_FN_SIZE];
-       sprintf(fn, "%s/capabilities", path);
-       if (rd(fn, capabilities)<0) {
-               perror("capabilities reading error.\n");
-               return -1;
-       }
-
-       return 0;
-  }
-
-  int rd_all(char *path)
-  {
-       unsigned long err_type_info, err_struct_info, err_data_buffer;
-       int status;
-       unsigned long capabilities, resources;
-       char fn[MAX_FN_SIZE];
-
-       sprintf(fn, "%s/err_type_info", path);
-       if (rd(fn, &err_type_info)<0) {
-               perror("err_type_info reading error.\n");
-               return -1;
-       }
-       printf("err_type_info=%lx\n", err_type_info);
-
-       sprintf(fn, "%s/err_struct_info", path);
-       if (rd(fn, &err_struct_info)<0) {
-               perror("err_struct_info reading error.\n");
-               return -1;
-       }
-       printf("err_struct_info=%lx\n", err_struct_info);
-
-       sprintf(fn, "%s/err_data_buffer", path);
-       if (rd(fn, &err_data_buffer)<0) {
-               perror("err_data_buffer reading error.\n");
-               return -1;
-       }
-       printf("err_data_buffer=%lx\n", err_data_buffer);
-
-       sprintf(fn, "%s/status", path);
-       if (rd("status", (u64*)&status)<0) {
-               perror("status reading error.\n");
-               return -1;
-       }
-       printf("status=%d\n", status);
-
-       sprintf(fn, "%s/capabilities", path);
-       if (rd(fn,&capabilities)<0) {
-               perror("capabilities reading error.\n");
-               return -1;
-       }
-       printf("capabilities=%lx\n", capabilities);
-
-       sprintf(fn, "%s/resources", path);
-       if (rd(fn, &resources)<0) {
-               perror("resources reading error.\n");
-               return -1;
-       }
-       printf("resources=%lx\n", resources);
-
-       return 0;
-  }
-
-  int query_capabilities(char *path, err_type_info_t err_type_info,
-                       u64 *capabilities)
-  {
-       char fn[MAX_FN_SIZE];
-       err_struct_info_t err_struct_info;
-       err_data_buffer_t err_data_buffer;
-
-       err_struct_info.err_struct_info=0;
-       memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8);
-
-       sprintf(fn, "%s/err_type_info", path);
-       wr(fn, err_type_info.err_type_info);
-       sprintf(fn, "%s/err_struct_info", path);
-       wr(fn, 0x0);
-       sprintf(fn, "%s/err_data_buffer", path);
-       wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
-
-       // Fire pal_mc_error_inject procedure.
-       sprintf(fn, "%s/call_start", path);
-       wr(fn, mode);
-
-       if (rd_capabilities(path, capabilities)<0)
-               return -1;
-
-       return 0;
-  }
-
-  int query_all_capabilities()
-  {
-       int status;
-       err_type_info_t err_type_info;
-       int err_sev, err_struct, struct_hier;
-       int cap=0;
-       u64 capabilities;
-       char path[MAX_FN_SIZE];
-
-       err_type_info.err_type_info=0;                  // Initial
-       err_type_info.err_type_info_u.mode=0;           // Query mode;
-       err_type_info.err_type_info_u.err_inj=0;
-
-       printf("All capabilities implemented in pal_mc_error_inject:\n");
-       sprintf(path, PATH_FORMAT ,0);
-       for (err_sev=0;err_sev<3;err_sev++)
-               for (err_struct=0;err_struct<5;err_struct++)
-                       for (struct_hier=0;struct_hier<5;struct_hier++)
-       {
-               status=-1;
-               capabilities=0;
-               err_type_info.err_type_info_u.err_sev=err_sev;
-               err_type_info.err_type_info_u.err_struct=err_struct;
-               err_type_info.err_type_info_u.struct_hier=struct_hier;
-
-               if (query_capabilities(path, err_type_info, &capabilities)<0)
-                       continue;
-
-               if (rd_status(path, &status)<0)
-                       continue;
-
-               if (status==0) {
-                       cap=1;
-                       printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ",
-                               err_sev, err_struct, struct_hier);
-                       printf("capabilities 0x%lx\n", capabilities);
-               }
-       }
-       if (!cap) {
-               printf("No capabilities supported.\n");
-               return 0;
-       }
-
-       return 0;
-  }
-
-  int err_inject(int cpu, char *path, err_type_info_t err_type_info,
-               err_struct_info_t err_struct_info,
-               err_data_buffer_t err_data_buffer)
-  {
-       int status;
-       char fn[MAX_FN_SIZE];
-
-       log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ",
-               err_type_info.err_type_info,
-               err_struct_info.err_struct_info);
-       log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n",
-               err_data_buffer.err_data_buffer[0],
-               err_data_buffer.err_data_buffer[1],
-               err_data_buffer.err_data_buffer[2]);
-       sprintf(fn, "%s/err_type_info", path);
-       wr(fn, err_type_info.err_type_info);
-       sprintf(fn, "%s/err_struct_info", path);
-       wr(fn, err_struct_info.err_struct_info);
-       sprintf(fn, "%s/err_data_buffer", path);
-       wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);
-
-       // Fire pal_mc_error_inject procedure.
-       sprintf(fn, "%s/call_start", path);
-       wr(fn,mode);
-
-       if (rd_status(path, &status)<0) {
-               vbprintf("fail: read status\n");
-               return -100;
-       }
-
-       if (status!=0) {
-               log_info(cpu, "fail: status=%d\n", status);
-               return status;
-       }
-
-       return status;
-  }
-
-  static int construct_data_buf(char *path, err_type_info_t err_type_info,
-               err_struct_info_t err_struct_info,
-               err_data_buffer_t *err_data_buffer,
-               void *va1)
-  {
-       char fn[MAX_FN_SIZE];
-       u64 virt_addr=0, phys_addr=0;
-
-       vbprintf("va1=%lx\n", (u64)va1);
-       memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8);
-
-       switch (err_type_info.err_type_info_u.err_struct) {
-               case 1: // Cache
-                       switch (err_struct_info.err_struct_info_cache.cl_id) {
-                               case 1: //Virtual addr
-                                       err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1;
-                                       break;
-                               case 2: //Phys addr
-                                       sprintf(fn, "%s/virtual_to_phys", path);
-                                       virt_addr=(u64)va1;
-                                       if (wr(fn,virt_addr)<0)
-                                               return -1;
-                                       rd(fn, &phys_addr);
-                                       err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr;
-                                       break;
-                               default:
-                                       printf("Not supported cl_id\n");
-                                       break;
-                       }
-                       break;
-               case 2: //  TLB
-                       break;
-               case 3: //  Register file
-                       break;
-               case 4: //  Bus/system interconnect
-               default:
-                       printf("Not supported err_struct\n");
-                       break;
-       }
-
-       return 0;
-  }
-
-  typedef struct {
-       u64 cpu;
-       u64 loop;
-       u64 interval;
-       u64 err_type_info;
-       u64 err_struct_info;
-       u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
-  } parameters_t;
-
-  parameters_t line_para;
-  int para;
-
-  static int empty_data_buffer(u64 *err_data_buffer)
-  {
-       int empty=1;
-       int i;
-
-       for (i=0;i<ERR_DATA_BUFFER_SIZE; i++)
-          if (err_data_buffer[i]!=-1)
-               empty=0;
-
-       return empty;
-  }
-
-  int err_inj()
-  {
-       err_type_info_t err_type_info;
-       err_struct_info_t err_struct_info;
-       err_data_buffer_t err_data_buffer;
-       int count;
-       FILE *fp;
-       unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf;
-       u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE];
-       int num;
-       int i;
-       char path[MAX_FN_SIZE];
-       parameters_t parameters[MAX_TASK_NUM]={};
-       pid_t child_pid[MAX_TASK_NUM];
-       time_t current_time;
-       int status;
-
-       if (!para) {
-           fp=fopen("err.conf", "r");
-           if (fp==NULL) {
-               perror("Error open err.conf");
-               return -1;
-           }
-
-           num=0;
-           while (!feof(fp)) {
-               char buf[256];
-               memset(buf,0,256);
-               fgets(buf, 256, fp);
-               count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
-                               &cpu, &loop, &interval,&err_type_info_conf,
-                               &err_struct_info_conf,
-                               &err_data_buffer_conf[0],
-                               &err_data_buffer_conf[1],
-                               &err_data_buffer_conf[2]);
-               if (count!=PARA_FIELD_NUM+3) {
-                       err_data_buffer_conf[0]=-1;
-                       err_data_buffer_conf[1]=-1;
-                       err_data_buffer_conf[2]=-1;
-                       count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n",
-                               &cpu, &loop, &interval,&err_type_info_conf,
-                               &err_struct_info_conf);
-                       if (count!=PARA_FIELD_NUM)
-                               continue;
-               }
-
-               parameters[num].cpu=cpu;
-               parameters[num].loop=loop;
-               parameters[num].interval= interval>MIN_INTERVAL
-                                         ?interval:MIN_INTERVAL;
-               parameters[num].err_type_info=err_type_info_conf;
-               parameters[num].err_struct_info=err_struct_info_conf;
-               memcpy(parameters[num++].err_data_buffer,
-                       err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ;
-
-               if (num>=MAX_TASK_NUM)
-                       break;
-           }
-       }
-       else {
-               parameters[0].cpu=line_para.cpu;
-               parameters[0].loop=line_para.loop;
-               parameters[0].interval= line_para.interval>MIN_INTERVAL
-                                         ?line_para.interval:MIN_INTERVAL;
-               parameters[0].err_type_info=line_para.err_type_info;
-               parameters[0].err_struct_info=line_para.err_struct_info;
-               memcpy(parameters[0].err_data_buffer,
-                       line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ;
-
-               num=1;
-       }
-
-       /* Create semaphore: If one_lock, one semaphore for all processors.
-          Otherwise, one semaphore for each processor. */
-       if (one_lock) {
-               if (create_sem(0)) {
-                       printf("Can not create semaphore...exit\n");
-                       free_sem(0);
-                       return -1;
-               }
-       }
-       else {
-               for (i=0;i<num;i++) {
-                  if (create_sem(parameters[i].cpu)) {
-                       printf("Can not create semaphore for cpu%d...exit\n",i);
-                       free_sem(parameters[num].cpu);
-                       return -1;
-                  }
-               }
-       }
-
-       /* Create a shm segment which will be used to inject/consume errors on.*/
-       if (create_shm()==-1) {
-               printf("Error to create shm...exit\n");
-               return -1;
-       }
-
-       for (i=0;i<num;i++) {
-               pid_t pid;
-
-               current_time=time(NULL);
-               log_info(parameters[i].cpu, "\nBegine at %s", ctime(&current_time));
-               log_info(parameters[i].cpu, "Configurations:\n");
-               log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)",
-                       parameters[i].cpu,
-                       parameters[i].loop,
-                       parameters[i].interval);
-               log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n",
-                       parameters[i].err_type_info,
-                       parameters[i].err_struct_info);
-
-               sprintf(path, PATH_FORMAT, (int)parameters[i].cpu);
-               err_type_info.err_type_info=parameters[i].err_type_info;
-               err_struct_info.err_struct_info=parameters[i].err_struct_info;
-               memcpy(err_data_buffer.err_data_buffer,
-                       parameters[i].err_data_buffer,
-                       ERR_DATA_BUFFER_SIZE*8);
-
-               pid=fork();
-               if (pid==0) {
-                       unsigned long mask[MASK_SIZE];
-                       int j, k;
-
-                       void *va1, *va2;
-
-                       /* Allocate two memory areas va1 and va2 in shm */
-                       va1=shmaddr+parameters[i].cpu*PAGE_SIZE;
-                       va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE;
-
-                       vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2);
-                       memset(va1, 0x1, PAGE_SIZE);
-                       memset(va2, 0x2, PAGE_SIZE);
-
-                       if (empty_data_buffer(err_data_buffer.err_data_buffer))
-                               /* If not specified yet, construct data buffer
-                                * with va1
-                                */
-                               construct_data_buf(path, err_type_info,
-                                       err_struct_info, &err_data_buffer,va1);
-
-                       for (j=0;j<MASK_SIZE;j++)
-                               mask[j]=0;
-
-                       cpu=parameters[i].cpu;
-                       k = cpu%64;
-                       j = cpu/64;
-                       mask[j] = 1UL << k;
-
-                       if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
-                               perror("Error sched_setaffinity:");
-                               return -1;
-                       }
-
-                       for (j=0; j<parameters[i].loop; j++) {
-                               log_info(parameters[i].cpu,"Injection ");
-                               log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ",
-
-                                       parameters[i].cpu,j+1, parameters[i].loop);
-
-                               /* Hold the lock */
-                               if (one_lock)
-                                       lock(0);
-                               else
-                               /* Hold lock on this cpu */
-                                       lock(parameters[i].cpu);
-
-                               if ((status=err_inject(parameters[i].cpu,
-                                          path, err_type_info,
-                                          err_struct_info, err_data_buffer))
-                                          ==0) {
-                                       /* consume the error for "inject only"*/
-                                       memcpy(va2, va1, PAGE_SIZE);
-                                       memcpy(va1, va2, PAGE_SIZE);
-                                       log_info(parameters[i].cpu,
-                                               "successful\n");
-                               }
-                               else {
-                                       log_info(parameters[i].cpu,"fail:");
-                                       log_info(parameters[i].cpu,
-                                               "status=%d\n", status);
-                                       unlock(parameters[i].cpu);
-                                       break;
-                               }
-                               if (one_lock)
-                               /* Release the lock */
-                                       unlock(0);
-                               /* Release lock on this cpu */
-                               else
-                                       unlock(parameters[i].cpu);
-
-                               if (j < parameters[i].loop-1)
-                                       sleep(parameters[i].interval);
-                       }
-                       current_time=time(NULL);
-                       log_info(parameters[i].cpu, "Done at %s", ctime(&current_time));
-                       return 0;
-               }
-               else if (pid<0) {
-                       perror("Error fork:");
-                       continue;
-               }
-               child_pid[i]=pid;
-       }
-       for (i=0;i<num;i++)
-               waitpid(child_pid[i], NULL, 0);
-
-       if (one_lock)
-               free_sem(0);
-       else
-               for (i=0;i<num;i++)
-                       free_sem(parameters[i].cpu);
-
-       printf("All done.\n");
-
-       return 0;
-  }
-
-  void help()
-  {
-       printf("err_inject_tool:\n");
-       printf("\t-q: query all capabilities. default: off\n");
-       printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n");
-       printf("\t-i: inject errors. default: off\n");
-       printf("\t-l: one lock per cpu. default: one lock for all\n");
-       printf("\t-e: error parameters:\n");
-       printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n");
-       printf("\t\t   cpu: logical cpu number the error will be inject in.\n");
-       printf("\t\t   loop: times the error will be injected.\n");
-       printf("\t\t   interval: In second. every so often one error is injected.\n");
-       printf("\t\t   err_type_info, err_struct_info: PAL parameters.\n");
-       printf("\t\t   err_data_buffer: PAL parameter. Optional. If not present,\n");
-       printf("\t\t                    it's constructed by tool automatically. Be\n");
-       printf("\t\t                    careful to provide err_data_buffer and make\n");
-       printf("\t\t                    sure it's working with the environment.\n");
-       printf("\t    Note:no space between error parameters.\n");
-       printf("\t    default: Take error parameters from err.conf instead of command line.\n");
-       printf("\t-v: verbose. default: off\n");
-       printf("\t-h: help\n\n");
-       printf("The tool will take err.conf file as ");
-       printf("input to inject single or multiple errors ");
-       printf("on one or multiple cpus in parallel.\n");
-  }
-
-  int main(int argc, char **argv)
-  {
-       char c;
-       int do_err_inj=0;
-       int do_query_all=0;
-       int count;
-       u32 m;
-
-       /* Default one lock for all cpu's */
-       one_lock=1;
-       while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF)
-               switch (c) {
-                       case 'm':       /* Procedure mode. 1: phys 2: virt */
-                               count=sscanf(optarg, "%x", &m);
-                               if (count!=1 || (m!=1 && m!=2)) {
-                                       printf("Wrong mode number.\n");
-                                       help();
-                                       return -1;
-                               }
-                               mode=m;
-                               break;
-                       case 'i':       /* Inject errors */
-                               do_err_inj=1;
-                               break;
-                       case 'q':       /* Query */
-                               do_query_all=1;
-                               break;
-                       case 'v':       /* Verbose */
-                               verbose=1;
-                               break;
-                       case 'l':       /* One lock per cpu */
-                               one_lock=0;
-                               break;
-                       case 'e':       /* error arguments */
-                               /* Take parameters:
-                                * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer]
-                                * err_data_buffer is optional. Recommend not to specify
-                                * err_data_buffer. Better to use tool to generate it.
-                                */
-                               count=sscanf(optarg,
-                                       "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
-                                       &line_para.cpu,
-                                       &line_para.loop,
-                                       &line_para.interval,
-                                       &line_para.err_type_info,
-                                       &line_para.err_struct_info,
-                                       &line_para.err_data_buffer[0],
-                                       &line_para.err_data_buffer[1],
-                                       &line_para.err_data_buffer[2]);
-                               if (count!=PARA_FIELD_NUM+3) {
-                                   line_para.err_data_buffer[0]=-1,
-                                   line_para.err_data_buffer[1]=-1,
-                                   line_para.err_data_buffer[2]=-1;
-                                   count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n",
-                                               &line_para.cpu,
-                                               &line_para.loop,
-                                               &line_para.interval,
-                                               &line_para.err_type_info,
-                                               &line_para.err_struct_info);
-                                   if (count!=PARA_FIELD_NUM) {
-                                       printf("Wrong error arguments.\n");
-                                       help();
-                                       return -1;
-                                   }
-                               }
-                               para=1;
-                               break;
-                       continue;
-                               break;
-                       case 'h':
-                               help();
-                               return 0;
-                       default:
-                               break;
-               }
-
-       if (do_query_all)
-               query_all_capabilities();
-       if (do_err_inj)
-               err_inj();
-
-       if (!do_query_all &&  !do_err_inj)
-               help();
-
-       return 0;
-  }
diff --git a/Documentation/ia64/features.rst b/Documentation/ia64/features.rst
deleted file mode 100644 (file)
index d7226fd..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features ia64
diff --git a/Documentation/ia64/fsys.rst b/Documentation/ia64/fsys.rst
deleted file mode 100644 (file)
index a702d2c..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-===================================
-Light-weight System Calls for IA-64
-===================================
-
-                       Started: 13-Jan-2003
-
-                   Last update: 27-Sep-2003
-
-                     David Mosberger-Tang
-                     <davidm@hpl.hp.com>
-
-Using the "epc" instruction effectively introduces a new mode of
-execution to the ia64 linux kernel.  We call this mode the
-"fsys-mode".  To recap, the normal states of execution are:
-
-  - kernel mode:
-       Both the register stack and the memory stack have been
-       switched over to kernel memory.  The user-level state is saved
-       in a pt-regs structure at the top of the kernel memory stack.
-
-  - user mode:
-       Both the register stack and the kernel stack are in
-       user memory.  The user-level state is contained in the
-       CPU registers.
-
-  - bank 0 interruption-handling mode:
-       This is the non-interruptible state which all
-       interruption-handlers start execution in.  The user-level
-       state remains in the CPU registers and some kernel state may
-       be stored in bank 0 of registers r16-r31.
-
-In contrast, fsys-mode has the following special properties:
-
-  - execution is at privilege level 0 (most-privileged)
-
-  - CPU registers may contain a mixture of user-level and kernel-level
-    state (it is the responsibility of the kernel to ensure that no
-    security-sensitive kernel-level state is leaked back to
-    user-level)
-
-  - execution is interruptible and preemptible (an fsys-mode handler
-    can disable interrupts and avoid all other interruption-sources
-    to avoid preemption)
-
-  - neither the memory-stack nor the register-stack can be trusted while
-    in fsys-mode (they point to the user-level stacks, which may
-    be invalid, or completely bogus addresses)
-
-In summary, fsys-mode is much more similar to running in user-mode
-than it is to running in kernel-mode.  Of course, given that the
-privilege level is at level 0, this means that fsys-mode requires some
-care (see below).
-
-
-How to tell fsys-mode
-=====================
-
-Linux operates in fsys-mode when (a) the privilege level is 0 (most
-privileged) and (b) the stacks have NOT been switched to kernel memory
-yet.  For convenience, the header file <asm-ia64/ptrace.h> provides
-three macros::
-
-       user_mode(regs)
-       user_stack(task,regs)
-       fsys_mode(task,regs)
-
-The "regs" argument is a pointer to a pt_regs structure.  The "task"
-argument is a pointer to the task structure to which the "regs"
-pointer belongs to.  user_mode() returns TRUE if the CPU state pointed
-to by "regs" was executing in user mode (privilege level 3).
-user_stack() returns TRUE if the state pointed to by "regs" was
-executing on the user-level stack(s).  Finally, fsys_mode() returns
-TRUE if the CPU state pointed to by "regs" was executing in fsys-mode.
-The fsys_mode() macro is equivalent to the expression::
-
-       !user_mode(regs) && user_stack(task,regs)
-
-How to write an fsyscall handler
-================================
-
-The file arch/ia64/kernel/fsys.S contains a table of fsyscall-handlers
-(fsyscall_table).  This table contains one entry for each system call.
-By default, a system call is handled by fsys_fallback_syscall().  This
-routine takes care of entering (full) kernel mode and calling the
-normal Linux system call handler.  For performance-critical system
-calls, it is possible to write a hand-tuned fsyscall_handler.  For
-example, fsys.S contains fsys_getpid(), which is a hand-tuned version
-of the getpid() system call.
-
-The entry and exit-state of an fsyscall handler is as follows:
-
-Machine state on entry to fsyscall handler
-------------------------------------------
-
-  ========= ===============================================================
-  r10      0
-  r11      saved ar.pfs (a user-level value)
-  r15      system call number
-  r16      "current" task pointer (in normal kernel-mode, this is in r13)
-  r32-r39   system call arguments
-  b6       return address (a user-level value)
-  ar.pfs    previous frame-state (a user-level value)
-  PSR.be    cleared to zero (i.e., little-endian byte order is in effect)
-  -         all other registers may contain values passed in from user-mode
-  ========= ===============================================================
-
-Required machine state on exit to fsyscall handler
---------------------------------------------------
-
-  ========= ===========================================================
-  r11      saved ar.pfs (as passed into the fsyscall handler)
-  r15      system call number (as passed into the fsyscall handler)
-  r32-r39   system call arguments (as passed into the fsyscall handler)
-  b6       return address (as passed into the fsyscall handler)
-  ar.pfs    previous frame-state (as passed into the fsyscall handler)
-  ========= ===========================================================
-
-Fsyscall handlers can execute with very little overhead, but with that
-speed comes a set of restrictions:
-
- * Fsyscall-handlers MUST check for any pending work in the flags
-   member of the thread-info structure and if any of the
-   TIF_ALLWORK_MASK flags are set, the handler needs to fall back on
-   doing a full system call (by calling fsys_fallback_syscall).
-
- * Fsyscall-handlers MUST preserve incoming arguments (r32-r39, r11,
-   r15, b6, and ar.pfs) because they will be needed in case of a
-   system call restart.  Of course, all "preserved" registers also
-   must be preserved, in accordance to the normal calling conventions.
-
- * Fsyscall-handlers MUST check argument registers for containing a
-   NaT value before using them in any way that could trigger a
-   NaT-consumption fault.  If a system call argument is found to
-   contain a NaT value, an fsyscall-handler may return immediately
-   with r8=EINVAL, r10=-1.
-
- * Fsyscall-handlers MUST NOT use the "alloc" instruction or perform
-   any other operation that would trigger mandatory RSE
-   (register-stack engine) traffic.
-
- * Fsyscall-handlers MUST NOT write to any stacked registers because
-   it is not safe to assume that user-level called a handler with the
-   proper number of arguments.
-
- * Fsyscall-handlers need to be careful when accessing per-CPU variables:
-   unless proper safe-guards are taken (e.g., interruptions are avoided),
-   execution may be pre-empted and resumed on another CPU at any given
-   time.
-
- * Fsyscall-handlers must be careful not to leak sensitive kernel'
-   information back to user-level.  In particular, before returning to
-   user-level, care needs to be taken to clear any scratch registers
-   that could contain sensitive information (note that the current
-   task pointer is not considered sensitive: it's already exposed
-   through ar.k6).
-
- * Fsyscall-handlers MUST NOT access user-memory without first
-   validating access-permission (this can be done typically via
-   probe.r.fault and/or probe.w.fault) and without guarding against
-   memory access exceptions (this can be done with the EX() macros
-   defined by asmmacro.h).
-
-The above restrictions may seem draconian, but remember that it's
-possible to trade off some of the restrictions by paying a slightly
-higher overhead.  For example, if an fsyscall-handler could benefit
-from the shadow register bank, it could temporarily disable PSR.i and
-PSR.ic, switch to bank 0 (bsw.0) and then use the shadow registers as
-needed.  In other words, following the above rules yields extremely
-fast system call execution (while fully preserving system call
-semantics), but there is also a lot of flexibility in handling more
-complicated cases.
-
-Signal handling
-===============
-
-The delivery of (asynchronous) signals must be delayed until fsys-mode
-is exited.  This is accomplished with the help of the lower-privilege
-transfer trap: arch/ia64/kernel/process.c:do_notify_resume_user()
-checks whether the interrupted task was in fsys-mode and, if so, sets
-PSR.lp and returns immediately.  When fsys-mode is exited via the
-"br.ret" instruction that lowers the privilege level, a trap will
-occur.  The trap handler clears PSR.lp again and returns immediately.
-The kernel exit path then checks for and delivers any pending signals.
-
-PSR Handling
-============
-
-The "epc" instruction doesn't change the contents of PSR at all.  This
-is in contrast to a regular interruption, which clears almost all
-bits.  Because of that, some care needs to be taken to ensure things
-work as expected.  The following discussion describes how each PSR bit
-is handled.
-
-======= =======================================================================
-PSR.be Cleared when entering fsys-mode.  A srlz.d instruction is used
-       to ensure the CPU is in little-endian mode before the first
-       load/store instruction is executed.  PSR.be is normally NOT
-       restored upon return from an fsys-mode handler.  In other
-       words, user-level code must not rely on PSR.be being preserved
-       across a system call.
-PSR.up Unchanged.
-PSR.ac Unchanged.
-PSR.mfl Unchanged.  Note: fsys-mode handlers must not write-registers!
-PSR.mfh        Unchanged.  Note: fsys-mode handlers must not write-registers!
-PSR.ic Unchanged.  Note: fsys-mode handlers can clear the bit, if needed.
-PSR.i  Unchanged.  Note: fsys-mode handlers can clear the bit, if needed.
-PSR.pk Unchanged.
-PSR.dt Unchanged.
-PSR.dfl        Unchanged.  Note: fsys-mode handlers must not write-registers!
-PSR.dfh        Unchanged.  Note: fsys-mode handlers must not write-registers!
-PSR.sp Unchanged.
-PSR.pp Unchanged.
-PSR.di Unchanged.
-PSR.si Unchanged.
-PSR.db Unchanged.  The kernel prevents user-level from setting a hardware
-       breakpoint that triggers at any privilege level other than
-       3 (user-mode).
-PSR.lp Unchanged.
-PSR.tb Lazy redirect.  If a taken-branch trap occurs while in
-       fsys-mode, the trap-handler modifies the saved machine state
-       such that execution resumes in the gate page at
-       syscall_via_break(), with privilege level 3.  Note: the
-       taken branch would occur on the branch invoking the
-       fsyscall-handler, at which point, by definition, a syscall
-       restart is still safe.  If the system call number is invalid,
-       the fsys-mode handler will return directly to user-level.  This
-       return will trigger a taken-branch trap, but since the trap is
-       taken _after_ restoring the privilege level, the CPU has already
-       left fsys-mode, so no special treatment is needed.
-PSR.rt Unchanged.
-PSR.cpl        Cleared to 0.
-PSR.is Unchanged (guaranteed to be 0 on entry to the gate page).
-PSR.mc Unchanged.
-PSR.it Unchanged (guaranteed to be 1).
-PSR.id Unchanged.  Note: the ia64 linux kernel never sets this bit.
-PSR.da Unchanged.  Note: the ia64 linux kernel never sets this bit.
-PSR.dd Unchanged.  Note: the ia64 linux kernel never sets this bit.
-PSR.ss Lazy redirect.  If set, "epc" will cause a Single Step Trap to
-       be taken.  The trap handler then modifies the saved machine
-       state such that execution resumes in the gate page at
-       syscall_via_break(), with privilege level 3.
-PSR.ri Unchanged.
-PSR.ed Unchanged.  Note: This bit could only have an effect if an fsys-mode
-       handler performed a speculative load that gets NaTted.  If so, this
-       would be the normal & expected behavior, so no special treatment is
-       needed.
-PSR.bn Unchanged.  Note: fsys-mode handlers may clear the bit, if needed.
-       Doing so requires clearing PSR.i and PSR.ic as well.
-PSR.ia Unchanged.  Note: the ia64 linux kernel never sets this bit.
-======= =======================================================================
-
-Using fast system calls
-=======================
-
-To use fast system calls, userspace applications need simply call
-__kernel_syscall_via_epc().  For example
-
--- example fgettimeofday() call --
-
--- fgettimeofday.S --
-
-::
-
-  #include <asm/asmmacro.h>
-
-  GLOBAL_ENTRY(fgettimeofday)
-  .prologue
-  .save ar.pfs, r11
-  mov r11 = ar.pfs
-  .body
-
-  mov r2 = 0xa000000000020660;;  // gate address
-                              // found by inspection of System.map for the
-                              // __kernel_syscall_via_epc() function.  See
-                              // below for how to do this for real.
-
-  mov b7 = r2
-  mov r15 = 1087                      // gettimeofday syscall
-  ;;
-  br.call.sptk.many b6 = b7
-  ;;
-
-  .restore sp
-
-  mov ar.pfs = r11
-  br.ret.sptk.many rp;;              // return to caller
-  END(fgettimeofday)
-
--- end fgettimeofday.S --
-
-In reality, getting the gate address is accomplished by two extra
-values passed via the ELF auxiliary vector (include/asm-ia64/elf.h)
-
- * AT_SYSINFO : is the address of __kernel_syscall_via_epc()
- * AT_SYSINFO_EHDR : is the address of the kernel gate ELF DSO
-
-The ELF DSO is a pre-linked library that is mapped in by the kernel at
-the gate page.  It is a proper ELF shared object so, with a dynamic
-loader that recognises the library, you should be able to make calls to
-the exported functions within it as with any other shared library.
-AT_SYSINFO points into the kernel DSO at the
-__kernel_syscall_via_epc() function for historical reasons (it was
-used before the kernel DSO) and as a convenience.
diff --git a/Documentation/ia64/ia64.rst b/Documentation/ia64/ia64.rst
deleted file mode 100644 (file)
index b725019..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-===========================================
-Linux kernel release for the IA-64 Platform
-===========================================
-
-   These are the release notes for Linux since version 2.4 for IA-64
-   platform.  This document provides information specific to IA-64
-   ONLY, to get additional information about the Linux kernel also
-   read the original Linux README provided with the kernel.
-
-Installing the Kernel
-=====================
-
- - IA-64 kernel installation is the same as the other platforms, see
-   original README for details.
-
-
-Software Requirements
-=====================
-
-   Compiling and running this kernel requires an IA-64 compliant GCC
-   compiler.  And various software packages also compiled with an
-   IA-64 compliant GCC compiler.
-
-
-Configuring the Kernel
-======================
-
-   Configuration is the same, see original README for details.
-
-
-Compiling the Kernel:
-
- - Compiling this kernel doesn't differ from other platform so read
-   the original README for details BUT make sure you have an IA-64
-   compliant GCC compiler.
-
-IA-64 Specifics
-===============
-
- - General issues:
-
-    * Hardly any performance tuning has been done. Obvious targets
-      include the library routines (IP checksum, etc.). Less
-      obvious targets include making sure we don't flush the TLB
-      needlessly, etc.
-
-    * SMP locks cleanup/optimization
-
-    * IA32 support.  Currently experimental.  It mostly works.
diff --git a/Documentation/ia64/index.rst b/Documentation/ia64/index.rst
deleted file mode 100644 (file)
index 761f215..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==================
-IA-64 Architecture
-==================
-
-.. toctree::
-   :maxdepth: 1
-
-   ia64
-   aliasing
-   efirtc
-   err_inject
-   fsys
-   irq-redir
-   mca
-   serial
-
-   features
diff --git a/Documentation/ia64/irq-redir.rst b/Documentation/ia64/irq-redir.rst
deleted file mode 100644 (file)
index 6bbbbe4..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-==============================
-IRQ affinity on IA64 platforms
-==============================
-
-07.01.2002, Erich Focht <efocht@ess.nec.de>
-
-
-By writing to /proc/irq/IRQ#/smp_affinity the interrupt routing can be
-controlled. The behavior on IA64 platforms is slightly different from
-that described in Documentation/core-api/irq/irq-affinity.rst for i386 systems.
-
-Because of the usage of SAPIC mode and physical destination mode the
-IRQ target is one particular CPU and cannot be a mask of several
-CPUs. Only the first non-zero bit is taken into account.
-
-
-Usage examples
-==============
-
-The target CPU has to be specified as a hexadecimal CPU mask. The
-first non-zero bit is the selected CPU. This format has been kept for
-compatibility reasons with i386.
-
-Set the delivery mode of interrupt 41 to fixed and route the
-interrupts to CPU #3 (logical CPU number) (2^3=0x08)::
-
-     echo "8" >/proc/irq/41/smp_affinity
-
-Set the default route for IRQ number 41 to CPU 6 in lowest priority
-delivery mode (redirectable)::
-
-     echo "r 40" >/proc/irq/41/smp_affinity
-
-The output of the command::
-
-     cat /proc/irq/IRQ#/smp_affinity
-
-gives the target CPU mask for the specified interrupt vector. If the CPU
-mask is preceded by the character "r", the interrupt is redirectable
-(i.e. lowest priority mode routing is used), otherwise its route is
-fixed.
-
-
-
-Initialization and default behavior
-===================================
-
-If the platform features IRQ redirection (info provided by SAL) all
-IO-SAPIC interrupts are initialized with CPU#0 as their default target
-and the routing is the so called "lowest priority mode" (actually
-fixed SAPIC mode with hint). The XTP chipset registers are used as hints
-for the IRQ routing. Currently in Linux XTP registers can have three
-values:
-
-       - minimal for an idle task,
-       - normal if any other task runs,
-       - maximal if the CPU is going to be switched off.
-
-The IRQ is routed to the CPU with lowest XTP register value, the
-search begins at the default CPU. Therefore most of the interrupts
-will be handled by CPU #0.
-
-If the platform doesn't feature interrupt redirection IOSAPIC fixed
-routing is used. The target CPUs are distributed in a round robin
-manner. IRQs will be routed only to the selected target CPUs. Check
-with::
-
-        cat /proc/interrupts
-
-
-
-Comments
-========
-
-On large (multi-node) systems it is recommended to route the IRQs to
-the node to which the corresponding device is connected.
-For systems like the NEC AzusA we get IRQ node-affinity for free. This
-is because usually the chipsets on each node redirect the interrupts
-only to their own CPUs (as they cannot see the XTP registers on the
-other nodes).
diff --git a/Documentation/ia64/mca.rst b/Documentation/ia64/mca.rst
deleted file mode 100644 (file)
index 08270bb..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-=============================================================
-An ad-hoc collection of notes on IA64 MCA and INIT processing
-=============================================================
-
-Feel free to update it with notes about any area that is not clear.
-
----
-
-MCA/INIT are completely asynchronous.  They can occur at any time, when
-the OS is in any state.  Including when one of the cpus is already
-holding a spinlock.  Trying to get any lock from MCA/INIT state is
-asking for deadlock.  Also the state of structures that are protected
-by locks is indeterminate, including linked lists.
-
----
-
-The complicated ia64 MCA process.  All of this is mandated by Intel's
-specification for ia64 SAL, error recovery and unwind, it is not as
-if we have a choice here.
-
-* MCA occurs on one cpu, usually due to a double bit memory error.
-  This is the monarch cpu.
-
-* SAL sends an MCA rendezvous interrupt (which is a normal interrupt)
-  to all the other cpus, the slaves.
-
-* Slave cpus that receive the MCA interrupt call down into SAL, they
-  end up spinning disabled while the MCA is being serviced.
-
-* If any slave cpu was already spinning disabled when the MCA occurred
-  then it cannot service the MCA interrupt.  SAL waits ~20 seconds then
-  sends an unmaskable INIT event to the slave cpus that have not
-  already rendezvoused.
-
-* Because MCA/INIT can be delivered at any time, including when the cpu
-  is down in PAL in physical mode, the registers at the time of the
-  event are _completely_ undefined.  In particular the MCA/INIT
-  handlers cannot rely on the thread pointer, PAL physical mode can
-  (and does) modify TP.  It is allowed to do that as long as it resets
-  TP on return.  However MCA/INIT events expose us to these PAL
-  internal TP changes.  Hence curr_task().
-
-* If an MCA/INIT event occurs while the kernel was running (not user
-  space) and the kernel has called PAL then the MCA/INIT handler cannot
-  assume that the kernel stack is in a fit state to be used.  Mainly
-  because PAL may or may not maintain the stack pointer internally.
-  Because the MCA/INIT handlers cannot trust the kernel stack, they
-  have to use their own, per-cpu stacks.  The MCA/INIT stacks are
-  preformatted with just enough task state to let the relevant handlers
-  do their job.
-
-* Unlike most other architectures, the ia64 struct task is embedded in
-  the kernel stack[1].  So switching to a new kernel stack means that
-  we switch to a new task as well.  Because various bits of the kernel
-  assume that current points into the struct task, switching to a new
-  stack also means a new value for current.
-
-* Once all slaves have rendezvoused and are spinning disabled, the
-  monarch is entered.  The monarch now tries to diagnose the problem
-  and decide if it can recover or not.
-
-* Part of the monarch's job is to look at the state of all the other
-  tasks.  The only way to do that on ia64 is to call the unwinder,
-  as mandated by Intel.
-
-* The starting point for the unwind depends on whether a task is
-  running or not.  That is, whether it is on a cpu or is blocked.  The
-  monarch has to determine whether or not a task is on a cpu before it
-  knows how to start unwinding it.  The tasks that received an MCA or
-  INIT event are no longer running, they have been converted to blocked
-  tasks.  But (and its a big but), the cpus that received the MCA
-  rendezvous interrupt are still running on their normal kernel stacks!
-
-* To distinguish between these two cases, the monarch must know which
-  tasks are on a cpu and which are not.  Hence each slave cpu that
-  switches to an MCA/INIT stack, registers its new stack using
-  set_curr_task(), so the monarch can tell that the _original_ task is
-  no longer running on that cpu.  That gives us a decent chance of
-  getting a valid backtrace of the _original_ task.
-
-* MCA/INIT can be nested, to a depth of 2 on any cpu.  In the case of a
-  nested error, we want diagnostics on the MCA/INIT handler that
-  failed, not on the task that was originally running.  Again this
-  requires set_curr_task() so the MCA/INIT handlers can register their
-  own stack as running on that cpu.  Then a recursive error gets a
-  trace of the failing handler's "task".
-
-[1]
-    My (Keith Owens) original design called for ia64 to separate its
-    struct task and the kernel stacks.  Then the MCA/INIT data would be
-    chained stacks like i386 interrupt stacks.  But that required
-    radical surgery on the rest of ia64, plus extra hard wired TLB
-    entries with its associated performance degradation.  David
-    Mosberger vetoed that approach.  Which meant that separate kernel
-    stacks meant separate "tasks" for the MCA/INIT handlers.
-
----
-
-INIT is less complicated than MCA.  Pressing the nmi button or using
-the equivalent command on the management console sends INIT to all
-cpus.  SAL picks one of the cpus as the monarch and the rest are
-slaves.  All the OS INIT handlers are entered at approximately the same
-time.  The OS monarch prints the state of all tasks and returns, after
-which the slaves return and the system resumes.
-
-At least that is what is supposed to happen.  Alas there are broken
-versions of SAL out there.  Some drive all the cpus as monarchs.  Some
-drive them all as slaves.  Some drive one cpu as monarch, wait for that
-cpu to return from the OS then drive the rest as slaves.  Some versions
-of SAL cannot even cope with returning from the OS, they spin inside
-SAL on resume.  The OS INIT code has workarounds for some of these
-broken SAL symptoms, but some simply cannot be fixed from the OS side.
-
----
-
-The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer
-violations.  Unfortunately MCA/INIT start off as massive layer
-violations (can occur at _any_ time) and they build from there.
-
-At least ia64 makes an attempt at recovering from hardware errors, but
-it is a difficult problem because of the asynchronous nature of these
-errors.  When processing an unmaskable interrupt we sometimes need
-special code to cope with our inability to take any locks.
-
----
-
-How is ia64 MCA/INIT different from x86 NMI?
-
-* x86 NMI typically gets delivered to one cpu.  MCA/INIT gets sent to
-  all cpus.
-
-* x86 NMI cannot be nested.  MCA/INIT can be nested, to a depth of 2
-  per cpu.
-
-* x86 has a separate struct task which points to one of multiple kernel
-  stacks.  ia64 has the struct task embedded in the single kernel
-  stack, so switching stack means switching task.
-
-* x86 does not call the BIOS so the NMI handler does not have to worry
-  about any registers having changed.  MCA/INIT can occur while the cpu
-  is in PAL in physical mode, with undefined registers and an undefined
-  kernel stack.
-
-* i386 backtrace is not very sensitive to whether a process is running
-  or not.  ia64 unwind is very, very sensitive to whether a process is
-  running or not.
-
----
-
-What happens when MCA/INIT is delivered what a cpu is running user
-space code?
-
-The user mode registers are stored in the RSE area of the MCA/INIT on
-entry to the OS and are restored from there on return to SAL, so user
-mode registers are preserved across a recoverable MCA/INIT.  Since the
-OS has no idea what unwind data is available for the user space stack,
-MCA/INIT never tries to backtrace user space.  Which means that the OS
-does not bother making the user space process look like a blocked task,
-i.e. the OS does not copy pt_regs and switch_stack to the user space
-stack.  Also the OS has no idea how big the user space RSE and memory
-stacks are, which makes it too risky to copy the saved state to a user
-mode stack.
-
----
-
-How do we get a backtrace on the tasks that were running when MCA/INIT
-was delivered?
-
-mca.c:::ia64_mca_modify_original_stack().  That identifies and
-verifies the original kernel stack, copies the dirty registers from
-the MCA/INIT stack's RSE to the original stack's RSE, copies the
-skeleton struct pt_regs and switch_stack to the original stack, fills
-in the skeleton structures from the PAL minstate area and updates the
-original stack's thread.ksp.  That makes the original stack look
-exactly like any other blocked task, i.e. it now appears to be
-sleeping.  To get a backtrace, just start with thread.ksp for the
-original task and unwind like any other sleeping task.
-
----
-
-How do we identify the tasks that were running when MCA/INIT was
-delivered?
-
-If the previous task has been verified and converted to a blocked
-state, then sos->prev_task on the MCA/INIT stack is updated to point to
-the previous task.  You can look at that field in dumps or debuggers.
-To help distinguish between the handler and the original tasks,
-handlers have _TIF_MCA_INIT set in thread_info.flags.
-
-The sos data is always in the MCA/INIT handler stack, at offset
-MCA_SOS_OFFSET.  You can get that value from mca_asm.h or calculate it
-as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct
-ia64_sal_os_state), with 16 byte alignment for all structures.
-
-Also the comm field of the MCA/INIT task is modified to include the pid
-of the original task, for humans to use.  For example, a comm field of
-'MCA 12159' means that pid 12159 was running when the MCA was
-delivered.
diff --git a/Documentation/ia64/serial.rst b/Documentation/ia64/serial.rst
deleted file mode 100644 (file)
index 1de70c3..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-==============
-Serial Devices
-==============
-
-Serial Device Naming
-====================
-
-    As of 2.6.10, serial devices on ia64 are named based on the
-    order of ACPI and PCI enumeration.  The first device in the
-    ACPI namespace (if any) becomes /dev/ttyS0, the second becomes
-    /dev/ttyS1, etc., and PCI devices are named sequentially
-    starting after the ACPI devices.
-
-    Prior to 2.6.10, there were confusing exceptions to this:
-
-       - Firmware on some machines (mostly from HP) provides an HCDP
-         table[1] that tells the kernel about devices that can be used
-         as a serial console.  If the user specified "console=ttyS0"
-         or the EFI ConOut path contained only UART devices, the
-         kernel registered the device described by the HCDP as
-         /dev/ttyS0.
-
-       - If there was no HCDP, we assumed there were UARTs at the
-         legacy COM port addresses (I/O ports 0x3f8 and 0x2f8), so
-         the kernel registered those as /dev/ttyS0 and /dev/ttyS1.
-
-    Any additional ACPI or PCI devices were registered sequentially
-    after /dev/ttyS0 as they were discovered.
-
-    With an HCDP, device names changed depending on EFI configuration
-    and "console=" arguments.  Without an HCDP, device names didn't
-    change, but we registered devices that might not really exist.
-
-    For example, an HP rx1600 with a single built-in serial port
-    (described in the ACPI namespace) plus an MP[2] (a PCI device) has
-    these ports:
-
-      ==========  ==========     ============    ============   =======
-      Type        MMIO           pre-2.6.10      pre-2.6.10     2.6.10+
-                 address
-                                (EFI console    (EFI console
-                                 on builtin)     on MP port)
-      ==========  ==========     ============    ============   =======
-      builtin     0xff5e0000        ttyS0           ttyS1         ttyS0
-      MP UPS      0xf8031000        ttyS1           ttyS2         ttyS1
-      MP Console  0xf8030000        ttyS2           ttyS0         ttyS2
-      MP 2        0xf8030010        ttyS3           ttyS3         ttyS3
-      MP 3        0xf8030038        ttyS4           ttyS4         ttyS4
-      ==========  ==========     ============    ============   =======
-
-Console Selection
-=================
-
-    EFI knows what your console devices are, but it doesn't tell the
-    kernel quite enough to actually locate them.  The DIG64 HCDP
-    table[1] does tell the kernel where potential serial console
-    devices are, but not all firmware supplies it.  Also, EFI supports
-    multiple simultaneous consoles and doesn't tell the kernel which
-    should be the "primary" one.
-
-    So how do you tell Linux which console device to use?
-
-       - If your firmware supplies the HCDP, it is simplest to
-         configure EFI with a single device (either a UART or a VGA
-         card) as the console.  Then you don't need to tell Linux
-         anything; the kernel will automatically use the EFI console.
-
-         (This works only in 2.6.6 or later; prior to that you had
-         to specify "console=ttyS0" to get a serial console.)
-
-       - Without an HCDP, Linux defaults to a VGA console unless you
-         specify a "console=" argument.
-
-    NOTE: Don't assume that a serial console device will be /dev/ttyS0.
-    It might be ttyS1, ttyS2, etc.  Make sure you have the appropriate
-    entries in /etc/inittab (for getty) and /etc/securetty (to allow
-    root login).
-
-Early Serial Console
-====================
-
-    The kernel can't start using a serial console until it knows where
-    the device lives.  Normally this happens when the driver enumerates
-    all the serial devices, which can happen a minute or more after the
-    kernel starts booting.
-
-    2.6.10 and later kernels have an "early uart" driver that works
-    very early in the boot process.  The kernel will automatically use
-    this if the user supplies an argument like "console=uart,io,0x3f8",
-    or if the EFI console path contains only a UART device and the
-    firmware supplies an HCDP.
-
-Troubleshooting Serial Console Problems
-=======================================
-
-    No kernel output after elilo prints "Uncompressing Linux... done":
-
-       - You specified "console=ttyS0" but Linux changed the device
-         to which ttyS0 refers.  Configure exactly one EFI console
-         device[3] and remove the "console=" option.
-
-       - The EFI console path contains both a VGA device and a UART.
-         EFI and elilo use both, but Linux defaults to VGA.  Remove
-         the VGA device from the EFI console path[3].
-
-       - Multiple UARTs selected as EFI console devices.  EFI and
-         elilo use all selected devices, but Linux uses only one.
-         Make sure only one UART is selected in the EFI console
-         path[3].
-
-       - You're connected to an HP MP port[2] but have a non-MP UART
-         selected as EFI console device.  EFI uses the MP as a
-         console device even when it isn't explicitly selected.
-         Either move the console cable to the non-MP UART, or change
-         the EFI console path[3] to the MP UART.
-
-    Long pause (60+ seconds) between "Uncompressing Linux... done" and
-    start of kernel output:
-
-       - No early console because you used "console=ttyS<n>".  Remove
-         the "console=" option if your firmware supplies an HCDP.
-
-       - If you don't have an HCDP, the kernel doesn't know where
-         your console lives until the driver discovers serial
-         devices.  Use "console=uart,io,0x3f8" (or appropriate
-         address for your machine).
-
-    Kernel and init script output works fine, but no "login:" prompt:
-
-       - Add getty entry to /etc/inittab for console tty.  Look for
-         the "Adding console on ttyS<n>" message that tells you which
-         device is the console.
-
-    "login:" prompt, but can't login as root:
-
-       - Add entry to /etc/securetty for console tty.
-
-    No ACPI serial devices found in 2.6.17 or later:
-
-       - Turn on CONFIG_PNP and CONFIG_PNPACPI.  Prior to 2.6.17, ACPI
-         serial devices were discovered by 8250_acpi.  In 2.6.17,
-         8250_acpi was replaced by the combination of 8250_pnp and
-         CONFIG_PNPACPI.
-
-
-
-[1]
-    http://www.dig64.org/specifications/agreement
-    The table was originally defined as the "HCDP" for "Headless
-    Console/Debug Port."  The current version is the "PCDP" for
-    "Primary Console and Debug Port Devices."
-
-[2]
-    The HP MP (management processor) is a PCI device that provides
-    several UARTs.  One of the UARTs is often used as a console; the
-    EFI Boot Manager identifies it as "Acpi(HWP0002,700)/Pci(...)/Uart".
-    The external connection is usually a 25-pin connector, and a
-    special dongle converts that to three 9-pin connectors, one of
-    which is labelled "Console."
-
-[3]
-    EFI console devices are configured using the EFI Boot Manager
-    "Boot option maintenance" menu.  You may have to interrupt the
-    boot sequence to use this menu, and you will have to reset the
-    box after changing console configuration.
index 76d1a3ec9be3de914aee1c301add8a43293d441e..9dfdc826618c08f5f62f81f1cea543dea3223967 100644 (file)
@@ -99,7 +99,7 @@ Architecture-specific documentation
 .. toctree::
    :maxdepth: 2
 
-   arch
+   arch/index
 
 
 Other documentation
index bfb51685073cb6c5dd09d2617d15912b49573ce9..c3851fe1900da15e47883e1d7d5292075cfaee48 100644 (file)
@@ -171,6 +171,10 @@ Getting Help
 Getting LLVM
 -------------
 
+We provide prebuilt stable versions of LLVM on `kernel.org <https://kernel.org/pub/tools/llvm/>`_.
+Below are links that may be useful for building LLVM from source or procuring
+it through a distribution's package manager.
+
 - https://releases.llvm.org/download.html
 - https://github.com/llvm/llvm-project
 - https://llvm.org/docs/GettingStarted.html
diff --git a/Documentation/kernel-hacking/false-sharing.rst b/Documentation/kernel-hacking/false-sharing.rst
new file mode 100644 (file)
index 0000000..122b0e1
--- /dev/null
@@ -0,0 +1,206 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============
+False Sharing
+=============
+
+What is False Sharing
+=====================
+False sharing is related with cache mechanism of maintaining the data
+coherence of one cache line stored in multiple CPU's caches; then
+academic definition for it is in [1]_. Consider a struct with a
+refcount and a string::
+
+       struct foo {
+               refcount_t refcount;
+               ...
+               char name[16];
+       } ____cacheline_internodealigned_in_smp;
+
+Member 'refcount'(A) and 'name'(B) _share_ one cache line like below::
+
+                +-----------+                     +-----------+
+                |   CPU 0   |                     |   CPU 1   |
+                +-----------+                     +-----------+
+               /                                        |
+              /                                         |
+             V                                          V
+         +----------------------+             +----------------------+
+         | A      B             | Cache 0     | A       B            | Cache 1
+         +----------------------+             +----------------------+
+                             |                  |
+  ---------------------------+------------------+-----------------------------
+                             |                  |
+                           +----------------------+
+                           |                      |
+                           +----------------------+
+              Main Memory  | A       B            |
+                           +----------------------+
+
+'refcount' is modified frequently, but 'name' is set once at object
+creation time and is never modified.  When many CPUs access 'foo' at
+the same time, with 'refcount' being only bumped by one CPU frequently
+and 'name' being read by other CPUs, all those reading CPUs have to
+reload the whole cache line over and over due to the 'sharing', even
+though 'name' is never changed.
+
+There are many real-world cases of performance regressions caused by
+false sharing.  One of these is a rw_semaphore 'mmap_lock' inside
+mm_struct struct, whose cache line layout change triggered a
+regression and Linus analyzed in [2]_.
+
+There are two key factors for a harmful false sharing:
+
+* A global datum accessed (shared) by many CPUs
+* In the concurrent accesses to the data, there is at least one write
+  operation: write/write or write/read cases.
+
+The sharing could be from totally unrelated kernel components, or
+different code paths of the same kernel component.
+
+
+False Sharing Pitfalls
+======================
+Back in time when one platform had only one or a few CPUs, hot data
+members could be purposely put in the same cache line to make them
+cache hot and save cacheline/TLB, like a lock and the data protected
+by it.  But for recent large system with hundreds of CPUs, this may
+not work when the lock is heavily contended, as the lock owner CPU
+could write to the data, while other CPUs are busy spinning the lock.
+
+Looking at past cases, there are several frequently occurring patterns
+for false sharing:
+
+* lock (spinlock/mutex/semaphore) and data protected by it are
+  purposely put in one cache line.
+* global data being put together in one cache line. Some kernel
+  subsystems have many global parameters of small size (4 bytes),
+  which can easily be grouped together and put into one cache line.
+* data members of a big data structure randomly sitting together
+  without being noticed (cache line is usually 64 bytes or more),
+  like 'mem_cgroup' struct.
+
+Following 'mitigation' section provides real-world examples.
+
+False sharing could easily happen unless they are intentionally
+checked, and it is valuable to run specific tools for performance
+critical workloads to detect false sharing affecting performance case
+and optimize accordingly.
+
+
+How to detect and analyze False Sharing
+========================================
+perf record/report/stat are widely used for performance tuning, and
+once hotspots are detected, tools like 'perf-c2c' and 'pahole' can
+be further used to detect and pinpoint the possible false sharing
+data structures.  'addr2line' is also good at decoding instruction
+pointer when there are multiple layers of inline functions.
+
+perf-c2c can capture the cache lines with most false sharing hits,
+decoded functions (line number of file) accessing that cache line,
+and in-line offset of the data. Simple commands are::
+
+  $ perf c2c record -ag sleep 3
+  $ perf c2c report --call-graph none -k vmlinux
+
+When running above during testing will-it-scale's tlb_flush1 case,
+perf reports something like::
+
+  Total records                     :    1658231
+  Locked Load/Store Operations      :      89439
+  Load Operations                   :     623219
+  Load Local HITM                   :      92117
+  Load Remote HITM                  :        139
+
+  #----------------------------------------------------------------------
+      4        0     2374        0        0        0  0xff1100088366d880
+  #----------------------------------------------------------------------
+    0.00%   42.29%    0.00%    0.00%    0.00%    0x8     1       1  0xffffffff81373b7b         0       231       129     5312        64  [k] __mod_lruvec_page_state    [kernel.vmlinux]  memcontrol.h:752   1
+    0.00%   13.10%    0.00%    0.00%    0.00%    0x8     1       1  0xffffffff81374718         0       226        97     3551        64  [k] folio_lruvec_lock_irqsave  [kernel.vmlinux]  memcontrol.h:752   1
+    0.00%   11.20%    0.00%    0.00%    0.00%    0x8     1       1  0xffffffff812c29bf         0       170       136      555        64  [k] lru_add_fn                 [kernel.vmlinux]  mm_inline.h:41     1
+    0.00%    7.62%    0.00%    0.00%    0.00%    0x8     1       1  0xffffffff812c3ec5         0       175       108      632        64  [k] release_pages              [kernel.vmlinux]  mm_inline.h:41     1
+    0.00%   23.29%    0.00%    0.00%    0.00%   0x10     1       1  0xffffffff81372d0a         0       234       279     1051        64  [k] __mod_memcg_lruvec_state   [kernel.vmlinux]  memcontrol.c:736   1
+
+A nice introduction for perf-c2c is [3]_.
+
+'pahole' decodes data structure layouts delimited in cache line
+granularity.  Users can match the offset in perf-c2c output with
+pahole's decoding to locate the exact data members.  For global
+data, users can search the data address in System.map.
+
+
+Possible Mitigations
+====================
+False sharing does not always need to be mitigated.  False sharing
+mitigations should balance performance gains with complexity and
+space consumption.  Sometimes, lower performance is OK, and it's
+unnecessary to hyper-optimize every rarely used data structure or
+a cold data path.
+
+False sharing hurting performance cases are seen more frequently with
+core count increasing.  Because of these detrimental effects, many
+patches have been proposed across variety of subsystems (like
+networking and memory management) and merged.  Some common mitigations
+(with examples) are:
+
+* Separate hot global data in its own dedicated cache line, even if it
+  is just a 'short' type. The downside is more consumption of memory,
+  cache line and TLB entries.
+
+  - Commit 91b6d3256356 ("net: cache align tcp_memory_allocated, tcp_sockets_allocated")
+
+* Reorganize the data structure, separate the interfering members to
+  different cache lines.  One downside is it may introduce new false
+  sharing of other members.
+
+  - Commit 802f1d522d5f ("mm: page_counter: re-layout structure to reduce false sharing")
+
+* Replace 'write' with 'read' when possible, especially in loops.
+  Like for some global variable, use compare(read)-then-write instead
+  of unconditional write. For example, use::
+
+       if (!test_bit(XXX))
+               set_bit(XXX);
+
+  instead of directly "set_bit(XXX);", similarly for atomic_t data::
+
+       if (atomic_read(XXX) == AAA)
+               atomic_set(XXX, BBB);
+
+  - Commit 7b1002f7cfe5 ("bcache: fixup bcache_dev_sectors_dirty_add() multithreaded CPU false sharing")
+  - Commit 292648ac5cf1 ("mm: gup: allow FOLL_PIN to scale in SMP")
+
+* Turn hot global data to 'per-cpu data + global data' when possible,
+  or reasonably increase the threshold for syncing per-cpu data to
+  global data, to reduce or postpone the 'write' to that global data.
+
+  - Commit 520f897a3554 ("ext4: use percpu_counters for extent_status cache hits/misses")
+  - Commit 56f3547bfa4d ("mm: adjust vm_committed_as_batch according to vm overcommit policy")
+
+Surely, all mitigations should be carefully verified to not cause side
+effects.  To avoid introducing false sharing when coding, it's better
+to:
+
+* Be aware of cache line boundaries
+* Group mostly read-only fields together
+* Group things that are written at the same time together
+* Separate frequently read and frequently written fields on
+  different cache lines.
+
+and better add a comment stating the false sharing consideration.
+
+One note is, sometimes even after a severe false sharing is detected
+and solved, the performance may still have no obvious improvement as
+the hotspot switches to a new place.
+
+
+Miscellaneous
+=============
+One open issue is that kernel has an optional data structure
+randomization mechanism, which also randomizes the situation of cache
+line sharing of data members.
+
+
+.. [1] https://en.wikipedia.org/wiki/False_sharing
+.. [2] https://lore.kernel.org/lkml/CAHk-=whoqV=cX5VC80mmR9rr+Z+yQ6fiQZm36Fb-izsanHg23w@mail.gmail.com/
+.. [3] https://joemario.github.io/blog/2016/09/01/c2c-blog/
index f530276522904c1ddd4db4655f399c5d02ed696a..79c03bac99a294bf005041100bf15d1fd64943cc 100644 (file)
@@ -9,3 +9,4 @@ Kernel Hacking Guides
 
    hacking
    locking
+   false-sharing
index 7f5c6c3ed6c3713ca070a7705aa7b61cfd2edf19..658d37860d3974b03aea570e6c212c79a09aa491 100644 (file)
@@ -9,7 +9,7 @@ a kernel test module based on a litmus test, please see
 tools/memory-model/README.
 
 
-atomic (/atomic derectory)
+atomic (/atomic directory)
 --------------------------
 
 Atomic-RMW+mb__after_atomic-is-stronger-than-acquire.litmus
diff --git a/Documentation/litmus-tests/locking/DCL-broken.litmus b/Documentation/litmus-tests/locking/DCL-broken.litmus
new file mode 100644 (file)
index 0000000..bfb7ba4
--- /dev/null
@@ -0,0 +1,54 @@
+C DCL-broken
+
+(*
+ * Result: Sometimes
+ *
+ * This litmus test demonstrates more than just locking is required to
+ * correctly implement double-checked locking.
+ *)
+
+{
+       int flag;
+       int data;
+}
+
+P0(int *flag, int *data, spinlock_t *lck)
+{
+       int r0;
+       int r1;
+       int r2;
+
+       r0 = READ_ONCE(*flag);
+       if (r0 == 0) {
+               spin_lock(lck);
+               r1 = READ_ONCE(*flag);
+               if (r1 == 0) {
+                       WRITE_ONCE(*data, 1);
+                       WRITE_ONCE(*flag, 1);
+               }
+               spin_unlock(lck);
+       }
+       r2 = READ_ONCE(*data);
+}
+
+P1(int *flag, int *data, spinlock_t *lck)
+{
+       int r0;
+       int r1;
+       int r2;
+
+       r0 = READ_ONCE(*flag);
+       if (r0 == 0) {
+               spin_lock(lck);
+               r1 = READ_ONCE(*flag);
+               if (r1 == 0) {
+                       WRITE_ONCE(*data, 1);
+                       WRITE_ONCE(*flag, 1);
+               }
+               spin_unlock(lck);
+       }
+       r2 = READ_ONCE(*data);
+}
+
+locations [flag;data;0:r0;0:r1;1:r0;1:r1]
+exists (0:r2=0 \/ 1:r2=0)
diff --git a/Documentation/litmus-tests/locking/DCL-fixed.litmus b/Documentation/litmus-tests/locking/DCL-fixed.litmus
new file mode 100644 (file)
index 0000000..d1b60bc
--- /dev/null
@@ -0,0 +1,55 @@
+C DCL-fixed
+
+(*
+ * Result: Never
+ *
+ * This litmus test demonstrates that double-checked locking can be
+ * reliable given proper use of smp_load_acquire() and smp_store_release()
+ * in addition to the locking.
+ *)
+
+{
+       int flag;
+       int data;
+}
+
+P0(int *flag, int *data, spinlock_t *lck)
+{
+       int r0;
+       int r1;
+       int r2;
+
+       r0 = smp_load_acquire(flag);
+       if (r0 == 0) {
+               spin_lock(lck);
+               r1 = READ_ONCE(*flag);
+               if (r1 == 0) {
+                       WRITE_ONCE(*data, 1);
+                       smp_store_release(flag, 1);
+               }
+               spin_unlock(lck);
+       }
+       r2 = READ_ONCE(*data);
+}
+
+P1(int *flag, int *data, spinlock_t *lck)
+{
+       int r0;
+       int r1;
+       int r2;
+
+       r0 = smp_load_acquire(flag);
+       if (r0 == 0) {
+               spin_lock(lck);
+               r1 = READ_ONCE(*flag);
+               if (r1 == 0) {
+                       WRITE_ONCE(*data, 1);
+                       smp_store_release(flag, 1);
+               }
+               spin_unlock(lck);
+       }
+       r2 = READ_ONCE(*data);
+}
+
+locations [flag;data;0:r0;0:r1;1:r0;1:r1]
+exists (0:r2=0 \/ 1:r2=0)
diff --git a/Documentation/litmus-tests/locking/RM-broken.litmus b/Documentation/litmus-tests/locking/RM-broken.litmus
new file mode 100644 (file)
index 0000000..b7ef30c
--- /dev/null
@@ -0,0 +1,41 @@
+C RM-broken
+
+(*
+ * Result: DEADLOCK
+ *
+ * This litmus test demonstrates that the old "roach motel" approach
+ * to locking, where code can be freely moved into critical sections,
+ * cannot be used in the Linux kernel.
+ *)
+
+{
+       int x;
+       atomic_t y;
+}
+
+P0(int *x, atomic_t *y, spinlock_t *lck)
+{
+       int r2;
+
+       spin_lock(lck);
+       r2 = atomic_inc_return(y);
+       WRITE_ONCE(*x, 1);
+       spin_unlock(lck);
+}
+
+P1(int *x, atomic_t *y, spinlock_t *lck)
+{
+       int r0;
+       int r1;
+       int r2;
+
+       spin_lock(lck);
+       r0 = READ_ONCE(*x);
+       r1 = READ_ONCE(*x);
+       r2 = atomic_inc_return(y);
+       spin_unlock(lck);
+}
+
+locations [x;0:r2;1:r0;1:r1;1:r2]
+filter (1:r0=0 /\ 1:r1=1)
+exists (1:r2=1)
diff --git a/Documentation/litmus-tests/locking/RM-fixed.litmus b/Documentation/litmus-tests/locking/RM-fixed.litmus
new file mode 100644 (file)
index 0000000..b628175
--- /dev/null
@@ -0,0 +1,41 @@
+C RM-fixed
+
+(*
+ * Result: Never
+ *
+ * This litmus test demonstrates that the old "roach motel" approach
+ * to locking, where code can be freely moved into critical sections,
+ * cannot be used in the Linux kernel.
+ *)
+
+{
+       int x;
+       atomic_t y;
+}
+
+P0(int *x, atomic_t *y, spinlock_t *lck)
+{
+       int r2;
+
+       spin_lock(lck);
+       r2 = atomic_inc_return(y);
+       WRITE_ONCE(*x, 1);
+       spin_unlock(lck);
+}
+
+P1(int *x, atomic_t *y, spinlock_t *lck)
+{
+       int r0;
+       int r1;
+       int r2;
+
+       r0 = READ_ONCE(*x);
+       r1 = READ_ONCE(*x);
+       spin_lock(lck);
+       r2 = atomic_inc_return(y);
+       spin_unlock(lck);
+}
+
+locations [x;0:r2;1:r0;1:r1;1:r2]
+filter (1:r0=0 /\ 1:r1=1)
+exists (1:r2=1)
diff --git a/Documentation/m68k/buddha-driver.rst b/Documentation/m68k/buddha-driver.rst
deleted file mode 100644 (file)
index 20e4014..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-=====================================
-Amiga Buddha and Catweasel IDE Driver
-=====================================
-
-The Amiga Buddha and Catweasel IDE Driver (part of ide.c) was written by
-Geert Uytterhoeven based on the following specifications:
-
-------------------------------------------------------------------------
-
-Register map of the Buddha IDE controller and the
-Buddha-part of the Catweasel Zorro-II version
-
-The Autoconfiguration has been implemented just as Commodore
-described  in  their  manuals, no tricks have been used (for
-example leaving some address lines out of the equations...).
-If you want to configure the board yourself (for example let
-a  Linux  kernel  configure the card), look at the Commodore
-Docs.  Reading the nibbles should give this information::
-
-  Vendor number: 4626 ($1212)
-  product number: 0 (42 for Catweasel Z-II)
-  Serial number: 0
-  Rom-vector: $1000
-
-The  card  should be a Z-II board, size 64K, not for freemem
-list, Rom-Vektor is valid, no second Autoconfig-board on the
-same card, no space preference, supports "Shutup_forever".
-
-Setting  the  base address should be done in two steps, just
-as  the Amiga Kickstart does:  The lower nibble of the 8-Bit
-address is written to $4a, then the whole Byte is written to
-$48, while it doesn't matter how often you're writing to $4a
-as  long as $48 is not touched.  After $48 has been written,
-the  whole card disappears from $e8 and is mapped to the new
-address just written.  Make sure $4a is written before $48,
-otherwise your chance is only 1:16 to find the board :-).
-
-The local memory-map is even active when mapped to $e8:
-
-==============  ===========================================
-$0-$7e         Autokonfig-space, see Z-II docs.
-
-$80-$7fd       reserved
-
-$7fe           Speed-select Register: Read & Write
-               (description see further down)
-
-$800-$8ff      IDE-Select 0 (Port 0, Register set 0)
-
-$900-$9ff      IDE-Select 1 (Port 0, Register set 1)
-
-$a00-$aff      IDE-Select 2 (Port 1, Register set 0)
-
-$b00-$bff      IDE-Select 3 (Port 1, Register set 1)
-
-$c00-$cff      IDE-Select 4 (Port 2, Register set 0,
-                Catweasel only!)
-
-$d00-$dff      IDE-Select 5 (Port 3, Register set 1,
-               Catweasel only!)
-
-$e00-$eff      local expansion port, on Catweasel Z-II the
-               Catweasel registers are also mapped here.
-               Never touch, use multidisk.device!
-
-$f00           read only, Byte-access: Bit 7 shows the
-               level of the IRQ-line of IDE port 0.
-
-$f01-$f3f      mirror of $f00
-
-$f40           read only, Byte-access: Bit 7 shows the
-               level of the IRQ-line of IDE port 1.
-
-$f41-$f7f      mirror of $f40
-
-$f80           read only, Byte-access: Bit 7 shows the
-               level of the IRQ-line of IDE port 2.
-               (Catweasel only!)
-
-$f81-$fbf      mirror of $f80
-
-$fc0           write-only: Writing any value to this
-               register enables IRQs to be passed from the
-               IDE ports to the Zorro bus. This mechanism
-               has been implemented to be compatible with
-               harddisks that are either defective or have
-               a buggy firmware and pull the IRQ line up
-               while starting up. If interrupts would
-               always be passed to the bus, the computer
-               might not start up. Once enabled, this flag
-               can not be disabled again. The level of the
-               flag can not be determined by software
-               (what for? Write to me if it's necessary!).
-
-$fc1-$fff      mirror of $fc0
-
-$1000-$ffff    Buddha-Rom with offset $1000 in the rom
-               chip. The addresses $0 to $fff of the rom
-               chip cannot be read. Rom is Byte-wide and
-               mapped to even addresses.
-==============  ===========================================
-
-The  IDE ports issue an INT2.  You can read the level of the
-IRQ-lines  of  the  IDE-ports by reading from the three (two
-for  Buddha-only)  registers  $f00, $f40 and $f80.  This way
-more  than one I/O request can be handled and you can easily
-determine  what  driver  has  to serve the INT2.  Buddha and
-Catweasel  expansion  boards  can issue an INT6.  A separate
-memory  map  is available for the I/O module and the sysop's
-I/O module.
-
-The IDE ports are fed by the address lines A2 to A4, just as
-the  Amiga  1200  and  Amiga  4000  IDE ports are.  This way
-existing  drivers  can be easily ported to Buddha.  A move.l
-polls  two  words  out of the same address of IDE port since
-every  word  is  mirrored  once.  movem is not possible, but
-it's  not  necessary  either,  because  you can only speedup
-68000  systems  with  this  technique.   A 68020 system with
-fastmem is faster with move.l.
-
-If you're using the mirrored registers of the IDE-ports with
-A6=1,  the Buddha doesn't care about the speed that you have
-selected  in  the  speed  register (see further down).  With
-A6=1  (for example $840 for port 0, register set 0), a 780ns
-access  is being made.  These registers should be used for a
-command   access   to  the  harddisk/CD-Rom,  since  command
-accesses  are Byte-wide and have to be made slower according
-to the ATA-X3T9 manual.
-
-Now  for the speed-register:  The register is byte-wide, and
-only  the  upper  three  bits are used (Bits 7 to 5).  Bit 4
-must  always  be set to 1 to be compatible with later Buddha
-versions  (if  I'll  ever  update this one).  I presume that
-I'll  never use the lower four bits, but they have to be set
-to 1 by definition.
-
-The  values in this table have to be shifted 5 bits to the
-left and or'd with $1f (this sets the lower 5 bits).
-
-All  the timings have in common:  Select and IOR/IOW rise at
-the  same  time.   IOR  and  IOW have a propagation delay of
-about  30ns  to  the clocks on the Zorro bus, that's why the
-values  are no multiple of 71.  One clock-cycle is 71ns long
-(exactly 70,5 at 14,18 Mhz on PAL systems).
-
-value 0 (Default after reset)
-  497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles)
-  (same timing as the Amiga 1200 does on it's IDE port without
-  accelerator card)
-
-value 1
-  639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles)
-
-value 2
-  781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles)
-
-value 3
-  355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
-
-value 4
-  355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles)
-
-value 5
-  355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles)
-
-value 6
-  1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles)
-
-value 7
-  355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
-
-When accessing IDE registers with A6=1 (for example $84x),
-the timing will always be mode 0 8-bit compatible, no matter
-what you have selected in the speed register:
-
-781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive.
-
-All  the  timings with a very short select-signal (the 355ns
-fast  accesses)  depend  on the accelerator card used in the
-system:  Sometimes two more clock cycles are inserted by the
-bus  interface,  making  the  whole access 497ns long.  This
-doesn't  affect  the  reliability  of the controller nor the
-performance  of  the  card,  since  this doesn't happen very
-often.
-
-All  the  timings  are  calculated  and  only  confirmed  by
-measurements  that allowed me to count the clock cycles.  If
-the  system  is clocked by an oscillator other than 28,37516
-Mhz  (for  example  the  NTSC-frequency  28,63636 Mhz), each
-clock  cycle is shortened to a bit less than 70ns (not worth
-mentioning).   You  could think of a small performance boost
-by  overclocking  the  system,  but  you would either need a
-multisync  monitor,  or  a  graphics card, and your internal
-diskdrive would go crazy, that's why you shouldn't tune your
-Amiga this way.
-
-Giving  you  the  possibility  to  write  software  that  is
-compatible  with both the Buddha and the Catweasel Z-II, The
-Buddha  acts  just  like  a  Catweasel  Z-II  with no device
-connected  to  the  third  IDE-port.   The IRQ-register $f80
-always  shows a "no IRQ here" on the Buddha, and accesses to
-the  third  IDE  port  are  going into data's Nirwana on the
-Buddha.
-
-Jens Schönfeld february 19th, 1997
-
-updated may 27th, 1997
-
-eMail: sysop@nostlgic.tng.oche.de
diff --git a/Documentation/m68k/features.rst b/Documentation/m68k/features.rst
deleted file mode 100644 (file)
index 5107a21..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features m68k
diff --git a/Documentation/m68k/index.rst b/Documentation/m68k/index.rst
deleted file mode 100644 (file)
index 0f890db..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=================
-m68k Architecture
-=================
-
-.. toctree::
-   :maxdepth: 2
-
-   kernel-options
-   buddha-driver
-
-   features
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/m68k/kernel-options.rst b/Documentation/m68k/kernel-options.rst
deleted file mode 100644 (file)
index 2008a20..0000000
+++ /dev/null
@@ -1,911 +0,0 @@
-===================================
-Command Line Options for Linux/m68k
-===================================
-
-Last Update: 2 May 1999
-
-Linux/m68k version: 2.2.6
-
-Author: Roman.Hodek@informatik.uni-erlangen.de (Roman Hodek)
-
-Update: jds@kom.auc.dk (Jes Sorensen) and faq@linux-m68k.org (Chris Lawrence)
-
-0) Introduction
-===============
-
-Often I've been asked which command line options the Linux/m68k
-kernel understands, or how the exact syntax for the ... option is, or
-... about the option ... . I hope, this document supplies all the
-answers...
-
-Note that some options might be outdated, their descriptions being
-incomplete or missing. Please update the information and send in the
-patches.
-
-
-1) Overview of the Kernel's Option Processing
-=============================================
-
-The kernel knows three kinds of options on its command line:
-
-  1) kernel options
-  2) environment settings
-  3) arguments for init
-
-To which of these classes an argument belongs is determined as
-follows: If the option is known to the kernel itself, i.e. if the name
-(the part before the '=') or, in some cases, the whole argument string
-is known to the kernel, it belongs to class 1. Otherwise, if the
-argument contains an '=', it is of class 2, and the definition is put
-into init's environment. All other arguments are passed to init as
-command line options.
-
-This document describes the valid kernel options for Linux/m68k in
-the version mentioned at the start of this file. Later revisions may
-add new such options, and some may be missing in older versions.
-
-In general, the value (the part after the '=') of an option is a
-list of values separated by commas. The interpretation of these values
-is up to the driver that "owns" the option. This association of
-options with drivers is also the reason that some are further
-subdivided.
-
-
-2) General Kernel Options
-=========================
-
-2.1) root=
-----------
-
-:Syntax: root=/dev/<device>
-:or:     root=<hex_number>
-
-This tells the kernel which device it should mount as the root
-filesystem. The device must be a block device with a valid filesystem
-on it.
-
-The first syntax gives the device by name. These names are converted
-into a major/minor number internally in the kernel in an unusual way.
-Normally, this "conversion" is done by the device files in /dev, but
-this isn't possible here, because the root filesystem (with /dev)
-isn't mounted yet... So the kernel parses the name itself, with some
-hardcoded name to number mappings. The name must always be a
-combination of two or three letters, followed by a decimal number.
-Valid names are::
-
-  /dev/ram: -> 0x0100 (initial ramdisk)
-  /dev/hda: -> 0x0300 (first IDE disk)
-  /dev/hdb: -> 0x0340 (second IDE disk)
-  /dev/sda: -> 0x0800 (first SCSI disk)
-  /dev/sdb: -> 0x0810 (second SCSI disk)
-  /dev/sdc: -> 0x0820 (third SCSI disk)
-  /dev/sdd: -> 0x0830 (forth SCSI disk)
-  /dev/sde: -> 0x0840 (fifth SCSI disk)
-  /dev/fd : -> 0x0200 (floppy disk)
-
-The name must be followed by a decimal number, that stands for the
-partition number. Internally, the value of the number is just
-added to the device number mentioned in the table above. The
-exceptions are /dev/ram and /dev/fd, where /dev/ram refers to an
-initial ramdisk loaded by your bootstrap program (please consult the
-instructions for your bootstrap program to find out how to load an
-initial ramdisk). As of kernel version 2.0.18 you must specify
-/dev/ram as the root device if you want to boot from an initial
-ramdisk. For the floppy devices, /dev/fd, the number stands for the
-floppy drive number (there are no partitions on floppy disks). I.e.,
-/dev/fd0 stands for the first drive, /dev/fd1 for the second, and so
-on. Since the number is just added, you can also force the disk format
-by adding a number greater than 3. If you look into your /dev
-directory, use can see the /dev/fd0D720 has major 2 and minor 16. You
-can specify this device for the root FS by writing "root=/dev/fd16" on
-the kernel command line.
-
-[Strange and maybe uninteresting stuff ON]
-
-This unusual translation of device names has some strange
-consequences: If, for example, you have a symbolic link from /dev/fd
-to /dev/fd0D720 as an abbreviation for floppy driver #0 in DD format,
-you cannot use this name for specifying the root device, because the
-kernel cannot see this symlink before mounting the root FS and it
-isn't in the table above. If you use it, the root device will not be
-set at all, without an error message. Another example: You cannot use a
-partition on e.g. the sixth SCSI disk as the root filesystem, if you
-want to specify it by name. This is, because only the devices up to
-/dev/sde are in the table above, but not /dev/sdf. Although, you can
-use the sixth SCSI disk for the root FS, but you have to specify the
-device by number... (see below). Or, even more strange, you can use the
-fact that there is no range checking of the partition number, and your
-knowledge that each disk uses 16 minors, and write "root=/dev/sde17"
-(for /dev/sdf1).
-
-[Strange and maybe uninteresting stuff OFF]
-
-If the device containing your root partition isn't in the table
-above, you can also specify it by major and minor numbers. These are
-written in hex, with no prefix and no separator between. E.g., if you
-have a CD with contents appropriate as a root filesystem in the first
-SCSI CD-ROM drive, you boot from it by "root=0b00". Here, hex "0b" =
-decimal 11 is the major of SCSI CD-ROMs, and the minor 0 stands for
-the first of these. You can find out all valid major numbers by
-looking into include/linux/major.h.
-
-In addition to major and minor numbers, if the device containing your
-root partition uses a partition table format with unique partition
-identifiers, then you may use them.  For instance,
-"root=PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF".  It is also
-possible to reference another partition on the same device using a
-known partition UUID as the starting point.  For example,
-if partition 5 of the device has the UUID of
-00112233-4455-6677-8899-AABBCCDDEEFF then partition 3 may be found as
-follows:
-
-  PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=-2
-
-Authoritative information can be found in
-"Documentation/admin-guide/kernel-parameters.rst".
-
-
-2.2) ro, rw
------------
-
-:Syntax: ro
-:or:     rw
-
-These two options tell the kernel whether it should mount the root
-filesystem read-only or read-write. The default is read-only, except
-for ramdisks, which default to read-write.
-
-
-2.3) debug
-----------
-
-:Syntax: debug
-
-This raises the kernel log level to 10 (the default is 7). This is the
-same level as set by the "dmesg" command, just that the maximum level
-selectable by dmesg is 8.
-
-
-2.4) debug=
------------
-
-:Syntax: debug=<device>
-
-This option causes certain kernel messages be printed to the selected
-debugging device. This can aid debugging the kernel, since the
-messages can be captured and analyzed on some other machine. Which
-devices are possible depends on the machine type. There are no checks
-for the validity of the device name. If the device isn't implemented,
-nothing happens.
-
-Messages logged this way are in general stack dumps after kernel
-memory faults or bad kernel traps, and kernel panics. To be exact: all
-messages of level 0 (panic messages) and all messages printed while
-the log level is 8 or more (their level doesn't matter). Before stack
-dumps, the kernel sets the log level to 10 automatically. A level of
-at least 8 can also be set by the "debug" command line option (see
-2.3) and at run time with "dmesg -n 8".
-
-Devices possible for Amiga:
-
- - "ser":
-         built-in serial port; parameters: 9600bps, 8N1
- - "mem":
-         Save the messages to a reserved area in chip mem. After
-          rebooting, they can be read under AmigaOS with the tool
-          'dmesg'.
-
-Devices possible for Atari:
-
- - "ser1":
-          ST-MFP serial port ("Modem1"); parameters: 9600bps, 8N1
- - "ser2":
-          SCC channel B serial port ("Modem2"); parameters: 9600bps, 8N1
- - "ser" :
-          default serial port
-           This is "ser2" for a Falcon, and "ser1" for any other machine
- - "midi":
-          The MIDI port; parameters: 31250bps, 8N1
- - "par" :
-          parallel port
-
-           The printing routine for this implements a timeout for the
-           case there's no printer connected (else the kernel would
-           lock up). The timeout is not exact, but usually a few
-           seconds.
-
-
-2.6) ramdisk_size=
-------------------
-
-:Syntax: ramdisk_size=<size>
-
-This option instructs the kernel to set up a ramdisk of the given
-size in KBytes. Do not use this option if the ramdisk contents are
-passed by bootstrap! In this case, the size is selected automatically
-and should not be overwritten.
-
-The only application is for root filesystems on floppy disks, that
-should be loaded into memory. To do that, select the corresponding
-size of the disk as ramdisk size, and set the root device to the disk
-drive (with "root=").
-
-
-2.7) swap=
-
-  I can't find any sign of this option in 2.2.6.
-
-2.8) buff=
------------
-
-  I can't find any sign of this option in 2.2.6.
-
-
-3) General Device Options (Amiga and Atari)
-===========================================
-
-3.1) ether=
------------
-
-:Syntax: ether=[<irq>[,<base_addr>[,<mem_start>[,<mem_end>]]]],<dev-name>
-
-<dev-name> is the name of a net driver, as specified in
-drivers/net/Space.c in the Linux source. Most prominent are eth0, ...
-eth3, sl0, ... sl3, ppp0, ..., ppp3, dummy, and lo.
-
-The non-ethernet drivers (sl, ppp, dummy, lo) obviously ignore the
-settings by this options. Also, the existing ethernet drivers for
-Linux/m68k (ariadne, a2065, hydra) don't use them because Zorro boards
-are really Plug-'n-Play, so the "ether=" option is useless altogether
-for Linux/m68k.
-
-
-3.2) hd=
---------
-
-:Syntax: hd=<cylinders>,<heads>,<sectors>
-
-This option sets the disk geometry of an IDE disk. The first hd=
-option is for the first IDE disk, the second for the second one.
-(I.e., you can give this option twice.) In most cases, you won't have
-to use this option, since the kernel can obtain the geometry data
-itself. It exists just for the case that this fails for one of your
-disks.
-
-
-3.3) max_scsi_luns=
--------------------
-
-:Syntax: max_scsi_luns=<n>
-
-Sets the maximum number of LUNs (logical units) of SCSI devices to
-be scanned. Valid values for <n> are between 1 and 8. Default is 8 if
-"Probe all LUNs on each SCSI device" was selected during the kernel
-configuration, else 1.
-
-
-3.4) st=
---------
-
-:Syntax: st=<buffer_size>,[<write_thres>,[<max_buffers>]]
-
-Sets several parameters of the SCSI tape driver. <buffer_size> is
-the number of 512-byte buffers reserved for tape operations for each
-device. <write_thres> sets the number of blocks which must be filled
-to start an actual write operation to the tape. Maximum value is the
-total number of buffers. <max_buffer> limits the total number of
-buffers allocated for all tape devices.
-
-
-3.5) dmasound=
---------------
-
-:Syntax: dmasound=[<buffers>,<buffer-size>[,<catch-radius>]]
-
-This option controls some configurations of the Linux/m68k DMA sound
-driver (Amiga and Atari): <buffers> is the number of buffers you want
-to use (minimum 4, default 4), <buffer-size> is the size of each
-buffer in kilobytes (minimum 4, default 32) and <catch-radius> says
-how much percent of error will be tolerated when setting a frequency
-(maximum 10, default 0). For example with 3% you can play 8000Hz
-AU-Files on the Falcon with its hardware frequency of 8195Hz and thus
-don't need to expand the sound.
-
-
-
-4) Options for Atari Only
-=========================
-
-4.1) video=
------------
-
-:Syntax: video=<fbname>:<sub-options...>
-
-The <fbname> parameter specifies the name of the frame buffer,
-eg. most atari users will want to specify `atafb` here. The
-<sub-options> is a comma-separated list of the sub-options listed
-below.
-
-NB:
-    Please notice that this option was renamed from `atavideo` to
-    `video` during the development of the 1.3.x kernels, thus you
-    might need to update your boot-scripts if upgrading to 2.x from
-    an 1.2.x kernel.
-
-NBB:
-    The behavior of video= was changed in 2.1.57 so the recommended
-    option is to specify the name of the frame buffer.
-
-4.1.1) Video Mode
------------------
-
-This sub-option may be any of the predefined video modes, as listed
-in atari/atafb.c in the Linux/m68k source tree. The kernel will
-activate the given video mode at boot time and make it the default
-mode, if the hardware allows. Currently defined names are:
-
- - stlow           : 320x200x4
- - stmid, default5 : 640x200x2
- - sthigh, default4: 640x400x1
- - ttlow           : 320x480x8, TT only
- - ttmid, default1 : 640x480x4, TT only
- - tthigh, default2: 1280x960x1, TT only
- - vga2            : 640x480x1, Falcon only
- - vga4            : 640x480x2, Falcon only
- - vga16, default3 : 640x480x4, Falcon only
- - vga256          : 640x480x8, Falcon only
- - falh2           : 896x608x1, Falcon only
- - falh16          : 896x608x4, Falcon only
-
-If no video mode is given on the command line, the kernel tries the
-modes names "default<n>" in turn, until one is possible with the
-hardware in use.
-
-A video mode setting doesn't make sense, if the external driver is
-activated by a "external:" sub-option.
-
-4.1.2) inverse
---------------
-
-Invert the display. This affects only text consoles.
-Usually, the background is chosen to be black. With this
-option, you can make the background white.
-
-4.1.3) font
------------
-
-:Syntax: font:<fontname>
-
-Specify the font to use in text modes. Currently you can choose only
-between `VGA8x8`, `VGA8x16` and `PEARL8x8`. `VGA8x8` is default, if the
-vertical size of the display is less than 400 pixel rows. Otherwise, the
-`VGA8x16` font is the default.
-
-4.1.4) `hwscroll_`
-------------------
-
-:Syntax: `hwscroll_<n>`
-
-The number of additional lines of video memory to reserve for
-speeding up the scrolling ("hardware scrolling"). Hardware scrolling
-is possible only if the kernel can set the video base address in steps
-fine enough. This is true for STE, MegaSTE, TT, and Falcon. It is not
-possible with plain STs and graphics cards (The former because the
-base address must be on a 256 byte boundary there, the latter because
-the kernel doesn't know how to set the base address at all.)
-
-By default, <n> is set to the number of visible text lines on the
-display. Thus, the amount of video memory is doubled, compared to no
-hardware scrolling. You can turn off the hardware scrolling altogether
-by setting <n> to 0.
-
-4.1.5) internal:
-----------------
-
-:Syntax: internal:<xres>;<yres>[;<xres_max>;<yres_max>;<offset>]
-
-This option specifies the capabilities of some extended internal video
-hardware, like e.g. OverScan. <xres> and <yres> give the (extended)
-dimensions of the screen.
-
-If your OverScan needs a black border, you have to write the last
-three arguments of the "internal:". <xres_max> is the maximum line
-length the hardware allows, <yres_max> the maximum number of lines.
-<offset> is the offset of the visible part of the screen memory to its
-physical start, in bytes.
-
-Often, extended interval video hardware has to be activated somehow.
-For this, see the "sw_*" options below.
-
-4.1.6) external:
-----------------
-
-:Syntax:
-  external:<xres>;<yres>;<depth>;<org>;<scrmem>[;<scrlen>[;<vgabase>
-  [;<colw>[;<coltype>[;<xres_virtual>]]]]]
-
-.. I had to break this line...
-
-This is probably the most complicated parameter... It specifies that
-you have some external video hardware (a graphics board), and how to
-use it under Linux/m68k. The kernel cannot know more about the hardware
-than you tell it here! The kernel also is unable to set or change any
-video modes, since it doesn't know about any board internal. So, you
-have to switch to that video mode before you start Linux, and cannot
-switch to another mode once Linux has started.
-
-The first 3 parameters of this sub-option should be obvious: <xres>,
-<yres> and <depth> give the dimensions of the screen and the number of
-planes (depth). The depth is the logarithm to base 2 of the number
-of colors possible. (Or, the other way round: The number of colors is
-2^depth).
-
-You have to tell the kernel furthermore how the video memory is
-organized. This is done by a letter as <org> parameter:
-
- 'n':
-      "normal planes", i.e. one whole plane after another
- 'i':
-      "interleaved planes", i.e. 16 bit of the first plane, than 16 bit
-      of the next, and so on... This mode is used only with the
-      built-in Atari video modes, I think there is no card that
-      supports this mode.
- 'p':
-      "packed pixels", i.e. <depth> consecutive bits stand for all
-      planes of one pixel; this is the most common mode for 8 planes
-      (256 colors) on graphic cards
- 't':
-      "true color" (more or less packed pixels, but without a color
-      lookup table); usually depth is 24
-
-For monochrome modes (i.e., <depth> is 1), the <org> letter has a
-different meaning:
-
- 'n':
-      normal colors, i.e. 0=white, 1=black
- 'i':
-      inverted colors, i.e. 0=black, 1=white
-
-The next important information about the video hardware is the base
-address of the video memory. That is given in the <scrmem> parameter,
-as a hexadecimal number with a "0x" prefix. You have to find out this
-address in the documentation of your hardware.
-
-The next parameter, <scrlen>, tells the kernel about the size of the
-video memory. If it's missing, the size is calculated from <xres>,
-<yres>, and <depth>. For now, it is not useful to write a value here.
-It would be used only for hardware scrolling (which isn't possible
-with the external driver, because the kernel cannot set the video base
-address), or for virtual resolutions under X (which the X server
-doesn't support yet). So, it's currently best to leave this field
-empty, either by ending the "external:" after the video address or by
-writing two consecutive semicolons, if you want to give a <vgabase>
-(it is allowed to leave this parameter empty).
-
-The <vgabase> parameter is optional. If it is not given, the kernel
-cannot read or write any color registers of the video hardware, and
-thus you have to set appropriate colors before you start Linux. But if
-your card is somehow VGA compatible, you can tell the kernel the base
-address of the VGA register set, so it can change the color lookup
-table. You have to look up this address in your board's documentation.
-To avoid misunderstandings: <vgabase> is the _base_ address, i.e. a 4k
-aligned address. For read/writing the color registers, the kernel
-uses the addresses vgabase+0x3c7...vgabase+0x3c9. The <vgabase>
-parameter is written in hexadecimal with a "0x" prefix, just as
-<scrmem>.
-
-<colw> is meaningful only if <vgabase> is specified. It tells the
-kernel how wide each of the color register is, i.e. the number of bits
-per single color (red/green/blue). Default is 6, another quite usual
-value is 8.
-
-Also <coltype> is used together with <vgabase>. It tells the kernel
-about the color register model of your gfx board. Currently, the types
-"vga" (which is also the default) and "mv300" (SANG MV300) are
-implemented.
-
-Parameter <xres_virtual> is required for ProMST or ET4000 cards where
-the physical linelength differs from the visible length. With ProMST,
-xres_virtual must be set to 2048. For ET4000, xres_virtual depends on the
-initialisation of the video-card.
-If you're missing a corresponding yres_virtual: the external part is legacy,
-therefore we don't support hardware-dependent functions like hardware-scroll,
-panning or blanking.
-
-4.1.7) eclock:
---------------
-
-The external pixel clock attached to the Falcon VIDEL shifter. This
-currently works only with the ScreenWonder!
-
-4.1.8) monitorcap:
--------------------
-
-:Syntax: monitorcap:<vmin>;<vmax>;<hmin>;<hmax>
-
-This describes the capabilities of a multisync monitor. Don't use it
-with a fixed-frequency monitor! For now, only the Falcon frame buffer
-uses the settings of "monitorcap:".
-
-<vmin> and <vmax> are the minimum and maximum, resp., vertical frequencies
-your monitor can work with, in Hz. <hmin> and <hmax> are the same for
-the horizontal frequency, in kHz.
-
-  The defaults are 58;62;31;32 (VGA compatible).
-
-  The defaults for TV/SC1224/SC1435 cover both PAL and NTSC standards.
-
-4.1.9) keep
-------------
-
-If this option is given, the framebuffer device doesn't do any video
-mode calculations and settings on its own. The only Atari fb device
-that does this currently is the Falcon.
-
-What you reach with this: Settings for unknown video extensions
-aren't overridden by the driver, so you can still use the mode found
-when booting, when the driver doesn't know to set this mode itself.
-But this also means, that you can't switch video modes anymore...
-
-An example where you may want to use "keep" is the ScreenBlaster for
-the Falcon.
-
-
-4.2) atamouse=
---------------
-
-:Syntax: atamouse=<x-threshold>,[<y-threshold>]
-
-With this option, you can set the mouse movement reporting threshold.
-This is the number of pixels of mouse movement that have to accumulate
-before the IKBD sends a new mouse packet to the kernel. Higher values
-reduce the mouse interrupt load and thus reduce the chance of keyboard
-overruns. Lower values give a slightly faster mouse responses and
-slightly better mouse tracking.
-
-You can set the threshold in x and y separately, but usually this is
-of little practical use. If there's just one number in the option, it
-is used for both dimensions. The default value is 2 for both
-thresholds.
-
-
-4.3) ataflop=
--------------
-
-:Syntax: ataflop=<drive type>[,<trackbuffering>[,<steprateA>[,<steprateB>]]]
-
-   The drive type may be 0, 1, or 2, for DD, HD, and ED, resp. This
-   setting affects how many buffers are reserved and which formats are
-   probed (see also below). The default is 1 (HD). Only one drive type
-   can be selected. If you have two disk drives, select the "better"
-   type.
-
-   The second parameter <trackbuffer> tells the kernel whether to use
-   track buffering (1) or not (0). The default is machine-dependent:
-   no for the Medusa and yes for all others.
-
-   With the two following parameters, you can change the default
-   steprate used for drive A and B, resp.
-
-
-4.4) atascsi=
--------------
-
-:Syntax: atascsi=<can_queue>[,<cmd_per_lun>[,<scat-gat>[,<host-id>[,<tagged>]]]]
-
-This option sets some parameters for the Atari native SCSI driver.
-Generally, any number of arguments can be omitted from the end. And
-for each of the numbers, a negative value means "use default". The
-defaults depend on whether TT-style or Falcon-style SCSI is used.
-Below, defaults are noted as n/m, where the first value refers to
-TT-SCSI and the latter to Falcon-SCSI. If an illegal value is given
-for one parameter, an error message is printed and that one setting is
-ignored (others aren't affected).
-
-  <can_queue>:
-    This is the maximum number of SCSI commands queued internally to the
-    Atari SCSI driver. A value of 1 effectively turns off the driver
-    internal multitasking (if it causes problems). Legal values are >=
-    1. <can_queue> can be as high as you like, but values greater than
-    <cmd_per_lun> times the number of SCSI targets (LUNs) you have
-    don't make sense. Default: 16/8.
-
-  <cmd_per_lun>:
-    Maximum number of SCSI commands issued to the driver for one
-    logical unit (LUN, usually one SCSI target). Legal values start
-    from 1. If tagged queuing (see below) is not used, values greater
-    than 2 don't make sense, but waste memory. Otherwise, the maximum
-    is the number of command tags available to the driver (currently
-    32). Default: 8/1. (Note: Values > 1 seem to cause problems on a
-    Falcon, cause not yet known.)
-
-    The <cmd_per_lun> value at a great part determines the amount of
-    memory SCSI reserves for itself. The formula is rather
-    complicated, but I can give you some hints:
-
-      no scatter-gather:
-       cmd_per_lun * 232 bytes
-      full scatter-gather:
-       cmd_per_lun * approx. 17 Kbytes
-
-  <scat-gat>:
-    Size of the scatter-gather table, i.e. the number of requests
-    consecutive on the disk that can be merged into one SCSI command.
-    Legal values are between 0 and 255. Default: 255/0. Note: This
-    value is forced to 0 on a Falcon, since scatter-gather isn't
-    possible with the ST-DMA. Not using scatter-gather hurts
-    performance significantly.
-
-  <host-id>:
-    The SCSI ID to be used by the initiator (your Atari). This is
-    usually 7, the highest possible ID. Every ID on the SCSI bus must
-    be unique. Default: determined at run time: If the NV-RAM checksum
-    is valid, and bit 7 in byte 30 of the NV-RAM is set, the lower 3
-    bits of this byte are used as the host ID. (This method is defined
-    by Atari and also used by some TOS HD drivers.) If the above
-    isn't given, the default ID is 7. (both, TT and Falcon).
-
-  <tagged>:
-    0 means turn off tagged queuing support, all other values > 0 mean
-    use tagged queuing for targets that support it. Default: currently
-    off, but this may change when tagged queuing handling has been
-    proved to be reliable.
-
-    Tagged queuing means that more than one command can be issued to
-    one LUN, and the SCSI device itself orders the requests so they
-    can be performed in optimal order. Not all SCSI devices support
-    tagged queuing (:-().
-
-4.5 switches=
--------------
-
-:Syntax: switches=<list of switches>
-
-With this option you can switch some hardware lines that are often
-used to enable/disable certain hardware extensions. Examples are
-OverScan, overclocking, ...
-
-The <list of switches> is a comma-separated list of the following
-items:
-
-  ikbd:
-       set RTS of the keyboard ACIA high
-  midi:
-       set RTS of the MIDI ACIA high
-  snd6:
-       set bit 6 of the PSG port A
-  snd7:
-       set bit 6 of the PSG port A
-
-It doesn't make sense to mention a switch more than once (no
-difference to only once), but you can give as many switches as you
-want to enable different features. The switch lines are set as early
-as possible during kernel initialization (even before determining the
-present hardware.)
-
-All of the items can also be prefixed with `ov_`, i.e. `ov_ikbd`,
-`ov_midi`, ... These options are meant for switching on an OverScan
-video extension. The difference to the bare option is that the
-switch-on is done after video initialization, and somehow synchronized
-to the HBLANK. A speciality is that ov_ikbd and ov_midi are switched
-off before rebooting, so that OverScan is disabled and TOS boots
-correctly.
-
-If you give an option both, with and without the `ov_` prefix, the
-earlier initialization (`ov_`-less) takes precedence. But the
-switching-off on reset still happens in this case.
-
-5) Options for Amiga Only:
-==========================
-
-5.1) video=
------------
-
-:Syntax: video=<fbname>:<sub-options...>
-
-The <fbname> parameter specifies the name of the frame buffer, valid
-options are `amifb`, `cyber`, 'virge', `retz3` and `clgen`, provided
-that the respective frame buffer devices have been compiled into the
-kernel (or compiled as loadable modules). The behavior of the <fbname>
-option was changed in 2.1.57 so it is now recommended to specify this
-option.
-
-The <sub-options> is a comma-separated list of the sub-options listed
-below. This option is organized similar to the Atari version of the
-"video"-option (4.1), but knows fewer sub-options.
-
-5.1.1) video mode
------------------
-
-Again, similar to the video mode for the Atari (see 4.1.1). Predefined
-modes depend on the used frame buffer device.
-
-OCS, ECS and AGA machines all use the color frame buffer. The following
-predefined video modes are available:
-
-NTSC modes:
- - ntsc            : 640x200, 15 kHz, 60 Hz
- - ntsc-lace       : 640x400, 15 kHz, 60 Hz interlaced
-
-PAL modes:
- - pal             : 640x256, 15 kHz, 50 Hz
- - pal-lace        : 640x512, 15 kHz, 50 Hz interlaced
-
-ECS modes:
- - multiscan       : 640x480, 29 kHz, 57 Hz
- - multiscan-lace  : 640x960, 29 kHz, 57 Hz interlaced
- - euro36          : 640x200, 15 kHz, 72 Hz
- - euro36-lace     : 640x400, 15 kHz, 72 Hz interlaced
- - euro72          : 640x400, 29 kHz, 68 Hz
- - euro72-lace     : 640x800, 29 kHz, 68 Hz interlaced
- - super72         : 800x300, 23 kHz, 70 Hz
- - super72-lace    : 800x600, 23 kHz, 70 Hz interlaced
- - dblntsc-ff      : 640x400, 27 kHz, 57 Hz
- - dblntsc-lace    : 640x800, 27 kHz, 57 Hz interlaced
- - dblpal-ff       : 640x512, 27 kHz, 47 Hz
- - dblpal-lace     : 640x1024, 27 kHz, 47 Hz interlaced
- - dblntsc         : 640x200, 27 kHz, 57 Hz doublescan
- - dblpal          : 640x256, 27 kHz, 47 Hz doublescan
-
-VGA modes:
- - vga             : 640x480, 31 kHz, 60 Hz
- - vga70           : 640x400, 31 kHz, 70 Hz
-
-Please notice that the ECS and VGA modes require either an ECS or AGA
-chipset, and that these modes are limited to 2-bit color for the ECS
-chipset and 8-bit color for the AGA chipset.
-
-5.1.2) depth
-------------
-
-:Syntax: depth:<nr. of bit-planes>
-
-Specify the number of bit-planes for the selected video-mode.
-
-5.1.3) inverse
---------------
-
-Use inverted display (black on white). Functionally the same as the
-"inverse" sub-option for the Atari.
-
-5.1.4) font
------------
-
-:Syntax: font:<fontname>
-
-Specify the font to use in text modes. Functionally the same as the
-"font" sub-option for the Atari, except that `PEARL8x8` is used instead
-of `VGA8x8` if the vertical size of the display is less than 400 pixel
-rows.
-
-5.1.5) monitorcap:
--------------------
-
-:Syntax: monitorcap:<vmin>;<vmax>;<hmin>;<hmax>
-
-This describes the capabilities of a multisync monitor. For now, only
-the color frame buffer uses the settings of "monitorcap:".
-
-<vmin> and <vmax> are the minimum and maximum, resp., vertical frequencies
-your monitor can work with, in Hz. <hmin> and <hmax> are the same for
-the horizontal frequency, in kHz.
-
-The defaults are 50;90;15;38 (Generic Amiga multisync monitor).
-
-
-5.2) fd_def_df0=
-----------------
-
-:Syntax: fd_def_df0=<value>
-
-Sets the df0 value for "silent" floppy drives. The value should be in
-hexadecimal with "0x" prefix.
-
-
-5.3) wd33c93=
--------------
-
-:Syntax: wd33c93=<sub-options...>
-
-These options affect the A590/A2091, A3000 and GVP Series II SCSI
-controllers.
-
-The <sub-options> is a comma-separated list of the sub-options listed
-below.
-
-5.3.1) nosync
--------------
-
-:Syntax: nosync:bitmask
-
-bitmask is a byte where the 1st 7 bits correspond with the 7
-possible SCSI devices. Set a bit to prevent sync negotiation on that
-device. To maintain backwards compatibility, a command-line such as
-"wd33c93=255" will be automatically translated to
-"wd33c93=nosync:0xff". The default is to disable sync negotiation for
-all devices, eg. nosync:0xff.
-
-5.3.2) period
--------------
-
-:Syntax: period:ns
-
-`ns` is the minimum # of nanoseconds in a SCSI data transfer
-period. Default is 500; acceptable values are 250 - 1000.
-
-5.3.3) disconnect
------------------
-
-:Syntax: disconnect:x
-
-Specify x = 0 to never allow disconnects, 2 to always allow them.
-x = 1 does 'adaptive' disconnects, which is the default and generally
-the best choice.
-
-5.3.4) debug
-------------
-
-:Syntax: debug:x
-
-If `DEBUGGING_ON` is defined, x is a bit mask that causes various
-types of debug output to printed - see the DB_xxx defines in
-wd33c93.h.
-
-5.3.5) clock
-------------
-
-:Syntax: clock:x
-
-x = clock input in MHz for WD33c93 chip. Normal values would be from
-8 through 20. The default value depends on your hostadapter(s),
-default for the A3000 internal controller is 14, for the A2091 it's 8
-and for the GVP hostadapters it's either 8 or 14, depending on the
-hostadapter and the SCSI-clock jumper present on some GVP
-hostadapters.
-
-5.3.6) next
------------
-
-No argument. Used to separate blocks of keywords when there's more
-than one wd33c93-based host adapter in the system.
-
-5.3.7) nodma
-------------
-
-:Syntax: nodma:x
-
-If x is 1 (or if the option is just written as "nodma"), the WD33c93
-controller will not use DMA (= direct memory access) to access the
-Amiga's memory.  This is useful for some systems (like A3000's and
-A4000's with the A3640 accelerator, revision 3.0) that have problems
-using DMA to chip memory.  The default is 0, i.e. to use DMA if
-possible.
-
-
-5.4) gvp11=
------------
-
-:Syntax: gvp11=<addr-mask>
-
-The earlier versions of the GVP driver did not handle DMA
-address-mask settings correctly which made it necessary for some
-people to use this option, in order to get their GVP controller
-running under Linux. These problems have hopefully been solved and the
-use of this option is now highly unrecommended!
-
-Incorrect use can lead to unpredictable behavior, so please only use
-this option if you *know* what you are doing and have a reason to do
-so. In any case if you experience problems and need to use this
-option, please inform us about it by mailing to the Linux/68k kernel
-mailing list.
-
-The address mask set by this option specifies which addresses are
-valid for DMA with the GVP Series II SCSI controller. An address is
-valid, if no bits are set except the bits that are set in the mask,
-too.
-
-Some versions of the GVP can only DMA into a 24 bit address range,
-some can address a 25 bit address range while others can use the whole
-32 bit address range for DMA. The correct setting depends on your
-controller and should be autodetected by the driver. An example is the
-24 bit region which is specified by a mask of 0x00fffffe.
index 09f988e7fa719e62a598e1846f112db002a851eb..85800ce95ae5fccc4452626a1fada16d8961b84a 100644 (file)
@@ -213,11 +213,7 @@ point rather than some random spot.  If your upstream-bound branch has
 emptied entirely into the mainline during the merge window, you can pull it
 forward with a command like::
 
-  git merge v5.2-rc1^0
-
-The "^0" will cause Git to do a fast-forward merge (which should be
-possible in this situation), thus avoiding the addition of a spurious merge
-commit.
+  git merge --ff-only v5.2-rc1
 
 The guidelines laid out above are just that: guidelines.  There will always
 be situations that call out for a different solution, and these guidelines
index 3d05d64de9b463ac1caa68c5d1d46487ab9f75bc..d9c2b0f01dcd0fc1a71c029c98ecdbbd9c790311 100644 (file)
@@ -5,10 +5,10 @@ Hugetlbfs Reservation
 Overview
 ========
 
-Huge pages as described at Documentation/mm/hugetlbpage.rst are typically
-preallocated for application use.  These huge pages are instantiated in a
-task's address space at page fault time if the VMA indicates huge pages are
-to be used.  If no huge page exists at page fault time, the task is sent
+Huge pages as described at Documentation/admin-guide/mm/hugetlbpage.rst are
+typically preallocated for application use.  These huge pages are instantiated
+in a task's address space at page fault time if the VMA indicates huge pages
+are to be used.  If no huge page exists at page fault time, the task is sent
 a SIGBUS and often dies an unhappy death.  Shortly after huge page support
 was added, it was determined that it would be better to detect a shortage
 of huge pages at mmap() time.  The idea is that if there were not enough
index f9d7ea4b9dca7fd6b81fba0d653186e88d0c607b..531e73b003ddd0f33275eebe522efa72d5e41655 100644 (file)
@@ -19,7 +19,7 @@ a bank of memory very suitable for DMA near peripheral devices.
 
 Each bank is called a node and the concept is represented under Linux by a
 ``struct pglist_data`` even if the architecture is UMA. This structure is
-always referenced to by it's typedef ``pg_data_t``. ``A pg_data_t`` structure
+always referenced by its typedef ``pg_data_t``. A ``pg_data_t`` structure
 for a particular node can be referenced by ``NODE_DATA(nid)`` macro where
 ``nid`` is the ID of that node.
 
@@ -66,7 +66,7 @@ one of the types described below.
   also populated on boot using one of ``kernelcore``, ``movablecore`` and
   ``movable_node`` kernel command line parameters. See
   Documentation/mm/page_migration.rst and
-  Documentation/admin-guide/mm/memory_hotplug.rst for additional details.
+  Documentation/admin-guide/mm/memory-hotplug.rst for additional details.
 
 * ``ZONE_DEVICE`` represents memory residing on devices such as PMEM and GPU.
   It has different characteristics than RAM zone types and it exists to provide
@@ -114,6 +114,25 @@ RAM equally split between two nodes, there will be ``ZONE_DMA32``,
   |  DMA32  |  NORMAL  |  MOVABLE  | |   NORMAL   |   MOVABLE   |
   +---------+----------+-----------+ +------------+-------------+
 
+
+Memory banks may belong to interleaving nodes. In the example below an x86
+machine has 16 Gbytes of RAM in 4 memory banks, even banks belong to node 0
+and odd banks belong to node 1::
+
+
+  0              4G              8G             12G            16G
+  +-------------+ +-------------+ +-------------+ +-------------+
+  |    node 0   | |    node 1   | |    node 0   | |    node 1   |
+  +-------------+ +-------------+ +-------------+ +-------------+
+
+  0   16M      4G
+  +-----+-------+ +-------------+ +-------------+ +-------------+
+  | DMA | DMA32 | |    NORMAL   | |    NORMAL   | |    NORMAL   |
+  +-----+-------+ +-------------+ +-------------+ +-------------+
+
+In this case node 0 will span from 0 to 12 Gbytes and node 1 will span from
+4 to 16 Gbytes.
+
 .. _nodes:
 
 Nodes
index 64d127bfc221fe243bbfb6e6758a547c6877585a..a3c26d587752fe04f34739f266c5f5416d431c9b 100644 (file)
@@ -39,13 +39,12 @@ With CONFIG_ZSMALLOC_STAT, we could see zsmalloc internal information via
 
  # cat /sys/kernel/debug/zsmalloc/zram0/classes
 
- class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage
+ class  size       10%       20%       30%       40%       50%       60%       70%       80%       90%       99%      100% obj_allocated   obj_used pages_used pages_per_zspage freeable
     ...
     ...
-     9   176           0            1           186        129          8                4
-    10   192           1            0          2880       2872        135                3
-    11   208           0            1           819        795         42                2
-    12   224           0            1           219        159         12                4
+    30   512         0        12         4         1         0         1         0         0         1         0       414          3464       3346        433                1       14
+    31   528         2         7         2         2         1         0         1         0         0         2       117          4154       3793        536                4       44
+    32   544         6         3         4         1         2         1         0         0         0         1       260          4170       3965        556                2       26
     ...
     ...
 
@@ -54,10 +53,28 @@ class
        index
 size
        object size zspage stores
-almost_empty
-       the number of ZS_ALMOST_EMPTY zspages(see below)
-almost_full
-       the number of ZS_ALMOST_FULL zspages(see below)
+10%
+       the number of zspages with usage ratio less than 10% (see below)
+20%
+       the number of zspages with usage ratio between 10% and 20%
+30%
+       the number of zspages with usage ratio between 20% and 30%
+40%
+       the number of zspages with usage ratio between 30% and 40%
+50%
+       the number of zspages with usage ratio between 40% and 50%
+60%
+       the number of zspages with usage ratio between 50% and 60%
+70%
+       the number of zspages with usage ratio between 60% and 70%
+80%
+       the number of zspages with usage ratio between 70% and 80%
+90%
+       the number of zspages with usage ratio between 80% and 90%
+99%
+       the number of zspages with usage ratio between 90% and 99%
+100%
+       the number of zspages with usage ratio 100%
 obj_allocated
        the number of objects allocated
 obj_used
@@ -66,19 +83,14 @@ pages_used
        the number of pages allocated for the class
 pages_per_zspage
        the number of 0-order pages to make a zspage
+freeable
+       the approximate number of pages class compaction can free
 
-We assign a zspage to ZS_ALMOST_EMPTY fullness group when n <= N / f, where
-
-* n = number of allocated objects
-* N = total number of objects zspage can store
-* f = fullness_threshold_frac(ie, 4 at the moment)
-
-Similarly, we assign zspage to:
-
-* ZS_ALMOST_FULL  when n > N / f
-* ZS_EMPTY        when n == 0
-* ZS_FULL         when n == N
-
+Each zspage maintains inuse counter which keeps track of the number of
+objects stored in the zspage.  The inuse counter determines the zspage's
+"fullness group" which is calculated as the ratio of the "inuse" objects to
+the total number of objects the zspage can hold (objs_per_zspage). The
+closer the inuse counter is to objs_per_zspage, the better.
 
 Internals
 =========
@@ -94,10 +106,10 @@ of objects that each zspage can store.
 
 For instance, consider the following size classes:::
 
-  class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage freeable
+  class  size       10%   ....    100% obj_allocated   obj_used pages_used pages_per_zspage freeable
   ...
-     94  1536           0            0             0          0          0                3        0
-    100  1632           0            0             0          0          0                2        0
+     94  1536        0    ....       0             0          0          0                3        0
+    100  1632        0    ....       0             0          0          0                2        0
   ...
 
 
@@ -134,10 +146,11 @@ reduces memory wastage.
 
 Let's take a closer look at the bottom of `/sys/kernel/debug/zsmalloc/zramX/classes`:::
 
-  class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage freeable
+  class  size       10%   ....    100% obj_allocated   obj_used pages_used pages_per_zspage freeable
+
   ...
-    202  3264           0            0             0          0          0                4        0
-    254  4096           0            0             0          0          0                1        0
+    202  3264         0   ..         0             0          0          0                4        0
+    254  4096         0   ..         0             0          0          0                1        0
   ...
 
 Size class #202 stores objects of size 3264 bytes and has a maximum of 4 pages
@@ -151,40 +164,42 @@ efficient storage of large objects.
 
 For zspage chain size of 8, huge class watermark becomes 3632 bytes:::
 
-  class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage freeable
+  class  size       10%   ....    100% obj_allocated   obj_used pages_used pages_per_zspage freeable
+
   ...
-    202  3264           0            0             0          0          0                4        0
-    211  3408           0            0             0          0          0                5        0
-    217  3504           0            0             0          0          0                6        0
-    222  3584           0            0             0          0          0                7        0
-    225  3632           0            0             0          0          0                8        0
-    254  4096           0            0             0          0          0                1        0
+    202  3264         0   ..         0             0          0          0                4        0
+    211  3408         0   ..         0             0          0          0                5        0
+    217  3504         0   ..         0             0          0          0                6        0
+    222  3584         0   ..         0             0          0          0                7        0
+    225  3632         0   ..         0             0          0          0                8        0
+    254  4096         0   ..         0             0          0          0                1        0
   ...
 
 For zspage chain size of 16, huge class watermark becomes 3840 bytes:::
 
-  class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage freeable
+  class  size       10%   ....    100% obj_allocated   obj_used pages_used pages_per_zspage freeable
+
   ...
-    202  3264           0            0             0          0          0                4        0
-    206  3328           0            0             0          0          0               13        0
-    207  3344           0            0             0          0          0                9        0
-    208  3360           0            0             0          0          0               14        0
-    211  3408           0            0             0          0          0                5        0
-    212  3424           0            0             0          0          0               16        0
-    214  3456           0            0             0          0          0               11        0
-    217  3504           0            0             0          0          0                6        0
-    219  3536           0            0             0          0          0               13        0
-    222  3584           0            0             0          0          0                7        0
-    223  3600           0            0             0          0          0               15        0
-    225  3632           0            0             0          0          0                8        0
-    228  3680           0            0             0          0          0                9        0
-    230  3712           0            0             0          0          0               10        0
-    232  3744           0            0             0          0          0               11        0
-    234  3776           0            0             0          0          0               12        0
-    235  3792           0            0             0          0          0               13        0
-    236  3808           0            0             0          0          0               14        0
-    238  3840           0            0             0          0          0               15        0
-    254  4096           0            0             0          0          0                1        0
+    202  3264         0   ..         0             0          0          0                4        0
+    206  3328         0   ..         0             0          0          0               13        0
+    207  3344         0   ..         0             0          0          0                9        0
+    208  3360         0   ..         0             0          0          0               14        0
+    211  3408         0   ..         0             0          0          0                5        0
+    212  3424         0   ..         0             0          0          0               16        0
+    214  3456         0   ..         0             0          0          0               11        0
+    217  3504         0   ..         0             0          0          0                6        0
+    219  3536         0   ..         0             0          0          0               13        0
+    222  3584         0   ..         0             0          0          0                7        0
+    223  3600         0   ..         0             0          0          0               15        0
+    225  3632         0   ..         0             0          0          0                8        0
+    228  3680         0   ..         0             0          0          0                9        0
+    230  3712         0   ..         0             0          0          0               10        0
+    232  3744         0   ..         0             0          0          0               11        0
+    234  3776         0   ..         0             0          0          0               12        0
+    235  3792         0   ..         0             0          0          0               13        0
+    236  3808         0   ..         0             0          0          0               14        0
+    238  3840         0   ..         0             0          0          0               15        0
+    254  4096         0   ..         0             0          0          0                1        0
   ...
 
 Overall the combined zspage chain size effect on zsmalloc pool configuration:::
@@ -214,9 +229,10 @@ zram as a build artifacts storage (Linux kernel compilation).
 
   zsmalloc classes stats:::
 
-    class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage freeable
+    class  size       10%   ....    100% obj_allocated   obj_used pages_used pages_per_zspage freeable
+
     ...
-    Total                13           51        413836     412973     159955                         3
+    Total              13   ..        51        413836     412973     159955                         3
 
   zram mm_stat:::
 
@@ -227,9 +243,10 @@ zram as a build artifacts storage (Linux kernel compilation).
 
   zsmalloc classes stats:::
 
-    class  size almost_full almost_empty obj_allocated   obj_used pages_used pages_per_zspage freeable
+    class  size       10%   ....    100% obj_allocated   obj_used pages_used pages_per_zspage freeable
+
     ...
-    Total                18           87        414852     412978     156666                         0
+    Total              18   ..        87        414852     412978     156666                         0
 
   zram mm_stat:::
 
index f082a5ad7cf1d47d127086111de8f6b1a8ac5acc..5c3642b3f802df5363d453350f421a37cc23ad25 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 %YAML 1.2
 ---
 $id: http://kernel.org/schemas/netlink/genetlink-c.yaml#
index c6b8c77f7d12e82f1ccd4f106a9ee2df34e5f5ff..5e98c6d2b9aae89e9a6b8f0111552e65709ab7ef 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 %YAML 1.2
 ---
 $id: http://kernel.org/schemas/netlink/genetlink-legacy.yaml#
index b2d56ab9e615d3262c1a2b757c465f1d5b41b007..d35dcd6f8d82a784414e3521945cff3b42644a49 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 %YAML 1.2
 ---
 $id: http://kernel.org/schemas/netlink/genetlink-legacy.yaml#
index 18ecb7d90cbe5f3baf464987be6eb09d3f8ae948..4727c067e2ba361ef1271a5afaac0307b10e744f 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 
 name: ethtool
 
index cff104288723bb9dfb723c0a47a038b10b9db6d6..3e13826a3fdf18c746c59ae35f9c48af434488de 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 
 name: fou
 
index 24de747b53443158fc8adab3816219dcd3e82ec7..b99e7ffef7a1578f837e96047ddd0e4967adbed8 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 
 name: netdev
 
@@ -9,6 +9,7 @@ definitions:
   -
     type: flags
     name: xdp-act
+    render-max: true
     entries:
       -
         name: basic
index 10f282c2117c6ca122ad509ba672976386b42fd4..2f60e34ab9267bca2b8c217399e205bcce91cea3 100644 (file)
@@ -7,6 +7,21 @@ ice devlink support
 This document describes the devlink features implemented by the ``ice``
 device driver.
 
+Parameters
+==========
+
+.. list-table:: Generic parameters implemented
+
+   * - Name
+     - Mode
+     - Notes
+   * - ``enable_roce``
+     - runtime
+     - mutually exclusive with ``enable_iwarp``
+   * - ``enable_iwarp``
+     - runtime
+     - mutually exclusive with ``enable_roce``
+
 Info versions
 =============
 
index 87dd1c5283e61c03b9508a2d3e77bd82722ed176..58a78a3166978bd6957e043511e95e455e018f1d 100644 (file)
@@ -340,6 +340,8 @@ tcp_app_win - INTEGER
        Reserve max(window/2^tcp_app_win, mss) of window for application
        buffer. Value 0 is special, it means that nothing is reserved.
 
+       Possible values are [0, 31], inclusive.
+
        Default: 31
 
 tcp_autocorking - BOOLEAN
index aac63fc2d08bd104634315d422d33f24717de4aa..25ce72af81c216322edfe56da3195fdd13a47db8 100644 (file)
@@ -23,10 +23,13 @@ metadata is supported, this set will grow:
 An XDP program can use these kfuncs to read the metadata into stack
 variables for its own consumption. Or, to pass the metadata on to other
 consumers, an XDP program can store it into the metadata area carried
-ahead of the packet.
+ahead of the packet. Not all packets will necessary have the requested
+metadata available in which case the driver returns ``-ENODATA``.
 
 Not all kfuncs have to be implemented by the device driver; when not
-implemented, the default ones that return ``-EOPNOTSUPP`` will be used.
+implemented, the default ones that return ``-EOPNOTSUPP`` will be used
+to indicate the device driver have not implemented this kfunc.
+
 
 Within an XDP frame, the metadata layout (accessed via ``xdp_buff``) is
 as follows::
diff --git a/Documentation/nios2/features.rst b/Documentation/nios2/features.rst
deleted file mode 100644 (file)
index 8449e63..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features nios2
diff --git a/Documentation/nios2/index.rst b/Documentation/nios2/index.rst
deleted file mode 100644 (file)
index 4468fe1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==============================
-Nios II Specific Documentation
-==============================
-
-.. toctree::
-   :maxdepth: 2
-   :numbered:
-
-   nios2
-   features
diff --git a/Documentation/nios2/nios2.rst b/Documentation/nios2/nios2.rst
deleted file mode 100644 (file)
index 43da3f7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-=================================
-Linux on the Nios II architecture
-=================================
-
-This is a port of Linux to Nios II (nios2) processor.
-
-In order to compile for Nios II, you need a version of GCC with support for the generic
-system call ABI. Please see this link for more information on how compiling and booting
-software for the Nios II platform:
-http://www.rocketboards.org/foswiki/Documentation/NiosIILinuxUserManual
-
-For reference, please see the following link:
-http://www.altera.com/literature/lit-nio2.jsp
-
-What is Nios II?
-================
-Nios II is a 32-bit embedded-processor architecture designed specifically for the
-Altera family of FPGAs. In order to support Linux, Nios II needs to be configured
-with MMU and hardware multiplier enabled.
-
-Nios II ABI
-===========
-Please refer to chapter "Application Binary Interface" in Nios II Processor Reference
-Handbook.
diff --git a/Documentation/openrisc/features.rst b/Documentation/openrisc/features.rst
deleted file mode 100644 (file)
index 3f7c40d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features openrisc
diff --git a/Documentation/openrisc/index.rst b/Documentation/openrisc/index.rst
deleted file mode 100644 (file)
index 6879f99..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=====================
-OpenRISC Architecture
-=====================
-
-.. toctree::
-   :maxdepth: 2
-
-   openrisc_port
-   todo
-
-   features
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/openrisc/openrisc_port.rst b/Documentation/openrisc/openrisc_port.rst
deleted file mode 100644 (file)
index 657ac4a..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-==============
-OpenRISC Linux
-==============
-
-This is a port of Linux to the OpenRISC class of microprocessors; the initial
-target architecture, specifically, is the 32-bit OpenRISC 1000 family (or1k).
-
-For information about OpenRISC processors and ongoing development:
-
-       =======         =============================
-       website         https://openrisc.io
-       email           openrisc@lists.librecores.org
-       =======         =============================
-
----------------------------------------------------------------------
-
-Build instructions for OpenRISC toolchain and Linux
-===================================================
-
-In order to build and run Linux for OpenRISC, you'll need at least a basic
-toolchain and, perhaps, the architectural simulator.  Steps to get these bits
-in place are outlined here.
-
-1) Toolchain
-
-Toolchain binaries can be obtained from openrisc.io or our github releases page.
-Instructions for building the different toolchains can be found on openrisc.io
-or Stafford's toolchain build and release scripts.
-
-       ==========      =================================================
-       binaries        https://github.com/openrisc/or1k-gcc/releases
-       toolchains      https://openrisc.io/software
-       building        https://github.com/stffrdhrn/or1k-toolchain-build
-       ==========      =================================================
-
-2) Building
-
-Build the Linux kernel as usual::
-
-       make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig
-       make ARCH=openrisc CROSS_COMPILE="or1k-linux-"
-
-3) Running on FPGA (optional)
-
-The OpenRISC community typically uses FuseSoC to manage building and programming
-an SoC into an FPGA.  The below is an example of programming a De0 Nano
-development board with the OpenRISC SoC.  During the build FPGA RTL is code
-downloaded from the FuseSoC IP cores repository and built using the FPGA vendor
-tools.  Binaries are loaded onto the board with openocd.
-
-::
-
-       git clone https://github.com/olofk/fusesoc
-       cd fusesoc
-       sudo pip install -e .
-
-       fusesoc init
-       fusesoc build de0_nano
-       fusesoc pgm de0_nano
-
-       openocd -f interface/altera-usb-blaster.cfg \
-               -f board/or1k_generic.cfg
-
-       telnet localhost 4444
-       > init
-       > halt; load_image vmlinux ; reset
-
-4) Running on a Simulator (optional)
-
-QEMU is a processor emulator which we recommend for simulating the OpenRISC
-platform.  Please follow the OpenRISC instructions on the QEMU website to get
-Linux running on QEMU.  You can build QEMU yourself, but your Linux distribution
-likely provides binary packages to support OpenRISC.
-
-       =============   ======================================================
-       qemu openrisc   https://wiki.qemu.org/Documentation/Platforms/OpenRISC
-       =============   ======================================================
-
----------------------------------------------------------------------
-
-Terminology
-===========
-
-In the code, the following particles are used on symbols to limit the scope
-to more or less specific processor implementations:
-
-========= =======================================
-openrisc: the OpenRISC class of processors
-or1k:     the OpenRISC 1000 family of processors
-or1200:   the OpenRISC 1200 processor
-========= =======================================
-
----------------------------------------------------------------------
-
-History
-========
-
-18-11-2003     Matjaz Breskvar (phoenix@bsemi.com)
-       initial port of linux to OpenRISC/or32 architecture.
-        all the core stuff is implemented and seams usable.
-
-08-12-2003     Matjaz Breskvar (phoenix@bsemi.com)
-       complete change of TLB miss handling.
-       rewrite of exceptions handling.
-       fully functional sash-3.6 in default initrd.
-       a much improved version with changes all around.
-
-10-04-2004     Matjaz Breskvar (phoenix@bsemi.com)
-       alot of bugfixes all over.
-       ethernet support, functional http and telnet servers.
-       running many standard linux apps.
-
-26-06-2004     Matjaz Breskvar (phoenix@bsemi.com)
-       port to 2.6.x
-
-30-11-2004     Matjaz Breskvar (phoenix@bsemi.com)
-       lots of bugfixes and enhancments.
-       added opencores framebuffer driver.
-
-09-10-2010    Jonas Bonn (jonas@southpole.se)
-       major rewrite to bring up to par with upstream Linux 2.6.36
diff --git a/Documentation/openrisc/todo.rst b/Documentation/openrisc/todo.rst
deleted file mode 100644 (file)
index 420b18b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-====
-TODO
-====
-
-The OpenRISC Linux port is fully functional and has been tracking upstream
-since 2.6.35.  There are, however, remaining items to be completed within
-the coming months.  Here's a list of known-to-be-less-than-stellar items
-that are due for investigation shortly, i.e. our TODO list:
-
--  Implement the rest of the DMA API... dma_map_sg, etc.
-
--  Finish the renaming cleanup... there are references to or32 in the code
-   which was an older name for the architecture.  The name we've settled on is
-   or1k and this change is slowly trickling through the stack.  For the time
-   being, or32 is equivalent to or1k.
diff --git a/Documentation/parisc/debugging.rst b/Documentation/parisc/debugging.rst
deleted file mode 100644 (file)
index de1b604..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-=================
-PA-RISC Debugging
-=================
-
-okay, here are some hints for debugging the lower-level parts of
-linux/parisc.
-
-
-1. Absolute addresses
-=====================
-
-A lot of the assembly code currently runs in real mode, which means
-absolute addresses are used instead of virtual addresses as in the
-rest of the kernel.  To translate an absolute address to a virtual
-address you can lookup in System.map, add __PAGE_OFFSET (0x10000000
-currently).
-
-
-2. HPMCs
-========
-
-When real-mode code tries to access non-existent memory, you'll get
-an HPMC instead of a kernel oops.  To debug an HPMC, try to find
-the System Responder/Requestor addresses.  The System Requestor
-address should match (one of the) processor HPAs (high addresses in
-the I/O range); the System Responder address is the address real-mode
-code tried to access.
-
-Typical values for the System Responder address are addresses larger
-than __PAGE_OFFSET (0x10000000) which mean a virtual address didn't
-get translated to a physical address before real-mode code tried to
-access it.
-
-
-3. Q bit fun
-============
-
-Certain, very critical code has to clear the Q bit in the PSW.  What
-happens when the Q bit is cleared is the CPU does not update the
-registers interruption handlers read to find out where the machine
-was interrupted - so if you get an interruption between the instruction
-that clears the Q bit and the RFI that sets it again you don't know
-where exactly it happened.  If you're lucky the IAOQ will point to the
-instruction that cleared the Q bit, if you're not it points anywhere
-at all.  Usually Q bit problems will show themselves in unexplainable
-system hangs or running off the end of physical memory.
diff --git a/Documentation/parisc/features.rst b/Documentation/parisc/features.rst
deleted file mode 100644 (file)
index 501d7c4..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features parisc
diff --git a/Documentation/parisc/index.rst b/Documentation/parisc/index.rst
deleted file mode 100644 (file)
index 2406857..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-====================
-PA-RISC Architecture
-====================
-
-.. toctree::
-   :maxdepth: 2
-
-   debugging
-   registers
-
-   features
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/parisc/registers.rst b/Documentation/parisc/registers.rst
deleted file mode 100644 (file)
index 59c8ecf..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-================================
-Register Usage for Linux/PA-RISC
-================================
-
-[ an asterisk is used for planned usage which is currently unimplemented ]
-
-General Registers as specified by ABI
-=====================================
-
-Control Registers
------------------
-
-===============================        ===============================================
-CR 0 (Recovery Counter)                used for ptrace
-CR 1-CR 7(undefined)           unused
-CR 8 (Protection ID)           per-process value*
-CR 9, 12, 13 (PIDS)            unused
-CR10 (CCR)                     lazy FPU saving*
-CR11                           as specified by ABI (SAR)
-CR14 (interruption vector)     initialized to fault_vector
-CR15 (EIEM)                    initialized to all ones*
-CR16 (Interval Timer)          read for cycle count/write starts Interval Tmr
-CR17-CR22                      interruption parameters
-CR19                           Interrupt Instruction Register
-CR20                           Interrupt Space Register
-CR21                           Interrupt Offset Register
-CR22                           Interrupt PSW
-CR23 (EIRR)                    read for pending interrupts/write clears bits
-CR24 (TR 0)                    Kernel Space Page Directory Pointer
-CR25 (TR 1)                    User   Space Page Directory Pointer
-CR26 (TR 2)                    not used
-CR27 (TR 3)                    Thread descriptor pointer
-CR28 (TR 4)                    not used
-CR29 (TR 5)                    not used
-CR30 (TR 6)                    current / 0
-CR31 (TR 7)                    Temporary register, used in various places
-===============================        ===============================================
-
-Space Registers (kernel mode)
------------------------------
-
-===============================        ===============================================
-SR0                            temporary space register
-SR4-SR7                        set to 0
-SR1                            temporary space register
-SR2                            kernel should not clobber this
-SR3                            used for userspace accesses (current process)
-===============================        ===============================================
-
-Space Registers (user mode)
----------------------------
-
-===============================        ===============================================
-SR0                            temporary space register
-SR1                             temporary space register
-SR2                             holds space of linux gateway page
-SR3                             holds user address space value while in kernel
-SR4-SR7                         Defines short address space for user/kernel
-===============================        ===============================================
-
-
-Processor Status Word
----------------------
-
-===============================        ===============================================
-W (64-bit addresses)           0
-E (Little-endian)              0
-S (Secure Interval Timer)      0
-T (Taken Branch Trap)          0
-H (Higher-privilege trap)      0
-L (Lower-privilege trap)       0
-N (Nullify next instruction)   used by C code
-X (Data memory break disable)  0
-B (Taken Branch)               used by C code
-C (code address translation)   1, 0 while executing real-mode code
-V (divide step correction)     used by C code
-M (HPMC mask)                  0, 1 while executing HPMC handler*
-C/B (carry/borrow bits)                used by C code
-O (ordered references)         1*
-F (performance monitor)                0
-R (Recovery Counter trap)      0
-Q (collect interruption state) 1 (0 in code directly preceding an rfi)
-P (Protection Identifiers)     1*
-D (Data address translation)   1, 0 while executing real-mode code
-I (external interrupt mask)    used by cli()/sti() macros
-===============================        ===============================================
-
-"Invisible" Registers
----------------------
-
-===============================        ===============================================
-PSW default W value            0
-PSW default E value            0
-Shadow Registers               used by interruption handler code
-TOC enable bit                 1
-===============================        ===============================================
-
--------------------------------------------------------------------------
-
-The PA-RISC architecture defines 7 registers as "shadow registers".
-Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce
-the state save and restore time by eliminating the need for general register
-(GR) saves and restores in interruption handlers.
-Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25.
-
--------------------------------------------------------------------------
-
-Register usage notes, originally from John Marvin, with some additional
-notes from Randolph Chung.
-
-For the general registers:
-
-r1,r2,r19-r26,r28,r29 & r31 can be used without saving them first. And of
-course, you need to save them if you care about them, before calling
-another procedure. Some of the above registers do have special meanings
-that you should be aware of:
-
-    r1:
-       The addil instruction is hardwired to place its result in r1,
-       so if you use that instruction be aware of that.
-
-    r2:
-       This is the return pointer. In general you don't want to
-       use this, since you need the pointer to get back to your
-       caller. However, it is grouped with this set of registers
-       since the caller can't rely on the value being the same
-       when you return, i.e. you can copy r2 to another register
-       and return through that register after trashing r2, and
-       that should not cause a problem for the calling routine.
-
-    r19-r22:
-       these are generally regarded as temporary registers.
-       Note that in 64 bit they are arg7-arg4.
-
-    r23-r26:
-       these are arg3-arg0, i.e. you can use them if you
-       don't care about the values that were passed in anymore.
-
-    r28,r29:
-       are ret0 and ret1. They are what you pass return values
-       in. r28 is the primary return. When returning small structures
-       r29 may also be used to pass data back to the caller.
-
-    r30:
-       stack pointer
-
-    r31:
-       the ble instruction puts the return pointer in here.
-
-
-    r3-r18,r27,r30 need to be saved and restored. r3-r18 are just
-    general purpose registers. r27 is the data pointer, and is
-    used to make references to global variables easier. r30 is
-    the stack pointer.
index 007e49ef6cec773e4231f543e47341a573e5ed6f..6db37a46d3059ee8e3fe6c3ee80711b6bff26e0d 100644 (file)
@@ -1267,5 +1267,5 @@ gcc internals and indent, all available from https://www.gnu.org/manual/
 WG14 is the international standardization working group for the programming
 language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
 
-Kernel :ref:`process/coding-style.rst <codingstyle>`, by greg@kroah.com at OLS 2002:
+Kernel CodingStyle, by greg@kroah.com at OLS 2002:
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff --git a/Documentation/process/contribution-maturity-model.rst b/Documentation/process/contribution-maturity-model.rst
new file mode 100644 (file)
index 0000000..b87ab34
--- /dev/null
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================================
+Linux Kernel Contribution Maturity Model
+========================================
+
+
+Background
+==========
+
+As a part of the 2021 Linux Kernel Maintainers’ Summit, there was a
+`discussion <https://lwn.net/Articles/870581/>`_ about the challenges in
+recruiting kernel maintainers as well as maintainer succession.  Some of
+the conclusions from that discussion included that companies which are a
+part of the Linux Kernel community need to allow engineers to be
+maintainers as part of their job, so they can grow into becoming
+respected leaders and eventually, kernel maintainers.  To support a
+strong talent pipeline, developers should be allowed and encouraged to
+take on upstream contributions such as reviewing other people’s patches,
+refactoring kernel infrastructure, and writing documentation.
+
+To that end, the Linux Foundation Technical Advisory Board (TAB)
+proposes this Linux Kernel Contribution Maturity Model. These common
+expectations for upstream community engagement aim to increase the
+influence of individual developers, increase the collaboration of
+organizations, and improve the overall health of the Linux Kernel
+ecosystem.
+
+The TAB urges organizations to continuously evaluate their Open Source
+maturity model and commit to improvements to align with this model.  To
+be effective, this evaluation should incorporate feedback from across
+the organization, including management and developers at all seniority
+levels.  In the spirit of Open Source, we encourage organizations to
+publish their evaluations and plans to improve their engagement with the
+upstream community.
+
+Level 0
+=======
+
+* Software Engineers are not allowed to contribute patches to the Linux
+  kernel.
+
+
+Level 1
+=======
+
+* Software Engineers are allowed to contribute patches to the Linux
+  kernel, either as part of their job responsibilities or on their own
+  time.
+
+Level 2
+=======
+
+* Software Engineers are expected to contribute to the Linux Kernel as
+  part of their job responsibilities.
+* Software Engineers will be supported to attend Linux-related
+  conferences as a part of their job.
+* A Software Engineer’s upstream code contributions will be considered
+  in promotion and performance reviews.
+
+Level 3
+=======
+
+* Software Engineers are expected to review patches (including patches
+  authored by engineers from other companies) as part of their job
+  responsibilities
+* Contributing presentations or papers to Linux-related or academic
+  conferences (such those organized by the Linux Foundation, Usenix,
+  ACM, etc.), are considered part of an engineer’s work.
+* A Software Engineer’s community contributions will be considered in
+  promotion and performance reviews.
+* Organizations will regularly report metrics of their open source
+  contributions and track these metrics over time.  These metrics may be
+  published only internally within the organization, or at the
+  organization’s discretion, some or all may be published externally.
+  Metrics that are strongly suggested include:
+
+  * The number of upstream kernel contributions by team or organization
+    (e.g., all people reporting up to a manager, director, or VP).
+  * The percentage of kernel developers who have made upstream
+    contributions relative to the total kernel developers in the
+    organization.
+  * The time interval between kernels used in the organization’s servers
+    and/or products, and the publication date of the upstream kernel
+    upon which the internal kernel is based.
+  * The number of out-of-tree commits present in internal kernels.
+
+Level 4
+=======
+
+* Software Engineers are encouraged to spend a portion of their work
+  time focused on Upstream Work, which is defined as reviewing patches,
+  serving on program committees, improving core project infrastructure
+  such as writing or maintaining tests, upstream tech debt reduction,
+  writing documentation, etc.
+* Software Engineers are supported in helping to organize Linux-related
+  conferences.
+* Organizations will consider community member feedback in official
+  performance reviews.
+
+Level 5
+=======
+
+* Upstream kernel development is considered a formal job position, with
+  at least a third of the engineer’s time spent doing Upstream Work.
+* Organizations will actively seek out community member feedback as a
+  factor in official performance reviews.
+* Organizations will regularly report internally on the ratio of
+  Upstream Work to work focused on directly pursuing business goals.
index cb6abcb2b6d07728a2de3cf9031d1825a76e067e..deb8235e20ff1df44138670983fb324b7f4282d6 100644 (file)
@@ -138,7 +138,7 @@ required reading:
     philosophy and is very important for people moving to Linux from
     development on other Operating Systems.
 
-  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+  :ref:`Documentation/process/security-bugs.rst <securitybugs>`
     If you feel you have found a security problem in the Linux kernel,
     please follow the steps in this document to help notify the kernel
     developers, and help solve the issue.
index d4b6217472b0a047a81c7e306fcaf2f54f5a2d46..b501cd977053fa37c765e8a33541a8613ebddab7 100644 (file)
@@ -35,6 +35,14 @@ Below are the essential guides that every developer should read.
    kernel-enforcement-statement
    kernel-driver-statement
 
+For security issues, see:
+
+.. toctree::
+   :maxdepth: 1
+
+   security-bugs
+   embargoed-hardware-issues
+
 Other guides to the community that are of interest to most developers are:
 
 .. toctree::
@@ -47,9 +55,9 @@ Other guides to the community that are of interest to most developers are:
    submit-checklist
    kernel-docs
    deprecated
-   embargoed-hardware-issues
    maintainers
    researcher-guidelines
+   contribution-maturity-model
 
 These are some overall technical guides that have been put here for now for
 lack of a better place.
index 1c6e2ab92f4e7f2714269078a5039907614d2484..46f927aae6ebcfc6a97ad231a1c720e5478255ad 100644 (file)
@@ -75,13 +75,39 @@ On-line docs
 Published books
 ---------------
 
+    * Title: **Linux Kernel Debugging: Leverage proven tools and advanced techniques to effectively debug Linux kernels and kernel modules**
+
+      :Author: Kaiwan N Billimoria
+      :Publisher: Packt Publishing Ltd
+      :Date: August, 2022
+      :Pages: 638
+      :ISBN: 978-1801075039
+      :Notes: Debugging book
+
     * Title: **Linux Kernel Programming: A Comprehensive Guide to Kernel Internals, Writing Kernel Modules, and Kernel Synchronization**
 
-          :Author: Kaiwan N. Billimoria
-          :Publisher: Packt Publishing Ltd
-          :Date: 2021
-          :Pages: 754
-          :ISBN: 978-1789953435
+      :Author: Kaiwan N Billimoria
+      :Publisher: Packt Publishing Ltd
+      :Date: March, 2021
+      :Pages: 754
+      :ISBN: 978-1789953435
+
+    * Title: **Linux Kernel Programming Part 2 - Char Device Drivers and Kernel Synchronization: Create user-kernel interfaces, work with peripheral I/O, and handle hardware interrupts**
+
+      :Author: Kaiwan N Billimoria
+      :Publisher: Packt Publishing Ltd
+      :Date: March, 2021
+      :Pages: 452
+      :ISBN: 978-1801079518
+
+    * Title: **Linux System Programming: Talking Directly to the Kernel and C Library**
+
+      :Author: Robert Love
+      :Publisher: O'Reilly Media
+      :Date: June, 2013
+      :Pages: 456
+      :ISBN: 978-1449339531
+      :Notes: Foundational book
 
     * Title: **Linux Kernel Development, 3rd Edition**
 
index 572a3289c9cbf3b893404b01fe372403ee6010c7..178c95fd17dcaded7f5d598987307d01b9eaa165 100644 (file)
@@ -128,8 +128,8 @@ uppercase letter and should be written in imperative tone.
 Changelog
 ^^^^^^^^^
 
-The general rules about changelogs in the process documentation, see
-:ref:`Documentation/process/ <submittingpatches>`, apply.
+The general rules about changelogs in the :ref:`Submitting patches guide
+<describe_changes>`, apply.
 
 The tip tree maintainers set value on following these rules, especially on
 the request to write changelogs in imperative mood and not impersonating
index 5fc9160ca1fa5b3054887d59e7336941d51d3a5e..bc56dee6d0bcb1c5ad558d88a97ae0a9ede718ad 100644 (file)
@@ -12,10 +12,6 @@ under ``-std=gnu11`` [gcc-c-dialect-options]_: the GNU dialect of ISO C11.
 This dialect contains many extensions to the language [gnu-extensions]_,
 and many of them are used within the kernel as a matter of course.
 
-There is some support for compiling the kernel with ``icc`` [icc]_ for several
-of the architectures, although at the time of writing it is not completed,
-requiring third-party patches.
-
 Attributes
 ----------
 
@@ -35,12 +31,28 @@ in order to feature detect which ones can be used and/or to shorten the code.
 
 Please refer to ``include/linux/compiler_attributes.h`` for more information.
 
+Rust
+----
+
+The kernel has experimental support for the Rust programming language
+[rust-language]_ under ``CONFIG_RUST``. It is compiled with ``rustc`` [rustc]_
+under ``--edition=2021`` [rust-editions]_. Editions are a way to introduce
+small changes to the language that are not backwards compatible.
+
+On top of that, some unstable features [rust-unstable-features]_ are used in
+the kernel. Unstable features may change in the future, thus it is an important
+goal to reach a point where only stable features are used.
+
+Please refer to Documentation/rust/index.rst for more information.
+
 .. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards
 .. [gcc] https://gcc.gnu.org
 .. [clang] https://clang.llvm.org
-.. [icc] https://software.intel.com/en-us/c-compilers
 .. [gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
 .. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
 .. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
 .. [n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
-
+.. [rust-language] https://www.rust-lang.org
+.. [rustc] https://doc.rust-lang.org/rustc/
+.. [rust-editions] https://doc.rust-lang.org/edition-guide/editions/
+.. [rust-unstable-features] https://github.com/Rust-for-Linux/linux/issues/2
index afc944e0e8986c1e8262a28894f4cc95a7c46e53..9fcfed3c350befc25dfafefd760a35d82657c207 100644 (file)
@@ -68,7 +68,7 @@ Before contributing, carefully read the appropriate documentation:
 * Documentation/process/development-process.rst
 * Documentation/process/submitting-patches.rst
 * Documentation/admin-guide/reporting-issues.rst
-* Documentation/admin-guide/security-bugs.rst
+* Documentation/process/security-bugs.rst
 
 Then send a patch (including a commit log with all the details listed
 below) and follow up on any feedback from other developers.
diff --git a/Documentation/process/security-bugs.rst b/Documentation/process/security-bugs.rst
new file mode 100644 (file)
index 0000000..82e2983
--- /dev/null
@@ -0,0 +1,96 @@
+.. _securitybugs:
+
+Security bugs
+=============
+
+Linux kernel developers take security very seriously.  As such, we'd
+like to know when a security bug is found so that it can be fixed and
+disclosed as quickly as possible.  Please report security bugs to the
+Linux kernel security team.
+
+Contact
+-------
+
+The Linux kernel security team can be contacted by email at
+<security@kernel.org>.  This is a private list of security officers
+who will help verify the bug report and develop and release a fix.
+If you already have a fix, please include it with your report, as
+that can speed up the process considerably.  It is possible that the
+security team will bring in extra help from area maintainers to
+understand and fix the security vulnerability.
+
+As it is with any bug, the more information provided the easier it
+will be to diagnose and fix.  Please review the procedure outlined in
+'Documentation/admin-guide/reporting-issues.rst' if you are unclear about what
+information is helpful.  Any exploit code is very helpful and will not
+be released without consent from the reporter unless it has already been
+made public.
+
+Please send plain text emails without attachments where possible.
+It is much harder to have a context-quoted discussion about a complex
+issue if all the details are hidden away in attachments.  Think of it like a
+:doc:`regular patch submission <../process/submitting-patches>`
+(even if you don't have a patch yet): describe the problem and impact, list
+reproduction steps, and follow it with a proposed fix, all in plain text.
+
+Disclosure and embargoed information
+------------------------------------
+
+The security list is not a disclosure channel.  For that, see Coordination
+below.
+
+Once a robust fix has been developed, the release process starts.  Fixes
+for publicly known bugs are released immediately.
+
+Although our preference is to release fixes for publicly undisclosed bugs
+as soon as they become available, this may be postponed at the request of
+the reporter or an affected party for up to 7 calendar days from the start
+of the release process, with an exceptional extension to 14 calendar days
+if it is agreed that the criticality of the bug requires more time.  The
+only valid reason for deferring the publication of a fix is to accommodate
+the logistics of QA and large scale rollouts which require release
+coordination.
+
+While embargoed information may be shared with trusted individuals in
+order to develop a fix, such information will not be published alongside
+the fix or on any other disclosure channel without the permission of the
+reporter.  This includes but is not limited to the original bug report
+and followup discussions (if any), exploits, CVE information or the
+identity of the reporter.
+
+In other words our only interest is in getting bugs fixed.  All other
+information submitted to the security list and any followup discussions
+of the report are treated confidentially even after the embargo has been
+lifted, in perpetuity.
+
+Coordination
+------------
+
+Fixes for sensitive bugs, such as those that might lead to privilege
+escalations, may need to be coordinated with the private
+<linux-distros@vs.openwall.org> mailing list so that distribution vendors
+are well prepared to issue a fixed kernel upon public disclosure of the
+upstream fix. Distros will need some time to test the proposed patch and
+will generally request at least a few days of embargo, and vendor update
+publication prefers to happen Tuesday through Thursday. When appropriate,
+the security team can assist with this coordination, or the reporter can
+include linux-distros from the start. In this case, remember to prefix
+the email Subject line with "[vs]" as described in the linux-distros wiki:
+<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>
+
+CVE assignment
+--------------
+
+The security team does not normally assign CVEs, nor do we require them
+for reports or fixes, as this can needlessly complicate the process and
+may delay the bug handling. If a reporter wishes to have a CVE identifier
+assigned ahead of public disclosure, they will need to contact the private
+linux-distros list, described above. When such a CVE identifier is known
+before a patch is provided, it is desirable to mention it in the commit
+message if the reporter agrees.
+
+Non-disclosure agreements
+-------------------------
+
+The Linux kernel security team is not a formal body and therefore unable
+to enter any non-disclosure agreements.
index 2fd8aa593a285173785241b0c21954cb8c75aa0c..51df1197d5abd47075552c92daa2d75489e2cd2c 100644 (file)
@@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree
 
    Security patches should not be handled (solely) by the -stable review
    process but should follow the procedures in
-   :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`.
+   :ref:`Documentation/process/security-bugs.rst <securitybugs>`.
 
 For all other submissions, choose one of the following procedures
 -----------------------------------------------------------------
index eac7167dce83d0fd7665a874aceaa4c9fa5d9e83..7a5619fecb384e442d7f020a43e97a8d42759939 100644 (file)
@@ -223,20 +223,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
@@ -254,7 +251,7 @@ If you have a patch that fixes an exploitable security bug, send that patch
 to security@kernel.org.  For severe bugs, a short embargo may be considered
 to allow distributors to get the patch out to users; in such cases,
 obviously, the patch should not be sent to any public lists. See also
-Documentation/admin-guide/security-bugs.rst.
+Documentation/process/security-bugs.rst.
 
 Patches that fix a severe bug in a released kernel should be directed
 toward the stable maintainers by putting a line like this::
@@ -320,7 +317,7 @@ for their time.  Code review is a tiring and time-consuming process, and
 reviewers sometimes get grumpy.  Even in that case, though, respond
 politely and address the problems they have pointed out.  When sending a next
 version, add a ``patch changelog`` to the cover letter or to individual patches
-explaining difference aganst previous submission (see
+explaining difference against previous submission (see
 :ref:`the_canonical_patch_format`).
 
 See Documentation/process/email-clients.rst for recommendations on email
index 3be44e74ec5d6b81006e2d0e9d3011e0ce464d2d..5462c84f4723ff0836ba62f44775280f13e45e8f 100644 (file)
@@ -47,7 +47,7 @@ RISC-V Linux Kernel SV39
                                                               | Kernel-space virtual memory, shared between all processes:
   ____________________________________________________________|___________________________________________________________
                     |            |                  |         |
-   ffffffc6fee00000 | -228    GB | ffffffc6feffffff |    2 MB | fixmap
+   ffffffc6fea00000 | -228    GB | ffffffc6feffffff |    6 MB | fixmap
    ffffffc6ff000000 | -228    GB | ffffffc6ffffffff |   16 MB | PCI io
    ffffffc700000000 | -228    GB | ffffffc7ffffffff |    4 GB | vmemmap
    ffffffc800000000 | -224    GB | ffffffd7ffffffff |   64 GB | vmalloc/ioremap space
@@ -83,7 +83,7 @@ RISC-V Linux Kernel SV48
                                                               | Kernel-space virtual memory, shared between all processes:
   ____________________________________________________________|___________________________________________________________
                     |            |                  |         |
-   ffff8d7ffee00000 |  -114.5 TB | ffff8d7ffeffffff |    2 MB | fixmap
+   ffff8d7ffea00000 |  -114.5 TB | ffff8d7ffeffffff |    6 MB | fixmap
    ffff8d7fff000000 |  -114.5 TB | ffff8d7fffffffff |   16 MB | PCI io
    ffff8d8000000000 |  -114.5 TB | ffff8f7fffffffff |    2 TB | vmemmap
    ffff8f8000000000 |  -112.5 TB | ffffaf7fffffffff |   32 TB | vmalloc/ioremap space
@@ -119,7 +119,7 @@ RISC-V Linux Kernel SV57
                                                               | Kernel-space virtual memory, shared between all processes:
   ____________________________________________________________|___________________________________________________________
                     |            |                  |         |
-   ff1bfffffee00000 | -57     PB | ff1bfffffeffffff |    2 MB | fixmap
+   ff1bfffffea00000 | -57     PB | ff1bfffffeffffff |    6 MB | fixmap
    ff1bffffff000000 | -57     PB | ff1bffffffffffff |   16 MB | PCI io
    ff1c000000000000 | -57     PB | ff1fffffffffffff |    1 PB | vmemmap
    ff20000000000000 | -56     PB | ff5fffffffffffff |   16 PB | vmalloc/ioremap space
index ed7f4f5b3cf157d12484a289f2efa2d3b9f228f8..b91e9ef4d0c21e45a4beb27eb8ac9f32a4d6669a 100644 (file)
@@ -15,7 +15,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file.
 ============  ================  ==============================================
 Architecture  Level of support  Constraints
 ============  ================  ==============================================
-``x86``       Maintained        ``x86_64`` only.
 ``um``        Maintained        ``x86_64`` only.
+``x86``       Maintained        ``x86_64`` only.
 ============  ================  ==============================================
 
index 8e2b8538bc2b7414d99a0f1726cec6af89fe1065..e2c1cf7431588e6bba3bf5b6fd489c85f652d7ec 100644 (file)
@@ -258,7 +258,7 @@ Linux cannot currently figure out CPU capacity on its own, this information thus
 needs to be handed to it. Architectures must define arch_scale_cpu_capacity()
 for that purpose.
 
-The arm and arm64 architectures directly map this to the arch_topology driver
+The arm, arm64, and RISC-V architectures directly map this to the arch_topology driver
 CPU scaling data, which is derived from the capacity-dmips-mhz CPU binding; see
 Documentation/devicetree/bindings/cpu/cpu-capacity.txt.
 
diff --git a/Documentation/sh/booting.rst b/Documentation/sh/booting.rst
deleted file mode 100644 (file)
index d851c49..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-DeviceTree Booting
-------------------
-
-  Device-tree compatible SH bootloaders are expected to provide the physical
-  address of the device tree blob in r4. Since legacy bootloaders did not
-  guarantee any particular initial register state, kernels built to
-  inter-operate with old bootloaders must either use a builtin DTB or
-  select a legacy board option (something other than CONFIG_SH_DEVICE_TREE)
-  that does not use device tree. Support for the latter is being phased out
-  in favor of device tree.
diff --git a/Documentation/sh/features.rst b/Documentation/sh/features.rst
deleted file mode 100644 (file)
index f722af3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features sh
diff --git a/Documentation/sh/index.rst b/Documentation/sh/index.rst
deleted file mode 100644 (file)
index c647767..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-=======================
-SuperH Interfaces Guide
-=======================
-
-:Author: Paul Mundt
-
-.. toctree::
-    :maxdepth: 1
-
-    booting
-    new-machine
-    register-banks
-
-    features
-
-Memory Management
-=================
-
-SH-4
-----
-
-Store Queue API
-~~~~~~~~~~~~~~~
-
-.. kernel-doc:: arch/sh/kernel/cpu/sh4/sq.c
-   :export:
-
-Machine Specific Interfaces
-===========================
-
-mach-dreamcast
---------------
-
-.. kernel-doc:: arch/sh/boards/mach-dreamcast/rtc.c
-   :internal:
-
-mach-x3proto
-------------
-
-.. kernel-doc:: arch/sh/boards/mach-x3proto/ilsel.c
-   :export:
-
-Busses
-======
-
-SuperHyway
-----------
-
-.. kernel-doc:: drivers/sh/superhyway/superhyway.c
-   :export:
-
-Maple
------
-
-.. kernel-doc:: drivers/sh/maple/maple.c
-   :export:
diff --git a/Documentation/sh/new-machine.rst b/Documentation/sh/new-machine.rst
deleted file mode 100644 (file)
index e501c52..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=============================
-Adding a new board to LinuxSH
-=============================
-
-               Paul Mundt <lethal@linux-sh.org>
-
-This document attempts to outline what steps are necessary to add support
-for new boards to the LinuxSH port under the new 2.5 and 2.6 kernels. This
-also attempts to outline some of the noticeable changes between the 2.4
-and the 2.5/2.6 SH backend.
-
-1. New Directory Structure
-==========================
-
-The first thing to note is the new directory structure. Under 2.4, most
-of the board-specific code (with the exception of stboards) ended up
-in arch/sh/kernel/ directly, with board-specific headers ending up in
-include/asm-sh/. For the new kernel, things are broken out by board type,
-companion chip type, and CPU type. Looking at a tree view of this directory
-hierarchy looks like the following:
-
-Board-specific code::
-
-    .
-    |-- arch
-    |   `-- sh
-    |       `-- boards
-    |           |-- adx
-    |           |   `-- board-specific files
-    |           |-- bigsur
-    |           |   `-- board-specific files
-    |           |
-    |           ... more boards here ...
-    |
-    `-- include
-       `-- asm-sh
-           |-- adx
-           |   `-- board-specific headers
-           |-- bigsur
-           |   `-- board-specific headers
-           |
-           .. more boards here ...
-
-Next, for companion chips::
-
-    .
-    `-- arch
-       `-- sh
-           `-- cchips
-               `-- hd6446x
-                   `-- hd64461
-                       `-- cchip-specific files
-
-... and so on. Headers for the companion chips are treated the same way as
-board-specific headers. Thus, include/asm-sh/hd64461 is home to all of the
-hd64461-specific headers.
-
-Finally, CPU family support is also abstracted::
-
-    .
-    |-- arch
-    |   `-- sh
-    |       |-- kernel
-    |       |   `-- cpu
-    |       |       |-- sh2
-    |       |       |   `-- SH-2 generic files
-    |       |       |-- sh3
-    |       |       |   `-- SH-3 generic files
-    |       |       `-- sh4
-    |       |           `-- SH-4 generic files
-    |       `-- mm
-    |           `-- This is also broken out per CPU family, so each family can
-    |               have their own set of cache/tlb functions.
-    |
-    `-- include
-       `-- asm-sh
-           |-- cpu-sh2
-           |   `-- SH-2 specific headers
-           |-- cpu-sh3
-           |   `-- SH-3 specific headers
-           `-- cpu-sh4
-               `-- SH-4 specific headers
-
-It should be noted that CPU subtypes are _not_ abstracted. Thus, these still
-need to be dealt with by the CPU family specific code.
-
-2. Adding a New Board
-=====================
-
-The first thing to determine is whether the board you are adding will be
-isolated, or whether it will be part of a family of boards that can mostly
-share the same board-specific code with minor differences.
-
-In the first case, this is just a matter of making a directory for your
-board in arch/sh/boards/ and adding rules to hook your board in with the
-build system (more on this in the next section). However, for board families
-it makes more sense to have a common top-level arch/sh/boards/ directory
-and then populate that with sub-directories for each member of the family.
-Both the Solution Engine and the hp6xx boards are an example of this.
-
-After you have setup your new arch/sh/boards/ directory, remember that you
-should also add a directory in include/asm-sh for headers localized to this
-board (if there are going to be more than one). In order to interoperate
-seamlessly with the build system, it's best to have this directory the same
-as the arch/sh/boards/ directory name, though if your board is again part of
-a family, the build system has ways of dealing with this (via incdir-y
-overloading), and you can feel free to name the directory after the family
-member itself.
-
-There are a few things that each board is required to have, both in the
-arch/sh/boards and the include/asm-sh/ hierarchy. In order to better
-explain this, we use some examples for adding an imaginary board. For
-setup code, we're required at the very least to provide definitions for
-get_system_type() and platform_setup(). For our imaginary board, this
-might look something like::
-
-    /*
-    * arch/sh/boards/vapor/setup.c - Setup code for imaginary board
-    */
-    #include <linux/init.h>
-
-    const char *get_system_type(void)
-    {
-           return "FooTech Vaporboard";
-    }
-
-    int __init platform_setup(void)
-    {
-           /*
-           * If our hardware actually existed, we would do real
-           * setup here. Though it's also sane to leave this empty
-           * if there's no real init work that has to be done for
-           * this board.
-           */
-
-           /* Start-up imaginary PCI ... */
-
-           /* And whatever else ... */
-
-           return 0;
-    }
-
-Our new imaginary board will also have to tie into the machvec in order for it
-to be of any use.
-
-machvec functions fall into a number of categories:
-
- - I/O functions to IO memory (inb etc) and PCI/main memory (readb etc).
- - I/O mapping functions (ioport_map, ioport_unmap, etc).
- - a 'heartbeat' function.
- - PCI and IRQ initialization routines.
- - Consistent allocators (for boards that need special allocators,
-   particularly for allocating out of some board-specific SRAM for DMA
-   handles).
-
-There are machvec functions added and removed over time, so always be sure to
-consult include/asm-sh/machvec.h for the current state of the machvec.
-
-The kernel will automatically wrap in generic routines for undefined function
-pointers in the machvec at boot time, as machvec functions are referenced
-unconditionally throughout most of the tree. Some boards have incredibly
-sparse machvecs (such as the dreamcast and sh03), whereas others must define
-virtually everything (rts7751r2d).
-
-Adding a new machine is relatively trivial (using vapor as an example):
-
-If the board-specific definitions are quite minimalistic, as is the case for
-the vast majority of boards, simply having a single board-specific header is
-sufficient.
-
- - add a new file include/asm-sh/vapor.h which contains prototypes for
-   any machine specific IO functions prefixed with the machine name, for
-   example vapor_inb. These will be needed when filling out the machine
-   vector.
-
-   Note that these prototypes are generated automatically by setting
-   __IO_PREFIX to something sensible. A typical example would be::
-
-       #define __IO_PREFIX vapor
-       #include <asm/io_generic.h>
-
-   somewhere in the board-specific header. Any boards being ported that still
-   have a legacy io.h should remove it entirely and switch to the new model.
-
- - Add machine vector definitions to the board's setup.c. At a bare minimum,
-   this must be defined as something like::
-
-       struct sh_machine_vector mv_vapor __initmv = {
-               .mv_name = "vapor",
-       };
-       ALIAS_MV(vapor)
-
- - finally add a file arch/sh/boards/vapor/io.c, which contains definitions of
-   the machine specific io functions (if there are enough to warrant it).
-
-3. Hooking into the Build System
-================================
-
-Now that we have the corresponding directories setup, and all of the
-board-specific code is in place, it's time to look at how to get the
-whole mess to fit into the build system.
-
-Large portions of the build system are now entirely dynamic, and merely
-require the proper entry here and there in order to get things done.
-
-The first thing to do is to add an entry to arch/sh/Kconfig, under the
-"System type" menu::
-
-    config SH_VAPOR
-           bool "Vapor"
-           help
-           select Vapor if configuring for a FooTech Vaporboard.
-
-next, this has to be added into arch/sh/Makefile. All boards require a
-machdir-y entry in order to be built. This entry needs to be the name of
-the board directory as it appears in arch/sh/boards, even if it is in a
-sub-directory (in which case, all parent directories below arch/sh/boards/
-need to be listed). For our new board, this entry can look like::
-
-    machdir-$(CONFIG_SH_VAPOR) += vapor
-
-provided that we've placed everything in the arch/sh/boards/vapor/ directory.
-
-Next, the build system assumes that your include/asm-sh directory will also
-be named the same. If this is not the case (as is the case with multiple
-boards belonging to a common family), then the directory name needs to be
-implicitly appended to incdir-y. The existing code manages this for the
-Solution Engine and hp6xx boards, so see these for an example.
-
-Once that is taken care of, it's time to add an entry for the mach type.
-This is done by adding an entry to the end of the arch/sh/tools/mach-types
-list. The method for doing this is self explanatory, and so we won't waste
-space restating it here. After this is done, you will be able to use
-implicit checks for your board if you need this somewhere throughout the
-common code, such as::
-
-       /* Make sure we're on the FooTech Vaporboard */
-       if (!mach_is_vapor())
-               return -ENODEV;
-
-also note that the mach_is_boardname() check will be implicitly forced to
-lowercase, regardless of the fact that the mach-types entries are all
-uppercase. You can read the script if you really care, but it's pretty ugly,
-so you probably don't want to do that.
-
-Now all that's left to do is providing a defconfig for your new board. This
-way, other people who end up with this board can simply use this config
-for reference instead of trying to guess what settings are supposed to be
-used on it.
-
-Also, as soon as you have copied over a sample .config for your new board
-(assume arch/sh/configs/vapor_defconfig), you can also use this directly as a
-build target, and it will be implicitly listed as such in the help text.
-
-Looking at the 'make help' output, you should now see something like:
-
-Architecture specific targets (sh):
-
-  =======================   =============================================
-  zImage                    Compressed kernel image (arch/sh/boot/zImage)
-  adx_defconfig             Build for adx
-  cqreek_defconfig          Build for cqreek
-  dreamcast_defconfig       Build for dreamcast
-  ...
-  vapor_defconfig           Build for vapor
-  =======================   =============================================
-
-which then allows you to do::
-
-    $ make ARCH=sh CROSS_COMPILE=sh4-linux- vapor_defconfig vmlinux
-
-which will in turn copy the defconfig for this board, run it through
-oldconfig (prompting you for any new options since the time of creation),
-and start you on your way to having a functional kernel for your new
-board.
diff --git a/Documentation/sh/register-banks.rst b/Documentation/sh/register-banks.rst
deleted file mode 100644 (file)
index 2bef5c8..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==========================================
-Notes on register bank usage in the kernel
-==========================================
-
-Introduction
-------------
-
-The SH-3 and SH-4 CPU families traditionally include a single partial register
-bank (selected by SR.RB, only r0 ... r7 are banked), whereas other families
-may have more full-featured banking or simply no such capabilities at all.
-
-SR.RB banking
--------------
-
-In the case of this type of banking, banked registers are mapped directly to
-r0 ... r7 if SR.RB is set to the bank we are interested in, otherwise ldc/stc
-can still be used to reference the banked registers (as r0_bank ... r7_bank)
-when in the context of another bank. The developer must keep the SR.RB value
-in mind when writing code that utilizes these banked registers, for obvious
-reasons. Userspace is also not able to poke at the bank1 values, so these can
-be used rather effectively as scratch registers by the kernel.
-
-Presently the kernel uses several of these registers.
-
-       - r0_bank, r1_bank (referenced as k0 and k1, used for scratch
-         registers when doing exception handling).
-
-       - r2_bank (used to track the EXPEVT/INTEVT code)
-
-               - Used by do_IRQ() and friends for doing irq mapping based off
-                 of the interrupt exception vector jump table offset
-
-       - r6_bank (global interrupt mask)
-
-               - The SR.IMASK interrupt handler makes use of this to set the
-                 interrupt priority level (used by local_irq_enable())
-
-       - r7_bank (current)
index 9b52f50a68542b932879f054bdd6b436ee7658a1..1204304500147637407240907078f17029999614 100644 (file)
@@ -704,7 +704,7 @@ ref
 no-jd
     BIOS setup but without jack-detection
 intel
-    Intel DG45* mobos
+    Intel D*45* mobos
 dell-m6-amic
     Dell desktops/laptops with analog mics
 dell-m6-dmic
diff --git a/Documentation/sparc/adi.rst b/Documentation/sparc/adi.rst
deleted file mode 100644 (file)
index dbcd8b6..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-================================
-Application Data Integrity (ADI)
-================================
-
-SPARC M7 processor adds the Application Data Integrity (ADI) feature.
-ADI allows a task to set version tags on any subset of its address
-space. Once ADI is enabled and version tags are set for ranges of
-address space of a task, the processor will compare the tag in pointers
-to memory in these ranges to the version set by the application
-previously. Access to memory is granted only if the tag in given pointer
-matches the tag set by the application. In case of mismatch, processor
-raises an exception.
-
-Following steps must be taken by a task to enable ADI fully:
-
-1. Set the user mode PSTATE.mcde bit. This acts as master switch for
-   the task's entire address space to enable/disable ADI for the task.
-
-2. Set TTE.mcd bit on any TLB entries that correspond to the range of
-   addresses ADI is being enabled on. MMU checks the version tag only
-   on the pages that have TTE.mcd bit set.
-
-3. Set the version tag for virtual addresses using stxa instruction
-   and one of the MCD specific ASIs. Each stxa instruction sets the
-   given tag for one ADI block size number of bytes. This step must
-   be repeated for entire page to set tags for entire page.
-
-ADI block size for the platform is provided by the hypervisor to kernel
-in machine description tables. Hypervisor also provides the number of
-top bits in the virtual address that specify the version tag.  Once
-version tag has been set for a memory location, the tag is stored in the
-physical memory and the same tag must be present in the ADI version tag
-bits of the virtual address being presented to the MMU. For example on
-SPARC M7 processor, MMU uses bits 63-60 for version tags and ADI block
-size is same as cacheline size which is 64 bytes. A task that sets ADI
-version to, say 10, on a range of memory, must access that memory using
-virtual addresses that contain 0xa in bits 63-60.
-
-ADI is enabled on a set of pages using mprotect() with PROT_ADI flag.
-When ADI is enabled on a set of pages by a task for the first time,
-kernel sets the PSTATE.mcde bit for the task. Version tags for memory
-addresses are set with an stxa instruction on the addresses using
-ASI_MCD_PRIMARY or ASI_MCD_ST_BLKINIT_PRIMARY. ADI block size is
-provided by the hypervisor to the kernel.  Kernel returns the value of
-ADI block size to userspace using auxiliary vector along with other ADI
-info. Following auxiliary vectors are provided by the kernel:
-
-       ============    ===========================================
-       AT_ADI_BLKSZ    ADI block size. This is the granularity and
-                       alignment, in bytes, of ADI versioning.
-       AT_ADI_NBITS    Number of ADI version bits in the VA
-       ============    ===========================================
-
-
-IMPORTANT NOTES
-===============
-
-- Version tag values of 0x0 and 0xf are reserved. These values match any
-  tag in virtual address and never generate a mismatch exception.
-
-- Version tags are set on virtual addresses from userspace even though
-  tags are stored in physical memory. Tags are set on a physical page
-  after it has been allocated to a task and a pte has been created for
-  it.
-
-- When a task frees a memory page it had set version tags on, the page
-  goes back to free page pool. When this page is re-allocated to a task,
-  kernel clears the page using block initialization ASI which clears the
-  version tags as well for the page. If a page allocated to a task is
-  freed and allocated back to the same task, old version tags set by the
-  task on that page will no longer be present.
-
-- ADI tag mismatches are not detected for non-faulting loads.
-
-- Kernel does not set any tags for user pages and it is entirely a
-  task's responsibility to set any version tags. Kernel does ensure the
-  version tags are preserved if a page is swapped out to the disk and
-  swapped back in. It also preserves that version tags if a page is
-  migrated.
-
-- ADI works for any size pages. A userspace task need not be aware of
-  page size when using ADI. It can simply select a virtual address
-  range, enable ADI on the range using mprotect() and set version tags
-  for the entire range. mprotect() ensures range is aligned to page size
-  and is a multiple of page size.
-
-- ADI tags can only be set on writable memory. For example, ADI tags can
-  not be set on read-only mappings.
-
-
-
-ADI related traps
-=================
-
-With ADI enabled, following new traps may occur:
-
-Disrupting memory corruption
-----------------------------
-
-       When a store accesses a memory location that has TTE.mcd=1,
-       the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
-       tag in the address used (bits 63:60) does not match the tag set on
-       the corresponding cacheline, a memory corruption trap occurs. By
-       default, it is a disrupting trap and is sent to the hypervisor
-       first. Hypervisor creates a sun4v error report and sends a
-       resumable error (TT=0x7e) trap to the kernel. The kernel sends
-       a SIGSEGV to the task that resulted in this trap with the following
-       info::
-
-               siginfo.si_signo = SIGSEGV;
-               siginfo.errno = 0;
-               siginfo.si_code = SEGV_ADIDERR;
-               siginfo.si_addr = addr; /* PC where first mismatch occurred */
-               siginfo.si_trapno = 0;
-
-
-Precise memory corruption
--------------------------
-
-       When a store accesses a memory location that has TTE.mcd=1,
-       the task is running with ADI enabled (PSTATE.mcde=1), and the ADI
-       tag in the address used (bits 63:60) does not match the tag set on
-       the corresponding cacheline, a memory corruption trap occurs. If
-       MCD precise exception is enabled (MCDPERR=1), a precise
-       exception is sent to the kernel with TT=0x1a. The kernel sends
-       a SIGSEGV to the task that resulted in this trap with the following
-       info::
-
-               siginfo.si_signo = SIGSEGV;
-               siginfo.errno = 0;
-               siginfo.si_code = SEGV_ADIPERR;
-               siginfo.si_addr = addr; /* address that caused trap */
-               siginfo.si_trapno = 0;
-
-       NOTE:
-               ADI tag mismatch on a load always results in precise trap.
-
-
-MCD disabled
-------------
-
-       When a task has not enabled ADI and attempts to set ADI version
-       on a memory address, processor sends an MCD disabled trap. This
-       trap is handled by hypervisor first and the hypervisor vectors this
-       trap through to the kernel as Data Access Exception trap with
-       fault type set to 0xa (invalid ASI). When this occurs, the kernel
-       sends the task SIGSEGV signal with following info::
-
-               siginfo.si_signo = SIGSEGV;
-               siginfo.errno = 0;
-               siginfo.si_code = SEGV_ACCADI;
-               siginfo.si_addr = addr; /* address that caused trap */
-               siginfo.si_trapno = 0;
-
-
-Sample program to use ADI
--------------------------
-
-Following sample program is meant to illustrate how to use the ADI
-functionality::
-
-  #include <unistd.h>
-  #include <stdio.h>
-  #include <stdlib.h>
-  #include <elf.h>
-  #include <sys/ipc.h>
-  #include <sys/shm.h>
-  #include <sys/mman.h>
-  #include <asm/asi.h>
-
-  #ifndef AT_ADI_BLKSZ
-  #define AT_ADI_BLKSZ 48
-  #endif
-  #ifndef AT_ADI_NBITS
-  #define AT_ADI_NBITS 49
-  #endif
-
-  #ifndef PROT_ADI
-  #define PROT_ADI     0x10
-  #endif
-
-  #define BUFFER_SIZE     32*1024*1024UL
-
-  main(int argc, char* argv[], char* envp[])
-  {
-          unsigned long i, mcde, adi_blksz, adi_nbits;
-          char *shmaddr, *tmp_addr, *end, *veraddr, *clraddr;
-          int shmid, version;
-       Elf64_auxv_t *auxv;
-
-       adi_blksz = 0;
-
-       while(*envp++ != NULL);
-       for (auxv = (Elf64_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
-               switch (auxv->a_type) {
-               case AT_ADI_BLKSZ:
-                       adi_blksz = auxv->a_un.a_val;
-                       break;
-               case AT_ADI_NBITS:
-                       adi_nbits = auxv->a_un.a_val;
-                       break;
-               }
-       }
-       if (adi_blksz == 0) {
-               fprintf(stderr, "Oops! ADI is not supported\n");
-               exit(1);
-       }
-
-       printf("ADI capabilities:\n");
-       printf("\tBlock size = %ld\n", adi_blksz);
-       printf("\tNumber of bits = %ld\n", adi_nbits);
-
-          if ((shmid = shmget(2, BUFFER_SIZE,
-                                  IPC_CREAT | SHM_R | SHM_W)) < 0) {
-                  perror("shmget failed");
-                  exit(1);
-          }
-
-          shmaddr = shmat(shmid, NULL, 0);
-          if (shmaddr == (char *)-1) {
-                  perror("shm attach failed");
-                  shmctl(shmid, IPC_RMID, NULL);
-                  exit(1);
-          }
-
-       if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE|PROT_ADI)) {
-               perror("mprotect failed");
-               goto err_out;
-       }
-
-          /* Set the ADI version tag on the shm segment
-           */
-          version = 10;
-          tmp_addr = shmaddr;
-          end = shmaddr + BUFFER_SIZE;
-          while (tmp_addr < end) {
-                  asm volatile(
-                          "stxa %1, [%0]0x90\n\t"
-                          :
-                          : "r" (tmp_addr), "r" (version));
-                  tmp_addr += adi_blksz;
-          }
-       asm volatile("membar #Sync\n\t");
-
-          /* Create a versioned address from the normal address by placing
-        * version tag in the upper adi_nbits bits
-           */
-          tmp_addr = (void *) ((unsigned long)shmaddr << adi_nbits);
-          tmp_addr = (void *) ((unsigned long)tmp_addr >> adi_nbits);
-          veraddr = (void *) (((unsigned long)version << (64-adi_nbits))
-                          | (unsigned long)tmp_addr);
-
-          printf("Starting the writes:\n");
-          for (i = 0; i < BUFFER_SIZE; i++) {
-                  veraddr[i] = (char)(i);
-                  if (!(i % (1024 * 1024)))
-                          printf(".");
-          }
-          printf("\n");
-
-          printf("Verifying data...");
-       fflush(stdout);
-          for (i = 0; i < BUFFER_SIZE; i++)
-                  if (veraddr[i] != (char)i)
-                          printf("\nIndex %lu mismatched\n", i);
-          printf("Done.\n");
-
-          /* Disable ADI and clean up
-           */
-       if (mprotect(shmaddr, BUFFER_SIZE, PROT_READ|PROT_WRITE)) {
-               perror("mprotect failed");
-               goto err_out;
-       }
-
-          if (shmdt((const void *)shmaddr) != 0)
-                  perror("Detach failure");
-          shmctl(shmid, IPC_RMID, NULL);
-
-          exit(0);
-
-  err_out:
-          if (shmdt((const void *)shmaddr) != 0)
-                  perror("Detach failure");
-          shmctl(shmid, IPC_RMID, NULL);
-          exit(1);
-  }
diff --git a/Documentation/sparc/console.rst b/Documentation/sparc/console.rst
deleted file mode 100644 (file)
index 73132db..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-Steps for sending 'break' on sunhv console
-==========================================
-
-On Baremetal:
-   1. press   Esc + 'B'
-
-On LDOM:
-   1. press    Ctrl + ']'
-   2. telnet> send  break
diff --git a/Documentation/sparc/features.rst b/Documentation/sparc/features.rst
deleted file mode 100644 (file)
index c0c9246..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features sparc
diff --git a/Documentation/sparc/index.rst b/Documentation/sparc/index.rst
deleted file mode 100644 (file)
index ae88422..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-==================
-Sparc Architecture
-==================
-
-.. toctree::
-   :maxdepth: 1
-
-   console
-   adi
-
-   oradax/oracle-dax
-
-   features
diff --git a/Documentation/sparc/oradax/dax-hv-api.txt b/Documentation/sparc/oradax/dax-hv-api.txt
deleted file mode 100644 (file)
index 7ecd0bf..0000000
+++ /dev/null
@@ -1,1433 +0,0 @@
-Excerpt from UltraSPARC Virtual Machine Specification
-Compiled from version 3.0.20+15
-Publication date 2017-09-25 08:21
-Copyright © 2008, 2015 Oracle and/or its affiliates. All rights reserved.
-Extracted via "pdftotext -f 547 -l 572 -layout sun4v_20170925.pdf"
-Authors:
-        Charles Kunzman
-        Sam Glidden
-        Mark Cianchetti
-
-
-Chapter 36. Coprocessor services
-        The following APIs provide access via the Hypervisor to hardware assisted data processing functionality.
-        These APIs may only be provided by certain platforms, and may not be available to all virtual machines
-        even on supported platforms. Restrictions on the use of these APIs may be imposed in order to support
-        live-migration and other system management activities.
-
-36.1. Data Analytics Accelerator
-        The Data Analytics Accelerator (DAX) functionality is a collection of hardware coprocessors that provide
-        high speed processoring of database-centric operations. The coprocessors may support one or more of
-        the following data query operations: search, extraction, compression, decompression, and translation. The
-        functionality offered may vary by virtual machine implementation.
-
-        The DAX is a virtual device to sun4v guests, with supported data operations indicated by the virtual device
-        compatibility property. Functionality is accessed through the submission of Command Control Blocks
-        (CCBs) via the ccb_submit API function. The operations are processed asynchronously, with the status
-        of the submitted operations reported through a Completion Area linked to each CCB. Each CCB has a
-        separate Completion Area and, unless execution order is specifically restricted through the use of serial-
-        conditional flags, the execution order of submitted CCBs is arbitrary. Likewise, the time to completion
-        for a given CCB is never guaranteed.
-
-        Guest software may implement a software timeout on CCB operations, and if the timeout is exceeded, the
-        operation may be cancelled or killed via the ccb_kill API function. It is recommended for guest software
-        to implement a software timeout to account for certain RAS errors which may result in lost CCBs. It is
-        recommended such implementation use the ccb_info API function to check the status of a CCB prior to
-        killing it in order to determine if the CCB is still in queue, or may have been lost due to a RAS error.
-
-        There is no fixed limit on the number of outstanding CCBs guest software may have queued in the virtual
-        machine, however, internal resource limitations within the virtual machine can cause CCB submissions
-        to be temporarily rejected with EWOULDBLOCK. In such cases, guests should continue to attempt
-        submissions until they succeed; waiting for an outstanding CCB to complete is not necessary, and would
-        not be a guarantee that a future submission would succeed.
-
-        The availablility of DAX coprocessor command service is indicated by the presence of the DAX virtual
-        device node in the guest MD (Section 8.24.17, “Database Analytics Accelerators (DAX) virtual-device
-        node”).
-
-36.1.1. DAX Compatibility Property
-        The query functionality may vary based on the compatibility property of the virtual device:
-
-36.1.1.1. "ORCL,sun4v-dax" Device Compatibility
-        Available CCB commands:
-
-        • No-op/Sync
-
-        • Extract
-
-        • Scan Value
-
-        • Inverted Scan Value
-
-        • Scan Range
-
-
-                                                     509
-\f                                             Coprocessor services
-
-
-        • Inverted Scan Range
-
-        • Translate
-
-        • Inverted Translate
-
-        • Select
-
-        See Section 36.2.1, “Query CCB Command Formats” for the corresponding CCB input and output formats.
-
-        Only version 0 CCBs are available.
-
-36.1.1.2. "ORCL,sun4v-dax-fc" Device Compatibility
-        "ORCL,sun4v-dax-fc" is compatible with the "ORCL,sun4v-dax" interface, and includes additional CCB
-        bit fields and controls.
-
-36.1.1.3. "ORCL,sun4v-dax2" Device Compatibility
-        Available CCB commands:
-
-        • No-op/Sync
-
-        • Extract
-
-        • Scan Value
-
-        • Inverted Scan Value
-
-        • Scan Range
-
-        • Inverted Scan Range
-
-        • Translate
-
-        • Inverted Translate
-
-        • Select
-
-        See Section 36.2.1, “Query CCB Command Formats” for the corresponding CCB input and output formats.
-
-        Version 0 and 1 CCBs are available. Only version 0 CCBs may use Huffman encoded data, whereas only
-        version 1 CCBs may use OZIP.
-
-36.1.2. DAX Virtual Device Interrupts
-        The DAX virtual device has multiple interrupts associated with it which may be used by the guest if
-        desired. The number of device interrupts available to the guest is indicated in the virtual device node of the
-        guest MD (Section 8.24.17, “Database Analytics Accelerators (DAX) virtual-device node”). If the device
-        node indicates N interrupts available, the guest may use any value from 0 to N - 1 (inclusive) in a CCB
-        interrupt number field. Using values outside this range will result in the CCB being rejected for an invalid
-        field value.
-
-        The interrupts may be bound and managed using the standard sun4v device interrupts API (Chapter 16,
-        Device interrupt services). Sysino interrupts are not available for DAX devices.
-
-36.2. Coprocessor Control Block (CCB)
-        CCBs are either 64 or 128 bytes long, depending on the operation type. The exact contents of the CCB
-        are command specific, but all CCBs contain at least one memory buffer address. All memory locations
-
-
-                                                      510
-\f                                    Coprocessor services
-
-
-referenced by a CCB must be pinned in memory until the CCB either completes execution or is killed
-via the ccb_kill API call. Changes in virtual address mappings occurring after CCB submission are not
-guaranteed to be visible, and as such all virtual address updates need to be synchronized with CCB
-execution.
-
-All CCBs begin with a common 32-bit header.
-
-Table 36.1. CCB Header Format
-Bits          Field Description
-[31:28]       CCB version. For API version 2.0: set to 1 if CCB uses OZIP encoding; set to 0 if the CCB
-              uses Huffman encoding; otherwise either 0 or 1. For API version 1.0: always set to 0.
-[27]          When API version 2.0 is negotiated, this is the Pipeline Flag [512]. It is reserved in
-              API version 1.0
-[26]          Long CCB flag [512]
-[25]          Conditional synchronization flag [512]
-[24]          Serial synchronization flag
-[23:16]       CCB operation code:
-               0x00        No Operation (No-op) or Sync
-               0x01        Extract
-               0x02        Scan Value
-               0x12        Inverted Scan Value
-               0x03        Scan Range
-               0x13        Inverted Scan Range
-               0x04        Translate
-               0x14        Inverted Translate
-               0x05        Select
-[15:13]       Reserved
-[12:11]       Table address type
-               0b'00       No address
-               0b'01       Alternate context virtual address
-               0b'10       Real address
-               0b'11       Primary context virtual address
-[10:8]        Output/Destination address type
-               0b'000      No address
-               0b'001      Alternate context virtual address
-               0b'010      Real address
-               0b'011      Primary context virtual address
-               0b'100      Reserved
-               0b'101      Reserved
-               0b'110      Reserved
-               0b'111      Reserved
-[7:5]         Secondary source address type
-
-
-                                            511
-\f                                    Coprocessor services
-
-
-Bits           Field Description
-                0b'000       No address
-                0b'001       Alternate context virtual address
-                0b'010       Real address
-                0b'011       Primary context virtual address
-                0b'100       Reserved
-                0b'101       Reserved
-                0b'110       Reserved
-                0b'111       Reserved
-[4:2]          Primary source address type
-                0b'000       No address
-                0b'001       Alternate context virtual address
-                0b'010       Real address
-                0b'011       Primary context virtual address
-                0b'100       Reserved
-                0b'101       Reserved
-                0b'110       Reserved
-                0b'111       Reserved
-[1:0]          Completion area address type
-                0b'00        No address
-                0b'01        Alternate context virtual address
-                0b'10        Real address
-                0b'11        Primary context virtual address
-
-The Long CCB flag indicates whether the submitted CCB is 64 or 128 bytes long; value is 0 for 64 bytes
-and 1 for 128 bytes.
-
-The Serial and Conditional flags allow simple relative ordering between CCBs. Any CCB with the Serial
-flag set will execute sequentially relative to any previous CCB that is also marked as Serial in the same
-CCB submission. CCBs without the Serial flag set execute independently, even if they are between CCBs
-with the Serial flag set. CCBs marked solely with the Serial flag will execute upon the completion of the
-previous Serial CCB, regardless of the completion status of that CCB. The Conditional flag allows CCBs
-to conditionally execute based on the successful execution of the closest CCB marked with the Serial flag.
-A CCB may only be conditional on exactly one CCB, however, a CCB may be marked both Conditional
-and Serial to allow execution chaining. The flags do NOT allow fan-out chaining, where multiple CCBs
-execute in parallel based on the completion of another CCB.
-
-The Pipeline flag is an optimization that directs the output of one CCB (the "source" CCB) directly to
-the input of the next CCB (the "target" CCB). The target CCB thus does not need to read the input from
-memory. The Pipeline flag is advisory and may be dropped.
-
-Both the Pipeline and Serial bits must be set in the source CCB. The Conditional bit must be set in the
-target CCB. Exactly one CCB must be made conditional on the source CCB; either 0 or 2 target CCBs
-is invalid. However, Pipelines can be extended beyond two CCBs: the sequence would start with a CCB
-with both the Pipeline and Serial bits set, proceed through CCBs with the Pipeline, Serial, and Conditional
-bits set, and terminate at a CCB that has the Conditional bit set, but not the Pipeline bit.
-
-
-                                             512
-\f                                               Coprocessor services
-
-
-          The input of the target CCB must start within 64 bytes of the output of the source CCB or the pipeline flag
-          will be ignored. All CCBs in a pipeline must be submitted in the same call to ccb_submit.
-
-          The various address type fields indicate how the various address values used in the CCB should be
-          interpreted by the virtual machine. Not all of the types specified are used by every CCB format. Types
-          which are not applicable to the given CCB command should be indicated as type 0 (No address). Virtual
-          addresses used in the CCB must have translation entries present in either the TLB or a configured TSB
-          for the submitting virtual processor. Virtual addresses which cannot be translated by the virtual machine
-          will result in the CCB submission being rejected, with the causal virtual address indicated. The CCB
-          may be resubmitted after inserting the translation, or the address may be translated by guest software and
-          resubmitted using the real address translation.
-
-36.2.1. Query CCB Command Formats
-36.2.1.1. Supported Data Formats, Elements Sizes and Offsets
-          Data for query commands may be encoded in multiple possible formats. The data query commands use a
-          common set of values to indicate the encoding formats of the data being processed. Some encoding formats
-          require multiple data streams for processing, requiring the specification of both primary data formats (the
-          encoded data) and secondary data streams (meta-data for the encoded data).
-
-36.2.1.1.1. Primary Input Format
-
-          The primary input format code is a 4-bit field when it is used. There are 10 primary input formats available.
-          The packed formats are not endian neutral. Code values not listed below are reserved.
-
-          Code        Format                              Description
-          0x0         Fixed width byte packed             Up to 16 bytes
-          0x1         Fixed width bit packed              Up to 15 bits (CCB version 0) or 23 bits (CCB version
-                                                          1); bits are read most significant bit to least significant bit
-                                                          within a byte
-          0x2         Variable width byte packed          Data stream of lengths must be provided as a secondary
-                                                          input
-          0x4         Fixed width byte packed with run Up to 16 bytes; data stream of run lengths must be
-                      length encoding                  provided as a secondary input
-          0x5         Fixed width bit packed with run Up to 15 bits (CCB version 0) or 23 bits (CCB version
-                      length encoding                 1); bits are read most significant bit to least significant bit
-                                                      within a byte; data stream of run lengths must be provided
-                                                      as a secondary input
-          0x8         Fixed width byte packed with Up to 16 bytes before the encoding; compressed stream
-                      Huffman (CCB version 0) or bits are read most significant bit to least significant bit
-                      OZIP (CCB version 1) encoding within a byte; pointer to the encoding table must be
-                                                    provided
-          0x9         Fixed width bit packed with Up to 15 bits (CCB version 0) or 23 bits (CCB version
-                      Huffman (CCB version 0) or 1); compressed stream bits are read most significant bit to
-                      OZIP (CCB version 1) encoding least significant bit within a byte; pointer to the encoding
-                                                    table must be provided
-          0xA         Variable width byte packed with Up to 16 bytes before the encoding; compressed stream
-                      Huffman (CCB version 0) or bits are read most significant bit to least significant bit
-                      OZIP (CCB version 1) encoding within a byte; data stream of lengths must be provided as
-                                                      a secondary input; pointer to the encoding table must be
-                                                      provided
-
-
-                                                        513
-\f                                               Coprocessor services
-
-
-          Code        Format                              Description
-          0xC         Fixed width byte packed with        Up to 16 bytes before the encoding; compressed stream
-                      run length encoding, followed by    bits are read most significant bit to least significant bit
-                      Huffman (CCB version 0) or          within a byte; data stream of run lengths must be provided
-                      OZIP (CCB version 1) encoding       as a secondary input; pointer to the encoding table must
-                                                          be provided
-          0xD         Fixed width bit packed with         Up to 15 bits (CCB version 0) or 23 bits(CCB version 1)
-                      run length encoding, followed by    before the encoding; compressed stream bits are read most
-                      Huffman (CCB version 0) or          significant bit to least significant bit within a byte; data
-                      OZIP (CCB version 1) encoding       stream of run lengths must be provided as a secondary
-                                                          input; pointer to the encoding table must be provided
-
-          If OZIP encoding is used, there must be no reserved bytes in the table.
-
-36.2.1.1.2. Primary Input Element Size
-
-          For primary input data streams with fixed size elements, the element size must be indicated in the CCB
-          command. The size is encoded as the number of bits or bytes, minus one. The valid value range for this
-          field depends on the input format selected, as listed in the table above.
-
-36.2.1.1.3. Secondary Input Format
-
-          For primary input data streams which require a secondary input stream, the secondary input stream is
-          always encoded in a fixed width, bit-packed format. The bits are read from most significant bit to least
-          significant bit within a byte. There are two encoding options for the secondary input stream data elements,
-          depending on whether the value of 0 is needed:
-
-          Secondary           Input Description
-          Format Code
-          0                          Element is stored as value minus 1 (0 evaluates to 1, 1 evaluates
-                                     to 2, etc)
-          1                          Element is stored as value
-
-36.2.1.1.4. Secondary Input Element Size
-
-          Secondary input element size is encoded as a two bit field:
-
-          Secondary Input Size Description
-          Code
-          0x0                        1 bit
-          0x1                        2 bits
-          0x2                        4 bits
-          0x3                        8 bits
-
-36.2.1.1.5. Input Element Offsets
-
-          Bit-wise input data streams may have any alignment within the base addressed byte. The offset, specified
-          from most significant bit to least significant bit, is provided as a fixed 3 bit field for each input type. A
-          value of 0 indicates that the first input element begins at the most significant bit in the first byte, and a
-          value of 7 indicates it begins with the least significant bit.
-
-          This field should be zero for any byte-wise primary input data streams.
-
-
-                                                        514
-\f                                              Coprocessor services
-
-
-36.2.1.1.6. Output Format
-
-          Query commands support multiple sizes and encodings for output data streams. There are four possible
-          output encodings, and up to four supported element sizes per encoding. Not all output encodings are
-          supported for every command. The format is indicated by a 4-bit field in the CCB:
-
-           Output Format Code        Description
-           0x0                       Byte aligned, 1 byte elements
-           0x1                       Byte aligned, 2 byte elements
-           0x2                       Byte aligned, 4 byte elements
-           0x3                       Byte aligned, 8 byte elements
-           0x4                       16 byte aligned, 16 byte elements
-           0x5                       Reserved
-           0x6                       Reserved
-           0x7                       Reserved
-           0x8                       Packed vector of single bit elements
-           0x9                       Reserved
-           0xA                       Reserved
-           0xB                       Reserved
-           0xC                       Reserved
-           0xD                       2 byte elements where each element is the index value of a bit,
-                                     from an bit vector, which was 1.
-           0xE                       4 byte elements where each element is the index value of a bit,
-                                     from an bit vector, which was 1.
-           0xF                       Reserved
-
-36.2.1.1.7. Application Data Integrity (ADI)
-
-          On platforms which support ADI, the ADI version number may be specified for each separate memory
-          access type used in the CCB command. ADI checking only occurs when reading data. When writing data,
-          the specified ADI version number overwrites any existing ADI value in memory.
-
-          An ADI version value of 0 or 0xF indicates the ADI checking is disabled for that data access, even if it is
-          enabled in memory. By setting the appropriate flag in CCB_SUBMIT (Section 36.3.1, “ccb_submit”) it is
-          also an option to disable ADI checking for all inputs accessed via virtual address for all CCBs submitted
-          during that hypercall invocation.
-
-          The ADI value is only guaranteed to be checked on the first 64 bytes of each data access. Mismatches on
-          subsequent data chunks may not be detected, so guest software should be careful to use page size checking
-          to protect against buffer overruns.
-
-36.2.1.1.8. Page size checking
-
-          All data accesses used in CCB commands must be bounded within a single memory page. When addresses
-          are provided using a virtual address, the page size for checking is extracted from the TTE for that virtual
-          address. When using real addresses, the guest must supply the page size in the same field as the address
-          value. The page size must be one of the sizes supported by the underlying virtual machine. Using a value
-          that is not supported may result in the CCB submission being rejected or the generation of a CCB parsing
-          error in the completion area.
-
-
-                                                       515
-\f                                               Coprocessor services
-
-
-36.2.1.2. Extract command
-
-        Converts an input vector in one format to an output vector in another format. All input format types are
-        supported.
-
-        The only supported output format is a padded, byte-aligned output stream, using output codes 0x0 - 0x4.
-        When the specified output element size is larger than the extracted input element size, zeros are padded to
-        the extracted input element. First, if the decompressed input size is not a whole number of bytes, 0 bits are
-        padded to the most significant bit side till the next byte boundary. Next, if the output element size is larger
-        than the byte padded input element, bytes of value 0 are added based on the Padding Direction bit in the
-        CCB. If the output element size is smaller than the byte-padded input element size, the input element is
-        truncated by dropped from the least significant byte side until the selected output size is reached.
-
-        The return value of the CCB completion area is invalid. The “number of elements processed” field in the
-        CCB completion area will be valid.
-
-        The extract CCB is a 64-byte “short format” CCB.
-
-        The extract CCB command format can be specified by the following packed C structure for a big-endian
-        machine:
-
-
-                  struct extract_ccb {
-                         uint32_t header;
-                         uint32_t control;
-                         uint64_t completion;
-                         uint64_t primary_input;
-                         uint64_t data_access_control;
-                         uint64_t secondary_input;
-                         uint64_t reserved;
-                         uint64_t output;
-                         uint64_t table;
-                  };
-
-
-        The exact field offsets, sizes, and composition are as follows:
-
-         Offset         Size            Field Description
-         0              4               CCB header (Table 36.1, “CCB Header Format”)
-         4              4               Command control
-                                        Bits        Field Description
-                                        [31:28]     Primary Input Format (see Section 36.2.1.1.1, “Primary Input
-                                                    Format”)
-                                        [27:23]     Primary Input Element Size (see Section 36.2.1.1.2, “Primary
-                                                    Input Element Size”)
-                                        [22:20]     Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                                                    Element Offsets”)
-                                        [19]        Secondary Input Format (see Section 36.2.1.1.3, “Secondary
-                                                    Input Format”)
-                                        [18:16]     Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                                                    Element Offsets”)
-
-
-                                                       516
-\f                        Coprocessor services
-
-
-Offset   Size   Field Description
-                Bits         Field Description
-                [15:14]      Secondary Input Element Size (see Section 36.2.1.1.4,
-                             “Secondary Input Element Size”
-                [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
-                [9]          Padding Direction selector: A value of 1 causes padding bytes
-                             to be added to the left side of output elements. A value of 0
-                             causes padding bytes to be added to the right side of output
-                             elements.
-                [8:0]        Reserved
-8        8      Completion
-                Bits         Field Description
-                [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
-                             Integrity (ADI)”)
-                [59]         If set to 1, a virtual device interrupt will be generated using
-                             the device interrupt number specified in the lower bits of this
-                             completion word. If 0, the lower bits of this completion word
-                             are ignored.
-                [58:6]       Completion area address bits [58:6]. Address type is
-                             determined by CCB header.
-                [5:0]        Virtual device interrupt number for completion interrupt, if
-                             enabled.
-16       8      Primary Input
-                Bits         Field Description
-                [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
-                             Integrity (ADI)”)
-                [59:56]      If using real address, these bits should be filled in with the
-                             page size code for the page boundary checking the guest wants
-                             the virtual machine to use when accessing this data stream
-                             (checking is only guaranteed to be performed when using API
-                             version 1.1 and later). If using a virtual address, this field will
-                             be used as as primary input address bits [59:56].
-                [55:0]       Primary input address bits [55:0]. Address type is determined
-                             by CCB header.
-24       8      Data Access Control
-                Bits         Field Description
-                [63:62]      Flow Control
-                             Value      Description
-                             0b'00      Disable flow control
-                             0b'01      Enable flow control (only valid with "ORCL,sun4v-
-                                        dax-fc" compatible virtual device variants)
-                             0b'10      Reserved
-                             0b'11      Reserved
-                [61:60]      Reserved (API 1.0)
-
-
-                                517
-\f                       Coprocessor services
-
-
-Offset   Size   Field Description
-                Bits        Field Description
-                            Pipeline target (API 2.0)
-                            Value      Description
-                            0b'00      Connect to primary input
-                            0b'01      Connect to secondary input
-                            0b'10      Reserved
-                            0b'11      Reserved
-                [59:40]     Output buffer size given in units of 64 bytes, minus 1. Value of
-                            0 means 64 bytes, value of 1 means 128 bytes, etc. Buffer size is
-                            only enforced if flow control is enabled in Flow Control field.
-                [39:32]     Reserved
-                [31:30]     Output Data Cache Allocation
-                            Value      Description
-                            0b'00      Do not allocate cache lines for output data stream.
-                            0b'01      Force cache lines for output data stream to be
-                                       allocated in the cache that is local to the submitting
-                                       virtual cpu.
-                            0b'10      Allocate cache lines for output data stream, but allow
-                                       existing cache lines associated with the data to remain
-                                       in their current cache instance. Any memory not
-                                       already in cache will be allocated in the cache local
-                                       to the submitting virtual cpu.
-                            0b'11      Reserved
-                [29:26]     Reserved
-                [25:24]     Primary Input Length Format
-                            Value      Description
-                            0b'00      Number of primary symbols
-                            0b'01      Number of primary bytes
-                            0b'10      Number of primary bits
-                            0b'11      Reserved
-                [23:0]      Primary Input Length
-                            Format                      Field Value
-                            # of primary symbols        Number of input elements to process,
-                                                        minus 1. Command execution stops
-                                                        once count is reached.
-                            # of primary bytes          Number of input bytes to process,
-                                                        minus 1. Command execution stops
-                                                        once count is reached. The count is
-                                                        done before any decompression or
-                                                        decoding.
-                            # of primary bits           Number of input bits to process,
-                                                        minus 1. Command execution stops
-
-
-
-                               518
-\f                                                Coprocessor services
-
-
-        Offset          Size           Field Description
-                                        Bits         Field Description
-                                                     Format                     Field Value
-                                                                                once count is reached. The count is
-                                                                                done before any decompression or
-                                                                                decoding, and does not include any
-                                                                                bits skipped by the Primary Input
-                                                                                Offset field value of the command
-                                                                                control word.
-        32              8              Secondary Input, if used by Primary Input Format. Same fields as Primary
-                                       Input.
-        40              8              Reserved
-        48              8              Output (same fields as Primary Input)
-        56              8              Symbol Table (if used by Primary Input)
-                                        Bits         Field Description
-                                        [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
-                                                     Integrity (ADI)”)
-                                        [59:56]      If using real address, these bits should be filled in with the
-                                                     page size code for the page boundary checking the guest wants
-                                                     the virtual machine to use when accessing this data stream
-                                                     (checking is only guaranteed to be performed when using API
-                                                     version 1.1 and later). If using a virtual address, this field will
-                                                     be used as as symbol table address bits [59:56].
-                                        [55:4]       Symbol table address bits [55:4]. Address type is determined
-                                                     by CCB header.
-                                        [3:0]        Symbol table version
-                                                     Value     Description
-                                                     0         Huffman encoding. Must use 64 byte aligned table
-                                                               address. (Only available when using version 0 CCBs)
-                                                     1         OZIP encoding. Must use 16 byte aligned table
-                                                               address. (Only available when using version 1 CCBs)
-
-
-36.2.1.3. Scan commands
-
-        The scan commands search a stream of input data elements for values which match the selection criteria.
-        All the input format types are supported. There are multiple formats for the scan commands, allowing the
-        scan to search for exact matches to one value, exact matches to either of two values, or any value within
-        a specified range. The specific type of scan is indicated by the command code in the CCB header. For the
-        scan range commands, the boundary conditions can be specified as greater-than-or-equal-to a value, less-
-        than-or-equal-to a value, or both by using two boundary values.
-
-        There are two supported formats for the output stream: the bit vector and index array formats (codes 0x8,
-        0xD, and 0xE). For the standard scan command using the bit vector output, for each input element there
-        exists one bit in the vector that is set if the input element matched the scan criteria, or clear if not. The
-        inverted scan command inverts the polarity of the bits in the output. The most significant bit of the first
-        byte of the output stream corresponds to the first element in the input stream. The standard index array
-        output format contains one array entry for each input element that matched the scan criteria. Each array
-
-
-
-                                                         519
-\f                                       Coprocessor services
-
-
-entry is the index of an input element that matched the scan criteria. An inverted scan command produces
-a similar array, but of all the input elements which did NOT match the scan criteria.
-
-The return value of the CCB completion area contains the number of input elements found which match
-the scan criteria (or number that did not match for the inverted scans). The “number of elements processed”
-field in the CCB completion area will be valid, indicating the number of input elements processed.
-
-These commands are 128-byte “long format” CCBs.
-
-The scan CCB command format can be specified by the following packed C structure for a big-endian
-machine:
-
-
-         struct scan_ccb         {
-                uint32_t         header;
-                uint32_t         control;
-                uint64_t         completion;
-                uint64_t         primary_input;
-                uint64_t         data_access_control;
-                uint64_t         secondary_input;
-                uint64_t         match_criteria0;
-                uint64_t         output;
-                uint64_t         table;
-                uint64_t         match_criteria1;
-                uint64_t         match_criteria2;
-                uint64_t         match_criteria3;
-                uint64_t         reserved[5];
-         };
-
-
-The exact field offsets, sizes, and composition are as follows:
-
-Offset         Size            Field Description
-0              4               CCB header (Table 36.1, “CCB Header Format”)
-4              4               Command control
-                               Bits         Field Description
-                               [31:28]      Primary Input Format (see Section 36.2.1.1.1, “Primary Input
-                                            Format”)
-                               [27:23]      Primary Input Element Size (see Section 36.2.1.1.2, “Primary
-                                            Input Element Size”)
-                               [22:20]      Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                                            Element Offsets”)
-                               [19]         Secondary Input Format (see Section 36.2.1.1.3, “Secondary
-                                            Input Format”)
-                               [18:16]      Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                                            Element Offsets”)
-                               [15:14]      Secondary Input Element Size (see Section 36.2.1.1.4,
-                                            “Secondary Input Element Size”
-                               [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
-                               [9:5]        Operand size for first scan criteria value. In a scan value
-                                            operation, this is one of two potential exact match values.
-                                            In a scan range operation, this is the size of the upper range
-
-
-                                               520
-\f                        Coprocessor services
-
-
-Offset   Size   Field Description
-                Bits         Field Description
-                             boundary. The value of this field is the number of bytes in the
-                             operand, minus 1. Values 0xF-0x1E are reserved. A value of
-                             0x1F indicates this operand is not in use for this scan operation.
-                [4:0]        Operand size for second scan criteria value. In a scan value
-                             operation, this is one of two potential exact match values.
-                             In a scan range operation, this is the size of the lower range
-                             boundary. The value of this field is the number of bytes in the
-                             operand, minus 1. Values 0xF-0x1E are reserved. A value of
-                             0x1F indicates this operand is not in use for this scan operation.
-8        8      Completion (same fields as Section 36.2.1.2, “Extract command”)
-16       8      Primary Input (same fields as Section 36.2.1.2, “Extract command”)
-24       8      Data Access Control (same fields as Section 36.2.1.2, “Extract command”)
-32       8      Secondary Input, if used by Primary Input Format. Same fields as Primary
-                Input.
-40       4      Most significant 4 bytes of first scan criteria operand. If first operand is less
-                than 4 bytes, the value is left-aligned to the lowest address bytes.
-44       4      Most significant 4 bytes of second scan criteria operand. If second operand
-                is less than 4 bytes, the value is left-aligned to the lowest address bytes.
-48       8      Output (same fields as Primary Input)
-56       8      Symbol Table (if used by Primary Input). Same fields as Section 36.2.1.2,
-                “Extract command”
-64       4      Next 4 most significant bytes of first scan criteria operand occurring after the
-                bytes specified at offset 40, if needed by the operand size. If first operand
-                is less than 8 bytes, the valid bytes are left-aligned to the lowest address.
-68       4      Next 4 most significant bytes of second scan criteria operand occurring after
-                the bytes specified at offset 44, if needed by the operand size. If second
-                operand is less than 8 bytes, the valid bytes are left-aligned to the lowest
-                address.
-72       4      Next 4 most significant bytes of first scan criteria operand occurring after the
-                bytes specified at offset 64, if needed by the operand size. If first operand
-                is less than 12 bytes, the valid bytes are left-aligned to the lowest address.
-76       4      Next 4 most significant bytes of second scan criteria operand occurring after
-                the bytes specified at offset 68, if needed by the operand size. If second
-                operand is less than 12 bytes, the valid bytes are left-aligned to the lowest
-                address.
-80       4      Next 4 most significant bytes of first scan criteria operand occurring after the
-                bytes specified at offset 72, if needed by the operand size. If first operand
-                is less than 16 bytes, the valid bytes are left-aligned to the lowest address.
-84       4      Next 4 most significant bytes of second scan criteria operand occurring after
-                the bytes specified at offset 76, if needed by the operand size. If second
-                operand is less than 16 bytes, the valid bytes are left-aligned to the lowest
-                address.
-
-
-
-
-                                521
-\f                                               Coprocessor services
-
-
-36.2.1.4. Translate commands
-
-        The translate commands takes an input array of indices, and a table of single bit values indexed by those
-        indices, and outputs a bit vector or index array created by reading the tables bit value at each index in
-        the input array. The output should therefore contain exactly one bit per index in the input data stream,
-        when outputting as a bit vector. When outputting as an index array, the number of elements depends on the
-        values read in the bit table, but will always be less than, or equal to, the number of input elements. Only
-        a restricted subset of the possible input format types are supported. No variable width or Huffman/OZIP
-        encoded input streams are allowed. The primary input data element size must be 3 bytes or less.
-
-        The maximum table index size allowed is 15 bits, however, larger input elements may be used to provide
-        additional processing of the output values. If 2 or 3 byte values are used, the least significant 15 bits are
-        used as an index into the bit table. The most significant 9 bits (when using 3-byte input elements) or single
-        bit (when using 2-byte input elements) are compared against a fixed 9-bit test value provided in the CCB.
-        If the values match, the value from the bit table is used as the output element value. If the values do not
-        match, the output data element value is forced to 0.
-
-        In the inverted translate operation, the bit value read from bit table is inverted prior to its use. The additional
-        additional processing based on any additional non-index bits remains unchanged, and still forces the output
-        element value to 0 on a mismatch. The specific type of translate command is indicated by the command
-        code in the CCB header.
-
-        There are two supported formats for the output stream: the bit vector and index array formats (codes 0x8,
-        0xD, and 0xE). The index array format is an array of indices of bits which would have been set if the
-        output format was a bit array.
-
-        The return value of the CCB completion area contains the number of bits set in the output bit vector,
-        or number of elements in the output index array. The “number of elements processed” field in the CCB
-        completion area will be valid, indicating the number of input elements processed.
-
-        These commands are 64-byte “short format” CCBs.
-
-        The translate CCB command format can be specified by the following packed C structure for a big-endian
-        machine:
-
-
-                 struct translate_ccb {
-                        uint32_t header;
-                        uint32_t control;
-                        uint64_t completion;
-                        uint64_t primary_input;
-                        uint64_t data_access_control;
-                        uint64_t secondary_input;
-                        uint64_t reserved;
-                        uint64_t output;
-                        uint64_t table;
-                 };
-
-
-        The exact field offsets, sizes, and composition are as follows:
-
-
-        Offset          Size             Field Description
-        0               4                CCB header (Table 36.1, “CCB Header Format”)
-
-
-                                                        522
-\f                        Coprocessor services
-
-
-Offset   Size   Field Description
-4        4      Command control
-                Bits         Field Description
-                [31:28]      Primary Input Format (see Section 36.2.1.1.1, “Primary Input
-                             Format”)
-                [27:23]      Primary Input Element Size (see Section 36.2.1.1.2, “Primary
-                             Input Element Size”)
-                [22:20]      Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                             Element Offsets”)
-                [19]         Secondary Input Format (see Section 36.2.1.1.3, “Secondary
-                             Input Format”)
-                [18:16]      Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                             Element Offsets”)
-                [15:14]      Secondary Input Element Size (see Section 36.2.1.1.4,
-                             “Secondary Input Element Size”
-                [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
-                [9]          Reserved
-                [8:0]        Test value used for comparison against the most significant bits
-                             in the input values, when using 2 or 3 byte input elements.
-8        8      Completion (same fields as Section 36.2.1.2, “Extract command”
-16       8      Primary Input (same fields as Section 36.2.1.2, “Extract command”
-24       8      Data Access Control (same fields as Section 36.2.1.2, “Extract command”,
-                except Primary Input Length Format may not use the 0x0 value)
-32       8      Secondary Input, if used by Primary Input Format. Same fields as Primary
-                Input.
-40       8      Reserved
-48       8      Output (same fields as Primary Input)
-56       8      Bit Table
-                Bits         Field Description
-                [63:60]      ADI version (see Section 36.2.1.1.7, “Application Data
-                             Integrity (ADI)”)
-                [59:56]      If using real address, these bits should be filled in with the
-                             page size code for the page boundary checking the guest wants
-                             the virtual machine to use when accessing this data stream
-                             (checking is only guaranteed to be performed when using API
-                             version 1.1 and later). If using a virtual address, this field will
-                             be used as as bit table address bits [59:56]
-                [55:4]       Bit table address bits [55:4]. Address type is determined by
-                             CCB header. Address must be 64-byte aligned (CCB version
-                             0) or 16-byte aligned (CCB version 1).
-                [3:0]        Bit table version
-                             Value      Description
-                             0          4KB table size
-                             1          8KB table size
-
-
-
-                                 523
-\f                                              Coprocessor services
-
-
-36.2.1.5. Select command
-        The select command filters the primary input data stream by using a secondary input bit vector to determine
-        which input elements to include in the output. For each bit set at a given index N within the bit vector,
-        the Nth input element is included in the output. If the bit is not set, the element is not included. Only a
-        restricted subset of the possible input format types are supported. No variable width or run length encoded
-        input streams are allowed, since the secondary input stream is used for the filtering bit vector.
-
-        The only supported output format is a padded, byte-aligned output stream. The stream follows the same
-        rules and restrictions as padded output stream described in Section 36.2.1.2, “Extract command”.
-
-        The return value of the CCB completion area contains the number of bits set in the input bit vector. The
-        "number of elements processed" field in the CCB completion area will be valid, indicating the number
-        of input elements processed.
-
-        The select CCB is a 64-byte “short format” CCB.
-
-        The select CCB command format can be specified by the following packed C structure for a big-endian
-        machine:
-
-
-                  struct select_ccb {
-                         uint32_t header;
-                         uint32_t control;
-                         uint64_t completion;
-                         uint64_t primary_input;
-                         uint64_t data_access_control;
-                         uint64_t secondary_input;
-                         uint64_t reserved;
-                         uint64_t output;
-                         uint64_t table;
-                  };
-
-
-        The exact field offsets, sizes, and composition are as follows:
-
-         Offset        Size            Field Description
-         0             4               CCB header (Table 36.1, “CCB Header Format”)
-         4             4               Command control
-                                       Bits        Field Description
-                                       [31:28]     Primary Input Format (see Section 36.2.1.1.1, “Primary Input
-                                                   Format”)
-                                       [27:23]     Primary Input Element Size (see Section 36.2.1.1.2, “Primary
-                                                   Input Element Size”)
-                                       [22:20]     Primary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                                                   Element Offsets”)
-                                       [19]        Secondary Input Format (see Section 36.2.1.1.3, “Secondary
-                                                   Input Format”)
-                                       [18:16]     Secondary Input Starting Offset (see Section 36.2.1.1.5, “Input
-                                                   Element Offsets”)
-                                       [15:14]     Secondary Input Element Size (see Section 36.2.1.1.4,
-                                                   “Secondary Input Element Size”
-
-
-                                                      524
-\f                                               Coprocessor services
-
-
-        Offset         Size            Field Description
-                                       Bits         Field Description
-                                       [13:10]      Output Format (see Section 36.2.1.1.6, “Output Format”)
-                                       [9]          Padding Direction selector: A value of 1 causes padding bytes
-                                                    to be added to the left side of output elements. A value of 0
-                                                    causes padding bytes to be added to the right side of output
-                                                    elements.
-                                       [8:0]        Reserved
-        8              8               Completion (same fields as Section 36.2.1.2, “Extract command”
-        16             8               Primary Input (same fields as Section 36.2.1.2, “Extract command”
-        24             8               Data Access Control (same fields as Section 36.2.1.2, “Extract command”)
-        32             8               Secondary Bit Vector Input. Same fields as Primary Input.
-        40             8               Reserved
-        48             8               Output (same fields as Primary Input)
-        56             8               Symbol Table (if used by Primary Input). Same fields as Section 36.2.1.2,
-                                       “Extract command”
-
-36.2.1.6. No-op and Sync commands
-        The no-op (no operation) command is a CCB which has no processing effect. The CCB, when processed
-        by the virtual machine, simply updates the completion area with its execution status. The CCB may have
-        the serial-conditional flags set in order to restrict when it executes.
-
-        The sync command is a variant of the no-op command which with restricted execution timing. A sync
-        command CCB will only execute when all previous commands submitted in the same request have
-        completed. This is stronger than the conditional flag sequencing, which is only dependent on a single
-        previous serial CCB. While the relative ordering is guaranteed, virtual machine implementations with
-        shared hardware resources may cause the sync command to wait for longer than the minimum required
-        time.
-
-        The return value of the CCB completion area is invalid for these CCBs. The “number of elements
-        processed” field is also invalid for these CCBs.
-
-        These commands are 64-byte “short format” CCBs.
-
-        The no-op CCB command format can be specified by the following packed C structure for a big-endian
-        machine:
-
-
-                 struct nop_ccb {
-                        uint32_t header;
-                        uint32_t control;
-                        uint64_t completion;
-                        uint64_t reserved[6];
-                 };
-
-
-        The exact field offsets, sizes, and composition are as follows:
-
-        Offset         Size            Field Description
-        0              4               CCB header (Table 36.1, “CCB Header Format”)
-
-
-                                                       525
-\f                                          Coprocessor services
-
-
-       Offset        Size          Field Description
-       4             4             Command control
-                                   Bits        Field Description
-                                   [31]        If set, this CCB functions as a Sync command. If clear, this
-                                               CCB functions as a No-op command.
-                                   [30:0]      Reserved
-       8             8             Completion (same fields as Section 36.2.1.2, “Extract command”
-       16            46            Reserved
-
-36.2.2. CCB Completion Area
-       All CCB commands use a common 128-byte Completion Area format, which can be specified by the
-       following packed C structure for a big-endian machine:
-
-
-                struct completion_area {
-                       uint8_t status_flag;
-                       uint8_t error_note;
-                       uint8_t rsvd0[2];
-                       uint32_t error_values;
-                       uint32_t output_size;
-                       uint32_t rsvd1;
-                       uint64_t run_time;
-                       uint64_t run_stats;
-                       uint32_t elements;
-                       uint8_t rsvd2[20];
-                       uint64_t return_value;
-                       uint64_t extra_return_value[8];
-                };
-
-
-       The Completion Area must be a 128-byte aligned memory location. The exact layout can be described
-       using byte offsets and sizes relative to the memory base:
-
-       Offset        Size          Field Description
-       0             1             CCB execution status
-                                   0x0                  Command not yet completed
-                                   0x1                  Command ran and succeeded
-                                   0x2                  Command ran and failed (partial results may be been
-                                                        produced)
-                                   0x3                  Command ran and was killed (partial execution may
-                                                        have occurred)
-                                   0x4                  Command was not run
-                                   0x5-0xF              Reserved
-       1             1             Error reason code
-                                   0x0                  Reserved
-                                   0x1                  Buffer overflow
-
-
-                                                  526
-\f                                      Coprocessor services
-
-
-Offset          Size           Field Description
-                                0x2                 CCB decoding error
-                                0x3                 Page overflow
-                                0x4-0x6             Reserved
-                                0x7                 Command was killed
-                                0x8                 Command execution timeout
-                                0x9                 ADI miscompare error
-                                0xA                 Data format error
-                                0xB-0xD             Reserved
-                                0xE                 Unexpected hardware error (Do not retry)
-                                0xF                 Unexpected hardware error (Retry is ok)
-                                0x10-0x7F           Reserved
-                                0x80                Partial Symbol Warning
-                                0x81-0xFF           Reserved
-2               2              Reserved
-4               4              If a partial symbol warning was generated, this field contains the number
-                               of remaining bits which were not decoded.
-8               4              Number of bytes of output produced
-12              4              Reserved
-16              8              Runtime of command (unspecified time units)
-24              8              Reserved
-32              4              Number of elements processed
-36              20             Reserved
-56              8              Return value
-64              64             Extended return value
-
-The CCB completion area should be treated as read-only by guest software. The CCB execution status
-byte will be cleared by the Hypervisor to reflect the pending execution status when the CCB is submitted
-successfully. All other fields are considered invalid upon CCB submission until the CCB execution status
-byte becomes non-zero.
-
-CCBs which complete with status 0x2 or 0x3 may produce partial results and/or side effects due to partial
-execution of the CCB command. Some valid data may be accessible depending on the fault type, however,
-it is recommended that guest software treat the destination buffer as being in an unknown state. If a CCB
-completes with a status byte of 0x2, the error reason code byte can be read to determine what corrective
-action should be taken.
-
-A buffer overflow indicates that the results of the operation exceeded the size of the output buffer indicated
-in the CCB. The operation can be retried by resubmitting the CCB with a larger output buffer.
-
-A CCB decoding error indicates that the CCB contained some invalid field values. It may be also be
-triggered if the CCB output is directed at a non-existent secondary input and the pipelining hint is followed.
-
-A page overflow error indicates that the operation required accessing a memory location beyond the page
-size associated with a given address. No data will have been read or written past the page boundary, but
-partial results may have been written to the destination buffer. The CCB can be resubmitted with a larger
-page size memory allocation to complete the operation.
-
-
-                                              527
-\f                                            Coprocessor services
-
-
-       In the case of pipelined CCBs, a page overflow error will be triggered if the output from the pipeline source
-       CCB ends before the input of the pipeline target CCB. Page boundaries are ignored when the pipeline
-       hint is followed.
-
-       Command kill indicates that the CCB execution was halted or prevented by use of the ccb_kill API call.
-
-       Command timeout indicates that the CCB execution began, but did not complete within a pre-determined
-       limit set by the virtual machine. The command may have produced some or no output. The CCB may be
-       resubmitted with no alterations.
-
-       ADI miscompare indicates that the memory buffer version specified in the CCB did not match the value
-       in memory when accessed by the virtual machine. Guest software should not attempt to resubmit the CCB
-       without determining the cause of the version mismatch.
-
-       A data format error indicates that the input data stream did not follow the specified data input formatting
-       selected in the CCB.
-
-       Some CCBs which encounter hardware errors may be resubmitted without change. Persistent hardware
-       errors may result in multiple failures until RAS software can identify and isolate the faulty component.
-
-       The output size field indicates the number of bytes of valid output in the destination buffer. This field is
-       not valid for all possible CCB commands.
-
-       The runtime field indicates the execution time of the CCB command once it leaves the internal virtual
-       machine queue. The time units are fixed, but unspecified, allowing only relative timing comparisons
-       by guest software. The time units may also vary by hardware platform, and should not be construed to
-       represent any absolute time value.
-
-       Some data query commands process data in units of elements. If applicable to the command, the number of
-       elements processed is indicated in the listed field. This field is not valid for all possible CCB commands.
-
-       The return value and extended return value fields are output locations for commands which do not use
-       a destination output buffer, or have secondary return results. The field is not valid for all possible CCB
-       commands.
-
-36.3. Hypervisor API Functions
-36.3.1. ccb_submit
-       trap#             FAST_TRAP
-       function#         CCB_SUBMIT
-       arg0              address
-       arg1              length
-       arg2              flags
-       arg3              reserved
-       ret0              status
-       ret1              length
-       ret2              status data
-       ret3              reserved
-
-       Submit one or more coprocessor control blocks (CCBs) for evaluation and processing by the virtual
-       machine. The CCBs are passed in a linear array indicated by address. length indicates the size of
-       the array in bytes.
-
-
-                                                     528
-\f                                      Coprocessor services
-
-
-The address should be aligned to the size indicated by length, rounded up to the nearest power of
-two. Virtual machines implementations may reject submissions which do not adhere to that alignment.
-length must be a multiple of 64 bytes. If length is zero, the maximum supported array length will be
-returned as length in ret1. In all other cases, the length value in ret1 will reflect the number of bytes
-successfully consumed from the input CCB array.
-
-      Implementation note
-      Virtual machines should never reject submissions based on the alignment of address if the
-      entire array is contained within a single memory page of the smallest page size supported by the
-      virtual machine.
-
-A guest may choose to submit addresses used in this API function, including the CCB array address,
-as either a real or virtual addresses, with the type of each address indicated in flags. Virtual addresses
-must be present in either the TLB or an active TSB to be processed. The translation context for virtual
-addresses is determined by a combination of CCB contents and the flags argument.
-
-The flags argument is divided into multiple fields defined as follows:
-
-
-Bits            Field Description
-[63:16]         Reserved
-[15]            Disable ADI for VA reads (in API 2.0)
-                Reserved (in API 1.0)
-[14]            Virtual addresses within CCBs are translated in privileged context
-[13:12]         Alternate translation context for virtual addresses within CCBs:
-                 0b'00        CCBs requesting alternate context are rejected
-                 0b'01        Reserved
-                 0b'10        CCBs requesting alternate context use secondary context
-                 0b'11        CCBs requesting alternate context use nucleus context
-[11:9]          Reserved
-[8]             Queue info flag
-[7]             All-or-nothing flag
-[6]             If address is a virtual address, treat its translation context as privileged
-[5:4]           Address type of address:
-                 0b'00        Real address
-                 0b'01        Virtual address in primary context
-                 0b'10        Virtual address in secondary context
-                 0b'11        Virtual address in nucleus context
-[3:2]           Reserved
-[1:0]           CCB command type:
-                 0b'00        Reserved
-                 0b'01        Reserved
-                 0b'10        Query command
-                 0b'11        Reserved
-
-
-
-                                              529
-\f                                             Coprocessor services
-
-
-         The CCB submission type and address type for the CCB array must be provided in the flags argument.
-         All other fields are optional values which change the default behavior of the CCB processing.
-
-         When set to one, the "Disable ADI for VA reads" bit will turn off ADI checking when using a virtual
-         address to load data. ADI checking will still be done when loading real-addressed memory. This bit is only
-         available when using major version 2 of the coprocessor API group; at major version 1 it is reserved. For
-         more information about using ADI and DAX, see Section 36.2.1.1.7, “Application Data Integrity (ADI)”.
-
-         By default, all virtual addresses are treated as user addresses. If the virtual address translations are
-         privileged, they must be marked as such in the appropriate flags field. The virtual addresses used within
-         the submitted CCBs must all be translated with the same privilege level.
-
-         By default, all virtual addresses used within the submitted CCBs are translated using the primary context
-         active at the time of the submission. The address type field within a CCB allows each address to request
-         translation in an alternate address context. The address context used when the alternate address context is
-         requested is selected in the flags argument.
-
-         The all-or-nothing flag specifies whether the virtual machine should allow partial submissions of the
-         input CCB array. When using CCBs with serial-conditional flags, it is strongly recommended to use
-         the all-or-nothing flag to avoid broken conditional chains. Using long CCB chains on a machine under
-         high coprocessor load may make this impractical, however, and require submitting without the flag.
-         When submitting serial-conditional CCBs without the all-or-nothing flag, guest software must manually
-         implement the serial-conditional behavior at any point where the chain was not submitted in a single API
-         call, and resubmission of the remaining CCBs should clear any conditional flag that might be set in the
-         first remaining CCB. Failure to do so will produce indeterminate CCB execution status and ordering.
-
-         When the all-or-nothing flag is not specified, callers should check the value of length in ret1 to determine
-         how many CCBs from the array were successfully submitted. Any remaining CCBs can be resubmitted
-         without modifications.
-
-         The value of length in ret1 is also valid when the API call returns an error, and callers should always
-         check its value to determine which CCBs in the array were already processed. This will additionally
-         identify which CCB encountered the processing error, and was not submitted successfully.
-
-         If the queue info flag is used during submission, and at least one CCB was successfully submitted, the
-         length value in ret1 will be a multi-field value defined as follows:
-          Bits          Field Description
-          [63:48]       DAX unit instance identifier
-          [47:32]       DAX queue instance identifier
-          [31:16]       Reserved
-          [15:0]        Number of CCB bytes successfully submitted
-
-         The value of status data depends on the status value. See error status code descriptions for details.
-         The value is undefined for status values that do not specifically list a value for the status data.
-
-         The API has a reserved input and output register which will be used in subsequent minor versions of this
-         API function. Guest software implementations should treat that register as voltile across the function call
-         in order to maintain forward compatibility.
-
-36.3.1.1. Errors
-          EOK                       One or more CCBs have been accepted and enqueued in the virtual machine
-                                    and no errors were been encountered during submission. Some submitted
-                                    CCBs may not have been enqueued due to internal virtual machine limitations,
-                                    and may be resubmitted without changes.
-
-
-                                                       530
-\f                        Coprocessor services
-
-
-EWOULDBLOCK    An internal resource conflict within the virtual machine has prevented it from
-               being able to complete the CCB submissions sufficiently quickly, requiring
-               it to abandon processing before it was complete. Some CCBs may have been
-               successfully enqueued prior to the block, and all remaining CCBs may be
-               resubmitted without changes.
-EBADALIGN      CCB array is not on a 64-byte boundary, or the array length is not a multiple
-               of 64 bytes.
-ENORADDR       A real address used either for the CCB array, or within one of the submitted
-               CCBs, is not valid for the guest. Some CCBs may have been enqueued prior
-               to the error being detected.
-ENOMAP         A virtual address used either for the CCB array, or within one of the submitted
-               CCBs, could not be translated by the virtual machine using either the TLB
-               or TSB contents. The submission may be retried after adding the required
-               mapping, or by converting the virtual address into a real address. Due to the
-               shared nature of address translation resources, there is no theoretical limit on
-               the number of times the translation may fail, and it is recommended all guests
-               implement some real address based backup. The virtual address which failed
-               translation is returned as status data in ret2. Some CCBs may have been
-               enqueued prior to the error being detected.
-EINVAL         The virtual machine detected an invalid CCB during submission, or invalid
-               input arguments, such as bad flag values. Note that not all invalid CCB values
-               will be detected during submission, and some may be reported as errors in the
-               completion area instead. Some CCBs may have been enqueued prior to the
-               error being detected. This error may be returned if the CCB version is invalid.
-ETOOMANY       The request was submitted with the all-or-nothing flag set, and the array size is
-               greater than the virtual machine can support in a single request. The maximum
-               supported size for the current virtual machine can be queried by submitting a
-               request with a zero length array, as described above.
-ENOACCESS      The guest does not have permission to submit CCBs, or an address used in a
-               CCBs lacks sufficient permissions to perform the required operation (no write
-               permission on the destination buffer address, for example). A virtual address
-               which fails permission checking is returned as status data in ret2. Some
-               CCBs may have been enqueued prior to the error being detected.
-EUNAVAILABLE   The requested CCB operation could not be performed at this time. The
-               restricted operation availability may apply only to the first unsuccessfully
-               submitted CCB, or may apply to a larger scope. The status should not be
-               interpreted as permanent, and the guest should attempt to submit CCBs in
-               the future which had previously been unable to be performed. The status
-               data provides additional information about scope of the restricted availability
-               as follows:
-               Value       Description
-               0           Processing for the exact CCB instance submitted was unavailable,
-                           and it is recommended the guest emulate the operation. The
-                           guest should continue to submit all other CCBs, and assume no
-                           restrictions beyond this exact CCB instance.
-               1           Processing is unavailable for all CCBs using the requested opcode,
-                           and it is recommended the guest emulate the operation. The
-                           guest should continue to submit all other CCBs that use different
-                           opcodes, but can expect continued rejections of CCBs using the
-                           same opcode in the near future.
-
-
-                                 531
-\f                                              Coprocessor services
-
-
-                                      Value     Description
-                                      2         Processing is unavailable for all CCBs using the requested CCB
-                                                version, and it is recommended the guest emulate the operation.
-                                                The guest should continue to submit all other CCBs that use
-                                                different CCB versions, but can expect continued rejections of
-                                                CCBs using the same CCB version in the near future.
-                                      3         Processing is unavailable for all CCBs on the submitting vcpu,
-                                                and it is recommended the guest emulate the operation or resubmit
-                                                the CCB on a different vcpu. The guest should continue to submit
-                                                CCBs on all other vcpus but can expect continued rejections of all
-                                                CCBs on this vcpu in the near future.
-                                      4         Processing is unavailable for all CCBs, and it is recommended
-                                                the guest emulate the operation. The guest should expect all CCB
-                                                submissions to be similarly rejected in the near future.
-
-
-36.3.2. ccb_info
-
-        trap#               FAST_TRAP
-        function#           CCB_INFO
-        arg0                address
-        ret0                status
-        ret1                CCB state
-        ret2                position
-        ret3                dax
-        ret4                queue
-
-       Requests status information on a previously submitted CCB. The previously submitted CCB is identified
-       by the 64-byte aligned real address of the CCBs completion area.
-
-       A CCB can be in one of 4 states:
-
-
-        State                     Value       Description
-        COMPLETED                 0           The CCB has been fetched and executed, and is no longer active in
-                                              the virtual machine.
-        ENQUEUED                  1           The requested CCB is current in a queue awaiting execution.
-        INPROGRESS                2           The CCB has been fetched and is currently being executed. It may still
-                                              be possible to stop the execution using the ccb_kill hypercall.
-        NOTFOUND                  3           The CCB could not be located in the virtual machine, and does not
-                                              appear to have been executed. This may occur if the CCB was lost
-                                              due to a hardware error, or the CCB may not have been successfully
-                                              submitted to the virtual machine in the first place.
-
-               Implementation note
-               Some platforms may not be able to report CCBs that are currently being processed, and therefore
-               guest software should invoke the ccb_kill hypercall prior to assuming the request CCB will never
-               be executed because it was in the NOTFOUND state.
-
-
-                                                       532
-\f                                             Coprocessor services
-
-
-         The position return value is only valid when the state is ENQUEUED. The value returned is the number
-         of other CCBs ahead of the requested CCB, to provide a relative estimate of when the CCB may execute.
-
-         The dax return value is only valid when the state is ENQUEUED. The value returned is the DAX unit
-         instance identifier for the DAX unit processing the queue where the requested CCB is located. The value
-         matches the value that would have been, or was, returned by ccb_submit using the queue info flag.
-
-         The queue return value is only valid when the state is ENQUEUED. The value returned is the DAX
-         queue instance identifier for the DAX unit processing the queue where the requested CCB is located. The
-         value matches the value that would have been, or was, returned by ccb_submit using the queue info flag.
-
-36.3.2.1. Errors
-
-          EOK                       The request was processed and the CCB state is valid.
-          EBADALIGN                 address is not on a 64-byte aligned.
-          ENORADDR                  The real address provided for address is not valid.
-          EINVAL                    The CCB completion area contents are not valid.
-          EWOULDBLOCK               Internal resource constraints prevented the CCB state from being queried at this
-                                    time. The guest should retry the request.
-          ENOACCESS                 The guest does not have permission to access the coprocessor virtual device
-                                    functionality.
-
-36.3.3. ccb_kill
-
-          trap#           FAST_TRAP
-          function#       CCB_KILL
-          arg0            address
-          ret0            status
-          ret1            result
-
-         Request to stop execution of a previously submitted CCB. The previously submitted CCB is identified by
-         the 64-byte aligned real address of the CCBs completion area.
-
-         The kill attempt can produce one of several values in the result return value, reflecting the CCB state
-         and actions taken by the Hypervisor:
-
-          Result                Value       Description
-          COMPLETED             0           The CCB has been fetched and executed, and is no longer active in
-                                            the virtual machine. It could not be killed and no action was taken.
-          DEQUEUED              1           The requested CCB was still enqueued when the kill request was
-                                            submitted, and has been removed from the queue. Since the CCB
-                                            never began execution, no memory modifications were produced by
-                                            it, and the completion area will never be updated. The same CCB may
-                                            be submitted again, if desired, with no modifications required.
-          KILLED                2           The CCB had been fetched and was being executed when the kill
-                                            request was submitted. The CCB execution was stopped, and the CCB
-                                            is no longer active in the virtual machine. The CCB completion area
-                                            will reflect the killed status, with the subsequent implications that
-                                            partial results may have been produced. Partial results may include full
-
-
-                                                      533
-\f                                              Coprocessor services
-
-
-          Result                 Value       Description
-                                             command execution if the command was stopped just prior to writing
-                                             to the completion area.
-          NOTFOUND               3           The CCB could not be located in the virtual machine, and does not
-                                             appear to have been executed. This may occur if the CCB was lost
-                                             due to a hardware error, or the CCB may not have been successfully
-                                             submitted to the virtual machine in the first place. CCBs in the state
-                                             are guaranteed to never execute in the future unless resubmitted.
-
-36.3.3.1. Interactions with Pipelined CCBs
-
-         If the pipeline target CCB is killed but the pipeline source CCB was skipped, the completion area of the
-         target CCB may contain status (4,0) "Command was skipped" instead of (3,7) "Command was killed".
-
-         If the pipeline source CCB is killed, the pipeline target CCB's completion status may read (1,0) "Success".
-         This does not mean the target CCB was processed; since the source CCB was killed, there was no
-         meaningful output on which the target CCB could operate.
-
-36.3.3.2. Errors
-
-          EOK                        The request was processed and the result is valid.
-          EBADALIGN                  address is not on a 64-byte aligned.
-          ENORADDR                   The real address provided for address is not valid.
-          EINVAL                     The CCB completion area contents are not valid.
-          EWOULDBLOCK                Internal resource constraints prevented the CCB from being killed at this time.
-                                     The guest should retry the request.
-          ENOACCESS                  The guest does not have permission to access the coprocessor virtual device
-                                     functionality.
-
-36.3.4. dax_info
-          trap#            FAST_TRAP
-          function#        DAX_INFO
-          ret0             status
-          ret1             Number of enabled DAX units
-          ret2             Number of disabled DAX units
-
-         Returns the number of DAX units that are enabled for the calling guest to submit CCBs. The number of
-         DAX units that are disabled for the calling guest are also returned. A disabled DAX unit would have been
-         available for CCB submission to the calling guest had it not been offlined.
-
-36.3.4.1. Errors
-
-          EOK                        The request was processed and the number of enabled/disabled DAX units
-                                     are valid.
-
-
-
-
-                                                       534
-\f
diff --git a/Documentation/sparc/oradax/oracle-dax.rst b/Documentation/sparc/oradax/oracle-dax.rst
deleted file mode 100644 (file)
index d1e14d5..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-=======================================
-Oracle Data Analytics Accelerator (DAX)
-=======================================
-
-DAX is a coprocessor which resides on the SPARC M7 (DAX1) and M8
-(DAX2) processor chips, and has direct access to the CPU's L3 caches
-as well as physical memory. It can perform several operations on data
-streams with various input and output formats.  A driver provides a
-transport mechanism and has limited knowledge of the various opcodes
-and data formats. A user space library provides high level services
-and translates these into low level commands which are then passed
-into the driver and subsequently the Hypervisor and the coprocessor.
-The library is the recommended way for applications to use the
-coprocessor, and the driver interface is not intended for general use.
-This document describes the general flow of the driver, its
-structures, and its programmatic interface. It also provides example
-code sufficient to write user or kernel applications that use DAX
-functionality.
-
-The user library is open source and available at:
-
-    https://oss.oracle.com/git/gitweb.cgi?p=libdax.git
-
-The Hypervisor interface to the coprocessor is described in detail in
-the accompanying document, dax-hv-api.txt, which is a plain text
-excerpt of the (Oracle internal) "UltraSPARC Virtual Machine
-Specification" version 3.0.20+15, dated 2017-09-25.
-
-
-High Level Overview
-===================
-
-A coprocessor request is described by a Command Control Block
-(CCB). The CCB contains an opcode and various parameters. The opcode
-specifies what operation is to be done, and the parameters specify
-options, flags, sizes, and addresses.  The CCB (or an array of CCBs)
-is passed to the Hypervisor, which handles queueing and scheduling of
-requests to the available coprocessor execution units. A status code
-returned indicates if the request was submitted successfully or if
-there was an error.  One of the addresses given in each CCB is a
-pointer to a "completion area", which is a 128 byte memory block that
-is written by the coprocessor to provide execution status. No
-interrupt is generated upon completion; the completion area must be
-polled by software to find out when a transaction has finished, but
-the M7 and later processors provide a mechanism to pause the virtual
-processor until the completion status has been updated by the
-coprocessor. This is done using the monitored load and mwait
-instructions, which are described in more detail later.  The DAX
-coprocessor was designed so that after a request is submitted, the
-kernel is no longer involved in the processing of it.  The polling is
-done at the user level, which results in almost zero latency between
-completion of a request and resumption of execution of the requesting
-thread.
-
-
-Addressing Memory
-=================
-
-The kernel does not have access to physical memory in the Sun4v
-architecture, as there is an additional level of memory virtualization
-present. This intermediate level is called "real" memory, and the
-kernel treats this as if it were physical.  The Hypervisor handles the
-translations between real memory and physical so that each logical
-domain (LDOM) can have a partition of physical memory that is isolated
-from that of other LDOMs.  When the kernel sets up a virtual mapping,
-it specifies a virtual address and the real address to which it should
-be mapped.
-
-The DAX coprocessor can only operate on physical memory, so before a
-request can be fed to the coprocessor, all the addresses in a CCB must
-be converted into physical addresses. The kernel cannot do this since
-it has no visibility into physical addresses. So a CCB may contain
-either the virtual or real addresses of the buffers or a combination
-of them. An "address type" field is available for each address that
-may be given in the CCB. In all cases, the Hypervisor will translate
-all the addresses to physical before dispatching to hardware. Address
-translations are performed using the context of the process initiating
-the request.
-
-
-The Driver API
-==============
-
-An application makes requests to the driver via the write() system
-call, and gets results (if any) via read(). The completion areas are
-made accessible via mmap(), and are read-only for the application.
-
-The request may either be an immediate command or an array of CCBs to
-be submitted to the hardware.
-
-Each open instance of the device is exclusive to the thread that
-opened it, and must be used by that thread for all subsequent
-operations. The driver open function creates a new context for the
-thread and initializes it for use.  This context contains pointers and
-values used internally by the driver to keep track of submitted
-requests. The completion area buffer is also allocated, and this is
-large enough to contain the completion areas for many concurrent
-requests.  When the device is closed, any outstanding transactions are
-flushed and the context is cleaned up.
-
-On a DAX1 system (M7), the device will be called "oradax1", while on a
-DAX2 system (M8) it will be "oradax2". If an application requires one
-or the other, it should simply attempt to open the appropriate
-device. Only one of the devices will exist on any given system, so the
-name can be used to determine what the platform supports.
-
-The immediate commands are CCB_DEQUEUE, CCB_KILL, and CCB_INFO. For
-all of these, success is indicated by a return value from write()
-equal to the number of bytes given in the call. Otherwise -1 is
-returned and errno is set.
-
-CCB_DEQUEUE
------------
-
-Tells the driver to clean up resources associated with past
-requests. Since no interrupt is generated upon the completion of a
-request, the driver must be told when it may reclaim resources.  No
-further status information is returned, so the user should not
-subsequently call read().
-
-CCB_KILL
---------
-
-Kills a CCB during execution. The CCB is guaranteed to not continue
-executing once this call returns successfully. On success, read() must
-be called to retrieve the result of the action.
-
-CCB_INFO
---------
-
-Retrieves information about a currently executing CCB. Note that some
-Hypervisors might return 'notfound' when the CCB is in 'inprogress'
-state. To ensure a CCB in the 'notfound' state will never be executed,
-CCB_KILL must be invoked on that CCB. Upon success, read() must be
-called to retrieve the details of the action.
-
-Submission of an array of CCBs for execution
----------------------------------------------
-
-A write() whose length is a multiple of the CCB size is treated as a
-submit operation. The file offset is treated as the index of the
-completion area to use, and may be set via lseek() or using the
-pwrite() system call. If -1 is returned then errno is set to indicate
-the error. Otherwise, the return value is the length of the array that
-was actually accepted by the coprocessor. If the accepted length is
-equal to the requested length, then the submission was completely
-successful and there is no further status needed; hence, the user
-should not subsequently call read(). Partial acceptance of the CCB
-array is indicated by a return value less than the requested length,
-and read() must be called to retrieve further status information.  The
-status will reflect the error caused by the first CCB that was not
-accepted, and status_data will provide additional data in some cases.
-
-MMAP
-----
-
-The mmap() function provides access to the completion area allocated
-in the driver.  Note that the completion area is not writeable by the
-user process, and the mmap call must not specify PROT_WRITE.
-
-
-Completion of a Request
-=======================
-
-The first byte in each completion area is the command status which is
-updated by the coprocessor hardware. Software may take advantage of
-new M7/M8 processor capabilities to efficiently poll this status byte.
-First, a "monitored load" is achieved via a Load from Alternate Space
-(ldxa, lduba, etc.) with ASI 0x84 (ASI_MONITOR_PRIMARY).  Second, a
-"monitored wait" is achieved via the mwait instruction (a write to
-%asr28). This instruction is like pause in that it suspends execution
-of the virtual processor for the given number of nanoseconds, but in
-addition will terminate early when one of several events occur. If the
-block of data containing the monitored location is modified, then the
-mwait terminates. This causes software to resume execution immediately
-(without a context switch or kernel to user transition) after a
-transaction completes. Thus the latency between transaction completion
-and resumption of execution may be just a few nanoseconds.
-
-
-Application Life Cycle of a DAX Submission
-==========================================
-
- - open dax device
- - call mmap() to get the completion area address
- - allocate a CCB and fill in the opcode, flags, parameters, addresses, etc.
- - submit CCB via write() or pwrite()
- - go into a loop executing monitored load + monitored wait and
-   terminate when the command status indicates the request is complete
-   (CCB_KILL or CCB_INFO may be used any time as necessary)
- - perform a CCB_DEQUEUE
- - call munmap() for completion area
- - close the dax device
-
-
-Memory Constraints
-==================
-
-The DAX hardware operates only on physical addresses. Therefore, it is
-not aware of virtual memory mappings and the discontiguities that may
-exist in the physical memory that a virtual buffer maps to. There is
-no I/O TLB or any scatter/gather mechanism. All buffers, whether input
-or output, must reside in a physically contiguous region of memory.
-
-The Hypervisor translates all addresses within a CCB to physical
-before handing off the CCB to DAX. The Hypervisor determines the
-virtual page size for each virtual address given, and uses this to
-program a size limit for each address. This prevents the coprocessor
-from reading or writing beyond the bound of the virtual page, even
-though it is accessing physical memory directly. A simpler way of
-saying this is that a DAX operation will never "cross" a virtual page
-boundary. If an 8k virtual page is used, then the data is strictly
-limited to 8k. If a user's buffer is larger than 8k, then a larger
-page size must be used, or the transaction size will be truncated to
-8k.
-
-Huge pages. A user may allocate huge pages using standard interfaces.
-Memory buffers residing on huge pages may be used to achieve much
-larger DAX transaction sizes, but the rules must still be followed,
-and no transaction will cross a page boundary, even a huge page.  A
-major caveat is that Linux on Sparc presents 8Mb as one of the huge
-page sizes. Sparc does not actually provide a 8Mb hardware page size,
-and this size is synthesized by pasting together two 4Mb pages. The
-reasons for this are historical, and it creates an issue because only
-half of this 8Mb page can actually be used for any given buffer in a
-DAX request, and it must be either the first half or the second half;
-it cannot be a 4Mb chunk in the middle, since that crosses a
-(hardware) page boundary. Note that this entire issue may be hidden by
-higher level libraries.
-
-
-CCB Structure
--------------
-A CCB is an array of 8 64-bit words. Several of these words provide
-command opcodes, parameters, flags, etc., and the rest are addresses
-for the completion area, output buffer, and various inputs::
-
-   struct ccb {
-       u64   control;
-       u64   completion;
-       u64   input0;
-       u64   access;
-       u64   input1;
-       u64   op_data;
-       u64   output;
-       u64   table;
-   };
-
-See libdax/common/sys/dax1/dax1_ccb.h for a detailed description of
-each of these fields, and see dax-hv-api.txt for a complete description
-of the Hypervisor API available to the guest OS (ie, Linux kernel).
-
-The first word (control) is examined by the driver for the following:
- - CCB version, which must be consistent with hardware version
- - Opcode, which must be one of the documented allowable commands
- - Address types, which must be set to "virtual" for all the addresses
-   given by the user, thereby ensuring that the application can
-   only access memory that it owns
-
-
-Example Code
-============
-
-The DAX is accessible to both user and kernel code.  The kernel code
-can make hypercalls directly while the user code must use wrappers
-provided by the driver. The setup of the CCB is nearly identical for
-both; the only difference is in preparation of the completion area. An
-example of user code is given now, with kernel code afterwards.
-
-In order to program using the driver API, the file
-arch/sparc/include/uapi/asm/oradax.h must be included.
-
-First, the proper device must be opened. For M7 it will be
-/dev/oradax1 and for M8 it will be /dev/oradax2. The simplest
-procedure is to attempt to open both, as only one will succeed::
-
-       fd = open("/dev/oradax1", O_RDWR);
-       if (fd < 0)
-               fd = open("/dev/oradax2", O_RDWR);
-       if (fd < 0)
-              /* No DAX found */
-
-Next, the completion area must be mapped::
-
-      completion_area = mmap(NULL, DAX_MMAP_LEN, PROT_READ, MAP_SHARED, fd, 0);
-
-All input and output buffers must be fully contained in one hardware
-page, since as explained above, the DAX is strictly constrained by
-virtual page boundaries.  In addition, the output buffer must be
-64-byte aligned and its size must be a multiple of 64 bytes because
-the coprocessor writes in units of cache lines.
-
-This example demonstrates the DAX Scan command, which takes as input a
-vector and a match value, and produces a bitmap as the output. For
-each input element that matches the value, the corresponding bit is
-set in the output.
-
-In this example, the input vector consists of a series of single bits,
-and the match value is 0. So each 0 bit in the input will produce a 1
-in the output, and vice versa, which produces an output bitmap which
-is the input bitmap inverted.
-
-For details of all the parameters and bits used in this CCB, please
-refer to section 36.2.1.3 of the DAX Hypervisor API document, which
-describes the Scan command in detail::
-
-       ccb->control =       /* Table 36.1, CCB Header Format */
-                 (2L << 48)     /* command = Scan Value */
-               | (3L << 40)     /* output address type = primary virtual */
-               | (3L << 34)     /* primary input address type = primary virtual */
-                            /* Section 36.2.1, Query CCB Command Formats */
-               | (1 << 28)     /* 36.2.1.1.1 primary input format = fixed width bit packed */
-               | (0 << 23)     /* 36.2.1.1.2 primary input element size = 0 (1 bit) */
-               | (8 << 10)     /* 36.2.1.1.6 output format = bit vector */
-               | (0 <<  5)     /* 36.2.1.3 First scan criteria size = 0 (1 byte) */
-               | (31 << 0);    /* 36.2.1.3 Disable second scan criteria */
-
-       ccb->completion = 0;    /* Completion area address, to be filled in by driver */
-
-       ccb->input0 = (unsigned long) input; /* primary input address */
-
-       ccb->access =       /* Section 36.2.1.2, Data Access Control */
-                 (2 << 24)    /* Primary input length format = bits */
-               | (nbits - 1); /* number of bits in primary input stream, minus 1 */
-
-       ccb->input1 = 0;       /* secondary input address, unused */
-
-       ccb->op_data = 0;      /* scan criteria (value to be matched) */
-
-       ccb->output = (unsigned long) output;   /* output address */
-
-       ccb->table = 0;        /* table address, unused */
-
-The CCB submission is a write() or pwrite() system call to the
-driver. If the call fails, then a read() must be used to retrieve the
-status::
-
-       if (pwrite(fd, ccb, 64, 0) != 64) {
-               struct ccb_exec_result status;
-               read(fd, &status, sizeof(status));
-               /* bail out */
-       }
-
-After a successful submission of the CCB, the completion area may be
-polled to determine when the DAX is finished. Detailed information on
-the contents of the completion area can be found in section 36.2.2 of
-the DAX HV API document::
-
-       while (1) {
-               /* Monitored Load */
-               __asm__ __volatile__("lduba [%1] 0x84, %0\n"
-                                    : "=r" (status)
-                                    : "r"  (completion_area));
-
-               if (status)          /* 0 indicates command in progress */
-                       break;
-
-               /* MWAIT */
-               __asm__ __volatile__("wr %%g0, 1000, %%asr28\n" ::);    /* 1000 ns */
-       }
-
-A completion area status of 1 indicates successful completion of the
-CCB and validity of the output bitmap, which may be used immediately.
-All other non-zero values indicate error conditions which are
-described in section 36.2.2::
-
-       if (completion_area[0] != 1) {  /* section 36.2.2, 1 = command ran and succeeded */
-               /* completion_area[0] contains the completion status */
-               /* completion_area[1] contains an error code, see 36.2.2 */
-       }
-
-After the completion area has been processed, the driver must be
-notified that it can release any resources associated with the
-request. This is done via the dequeue operation::
-
-       struct dax_command cmd;
-       cmd.command = CCB_DEQUEUE;
-       if (write(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
-               /* bail out */
-       }
-
-Finally, normal program cleanup should be done, i.e., unmapping
-completion area, closing the dax device, freeing memory etc.
-
-Kernel example
---------------
-
-The only difference in using the DAX in kernel code is the treatment
-of the completion area. Unlike user applications which mmap the
-completion area allocated by the driver, kernel code must allocate its
-own memory to use for the completion area, and this address and its
-type must be given in the CCB::
-
-       ccb->control |=      /* Table 36.1, CCB Header Format */
-               (3L << 32);     /* completion area address type = primary virtual */
-
-       ccb->completion = (unsigned long) completion_area;   /* Completion area address */
-
-The dax submit hypercall is made directly. The flags used in the
-ccb_submit call are documented in the DAX HV API in section 36.3.1/
-
-::
-
-  #include <asm/hypervisor.h>
-
-       hv_rv = sun4v_ccb_submit((unsigned long)ccb, 64,
-                                HV_CCB_QUERY_CMD |
-                                HV_CCB_ARG0_PRIVILEGED | HV_CCB_ARG0_TYPE_PRIMARY |
-                                HV_CCB_VA_PRIVILEGED,
-                                0, &bytes_accepted, &status_data);
-
-       if (hv_rv != HV_EOK) {
-               /* hv_rv is an error code, status_data contains */
-               /* potential additional status, see 36.3.1.1 */
-       }
-
-After the submission, the completion area polling code is identical to
-that in user land::
-
-       while (1) {
-               /* Monitored Load */
-               __asm__ __volatile__("lduba [%1] 0x84, %0\n"
-                                    : "=r" (status)
-                                    : "r"  (completion_area));
-
-               if (status)          /* 0 indicates command in progress */
-                       break;
-
-               /* MWAIT */
-               __asm__ __volatile__("wr %%g0, 1000, %%asr28\n" ::);    /* 1000 ns */
-       }
-
-       if (completion_area[0] != 1) {  /* section 36.2.2, 1 = command ran and succeeded */
-               /* completion_area[0] contains the completion status */
-               /* completion_area[1] contains an error code, see 36.2.2 */
-       }
-
-The output bitmap is ready for consumption immediately after the
-completion status indicates success.
-
-Excer[t from UltraSPARC Virtual Machine Specification
-=====================================================
-
- .. include:: dax-hv-api.txt
-    :literal:
index 498343c7ab088e8ed6b981ead561dd94f39fbff6..22baa077a3b90842756c1500477ec4f9b6193d59 100644 (file)
@@ -214,6 +214,57 @@ call is done from the thread assisting the interrupt handler. This is a
 building block for OP-TEE OS in secure world to implement the top half and
 bottom half style of device drivers.
 
+OPTEE_INSECURE_LOAD_IMAGE Kconfig option
+----------------------------------------
+
+The OPTEE_INSECURE_LOAD_IMAGE Kconfig option enables the ability to load the
+BL32 OP-TEE image from the kernel after the kernel boots, rather than loading
+it from the firmware before the kernel boots. This also requires enabling the
+corresponding option in Trusted Firmware for Arm. The Trusted Firmware for Arm
+documentation [8] explains the security threat associated with enabling this as
+well as mitigations at the firmware and platform level.
+
+There are additional attack vectors/mitigations for the kernel that should be
+addressed when using this option.
+
+1. Boot chain security.
+
+   * Attack vector: Replace the OP-TEE OS image in the rootfs to gain control of
+     the system.
+
+   * Mitigation: There must be boot chain security that verifies the kernel and
+     rootfs, otherwise an attacker can modify the loaded OP-TEE binary by
+     modifying it in the rootfs.
+
+2. Alternate boot modes.
+
+   * Attack vector: Using an alternate boot mode (i.e. recovery mode), the
+     OP-TEE driver isn't loaded, leaving the SMC hole open.
+
+   * Mitigation: If there are alternate methods of booting the device, such as a
+     recovery mode, it should be ensured that the same mitigations are applied
+     in that mode.
+
+3. Attacks prior to SMC invocation.
+
+   * Attack vector: Code that is executed prior to issuing the SMC call to load
+     OP-TEE can be exploited to then load an alternate OS image.
+
+   * Mitigation: The OP-TEE driver must be loaded before any potential attack
+     vectors are opened up. This should include mounting of any modifiable
+     filesystems, opening of network ports or communicating with external
+     devices (e.g. USB).
+
+4. Blocking SMC call to load OP-TEE.
+
+   * Attack vector: Prevent the driver from being probed, so the SMC call to
+     load OP-TEE isn't executed when desired, leaving it open to being executed
+     later and loading a modified OS.
+
+   * Mitigation: It is recommended to build the OP-TEE driver as builtin driver
+     rather than as a module to prevent exploits that may cause the module to
+     not be loaded.
+
 AMD-TEE driver
 ==============
 
@@ -309,3 +360,5 @@ References
 [6] include/linux/psp-tee.h
 
 [7] drivers/tee/amdtee/amdtee_if.h
+
+[8] https://trustedfirmware-a.readthedocs.io/en/latest/threat_model/threat_model.html
index b927fb2b94dc43eb2ac062f16f470e6a736fa385..e8bca5fea7ccc9d33d222cb7a3d182eacda9e731 100644 (file)
@@ -3510,7 +3510,7 @@ directories, the rmdir will fail with EBUSY.
 Stack trace
 -----------
 Since the kernel has a fixed sized stack, it is important not to
-waste it in functions. A kernel developer must be conscience of
+waste it in functions. A kernel developer must be conscious of
 what they allocate on the stack. If they add too much, the system
 can be in danger of a stack overflow, and corruption will occur,
 usually leading to a system panic.
index 18a5822c7d9a85be55502990ebe6b2690e4fae52..20994f4bfa31e9417686bc3153c084a086e80539 100644 (file)
@@ -1,6 +1,6 @@
 .. include:: ../disclaimer-ita.rst
 
-:Original: :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+:Original: :ref:`Documentation/process/security-bugs.rst <securitybugs>`
 
 .. _it_securitybugs:
 
index 0f6898860d6d1ece70c9efb9e76011007c693668..17abc25ee4c1e4ad581bb737cb70f3f20ec32b8e 100644 (file)
@@ -1,7 +1,6 @@
 .. include:: ../disclaimer-ita.rst
 
-:Original: :doc:`../../../core-api/symbol-namespaces`
-:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
+:Original: Documentation/core-api/symbol-namespaces.rst
 
 ===========================
 Spazio dei nomi dei simboli
index 993d549ee2b809fc2c4977803239fcb789fd122f..c7076a21667a64471019addf568ec1fd7999e6a1 100644 (file)
@@ -1,7 +1,6 @@
 .. include:: ../disclaimer-ita.rst
 
-.. note:: Per leggere la documentazione originale in inglese:
-         :ref:`Documentation/doc-guide/index.rst <doc_guide>`
+:Original: Documentation/doc-guide/index.rst
 
 =========================================
 Includere gli i file di intestazione uAPI
@@ -190,7 +189,7 @@ COPYRIGHT
 
 Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
 
-Licenza GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+Licenza GPLv2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>.
 
 Questo è software libero: siete liberi di cambiarlo e ridistribuirlo.
 Non c'è alcuna garanzia, nei limiti permessi dalla legge.
index fc5f39814e831ea215aedd3ee6a9abb7049977b9..b95dfa1ded0484cb61359a22443c8526f1058703 100644 (file)
@@ -2,9 +2,9 @@
 
 .. _it_linux_doc:
 
-===================
-Traduzione italiana
-===================
+==================================
+La documentazione del kernel Linux
+==================================
 
 .. raw:: latex
 
@@ -12,6 +12,18 @@ Traduzione italiana
 
 :manutentore: Federico Vaga <federico.vaga@vaga.pv.it>
 
+Questo è il livello principale della documentazione del kernel in
+lingua italiana. La traduzione è incompleta, noterete degli avvisi
+che vi segnaleranno la mancanza di una traduzione o di un gruppo di
+traduzioni.
+
+Più in generale, la documentazione, come il kernel stesso, sono in
+costante sviluppo; particolarmente vero in quanto stiamo lavorando
+alla riorganizzazione della documentazione in modo più coerente.
+I miglioramenti alla documentazione sono sempre i benvenuti; per cui,
+se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso
+vger.kernel.org.
+
 .. _it_disclaimer:
 
 Avvertenze
@@ -54,23 +66,8 @@ Se avete bisogno d'aiuto per comunicare con la comunità Linux ma non vi sentite
 a vostro agio nello scrivere in inglese, potete chiedere aiuto al manutentore
 della traduzione.
 
-La documentazione del kernel Linux
-==================================
-
-Questo è il livello principale della documentazione del kernel in
-lingua italiana. La traduzione è incompleta, noterete degli avvisi
-che vi segnaleranno la mancanza di una traduzione o di un gruppo di
-traduzioni.
-
-Più in generale, la documentazione, come il kernel stesso, sono in
-costante sviluppo; particolarmente vero in quanto stiamo lavorando
-alla riorganizzazione della documentazione in modo più coerente.
-I miglioramenti alla documentazione sono sempre i benvenuti; per cui,
-se vuoi aiutare, iscriviti alla lista di discussione linux-doc presso
-vger.kernel.org.
-
 Lavorare con la comunità di sviluppo
-------------------------------------
+====================================
 
 Le guide fondamentali per l'interazione con la comunità di sviluppo del kernel e
 su come vedere il proprio lavoro integrato.
@@ -85,7 +82,7 @@ su come vedere il proprio lavoro integrato.
 
 
 Manuali sull'API interna
-------------------------
+========================
 
 Di seguito una serie di manuali per gli sviluppatori che hanno bisogno di
 interfacciarsi con il resto del kernel.
@@ -96,7 +93,7 @@ interfacciarsi con il resto del kernel.
    core-api/index
 
 Strumenti e processi per lo sviluppo
-------------------------------------
+====================================
 
 Di seguito una serie di manuali contenenti informazioni utili a tutti gli
 sviluppatori del kernel.
@@ -109,7 +106,7 @@ sviluppatori del kernel.
    kernel-hacking/index
 
 Documentazione per gli utenti
------------------------------
+=============================
 
 Di seguito una serie di manuali per gli *utenti* del kernel - ovvero coloro che
 stanno cercando di farlo funzionare al meglio per un dato sistema, ma anche
@@ -120,16 +117,16 @@ Consultate anche `Linux man pages <https://www.kernel.org/doc/man-pages/>`_, che
 vengono mantenuti separatamente dalla documentazione del kernel Linux
 
 Documentazione relativa ai firmware
------------------------------------
+===================================
 Di seguito informazioni sulle aspettative del kernel circa i firmware.
 
 
 Documentazione specifica per architettura
------------------------------------------
+=========================================
 
 
 Documentazione varia
---------------------
+====================
 
 Ci sono documenti che sono difficili da inserire nell'attuale organizzazione
 della documentazione; altri hanno bisogno di essere migliorati e/o convertiti
index 05d362b16bf0b2af3b7c9049f1b5b022bc949589..a9e781d2e323021a6c2af16d1e7429e324a99527 100644 (file)
@@ -1029,6 +1029,11 @@ Dato che questo è un problema abbastanza comune con una propensione
 alle corse critiche, dovreste usare timer_delete_sync()
 (``include/linux/timer.h``) per gestire questo caso.
 
+Prima di rilasciare un temporizzatore dovreste chiamare la funzione
+timer_shutdown() o timer_shutdown_sync() di modo che non venga più ricarmato.
+Ogni successivo tentativo di riarmare il temporizzatore verrà silenziosamente
+ignorato.
+
 Velocità della sincronizzazione
 ===============================
 
index cf92a16ed7e5e274de9f934ce9cc25453bb2dfa4..a7e2a3238415b11e5a6f5197598a811ff260ec01 100644 (file)
@@ -265,15 +265,18 @@ Le etichette in uso più comuni sono:
    :ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>`
 
  - Reported-by: menziona l'utente che ha riportato il problema corretto da
-   questa patch; quest'etichetta viene usata per dare credito alle persone
-   che hanno verificato il codice e ci hanno fatto sapere quando le cose non
-   funzionavano correttamente.
+   questa patch; quest'etichetta viene usata per dare credito alle persone che
+   hanno verificato il codice e ci hanno fatto sapere quando le cose non
+   funzionavano correttamente. Se esiste un rapporto disponibile sul web, allora
+   L'etichetta dovrebbe essere seguita da un collegamento al suddetto rapporto.
 
  - Cc: la persona menzionata ha ricevuto una copia della patch ed ha avuto
    l'opportunità di commentarla.
 
-State attenti ad aggiungere queste etichette alla vostra patch: solo
-"Cc:" può essere aggiunta senza il permesso esplicito della persona menzionata.
+State attenti ad aggiungere queste etichette alla vostra patch: solo "Cc:" può
+essere aggiunta senza il permesso esplicito della persona menzionata. Il più
+delle volte anche Reported-by: va bene, ma è sempre meglio chiedere specialmente
+se il baco è stato riportato in una comunicazione privata.
 
 Inviare la modifica
 -------------------
index 473ec2cc558e48f5e55b22b11e84dfe6bd31873c..f37c53f8b5242638aa18a70d54028428c3f02905 100644 (file)
@@ -36,7 +36,7 @@ GNU C                  5.1                gcc --version
 Clang/LLVM (optional)  11.0.0             clang --version
 GNU make               3.81               make --version
 bash                   4.2                bash --version
-binutils               2.23               ld -v
+binutils               2.25               ld -v
 flex                   2.5.35             flex --version
 bison                  2.0                bison --version
 pahole                 1.16               pahole --version
@@ -97,7 +97,7 @@ Questo richiede bash 4.2 o successivo.
 Binutils
 --------
 
-Per generare il kernel è necessario avere Binutils 2.23 o superiore.
+Per generare il kernel è necessario avere Binutils 2.25 o superiore.
 
 pkg-config
 ----------
index 77eac809a63929feeb68205f7ebcfc8ee3376b67..29f83c198025c6d3ce7d2866f785c60d6f06f200 100644 (file)
@@ -40,7 +40,7 @@ Linux più popolari. Cercate ``clang-format`` nel vostro repositorio.
 Altrimenti, potete scaricare una versione pre-generata dei binari di LLVM/clang
 oppure generarlo dai codici sorgenti:
 
-    http://releases.llvm.org/download.html
+    https://releases.llvm.org/download.html
 
 Troverete più informazioni ai seguenti indirizzi:
 
index a393ee4182af4544f9dab5230e3561c463e17145..5f244e16f51148d49c89178b3757652d54f54878 100644 (file)
@@ -1204,10 +1204,10 @@ ISBN 0-201-61586-X.
 
 Manuali GNU - nei casi in cui sono compatibili con K&R e questo documento -
 per indent, cpp, gcc e i suoi dettagli interni, tutto disponibile qui
-http://www.gnu.org/manual/
+https://www.gnu.org/manual/
 
 WG14 è il gruppo internazionale di standardizzazione per il linguaggio C,
-URL: http://www.open-std.org/JTC1/SC22/WG14/
+URL: https://www.open-std.org/JTC1/SC22/WG14/
 
-Kernel process/coding-style.rst, by greg@kroah.com at OLS 2002:
+Kernel CodingStyle, by greg@kroah.com at OLS 2002:
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
index febf838977835a2589d30f66b5824a11fa07ee13..57b501f0dfa4811564e035a837f26562d01ce1e3 100644 (file)
@@ -332,7 +332,7 @@ zero come risultato::
 
 Il valore di ``size`` nell'ultima riga sarà ``zero``, quando uno
 invece si aspetterebbe che il suo valore sia la dimensione totale in
-byte dell'allocazione dynamica che abbiamo appena fatto per l'array
+byte dell'allocazione dinamica che abbiamo appena fatto per l'array
 ``items``. Qui un paio di esempi reali del problema: `collegamento 1
 <https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
 `collegamento 2
@@ -381,4 +381,29 @@ combinazione con struct_size() e flex_array_size()::
         instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
         instance->count = count;
 
-       memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
+        memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
+
+Ci sono due casi speciali dove è necessario usare la macro DECLARE_FLEX_ARRAY()
+(da notare che la stessa macro è chiamata __DECLARE_FLEX_ARRAY() nei file di
+intestazione UAPI). Uno è quando l'array flessibile è l'unico elemento di una
+struttura, e l'altro è quando è parti un unione. Per motivi non tecnici, entrambi
+i casi d'uso non sono permessi dalla specifica C99. Per esempio, per
+convertire il seguente codice::
+
+    struct something {
+        ...
+        union {
+            struct type1 one[0];
+            struct type2 two[0];
+        };
+    };
+
+La macro di supporto dev'essere usata::
+
+    struct something {
+        ...
+        union {
+            DECLARE_FLEX_ARRAY(struct type1, one);
+            DECLARE_FLEX_ARRAY(struct type2, two);
+        };
+    };
index 970671cd91af353c4d37a7b010c19e1eaf9af73c..76ca3226c8cd7a691aaa5bb4fd1c06e92088b3e9 100644 (file)
@@ -364,3 +364,28 @@ un editor esterno.
 
 Un altro problema è che Gmail usa la codifica base64 per tutti quei messaggi
 che contengono caratteri non ASCII. Questo include cose tipo i nomi europei.
+
+Proton Mail
+***********
+
+Il servizio Proton Mail ha una funzionalità che cripta tutti i messaggi verso
+ogni destinatario per cui è possibile trovare una chiave usando il *Web Key
+Directory* (WKD). Il servizio kernel.org pubblica il WKD per ogni sviluppatore
+in possesso di un conto kernel.org. Di conseguenza, tutti i messaggi inviati
+usando Proton Mail verso indirizzi kernel.org verranno criptati.
+
+Proton Mail non fornisce alcun meccanismo per disabilitare questa funzionalità
+perché verrebbe considerato un problema per la riservatezza. Questa funzionalità
+è attiva anche quando si inviano messaggi usando il Proton Mail Bridge. Dunque
+tutta la posta in uscita verrà criptata, incluse le patch inviate con ``git
+send-email``.
+
+I messaggi criptati sono una fonte di problemi; altri sviluppatori potrebbero
+non aver configurato i loro programmi, o strumenti, per gestire messaggi
+criptati; inoltre, alcuni programmi di posta elettronica potrebbero criptare le
+risposte a messaggi criptati per tutti i partecipanti alla discussione, inclusa
+la lista di discussione stessa.
+
+A meno che non venga introdotta una maniera per disabilitare questa
+funzionalità, non è consigliato usare Proton Mail per contribuire allo sviluppo
+del kernel.
index 25602c1a97d1724f8fc2bc3eb9bedcb4b91d4594..cd7977905fb880acc63fb7f8cc128d9929ef30f5 100644 (file)
@@ -10,6 +10,7 @@
 
 .. _it_process_index:
 
+===============================================
 Lavorare con la comunità di sviluppo del kernel
 ===============================================
 
index 5526bcabeb0aac5d480f1cd222700312353837bb..cdc43c4a9b0b0d0c8491a804c7475c416e05dd92 100644 (file)
@@ -68,42 +68,24 @@ stesso.
 Strumenti PGP
 =============
 
-Usare GnuPG v2
---------------
+Usare GnuPG 2.2 o successivo
+----------------------------
 
 La vostra distribuzione potrebbe avere già installato GnuPG, dovete solo
-verificare che stia utilizzando la versione 2.x e non la serie 1.4 --
-molte distribuzioni forniscono entrambe, di base il comando ''gpg''
-invoca GnuPG v.1. Per controllate usate::
+verificare che stia utilizzando la versione abbastanza recente. Per controllate
+usate::
 
     $ gpg --version | head -n1
 
-Se visualizzate ``gpg (GnuPG) 1.4.x``, allora state usando GnuPG v.1.
-Provate il comando ``gpg2`` (se non lo avete, potreste aver bisogno
-di installare il pacchetto gnupg2)::
-
-    $ gpg2 --version | head -n1
-
-Se visualizzate  ``gpg (GnuPG) 2.x.x``, allora siete pronti a partire.
-Questa guida assume che abbiate la versione 2.2.(o successiva) di GnuPG.
-Se state usando la versione 2.0, alcuni dei comandi indicati qui non
-funzioneranno, in questo caso considerate un aggiornamento all'ultima versione,
-la 2.2. Versioni di gnupg-2.1.11 e successive dovrebbero essere compatibili
-per gli obiettivi di questa guida.
-
-Se avete entrambi i comandi: ``gpg`` e ``gpg2``, assicuratevi di utilizzare
-sempre la versione V2, e non quella vecchia. Per evitare errori potreste creare
-un alias::
-
-    $ alias gpg=gpg2
-
-Potete mettere questa opzione nel vostro  ``.bashrc`` in modo da essere sicuri.
+Se state utilizzando la version 2.2 o successiva, allora siete pronti a partire.
+Se invece state usando una versione precedente, allora alcuni comandi elencati
+in questa guida potrebbero non funzionare.
 
 Configurare le opzioni di gpg-agent
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 L'agente GnuPG è uno strumento di aiuto che partirà automaticamente ogni volta
-che userete il comando ``gpg`` e funzionerà in background con l'obiettivo di
+che userete il comando ``gpg`` e funzionerà in *background* con l'obiettivo di
 individuare la passphrase. Ci sono due opzioni che dovreste conoscere
 per personalizzare la scadenza della passphrase nella cache:
 
@@ -131,19 +113,7 @@ valori::
     riguarda vecchie le versioni di GnuPG, poiché potrebbero non svolgere più
     bene il loro compito.
 
-Impostare un *refresh* con cronjob
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Potreste aver bisogno di rinfrescare regolarmente il vostro portachiavi in
-modo aggiornare le chiavi pubbliche di altre persone, lavoro che è svolto
-al meglio con un cronjob giornaliero::
-
-    @daily /usr/bin/gpg2 --refresh >/dev/null 2>&1
-
-Controllate il percorso assoluto del vostro comando ``gpg`` o ``gpg2`` e usate
-il comando ``gpg2`` se per voi ``gpg`` corrisponde alla versione GnuPG v.1.
-
-.. _it_master_key:
+.. _it_protect_your_key:
 
 Proteggere la vostra chiave PGP primaria
 ========================================
@@ -155,55 +125,62 @@ al documento "`Protecting Code Integrity`_" che abbiamo menzionato prima.
 Dovreste inoltre creare una nuova chiave se quella attuale è inferiore a 2048
 bit (RSA).
 
-Chiave principale o sottochiavi
--------------------------------
-
-Le sottochiavi sono chiavi PGP totalmente indipendenti, e sono collegate alla
-chiave principale attraverso firme certificate. È quindi importante
-comprendere i seguenti punti:
-
-1. Non ci sono differenze tecniche tra la chiave principale e la sottochiave.
-2. In fase di creazione, assegniamo limitazioni funzionali ad ogni chiave
-   assegnando capacità specifiche.
-3. Una chiave PGP può avere 4 capacità:
+Le sottochiavi PGP
+------------------
 
-   - **[S]** può essere usata per firmare
-   - **[E]** può essere usata per criptare
-   - **[A]** può essere usata per autenticare
-   - **[C]** può essere usata per certificare altre chiavi
+Raramente le chiavi PGP sono composte da una singola coppia -- solitamente, sono
+una collezione di sottochiavi indipendenti usate per diversi scopi in funzione
+delle capacità assegnate al momento della creazione. Una chiave PGP può avere
+quattro capacità:
+
+- **[S]** può essere usata per firmare
+- **[E]** può essere usata per criptare
+- **[A]** può essere usata per autenticare
+- **[C]** può essere usata per certificare altre chiavi
+
+La chiave con la capacità **[C]** viene spesso chiamata chiave "passepartout"
+(*master key*), ma è una terminologia fuorviante perché lascia intendere che la
+chiave di certificato possa essere usate in sostituzione delle altre (proprio
+come le vere chiavi passpartout in grado di aprire diverse serrature). Dato che
+questo non è il caso, per evitare fraintendimenti, in questa guida ci riferiremo
+a questa chiave chiamandola "La chiave di certificazione".
+
+I seguenti punti sono molto importanti:
+
+1. Tutte le sottochiavi sono indipendenti. Se perdete una sottochiave privata
+   non potrete recuperarla usando le altre.
+2. Ad eccezione della chiave di certificazione, ci possono essere più
+   sottochiavi con le stesse capacità (per esempio, potete avere 2 sottochiavi
+   per criptare, 3 per firmare, ma solo una per una sola per certificare). Tutte
+   le sottochiavi sono indipendenti -- un messaggio criptato usando una chiave
+   **[E]** non può essere decriptato usano altre sottochiavi **[E]**.
+3. Una sottochiave può avere più capacità (per esempio, la chiave **[C]** può
+   anche essere una chiave **[S]**).
+
+La chiave con capacità **[C]** (certificazione) è la sola che può essere usata
+per indicare relazioni fra chiavi. Solo la chiave **[C]** può essere usata per:
+
+- aggiungere o revocare altre chiavi (sottochiavi) che hanno capacità S/E/A;
+- aggiungere, modificare o eliminare le identità (unids) associate alla chiave;
+- aggiungere o modificare la propria data di scadenza o delle sottochiavi;
+- firmare le chiavi di altre persone a scopo di creare una rete di fiducia.
 
-4. Una singola chiave può avere più capacità
-5. Una sottochiave è completamente indipendente dalla chiave principale.
-   Un messaggio criptato con la sottochiave non può essere decrittato con
-   quella principale. Se perdete la vostra sottochiave privata, non può
-   essere rigenerata in nessun modo da quella principale.
+Di base, alla creazione di nuove chiavi, GnuPG genera quanto segue:
 
-La chiave con capacità **[C]** (certify) è identificata come la chiave
-principale perché è l'unica che può essere usata per indicare la relazione
-con altre chiavi. Solo la chiave **[C]** può essere usata per:
+- Una chiave la capacità di certificazione che quella di firma (**[SC]**)
+- Una sottochiave separata con capacità di criptare (**[E]**)
 
-- Aggiungere o revocare altre chiavi (sottochiavi) che hanno capacità S/E/A
-- Aggiungere, modificare o eliminare le identità (unids) associate alla chiave
-- Aggiungere o modificare la data di termine di sé stessa o di ogni sottochiave
-- Firmare le chiavi di altre persone a scopo di creare una rete di fiducia
 
-Di base, alla creazione di nuove chiavi, GnuPG genera quanto segue:
 
-- Una chiave madre che porta sia la capacità di certificazione che quella
-  di firma (**[SC]**)
-- Una sottochiave separata con capacità di criptaggio (**[E]**)
 
-Se avete usato i parametri di base per generare la vostra chiave, quello
+Se avete usato i parametri predefiniti per generare la vostra chiave, quello
 sarà il risultato. Potete verificarlo utilizzando ``gpg --list-secret-keys``,
 per esempio::
 
-    sec   rsa2048 2018-01-23 [SC] [expires: 2020-01-23]
+    sec   ed25519 2022-12-20 [SC] [expires: 2024-12-19]
           000000000000000000000000AAAABBBBCCCCDDDD
     uid           [ultimate] Alice Dev <adev@kernel.org>
-    ssb   rsa2048 2018-01-23 [E] [expires: 2020-01-23]
-
-Qualsiasi chiave che abbia la capacità **[C]** è la vostra chiave madre,
-indipendentemente da quali altre capacità potreste averle assegnato.
+    ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]
 
 La lunga riga sotto la voce ``sec`` è la vostra impronta digitale --
 negli esempi che seguono, quando vedere ``[fpr]`` ci si riferisce a questa
@@ -238,20 +215,10 @@ possano ricevere la vostra nuova sottochiave::
     $ gpg --send-key [fpr]
 
 .. note:: Supporto ECC in GnuPG
-    GnuPG 2.1 e successivi supportano pienamente *Elliptic Curve Cryptography*,
-    con la possibilità di combinare sottochiavi ECC con le tradizionali chiavi
-    primarie RSA. Il principale vantaggio della crittografia ECC è che è molto
-    più veloce da calcolare e crea firme più piccole se confrontate byte per
-    byte con le chiavi RSA a più di 2048 bit. A meno che non pensiate di
-    utilizzare un dispositivo smartcard che non supporta le operazioni ECC, vi
-    raccomandiamo ti creare sottochiavi di firma ECC per il vostro lavoro col
-    kernel.
-
-    Se per qualche ragione preferite rimanere con sottochiavi RSA, nel comando
-    precedente, sostituite "ed25519" con "rsa2048". In aggiunta, se avete
-    intenzione di usare un dispositivo hardware che non supporta le chiavi
-    ED25519 ECC, come la Nitrokey Pro o la Yubikey, allora dovreste usare
-    "nistp256" al posto di "ed25519".
+
+   Tenete presente che se avete intenzione di usare un dispositivo che non
+   supporta chiavi ED25519 ECC, allora dovreste usare "nistp256" al posto di
+   "ed25519". Più avanti ci sono alcune raccomandazioni per i dispositivi.
 
 Copia di riserva della chiave primaria per gestire il recupero da disastro
 --------------------------------------------------------------------------
@@ -360,13 +327,13 @@ Per prima cosa, identificate il keygrip della vostra chiave primaria::
 
 L'output assomiglierà a questo::
 
-    pub   rsa2048 2018-01-24 [SC] [expires: 2020-01-24]
+    pub   ed25519 2022-12-20 [SC] [expires: 2022-12-19]
           000000000000000000000000AAAABBBBCCCCDDDD
           Keygrip = 1111000000000000000000000000000000000000
     uid           [ultimate] Alice Dev <adev@kernel.org>
-    sub   rsa2048 2018-01-24 [E] [expires: 2020-01-24]
+    sub   cv25519 2022-12-20 [E] [expires: 2022-12-19]
           Keygrip = 2222000000000000000000000000000000000000
-    sub   ed25519 2018-01-24 [S]
+    sub   ed25519 2022-12-20 [S]
           Keygrip = 3333000000000000000000000000000000000000
 
 Trovate la voce keygrid che si trova sotto alla riga ``pub`` (appena sotto
@@ -389,11 +356,11 @@ Ora, se eseguite il comando ``--list-secret-keys``, vedrete che la chiave
 primaria non compare più (il simbolo ``#`` indica che non è disponibile)::
 
     $ gpg --list-secret-keys
-    sec#  rsa2048 2018-01-24 [SC] [expires: 2020-01-24]
+    sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
           000000000000000000000000AAAABBBBCCCCDDDD
     uid           [ultimate] Alice Dev <adev@kernel.org>
-    ssb   rsa2048 2018-01-24 [E] [expires: 2020-01-24]
-    ssb   ed25519 2018-01-24 [S]
+    ssb   cv25519 2022-12-20 [E] [expires: 2024-12-19]
+    ssb   ed25519 2022-12-20 [S]
 
 Dovreste rimuovere anche i file ``secring.gpg`` che si trovano nella cartella
 ``~/.gnupg``, in quanto rimasugli delle versioni precedenti di GnuPG.
@@ -461,18 +428,20 @@ soluzioni disponibili:
   computer portatili più recenti. In aggiunta, offre altre funzionalità di
   sicurezza come FIDO, U2F, e ora supporta anche le chiavi ECC (NISTP)
 
-`Su LWN c'è una buona recensione`_ dei modelli elencati qui sopra e altri.
-La scelta dipenderà dal costo, dalla disponibilità nella vostra area
-geografica e vostre considerazioni sull'hardware aperto/proprietario.
+La vostra scelta dipenderà dal costo, la disponibilità nella vostra regione, e
+sulla scelta fra dispositivi aperti e proprietari.
 
-Se volete usare chiavi ECC, la vostra migliore scelta sul mercato è la
-Nitrokey Start.
+.. note::
+
+    Se siete nella lista MAINTAINERS o avete un profilo su kernel.org, allora
+    `potrete avere gratuitamente una Nitrokey Start`_ grazie alla fondazione
+    Linux.
 
 .. _`Nitrokey Start`: https://shop.nitrokey.com/shop/product/nitrokey-start-6
 .. _`Nitrokey Pro 2`: https://shop.nitrokey.com/shop/product/nitrokey-pro-2-3
 .. _`Yubikey 5`: https://www.yubico.com/product/yubikey-5-overview/
-.. _Gnuk: http://www.fsij.org/doc-gnuk/
-.. _`Su LWN c'è una buona recensione`: https://lwn.net/Articles/736231/
+.. _Gnuk: https://www.fsij.org/doc-gnuk/
+.. _`potrete avere gratuitamente una Nitrokey Start`: https://www.kernel.org/nitrokey-digital-tokens-for-kernel-developers.html
 
 Configurare il vostro dispositivo smartcard
 -------------------------------------------
@@ -513,6 +482,12 @@ altre informazioni sulla carta che potrebbero trapelare in caso di smarrimento.
     A dispetto del nome "PIN", né il PIN utente né quello dell'amministratore
     devono essere esclusivamente numerici.
 
+.. warning::
+
+    Alcuni dispositivi richiedono la presenza delle sottochiavi nel dispositivo
+    stesso prima che possiate cambiare la passphare. Verificate la
+    documentazione del produttore.
+
 Spostare le sottochiavi sulla smartcard
 ---------------------------------------
 
@@ -525,11 +500,11 @@ dell'amministratore::
 
     Secret subkeys are available.
 
-    pub  rsa2048/AAAABBBBCCCCDDDD
-         created: 2018-01-23  expires: 2020-01-23  usage: SC
+    pub  ed25519/AAAABBBBCCCCDDDD
+         created: 2022-12-20  expires: 2024-12-19  usage: SC
          trust: ultimate      validity: ultimate
-    ssb  rsa2048/1111222233334444
-         created: 2018-01-23  expires: never       usage: E
+    ssb  cv25519/1111222233334444
+         created: 2022-12-20  expires: never       usage: E
     ssb  ed25519/5555666677778888
          created: 2017-12-07  expires: never       usage: S
     [ultimate] (1). Alice Dev <adev@kernel.org>
@@ -594,11 +569,11 @@ Ora, se doveste usare l'opzione ``--list-secret-keys``, vedrete una
 sottile differenza nell'output::
 
     $ gpg --list-secret-keys
-    sec#  rsa2048 2018-01-24 [SC] [expires: 2020-01-24]
+    sec#  ed25519 2022-12-20 [SC] [expires: 2024-12-19]
           000000000000000000000000AAAABBBBCCCCDDDD
     uid           [ultimate] Alice Dev <adev@kernel.org>
-    ssb>  rsa2048 2018-01-24 [E] [expires: 2020-01-24]
-    ssb>  ed25519 2018-01-24 [S]
+    ssb>  cv25519 2022-12-20 [E] [expires: 2024-12-19]
+    ssb>  ed25519 2022-12-20 [S]
 
 Il simbolo ``>`` in ``ssb>`` indica che la sottochiave è disponibile solo
 nella smartcard. Se tornate nella vostra cartella delle chiavi segrete e
@@ -661,7 +636,7 @@ eseguite::
 Se per voi è più facile da memorizzare, potete anche utilizzare una data
 specifica (per esempio, il vostro compleanno o capodanno)::
 
-    $ gpg --quick-set-expire [fpr] 2020-07-01
+    $ gpg --quick-set-expire [fpr] 2025-07-01
 
 Ricordatevi di inviare l'aggiornamento ai keyserver::
 
@@ -676,6 +651,21 @@ dovreste importarle nella vostra cartella di lavoro abituale::
     $ gpg --export | gpg --homedir ~/.gnupg --import
     $ unset GNUPGHOME
 
+Usare gpg-agent con ssh
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Se dovete firmare tag o commit su un sistema remoto, potete ridirezionare il
+vostro gpg-agent attraverso ssh. Consultate le istruzioni disponibili nella wiki
+GnuPG:
+
+- `Agent Forwarding over SSH`_
+
+Funziona senza troppi intoppi se avete la possibilità di modificare le
+impostazioni di sshd sul sistema remoto.
+
+.. _`Agent Forwarding over SSH`: https://wiki.gnupg.org/AgentForwarding
+
+.. _it_pgp_with_git:
 
 Usare PGP con Git
 =================
@@ -709,11 +699,6 @@ avere più chiavi segrete, potete dire a git quale dovrebbe usare (``[fpg]``
 
     $ git config --global user.signingKey [fpr]
 
-**IMPORTANTE**: se avete una comando dedicato per ``gpg2``, allora dovreste
-dire a git di usare sempre quello piuttosto che il vecchio comando ``gpg``::
-
-    $ git config --global gpg.program gpg2
-
 Come firmare i tag
 ------------------
 
@@ -812,6 +797,61 @@ Potete dire a git di firmare sempre i commit::
 
 .. _it_verify_identities:
 
+Come lavorare con patch firmate
+-------------------------------
+
+Esiste la possibilità di usare la vostra chiave PGP per firmare le patch che
+invierete alla liste di discussione del kernel. I meccanismi esistenti per la
+firma delle email (PGP-Mime o PGP-inline) tendono a causare problemi
+nell'attività di revisione del codice. Si suggerisce, invece, di utilizare lo
+strumento sviluppato da kernel.org che mette nell'intestazione del messaggio
+un'attestazione delle firme crittografiche (tipo DKIM):
+
+- `Patatt Patch Attestation`_
+
+.. _`Patatt Patch Attestation`: https://pypi.org/project/patatt/
+
+Installare e configurate patatt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Lo strumento patatt è disponibile per diverse distribuzioni, dunque cercatelo
+prima lì. Oppure potete installarlo usano pypi "``pip install patatt``"
+
+Se avete già configurato git con la vostra chiave PGP (usando
+``user.signingKey``), allora patatt non ha bisogno di alcuna configurazione
+aggiuntiva. Potete iniziare a firmare le vostre patch aggiungendo un aggancio a
+git-send-email nel vostro repositorio::
+
+    patatt install-hook
+
+Ora, qualsiasi patch che invierete con ``git send-email`` verrà automaticamente
+firmata usando la vostra firma crittografica.
+
+Verificare le firme di patatt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Se usate ``b4`` per verificare ed applicare le patch, allora tenterà
+automaticamente di verificare tutte le firme DKIM e patatt disponibili. Per
+esempio::
+
+    $ b4 am 20220720205013.890942-1-broonie@kernel.org
+    [...]
+    Checking attestation on all messages, may take a moment...
+    ---
+      ✓ [PATCH v1 1/3] kselftest/arm64: Correct buffer allocation for SVE Z registers
+      ✓ [PATCH v1 2/3] arm64/sve: Document our actual ABI for clearing registers on syscall
+      ✓ [PATCH v1 3/3] kselftest/arm64: Enforce actual ABI for SVE syscalls
+      ---
+      ✓ Signed: openpgp/broonie@kernel.org
+      ✓ Signed: DKIM/kernel.org
+
+.. note::
+
+   Lo sviluppo di patatt e b4 è piuttosto attivo. Si consiglia di verificare la
+   documentazione più recente.
+
+.. _it_kernel_identities:
+
 Come verificare l'identità degli sviluppatori del kernel
 ========================================================
 
@@ -884,64 +924,18 @@ di base di GnuPG v2). Per farlo, aggiungete (o modificate) l'impostazione
 
     trust-model tofu+pgp
 
-Come usare i keyserver in sicurezza
------------------------------------
-Se ottenete l'errore "No public key" quando cercate di validate il tag di
-qualcuno, allora dovreste cercare quella chiave usando un keyserver. È
-importante tenere bene a mente che non c'è alcuna garanzia che la chiave
-che avete recuperato da un keyserver PGP appartenga davvero alla persona
-reale -- è progettato così. Dovreste usare il Web of Trust per assicurarvi
-che la chiave sia valida.
-
-Come mantenere il Web of Trust va oltre gli scopi di questo documento,
-semplicemente perché farlo come si deve richiede sia sforzi che perseveranza
-che tendono ad andare oltre al livello di interesse della maggior parte degli
-esseri umani. Qui di seguito alcuni rapidi suggerimenti per aiutarvi a ridurre
-il rischio di importare chiavi maligne.
-
-Primo, diciamo che avete provato ad eseguire ``git verify-tag`` ma restituisce
-un errore dicendo che la chiave non è stata trovata::
-
-    $ git verify-tag sunxi-fixes-for-4.15-2
-    gpg: Signature made Sun 07 Jan 2018 10:51:55 PM EST
-    gpg:                using RSA key DA73759BF8619E484E5A3B47389A54219C0F2430
-    gpg:                issuer "wens@...org"
-    gpg: Can't check signature: No public key
-
-Cerchiamo nel keyserver per maggiori informazioni sull'impronta digitale
-della chiave (l'impronta digitale, probabilmente, appartiene ad una
-sottochiave, dunque non possiamo usarla direttamente senza trovare prima
-l'ID della chiave primaria associata ad essa)::
-
-    $ gpg --search DA73759BF8619E484E5A3B47389A54219C0F2430
-    gpg: data source: hkp://keys.gnupg.net
-    (1) Chen-Yu Tsai <wens@...org>
-          4096 bit RSA key C94035C21B4F2AEB, created: 2017-03-14, expires: 2019-03-15
-    Keys 1-1 of 1 for "DA73759BF8619E484E5A3B47389A54219C0F2430".  Enter number(s), N)ext, or Q)uit > q
-
-Localizzate l'ID della chiave primaria, nel nostro esempio
-``C94035C21B4F2AEB``. Ora visualizzate le chiavi di Linus Torvalds
-che avete nel vostro portachiavi::
-
-    $ gpg --list-key torvalds@kernel.org
-    pub   rsa2048 2011-09-20 [SC]
-          ABAF11C65A2970B130ABE3C479BE3E4300411886
-    uid           [ unknown] Linus Torvalds <torvalds@kernel.org>
-    sub   rsa2048 2011-09-20 [E]
-
-Poi, cercate un percorso affidabile da Linux Torvalds alla chiave che avete
-trovato con ``gpg --search`` usando la chiave sconosciuta.Per farlo potete usare
-diversi strumenti come https://github.com/mricon/wotmate,
-https://git.kernel.org/pub/scm/docs/kernel/pgpkeys.git/tree/graphs, e
-https://the.earth.li/~noodles/pathfind.html.
-
-Se trovate un paio di percorsi affidabili è un buon segno circa la validità
-della chiave. Ora, potete aggiungerla al vostro portachiavi dal keyserver::
-
-    $ gpg --recv-key C94035C21B4F2AEB
-
-Questa procedura non è perfetta, e ovviamente state riponendo la vostra
-fiducia nell'amministratore del servizio *PGP Pathfinder* sperando che non
-sia malintenzionato (infatti, questo va contro :ref:`it_devs_not_infra`).
-Tuttavia, se mantenete con cura la vostra rete di fiducia sarà un deciso
-miglioramento rispetto alla cieca fiducia nei keyserver.
+Usare il repositorio kernel.org per il web of trust
+---------------------------------------------------
+
+Il progetto kernel.org mantiene un repositorio git con le chiavi pubbliche degli sviluppatori in alternativa alla replica dei server di chiavi che negli ultimi anni sono spariti. La documentazione completa su come impostare il repositorio come vostra sorgente di chiavi pubbliche può essere trovato qui:
+
+- `Kernel developer PGP Keyring`_
+
+Se siete uno sviluppatore del kernel, per favore valutate l'idea di inviare la
+vostra chiave per l'inclusione in quel portachiavi.
+
+
+If you are a kernel developer, please consider submitting your key for
+inclusion into that keyring.
+
+.. _`Kernel developer PGP Keyring`: https://korg.docs.kernel.org/pgpkeys.html
index c1a9b481a6f9989a060a72c1e760e820777ac043..5bc5b9d42f31881735d83d72a06d09de4211683f 100644 (file)
@@ -18,10 +18,6 @@ Linux supporta anche ``clang`` [it-clang]_, leggete la documentazione
 Questo dialetto contiene diverse estensioni al linguaggio [it-gnu-extensions]_,
 e molte di queste vengono usate sistematicamente dal kernel.
 
-Il kernel offre un certo livello di supporto per la compilazione con
-``icc`` [it-icc]_ su diverse architetture, tuttavia in questo momento
-il supporto non è completo e richiede delle patch aggiuntive.
-
 Attributi
 ---------
 
@@ -43,11 +39,30 @@ possono usare e/o per accorciare il codice.
 Per maggiori informazioni consultate il file d'intestazione
 ``include/linux/compiler_attributes.h``.
 
+Rust
+----
+
+Il kernel supporta sperimentalmente il linguaggio di programmazione Rust
+[it-rust-language]_ abilitando l'opzione di configurazione ``CONFIG_RUST``. Il
+codice verrà compilato usando ``rustc`` [it-rustc]_ con l'opzione
+``--edition=2021`` [it-rust-editions]_. Le edizioni Rust sono un modo per
+introdurre piccole modifiche senza compatibilità all'indietro._
+
+In aggiunta, nel kernel vengono utilizzate alcune funzionalità considerate
+instabili [it-rust-unstable-features]_. Queste funzionalità potrebbero cambiare
+in futuro, dunque è un'obiettivo importante è quello di far uso solo di
+funzionalità stabili.
+
+Per maggiori informazioni fate riferimento a Documentation/rust/index.rst .
+
 .. [it-c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards
 .. [it-gcc] https://gcc.gnu.org
 .. [it-clang] https://clang.llvm.org
-.. [it-icc] https://software.intel.com/en-us/c-compilers
 .. [it-gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
 .. [it-gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
 .. [it-gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
 .. [it-n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+.. [it-rust-language] https://www.rust-lang.org
+.. [it-rustc] https://doc.rust-lang.org/rustc/
+.. [it-rust-editions] https://doc.rust-lang.org/edition-guide/editions/
+.. [it-rust-unstable-features] https://github.com/Rust-for-Linux/linux/issues/2
index 0be675b0319931b9c514f76f43a2738379306635..248bf1e4b171b49631d09953713531e3b9423b34 100644 (file)
@@ -106,6 +106,12 @@ al messaggio della patch, così:
 
     commit <sha1> upstream.
 
+o in alternativa:
+
+.. code-block:: none
+
+    [ Upstream commit <sha1>  ]
+
 In aggiunta, alcune patch inviate attraverso l':ref:`it_option_1` potrebbero
 dipendere da altre che devo essere incluse. Questa situazione può essere
 indicata nel seguente modo nell'area dedicata alle firme:
index c2cfa0948b2bc2994db7a497eb14b3f6dc7a64c4..447b18792e61a29ab9ed3faa362adbab70eebf18 100644 (file)
@@ -272,7 +272,7 @@ embargo potrebbe essere preso in considerazione per dare il tempo alle
 distribuzioni di prendere la patch e renderla disponibile ai loro utenti;
 in questo caso, ovviamente, la patch non dovrebbe essere inviata su alcuna
 lista di discussione pubblica. Leggete anche
-Documentation/admin-guide/security-bugs.rst.
+Documentation/process/security-bugs.rst.
 
 Patch che correggono bachi importanti su un kernel già rilasciato, dovrebbero
 essere inviate ai manutentori dei kernel stabili aggiungendo la seguente riga::
@@ -429,7 +429,7 @@ poi dovete solo aggiungere una riga che dice::
 
        Signed-off-by: Random J Developer <random@developer.example.org>
 
-usando il vostro vero nome (spiacenti, non si accettano pseudonimi o
+usando il vostro vero nome (spiacenti, non si accettano
 contributi anonimi). Questo verrà fatto automaticamente se usate
 ``git commit -s``. Anche il ripristino di uno stato precedente dovrebbe
 includere "Signed-off-by", se usate ``git revert -s`` questo verrà
@@ -785,7 +785,7 @@ Riferimenti
 -----------
 
 Andrew Morton, "La patch perfetta" (tpp).
-  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
+  <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
 
 Jeff Garzik, "Formato per la sottomissione di patch per il kernel Linux"
   <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
index efc640cac596ebeaec08d31c111418b15b428bca..4fff9a59b5482f83b765d03c86781162fdf45538 100644 (file)
@@ -119,9 +119,9 @@ concorrenza siano stati opportunamente considerati.
 Riferimenti
 ===========
 
-[1] http://lwn.net/Articles/233481/
+[1] https://lwn.net/Articles/233481/
 
-[2] http://lwn.net/Articles/233482/
+[2] https://lwn.net/Articles/233482/
 
 Crediti
 =======
index 9b0b3436dfcf785161727fc1dace32fdf9179831..8d856ebe873c65162c213eba423dcd054c52366f 100644 (file)
@@ -167,7 +167,7 @@ linux-api@vger.kernel.org に送ることを勧めます。
     このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
     そして、他のOSでの開発者が Linux に移る時にとても重要です。
 
-  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+  :ref:`Documentation/process/security-bugs.rst <securitybugs>`
     もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ
     のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を
     支援してください。
index 969e91a95bb0ca970dcf4b2035fb5cc706468357..34f14899c1559d125b6b2559ec1844931178fff8 100644 (file)
@@ -157,7 +157,7 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다.
     리눅스로 전향하는 사람들에게는 매우 중요하다.
 
 
-  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+  :ref:`Documentation/process/security-bugs.rst <securitybugs>`
     여러분들이 리눅스 커널의 보안 문제를 발견했다고 생각한다면 이 문서에
     나온 단계에 따라서 커널 개발자들에게 알리고 그 문제를 해결할 수 있도록
     도와 달라.
index f9818d687b540b3e744782e87a12b2c449d1938c..f1629738b49d034be2201592180d9210488360fa 100644 (file)
@@ -135,7 +135,7 @@ de obligada lectura:
      de Linux y es muy importante para las personas que se mudan a Linux
      tras desarrollar otros sistemas operativos.
 
-  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+  :ref:`Documentation/process/security-bugs.rst <securitybugs>`
     Si cree que ha encontrado un problema de seguridad en el kernel de
     Linux, siga los pasos de este documento para ayudar a notificar a los
     desarrolladores del kernel y ayudar a resolver el problema.
index f62bd797216dd97a272e00de03a8f6452569aaea..27097a808c8840e6f89b4032927f702081ac296e 100644 (file)
@@ -604,7 +604,7 @@ READ_ONCE() para DEC Alpha, lo que significa que las únicas personas que
 necesitan prestar atención a esta sección son aquellas que trabajan en el
 código específico de la arquitectura DEC Alpha y aquellas que trabajan en
 READ_ONCE() por dentro. Para aquellos que lo necesitan, y para aquellos que
-estén interesados ​​desde un punto de vista histórico, aquí está la historia
+estén interesados desde un punto de vista histórico, aquí está la historia
 de las barreras de dependencia de dirección.
 
 [!] Si bien las dependencias de direcciones se observan tanto en carga a
diff --git a/Documentation/translations/sp_SP/process/deprecated.rst b/Documentation/translations/sp_SP/process/deprecated.rst
new file mode 100644 (file)
index 0000000..d52120e
--- /dev/null
@@ -0,0 +1,381 @@
+.. include:: ../disclaimer-sp.rst
+
+:Original: :ref:`Documentation/process/deprecated.rst <deprecated>`
+:Translator: Sergio Gonzalez <sergio.collado@gmail.com>
+
+.. _sp_deprecated:
+
+============================================================================
+Interfaces obsoletos, Características del lenguaje, Atributos y Convenciones
+============================================================================
+
+En un mundo perfecto, sería posible convertir todas las instancias de
+alguna API obsoleta en una nueva API y quitar la API anterior en un
+único ciclo de desarrollo. Desafortunadamente, debido al tamaño del kernel,
+la jerarquía de mantenimiento, y el tiempo, no siempre es posible hacer
+estos cambios de una única vez. Esto significa que las nuevas instancias
+han de ir creándose en el kernel, mientras que las antiguas se quitan,
+haciendo que la cantidad de trabajo para limpiar las APIs crezca. Para
+informar a los desarrolladores sobre qué ha sido declarado obsoleto y por
+qué, ha sido creada esta lista como un lugar donde indicar cuando los usos
+obsoletos son propuestos para incluir en el kernel.
+
+__deprecated
+------------
+Mientras que este atributo señala visualmente que un interface ha sido
+declarado obsoleto, este `no produce más avisos durante las compilaciones
+<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_
+porque uno de los objetivos del kernel es que compile sin avisos, y
+nadie ha hecho nada para quitar estos interfaces obsoletos. Mientras
+que usar `__deprecated` es sencillo para anotar una API obsoleta en
+un archivo de cabecera, no es la solución completa. Dichos interfaces
+deben o bien ser quitados por completo, o añadidos a este archivo para
+desanimar a otros a usarla en el futuro.
+
+BUG() y BUG_ON()
+----------------
+Use WARN() y WARN_ON() en su lugar, y gestione las condiciones de error
+"imposibles" tan elegantemente como se pueda. Mientras que la familia de
+funciones BUG() fueron originalmente diseñadas para actuar como una
+"situación imposible", confirmar y disponer de un hilo del kernel de forma
+"segura", estas funciones han resultado ser demasiado arriesgadas. (e.g.
+"¿en qué orden se necesitan liberar los locks? ¿Se han restaurado sus
+estados?). La popular función BUG() desestabilizará el sistema o lo romperá
+totalmente, lo cual hace imposible depurarlo o incluso generar reportes de
+crash. Linus tiene una `opinión muy fuerte
+<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_
+y sentimientos `sobre esto
+<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_.
+
+Nótese que la familia de funciones WARN() únicamente debería ser usada
+en situaciones que se "esperan no sean alcanzables". Si se quiere
+avisar sobre situaciones "alcanzables pero no deseadas", úsese la familia
+de funciones pr_warn(). Los responsables del sistema pueden haber definido
+*panic_on_warn* sysctl para asegurarse que sus sistemas no continúan
+ejecutándose en presencia del condiciones "no alcanzables". (Por ejemplo,
+véase commits como `este
+<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.)
+
+Operaciones aritméticas en los argumentos de reserva de memoria
+---------------------------------------------------------------
+Los cálculos dinámicos de tamaño (especialmente multiplicaciones) no
+deberían realizarse en los argumentos de reserva de memoria (o similares)
+debido al riesgo de desbordamiento. Esto puede llevar a valores rotando y
+que se realicen reservas de memoria menores que las que se esperaban. El
+uso de esas reservas puede llevar a desbordamientos en el 'heap' de memoria
+y otros funcionamientos incorrectos. (Una excepción a esto son los valores
+literales donde el compilador si puede avisar si estos puede desbordarse.
+De todos modos, el método recomendado en estos caso es reescribir el código
+como se sugiere a continuación para evitar las operaciones aritméticas en
+la reserva de memoria.)
+
+Por ejemplo, no utilice `count * size`` como argumento, como en::
+
+    foo = kmalloc(count * size, GFP_KERNEL);
+
+En vez de eso, utilice la reserva con dos argumentos::
+
+       foo = kmalloc_array(count, size, GFP_KERNEL);
+
+Específicamente, kmalloc() puede ser sustituido con kmalloc_array(),
+kzalloc() puede ser sustituido con kcalloc().
+
+Si no existen funciones con dos argumentos, utilice las funciones que se
+saturan, en caso de desbordamiento::
+
+       bar = vmalloc(array_size(count, size));
+
+Otro caso común a evitar es calcular el tamaño de una estructura com
+la suma de otras estructuras, como en::
+
+    header = kzalloc(sizeof(*header) + count * sizeof(*header->item),
+                 GFP_KERNEL);
+
+En vez de eso emplee::
+
+    header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
+
+.. note:: Si se usa struct_size() en una estructura que contiene un elemento
+       de longitud cero o un array de un único elemento como un array miembro,
+       por favor reescribir ese uso y cambiar a un `miembro array flexible
+       <#zero-length-and-one-element-arrays>`_
+
+
+Para otros cálculos, por favor use las funciones de ayuda: size_mul(),
+size_add(), and size_sub(). Por ejemplo, en el caso de::
+
+    foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
+
+Re-escríbase, como::
+
+    foo = krealloc(size_add(current_size,
+                        size_mul(chunk_size,
+                                 size_sub(count, 3))), GFP_KERNEL);
+
+Para más detalles, mire también array3_size() y flex_array_size(),
+como también la familia de funciones relacionadas check_mul_overflow(),
+check_add_overflow(), check_sub_overflow(), y check_shl_overflow().
+
+
+simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
+----------------------------------------------------------------------
+Las funciones: simple_strtol(), simple_strtoll(), simple_strtoul(), y
+simple_strtoull() explícitamente ignoran los desbordamientos, lo que puede
+llevar a resultados inesperados por las funciones que las llaman. Las
+funciones respectivas kstrtol(), kstrtoll(), kstrtoul(), y kstrtoull()
+tienden a ser reemplazos correctos, aunque nótese que necesitarán que la
+cadena de caracteres termine en NUL o en el carácter de línea nueva.
+
+
+strcpy()
+--------
+strcpy() no realiza verificaciones de los límites del buffer de destino.
+Esto puede resultar en desbordamientos lineals más allá del fin del buffer,
+causando todo tipo de errores. Mientras `CONFIG_FORTIFY_SOURCE=y` otras
+varias opciones de compilación reducen el riesgo de usar esta función, no
+hay ninguna buena razón para añadir nuevos usos de esta. El remplazo seguro
+es la función strscpy(), aunque se ha de tener cuidado con cualquier caso
+en el el valor retornado por strcpy() sea usado, ya que strscpy() no
+devuelve un puntero a el destino, sino el número de caracteres no nulos
+compilados (o el valor negativo de errno cuando se trunca la cadena de
+caracteres).
+
+strncpy() en cadenas de caracteres terminadas en NUL
+----------------------------------------------------
+El uso de strncpy() no garantiza que el buffer de destino esté terminado en
+NUL. Esto puede causar varios errores de desbordamiento en lectura y otros
+tipos de funcionamiento erróneo debido a que falta la terminación en NUL.
+Esta función también termina la cadena de caracteres en NUL en el buffer de
+destino si la cadena de origen es más corta que el buffer de destino, lo
+cual puede ser una penalización innecesaria para funciones usen esta
+función con cadenas de caracteres que sí están terminadas en NUL.
+
+Cuando se necesita que la cadena de destino sea terminada en NUL,
+el mejor reemplazo es usar la función strscpy(), aunque se ha de tener
+cuidado en los casos en los que el valor de strncpy() fuera usado, ya que
+strscpy() no devuelve un puntero al destino, sino el número de
+caracteres no nulos copiados (o el valor negativo de errno cuando se trunca
+la cadena de caracteres). Cualquier caso restante que necesitase todavía
+ser terminado en el caracter nulo, debería usar strscpy_pad().
+
+Si una función usa cadenas de caracteres que no necesitan terminar en NUL,
+debería usarse strtomem(), y el destino debería señalarse con el atributo
+`__nonstring
+<https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_
+para evitar avisos futuros en el compilador. Para casos que todavía
+necesitan cadenas de caracteres que se rellenen al final con el
+caracter NUL, usar strtomem_pad().
+
+strlcpy()
+---------
+strlcpy() primero lee por completo el buffer de origen (ya que el valor
+devuelto intenta ser el mismo que el de strlen()). Esta lectura puede
+sobrepasar el límite de tamaño del destino. Esto ineficiente y puede causar
+desbordamientos de lectura si la cadena de origen no está terminada en el
+carácter NUL. El reemplazo seguro de esta función es strscpy(), pero se ha
+de tener cuidado que en los casos en lso que se usase el valor devuelto de
+strlcpy(), ya que strscpy() devolverá valores negativos de erno cuando se
+produzcan truncados.
+
+Especificación de formato %p
+----------------------------
+Tradicionalmente,el uso de "%p" en el formato de cadenas de caracteres
+resultaría en exponer esas direcciones en dmesg, proc, sysfs, etc. En vez
+de dejar que sean una vulnerabilidad, todos los "%p" que se usan en el
+kernel se imprimen como un hash, haciéndolos efectivamente inutilizables
+para usarlos como direcciones de memoria. Nuevos usos de "%p" no deberían
+ser añadidos al kernel. Para textos de direcciones, usar "%pS" es
+mejor, ya que resulta en el nombre del símbolo. Para prácticamente el
+resto de casos, mejor no usar "%p" en absoluto.
+
+Parafraseando las actuales `direcciones de Linus <https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_:
+
+- Si el valor "hasheado" "%p" no tienen ninguna finalidad, preguntarse si el
+  puntero es realmente importante. ¿Quizás se podría quitar totalmente?
+- Si realmente se piensa que el valor del puntero es importante, ¿porqué
+  algún estado del sistema o nivel de privilegio de usuario es considerado
+  "especial"? Si piensa que puede justificarse (en comentarios y mensajes
+  del commit), de forma suficiente como para pasar el escrutinio de Linux,
+  quizás pueda usar el "%p", a la vez que se asegura que tiene los permisos
+  correspondientes.
+
+Si está depurando algo donde el "%p" hasheado está causando problemas,
+se puede arrancar temporalmente con la opción de depuración "`no_hash_pointers
+<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_".
+
+
+Arrays de longitud variable (VLAs)
+----------------------------------
+Usando VLA en la pila (stack) produce un código mucho peor que los arrays
+de tamaño estático. Mientras que estos errores no triviales de `rendimiento
+<https://git.kernel.org/linus/02361bc77888>`_  son razón suficiente
+para no usar VLAs, esto además son un riesgo de seguridad. El crecimiento
+dinámico del array en la pila, puede exceder la memoria restante en
+el segmento de la pila. Esto podría llevara a un fallo, posible sobre-escritura
+de contenido al final de la pila (cuando se construye sin
+`CONFIG_THREAD_INFO_IN_TASK=y`), o sobre-escritura de la memoria adyacente
+a la pila (cuando se construye sin `CONFIG_VMAP_STACK=y`).
+
+
+Switch case fall-through implícito
+----------------------------------
+El lenguaje C permite a las sentencias 'switch' saltar de un caso al
+siguiente caso cuando la sentencia de ruptura "break" no aparece al final
+del caso. Esto, introduce ambigüedad en el código, ya que no siempre está
+claro si el 'break' que falta es intencionado o un olvido. Por ejemplo, no
+es obvio solamente mirando al código si `STATE_ONE` está escrito para
+intencionadamente saltar en `STATE_TWO`::
+
+    switch (value) {
+    case STATE_ONE:
+        do_something();
+    case STATE_TWO:
+        do_other();
+        break;
+    default:
+        WARN("unknown state");
+    }
+
+Ya que ha habido una larga lista de defectos `debidos a declaraciones de "break"
+que faltan <https://cwe.mitre.org/data/definitions/484.html>`_, no se
+permiten 'fall-through' implícitos. Para identificar 'fall-through'
+intencionados, se ha adoptado la pseudo-palabra-clave macro "falltrhrough",
+que expande las extensiones de gcc `__attribute__((__fallthrough__))
+<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_.
+(Cuando la sintaxis de C17/c18 `[[fallthrough]]` sea más comúnmente
+soportadas por los compiladores de C, analizadores estáticos, e IDEs,
+se puede cambiar a usar esa sintaxis para esa pseudo-palabra-clave.
+
+Todos los bloques switch/case deben acabar en uno de:
+
+* break;
+* fallthrough;
+* continue;
+* goto <label>;
+* return [expression];
+
+
+Arrays de longitud cero y un elemento
+-------------------------------------
+Hay una necesidad habitual en el kernel de proveer una forma para declarar
+un grupo de elementos consecutivos de tamaño dinámico en una estructura.
+El código del kernel debería usar siempre `"miembros array flexible" <https://en.wikipedia.org/wiki/Flexible_array_member>`_
+en estos casos. El estilo anterior de arrays de un elemento o de longitud
+cero, no deben usarse más.
+
+En el código C más antiguo, los elementos finales de tamaño dinámico se
+obtenían especificando un array de un elemento al final de una estructura::
+
+       struct something {
+               size_t count;
+               struct foo items[1];
+       };
+
+En código C más antiguo, elementos seguidos de tamaño dinámico eran creados
+especificando una array de un único elemento al final de una estructura::
+
+       struct something {
+               size_t count;
+               struct foo items[1];
+       };
+
+Esto llevó a resultados incorrectos en los cálculos de tamaño mediante
+sizeof() (el cual hubiera necesitado eliminar el tamaño del último elemento
+para tener un tamaño correcto de la "cabecera"). Una `extensión de GNU C
+<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ se empezó a usar
+para permitir los arrays de longitud cero, para evitar estos tipos de
+problemas de tamaño::
+
+       struct something {
+               size_t count;
+               struct foo items[0];
+       };
+
+Pero esto llevó a otros problemas, y no solucionó algunos otros problemas
+compartidos por ambos estilos, como no ser capaz de detectar cuando ese array
+accidentalmente _no_ es usado al final de la estructura (lo que podía pasar
+directamente, o cuando dicha estructura era usada en uniones, estructuras
+de estructuras, etc).
+
+C99 introdujo "los arrays miembros flexibles", los cuales carecen de un
+tamaño numérico en su declaración del array::
+
+       struct something {
+               size_t count;
+               struct foo items[];
+       };
+
+Esta es la forma en la que el kernel espera que se declaren los elementos
+de tamaño dinámico concatenados. Esto permite al compilador generar
+errores, cuando el array flexible no es declarado en el último lugar de la
+estructura, lo que ayuda a prevenir errores en él código del tipo
+`comportamiento indefinido <https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_.
+Esto también permite al compilador analizar correctamente los tamaños de
+los arrays (via sizeof(), `CONFIG_FORTIFY_SOURCE`, y `CONFIG_UBSAN_BOUNDS`).
+Por ejemplo, si no hay un mecanismo que avise que el siguiente uso de
+sizeof() en un array de longitud cero, siempre resulta en cero::
+
+        struct something {
+                size_t count;
+                struct foo items[0];
+        };
+
+        struct something *instance;
+
+        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
+        instance->count = count;
+
+        size = sizeof(instance->items) * instance->count;
+        memcpy(instance->items, source, size);
+
+En la última línea del código anterior, ``zero`` vale ``cero``, cuando uno
+podría esperar que representa el tamaño total en bytes de la memoria dinámica
+reservada para el array consecutivo ``items``. Aquí hay un par de ejemplos
+más sobre este tema:  `link 1
+<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
+`link 2
+<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_.
+Sin embargo, los array de miembros flexibles tienen un type incompleto, y
+no se ha de aplicar el operador sizeof()<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_,
+así cualquier mal uso de dichos operadores será detectado inmediatamente en
+el momento de compilación.
+
+Con respecto a los arrays de un único elemento, se ha de ser consciente de
+que dichos arrays ocupan al menos tanto espacio como un único objeto del
+tipo https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de ahí que
+estos contribuyan al tamaño de la estructura que los contiene. Esto es
+proclive a errores cada vez que se quiere calcular el tamaño total de la
+memoria dinámica para reservar una estructura que contenga un array de este
+tipo como su miembro::
+
+        struct something {
+                size_t count;
+                struct foo items[1];
+        };
+
+        struct something *instance;
+
+        instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL);
+        instance->count = count;
+
+        size = sizeof(instance->items) * instance->count;
+        memcpy(instance->items, source, size);
+
+En el ejemplo anterior, hemos de recordar calcular ``count - 1``, cuando se
+usa la función de ayuda struct_size(), de otro modo estaríamos
+--desintencionadamente--reservando memoria para un  ``items`` de más. La
+forma más clara y menos proclive a errores es implementar esto mediante el
+uso de `array miembro flexible`, junto con las funciones de ayuda:
+struct_size() y flex_array_size()::
+
+        struct something {
+                size_t count;
+                struct foo items[];
+        };
+
+        struct something *instance;
+
+        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
+        instance->count = count;
+
+        memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
index 0f1e131b3bb14d049aedc1e33be046ae5bdcbdb6..3b0c3259372684fb2e61b9f5278c78b883aaa29f 100644 (file)
@@ -18,3 +18,4 @@
    email-clients
    magic-number
    programming-language
+   deprecated
index bf95ceb5e865a15372cd73d080d78a94b17d03f6..c2757d9ab2168e3900913d970642ec8885d94c97 100644 (file)
@@ -276,7 +276,7 @@ parche a security@kernel.org. Para errores graves, se debe mantener un
 poco de discreción y permitir que los distribuidores entreguen el parche a
 los usuarios; en esos casos, obviamente, el parche no debe enviarse a
 ninguna lista pública. Revise también
-Documentation/admin-guide/security-bugs.rst.
+Documentation/process/security-bugs.rst.
 
 Los parches que corrigen un error grave en un kernel en uso deben dirigirse
 hacia los maintainers estables poniendo una línea como esta::
index 812ef315c8f69b13b8a18b5a808029a15c22833c..03d33c710604c93402707d46ed2fcd6aa12fe63d 100644 (file)
@@ -250,7 +250,7 @@ LRU的优先级的提升,同时降低那些超过120秒无人访问的内存
 理被限制在最多1%的CPU以避免DAMON_LRU_SORT消费过多CPU时间。在系统空闲内存超过50%
 时DAMON_LRU_SORT停止工作,并在低于40%时重新开始工作。如果DAMON_RECLAIM没有取得
 进展且空闲内存低于20%,再次让DAMON_LRU_SORT停止工作,以此回退到以LRU链表为基础
-以页面为单位的内存回收上。
+以页面为单位的内存回收上。 ::
 
     # cd /sys/modules/damon_lru_sort/parameters
     # echo 500 > hot_thres_access_freq
index b8120391755d46a4198181ddf53d02f6d3f3ff76..d6b8f8a4e7f63de2d7e01cce2c5dce550ac3cc07 100644 (file)
@@ -1,6 +1,6 @@
 .. include:: ../disclaimer-zh_CN.rst
 
-:Original: :doc:`../../../admin-guide/security-bugs`
+:Original: :doc:`../../../process/security-bugs`
 
 :译者:
 
diff --git a/Documentation/translations/zh_CN/arch.rst b/Documentation/translations/zh_CN/arch.rst
deleted file mode 100644 (file)
index 690e173..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-处理器体系结构
-==============
-
-以下文档提供了具体架构实现的编程细节。
-
-.. toctree::
-   :maxdepth: 2
-
-   mips/index
-   arm64/index
-   riscv/index
-   openrisc/index
-   parisc/index
-   loongarch/index
-
-TODOList:
-
-* arm/index
-* ia64/index
-* m68k/index
-* nios2/index
-* powerpc/index
-* s390/index
-* sh/index
-* sparc/index
-* x86/index
-* xtensa/index
diff --git a/Documentation/translations/zh_CN/arch/index.rst b/Documentation/translations/zh_CN/arch/index.rst
new file mode 100644 (file)
index 0000000..908ea13
--- /dev/null
@@ -0,0 +1,29 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+处理器体系结构
+==============
+
+以下文档提供了具体架构实现的编程细节。
+
+.. toctree::
+   :maxdepth: 2
+
+   ../mips/index
+   ../arm64/index
+   ../riscv/index
+   openrisc/index
+   parisc/index
+   ../loongarch/index
+
+TODOList:
+
+* arm/index
+* ia64/index
+* m68k/index
+* nios2/index
+* powerpc/index
+* s390/index
+* sh/index
+* sparc/index
+* x86/index
+* xtensa/index
diff --git a/Documentation/translations/zh_CN/arch/openrisc/index.rst b/Documentation/translations/zh_CN/arch/openrisc/index.rst
new file mode 100644 (file)
index 0000000..da21f8a
--- /dev/null
@@ -0,0 +1,32 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/arch/openrisc/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+.. _cn_openrisc_index:
+
+=================
+OpenRISC 体系架构
+=================
+
+.. toctree::
+   :maxdepth: 2
+
+   openrisc_port
+   todo
+
+Todolist:
+    features
+
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/arch/openrisc/openrisc_port.rst b/Documentation/translations/zh_CN/arch/openrisc/openrisc_port.rst
new file mode 100644 (file)
index 0000000..cadc580
--- /dev/null
@@ -0,0 +1,127 @@
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/arch/openrisc/openrisc_port.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+.. _cn_openrisc_port:
+
+==============
+OpenRISC Linux
+==============
+
+这是Linux对OpenRISC类微处理器的移植;具体来说,最早移植目标是32位
+OpenRISC 1000系列(或1k)。
+
+关于OpenRISC处理器和正在进行中的开发的信息:
+
+       =======         =============================
+       网站          https://openrisc.io
+       邮箱          openrisc@lists.librecores.org
+       =======         =============================
+
+---------------------------------------------------------------------
+
+OpenRISC工具链和Linux的构建指南
+===============================
+
+为了构建和运行Linux for OpenRISC,你至少需要一个基本的工具链,或许
+还需要架构模拟器。 这里概述了准备就位这些部分的步骤。
+
+1) 工具链
+
+工具链二进制文件可以从openrisc.io或我们的github发布页面获得。不同
+工具链的构建指南可以在openrisc.io或Stafford的工具链构建和发布脚本
+中找到。
+
+       ======      =================================================
+       二进制      https://github.com/openrisc/or1k-gcc/releases
+       工具链      https://openrisc.io/software
+       构建        https://github.com/stffrdhrn/or1k-toolchain-build
+       ======      =================================================
+
+2) 构建
+
+像往常一样构建Linux内核::
+
+       make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig
+       make ARCH=openrisc CROSS_COMPILE="or1k-linux-"
+
+3) 在FPGA上运行(可选)
+
+OpenRISC社区通常使用FuseSoC来管理构建和编程SoC到FPGA中。 下面是用
+OpenRISC SoC对De0 Nano开发板进行编程的一个例子。 在构建过程中,
+FPGA RTL是从FuseSoC IP核库中下载的代码,并使用FPGA供应商工具构建。
+二进制文件用openocd加载到电路板上。
+
+::
+
+       git clone https://github.com/olofk/fusesoc
+       cd fusesoc
+       sudo pip install -e .
+
+       fusesoc init
+       fusesoc build de0_nano
+       fusesoc pgm de0_nano
+
+       openocd -f interface/altera-usb-blaster.cfg \
+               -f board/or1k_generic.cfg
+
+       telnet localhost 4444
+       > init
+       > halt; load_image vmlinux ; reset
+
+4) 在模拟器上运行(可选)
+
+QEMU是一个处理器仿真器,我们推荐它来模拟OpenRISC平台。 请按照QEMU网
+站上的OpenRISC说明,让Linux在QEMU上运行。 你可以自己构建QEMU,但你的
+Linux发行版可能提供了支持OpenRISC的二进制包。
+
+       =============   ======================================================
+       qemu openrisc   https://wiki.qemu.org/Documentation/Platforms/OpenRISC
+       =============   ======================================================
+
+---------------------------------------------------------------------
+
+术语表
+======
+
+代码中使用了以下符号约定以将范围限制在几个特定处理器实现上:
+
+========= =======================
+openrisc: OpenRISC类型处理器
+or1k:     OpenRISC 1000系列处理器
+or1200:   OpenRISC 1200处理器
+========= =======================
+
+---------------------------------------------------------------------
+
+历史
+====
+
+2003-11-18     Matjaz Breskvar (phoenix@bsemi.com)
+   将linux初步移植到OpenRISC或32架构。
+       所有的核心功能都实现了,并且可以使用。
+
+2003-12-08     Matjaz Breskvar (phoenix@bsemi.com)
+   彻底改变TLB失误处理。
+   重写异常处理。
+   在默认的initrd中实现了sash-3.6的所有功能。
+   大幅改进的版本。
+
+2004-04-10     Matjaz Breskvar (phoenix@bsemi.com)
+   大量的bug修复。
+   支持以太网,http和telnet服务器功能。
+   可以运行许多标准的linux应用程序。
+
+2004-06-26     Matjaz Breskvar (phoenix@bsemi.com)
+   移植到2.6.x。
+
+2004-11-30     Matjaz Breskvar (phoenix@bsemi.com)
+   大量的bug修复和增强功能。
+   增加了opencores framebuffer驱动。
+
+2010-10-09    Jonas Bonn (jonas@southpole.se)
+   重大重写,使其与上游的Linux 2.6.36看齐。
diff --git a/Documentation/translations/zh_CN/arch/openrisc/todo.rst b/Documentation/translations/zh_CN/arch/openrisc/todo.rst
new file mode 100644 (file)
index 0000000..1f6f956
--- /dev/null
@@ -0,0 +1,23 @@
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/arch/openrisc/todo.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+.. _cn_openrisc_todo.rst:
+
+========
+待办事项
+========
+
+OpenRISC Linux的移植已经完全投入使用,并且从 2.6.35 开始就一直在上游同步。
+然而,还有一些剩余的项目需要在未来几个月内完成。 下面是一个即将进行调查的已知
+不尽完美的项目列表,即我们的待办事项列表。
+
+-   实现其余的DMA API……dma_map_sg等。
+
+-   完成重命名清理工作……代码中提到了or32,这是架构的一个老名字。 我们
+    已经确定的名字是or1k,这个改变正在以缓慢积累的方式进行。 目前,or32相当
+    于or1k。
diff --git a/Documentation/translations/zh_CN/arch/parisc/debugging.rst b/Documentation/translations/zh_CN/arch/parisc/debugging.rst
new file mode 100644 (file)
index 0000000..c6b9de6
--- /dev/null
@@ -0,0 +1,45 @@
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/arch/parisc/debugging.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+.. _cn_parisc_debugging:
+
+=================
+调试PA-RISC
+=================
+
+好吧,这里有一些关于调试linux/parisc的较底层部分的信息。
+
+
+1. 绝对地址
+=====================
+
+很多汇编代码目前运行在实模式下,这意味着会使用绝对地址,而不是像内核其他
+部分那样使用虚拟地址。要将绝对地址转换为虚拟地址,你可以在System.map中查
+找,添加__PAGE_OFFSET(目前是0x10000000)。
+
+
+2. HPMCs
+========
+
+当实模式的代码试图访问不存在的内存时,会出现HPMC(high priority machine
+check)而不是内核oops。若要调试HPMC,请尝试找到系统响应程序/请求程序地址。
+系统请求程序地址应该与(某)处理器的HPA(I/O范围内的高地址)相匹配;系统响应程
+序地址是实模式代码试图访问的地址。
+
+系统响应程序地址的典型值是大于__PAGE_OFFSET (0x10000000)的地址,这意味着
+在实模式试图访问它之前,虚拟地址没有被翻译成物理地址。
+
+
+3. 有趣的Q位
+============
+
+某些非常关键的代码必须清除PSW中的Q位。当Q位被清除时,CPU不会更新中断处理
+程序所读取的寄存器,以找出机器被中断的位置——所以如果你在清除Q位的指令和再
+次设置Q位的RFI之间遇到中断,你不知道它到底发生在哪里。如果你幸运的话,IAOQ
+会指向清除Q位的指令,如果你不幸运的话,它会指向任何地方。通常Q位的问题会
+表现为无法解释的系统挂起或物理内存越界。
diff --git a/Documentation/translations/zh_CN/arch/parisc/index.rst b/Documentation/translations/zh_CN/arch/parisc/index.rst
new file mode 100644 (file)
index 0000000..9f69283
--- /dev/null
@@ -0,0 +1,31 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/arch/parisc/index.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+.. _cn_parisc_index:
+
+====================
+PA-RISC体系架构
+====================
+
+.. toctree::
+   :maxdepth: 2
+
+   debugging
+   registers
+
+Todolist:
+
+   features
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/arch/parisc/registers.rst b/Documentation/translations/zh_CN/arch/parisc/registers.rst
new file mode 100644 (file)
index 0000000..a55250a
--- /dev/null
@@ -0,0 +1,156 @@
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/arch/parisc/registers.rst
+
+:翻译:
+
+ 司延腾 Yanteng Si <siyanteng@loongson.cn>
+
+.. _cn_parisc_registers:
+
+=========================
+Linux/PA-RISC的寄存器用法
+=========================
+
+[ 用星号表示目前尚未实现的计划用途。 ]
+
+ABI约定的通用寄存器
+===================
+
+控制寄存器
+----------
+
+============================    =================================
+CR 0 (恢复计数器)               用于ptrace
+CR 1-CR 7(无定义)               未使用
+CR 8 (Protection ID)            每进程值*
+CR 9, 12, 13 (PIDS)             未使用
+CR10 (CCR)                      FPU延迟保存*
+CR11                            按照ABI的规定(SAR)
+CR14 (中断向量)                 初始化为 fault_vector
+CR15 (EIEM)                     所有位初始化为1*
+CR16 (间隔计时器)               读取周期数/写入开始时间间隔计时器
+CR17-CR22                       中断参数
+CR19                            中断指令寄存器
+CR20                            中断空间寄存器
+CR21                            中断偏移量寄存器
+CR22                            中断 PSW
+CR23 (EIRR)                     读取未决中断/写入清除位
+CR24 (TR 0)                     内核空间页目录指针
+CR25 (TR 1)                     用户空间页目录指针
+CR26 (TR 2)                     不使用
+CR27 (TR 3)                     线程描述符指针
+CR28 (TR 4)                     不使用
+CR29 (TR 5)                     不使用
+CR30 (TR 6)                     当前 / 0
+CR31 (TR 7)                     临时寄存器,在不同地方使用
+============================    =================================
+
+空间寄存器(内核模式)
+----------------------
+
+========                        ==============================
+SR0                             临时空间寄存器
+SR4-SR7                         设置为0
+SR1                             临时空间寄存器
+SR2                             内核不应该破坏它
+SR3                             用于用户空间访问(当前进程)
+========                        ==============================
+
+空间寄存器(用户模式)
+----------------------
+
+========                        ============================
+SR0                             临时空间寄存器
+SR1                             临时空间寄存器
+SR2                             保存Linux gateway page的空间
+SR3                             在内核中保存用户地址空间的值
+SR4-SR7                         定义了用户/内核的短地址空间
+========                        ============================
+
+
+处理器状态字
+------------
+
+======================          ================================================
+W (64位地址)                  0
+E (小尾端)                    0
+S (安全间隔计时器)            0
+T (产生分支陷阱)              0
+H (高特权级陷阱)              0
+L (低特权级陷阱)              0
+N (撤销下一条指令)            被C代码使用
+X (数据存储中断禁用)          0
+B (产生分支)                  被C代码使用
+C (代码地址转译)              1, 在执行实模式代码时为0
+V (除法步长校正)              被C代码使用
+M (HPMC 掩码)                 0, 在执行HPMC操作*时为1
+C/B (进/借 位)                被C代码使用
+O (有序引用)                  1*
+F (性能监视器)                0
+R (回收计数器陷阱)            0
+Q (收集中断状态)              1 (在rfi之前的代码中为0)
+P (保护标识符)                1*
+D (数据地址转译)              1, 在执行实模式代码时为0
+I (外部中断掩码)              由cli()/sti()宏使用。
+======================          ================================================
+
+“隐形”寄存器(影子寄存器)
+---------------------------
+
+=============                   ===================
+PSW W 默认值                    0
+PSW E 默认值                    0
+影子寄存器                      被中断处理代码使用
+TOC启用位                       1
+=============                   ===================
+
+----------------------------------------------------------
+
+PA-RISC架构定义了7个寄存器作为“影子寄存器”。这些寄存器在
+RETURN FROM INTERRUPTION AND RESTORE指令中使用,通过消
+除中断处理程序中对一般寄存器(GR)的保存和恢复的需要来减
+少状态保存和恢复时间。影子寄存器是GRs 1, 8, 9, 16, 17,
+24和25。
+
+-------------------------------------------------------------------------
+
+寄存器使用说明,最初由John Marvin提供,并由Randolph Chung提供一些补充说明。
+
+对于通用寄存器:
+
+r1,r2,r19-r26,r28,r29 & r31可以在不保存它们的情况下被使用。当然,如果你
+关心它们,在调用另一个程序之前,你也需要保存它们。上面的一些寄存器确实
+有特殊的含义,你应该注意一下:
+
+    r1:
+       addil指令是硬性规定将其结果放在r1中,所以如果你使用这条指令要
+       注意这点。
+
+    r2:
+       这就是返回指针。一般来说,你不想使用它,因为你需要这个指针来返
+       回给你的调用者。然而,它与这组寄存器组合在一起,因为调用者不能
+       依赖你返回时的值是相同的,也就是说,你可以将r2复制到另一个寄存
+       器,并在作废r2后通过该寄存器返回,这应该不会给调用程序带来问题。
+
+    r19-r22:
+       这些通常被认为是临时寄存器。
+       请注意,在64位中它们是arg7-arg4。
+
+    r23-r26:
+       这些是arg3-arg0,也就是说,如果你不再关心传入的值,你可以使用
+       它们。
+
+    r28,r29:
+       这俩是ret0和ret1。它们是你传入返回值的地方。r28是主返回值。当返回
+       小结构体时,r29也可以用来将数据传回给调用程序。
+
+    r30:
+       栈指针
+
+    r31:
+       ble指令将返回指针放在这里。
+
+
+    r3-r18,r27,r30需要被保存和恢复。r3-r18只是一般用途的寄存器。
+    r27是数据指针,用来使对全局变量的引用更容易。r30是栈指针。
index 7c3216845b71fe72cc6620552e539f9daaac601e..299704c0818dbcf7d30b15ee9d84947cdbb48b75 100644 (file)
@@ -120,7 +120,7 @@ TODOList:
 .. toctree::
    :maxdepth: 2
 
-   arch
+   arch/index
 
 其他文档
 --------
index c1fa35315d8b2238892d1ff7661873a532088388..b7a0544224ad1aa70213b37c7c68aece4f8dfb5f 100644 (file)
@@ -15,7 +15,8 @@ Hugetlbfs 预留
 概述
 ====
 
-Documentation/mm/hugetlbpage.rst 中描述的巨页通常是预先分配给应用程序使用的。如果VMA指
+Documentation/admin-guide/mm/hugetlbpage.rst
+中描述的巨页通常是预先分配给应用程序使用的 。如果VMA指
 示要使用巨页,这些巨页会在缺页异常时被实例化到任务的地址空间。如果在缺页异常
 时没有巨页存在,任务就会被发送一个SIGBUS,并经常不高兴地死去。在加入巨页支
 持后不久,人们决定,在mmap()时检测巨页的短缺情况会更好。这个想法是,如果
diff --git a/Documentation/translations/zh_CN/openrisc/index.rst b/Documentation/translations/zh_CN/openrisc/index.rst
deleted file mode 100644 (file)
index 9ad6cc6..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. include:: ../disclaimer-zh_CN.rst
-
-:Original: Documentation/openrisc/index.rst
-
-:翻译:
-
- 司延腾 Yanteng Si <siyanteng@loongson.cn>
-
-.. _cn_openrisc_index:
-
-=================
-OpenRISC 体系架构
-=================
-
-.. toctree::
-   :maxdepth: 2
-
-   openrisc_port
-   todo
-
-Todolist:
-    features
-
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/openrisc/openrisc_port.rst b/Documentation/translations/zh_CN/openrisc/openrisc_port.rst
deleted file mode 100644 (file)
index b8a6767..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-.. include:: ../disclaimer-zh_CN.rst
-
-:Original: Documentation/openrisc/openrisc_port.rst
-
-:翻译:
-
- 司延腾 Yanteng Si <siyanteng@loongson.cn>
-
-.. _cn_openrisc_port:
-
-==============
-OpenRISC Linux
-==============
-
-这是Linux对OpenRISC类微处理器的移植;具体来说,最早移植目标是32位
-OpenRISC 1000系列(或1k)。
-
-关于OpenRISC处理器和正在进行中的开发的信息:
-
-       =======         =============================
-       网站          https://openrisc.io
-       邮箱          openrisc@lists.librecores.org
-       =======         =============================
-
----------------------------------------------------------------------
-
-OpenRISC工具链和Linux的构建指南
-===============================
-
-为了构建和运行Linux for OpenRISC,你至少需要一个基本的工具链,或许
-还需要架构模拟器。 这里概述了准备就位这些部分的步骤。
-
-1) 工具链
-
-工具链二进制文件可以从openrisc.io或我们的github发布页面获得。不同
-工具链的构建指南可以在openrisc.io或Stafford的工具链构建和发布脚本
-中找到。
-
-       ======      =================================================
-       二进制      https://github.com/openrisc/or1k-gcc/releases
-       工具链      https://openrisc.io/software
-       构建        https://github.com/stffrdhrn/or1k-toolchain-build
-       ======      =================================================
-
-2) 构建
-
-像往常一样构建Linux内核::
-
-       make ARCH=openrisc CROSS_COMPILE="or1k-linux-" defconfig
-       make ARCH=openrisc CROSS_COMPILE="or1k-linux-"
-
-3) 在FPGA上运行(可选)
-
-OpenRISC社区通常使用FuseSoC来管理构建和编程SoC到FPGA中。 下面是用
-OpenRISC SoC对De0 Nano开发板进行编程的一个例子。 在构建过程中,
-FPGA RTL是从FuseSoC IP核库中下载的代码,并使用FPGA供应商工具构建。
-二进制文件用openocd加载到电路板上。
-
-::
-
-       git clone https://github.com/olofk/fusesoc
-       cd fusesoc
-       sudo pip install -e .
-
-       fusesoc init
-       fusesoc build de0_nano
-       fusesoc pgm de0_nano
-
-       openocd -f interface/altera-usb-blaster.cfg \
-               -f board/or1k_generic.cfg
-
-       telnet localhost 4444
-       > init
-       > halt; load_image vmlinux ; reset
-
-4) 在模拟器上运行(可选)
-
-QEMU是一个处理器仿真器,我们推荐它来模拟OpenRISC平台。 请按照QEMU网
-站上的OpenRISC说明,让Linux在QEMU上运行。 你可以自己构建QEMU,但你的
-Linux发行版可能提供了支持OpenRISC的二进制包。
-
-       =============   ======================================================
-       qemu openrisc   https://wiki.qemu.org/Documentation/Platforms/OpenRISC
-       =============   ======================================================
-
----------------------------------------------------------------------
-
-术语表
-======
-
-代码中使用了以下符号约定以将范围限制在几个特定处理器实现上:
-
-========= =======================
-openrisc: OpenRISC类型处理器
-or1k:     OpenRISC 1000系列处理器
-or1200:   OpenRISC 1200处理器
-========= =======================
-
----------------------------------------------------------------------
-
-历史
-====
-
-2003-11-18     Matjaz Breskvar (phoenix@bsemi.com)
-   将linux初步移植到OpenRISC或32架构。
-       所有的核心功能都实现了,并且可以使用。
-
-2003-12-08     Matjaz Breskvar (phoenix@bsemi.com)
-   彻底改变TLB失误处理。
-   重写异常处理。
-   在默认的initrd中实现了sash-3.6的所有功能。
-   大幅改进的版本。
-
-2004-04-10     Matjaz Breskvar (phoenix@bsemi.com)
-   大量的bug修复。
-   支持以太网,http和telnet服务器功能。
-   可以运行许多标准的linux应用程序。
-
-2004-06-26     Matjaz Breskvar (phoenix@bsemi.com)
-   移植到2.6.x。
-
-2004-11-30     Matjaz Breskvar (phoenix@bsemi.com)
-   大量的bug修复和增强功能。
-   增加了opencores framebuffer驱动。
-
-2010-10-09    Jonas Bonn (jonas@southpole.se)
-   重大重写,使其与上游的Linux 2.6.36看齐。
diff --git a/Documentation/translations/zh_CN/openrisc/todo.rst b/Documentation/translations/zh_CN/openrisc/todo.rst
deleted file mode 100644 (file)
index 63c3871..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-.. include:: ../disclaimer-zh_CN.rst
-
-:Original: Documentation/openrisc/todo.rst
-
-:翻译:
-
- 司延腾 Yanteng Si <siyanteng@loongson.cn>
-
-.. _cn_openrisc_todo.rst:
-
-========
-待办事项
-========
-
-OpenRISC Linux的移植已经完全投入使用,并且从 2.6.35 开始就一直在上游同步。
-然而,还有一些剩余的项目需要在未来几个月内完成。 下面是一个即将进行调查的已知
-不尽完美的项目列表,即我们的待办事项列表。
-
--   实现其余的DMA API……dma_map_sg等。
-
--   完成重命名清理工作……代码中提到了or32,这是架构的一个老名字。 我们
-    已经确定的名字是or1k,这个改变正在以缓慢积累的方式进行。 目前,or32相当
-    于or1k。
diff --git a/Documentation/translations/zh_CN/parisc/debugging.rst b/Documentation/translations/zh_CN/parisc/debugging.rst
deleted file mode 100644 (file)
index 68b73eb..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-.. include:: ../disclaimer-zh_CN.rst
-
-:Original: Documentation/parisc/debugging.rst
-
-:翻译:
-
- 司延腾 Yanteng Si <siyanteng@loongson.cn>
-
-.. _cn_parisc_debugging:
-
-=================
-调试PA-RISC
-=================
-
-好吧,这里有一些关于调试linux/parisc的较底层部分的信息。
-
-
-1. 绝对地址
-=====================
-
-很多汇编代码目前运行在实模式下,这意味着会使用绝对地址,而不是像内核其他
-部分那样使用虚拟地址。要将绝对地址转换为虚拟地址,你可以在System.map中查
-找,添加__PAGE_OFFSET(目前是0x10000000)。
-
-
-2. HPMCs
-========
-
-当实模式的代码试图访问不存在的内存时,会出现HPMC(high priority machine
-check)而不是内核oops。若要调试HPMC,请尝试找到系统响应程序/请求程序地址。
-系统请求程序地址应该与(某)处理器的HPA(I/O范围内的高地址)相匹配;系统响应程
-序地址是实模式代码试图访问的地址。
-
-系统响应程序地址的典型值是大于__PAGE_OFFSET (0x10000000)的地址,这意味着
-在实模式试图访问它之前,虚拟地址没有被翻译成物理地址。
-
-
-3. 有趣的Q位
-============
-
-某些非常关键的代码必须清除PSW中的Q位。当Q位被清除时,CPU不会更新中断处理
-程序所读取的寄存器,以找出机器被中断的位置——所以如果你在清除Q位的指令和再
-次设置Q位的RFI之间遇到中断,你不知道它到底发生在哪里。如果你幸运的话,IAOQ
-会指向清除Q位的指令,如果你不幸运的话,它会指向任何地方。通常Q位的问题会
-表现为无法解释的系统挂起或物理内存越界。
diff --git a/Documentation/translations/zh_CN/parisc/index.rst b/Documentation/translations/zh_CN/parisc/index.rst
deleted file mode 100644 (file)
index 0cc553f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-.. include:: ../disclaimer-zh_CN.rst
-
-:Original: Documentation/parisc/index.rst
-
-:翻译:
-
- 司延腾 Yanteng Si <siyanteng@loongson.cn>
-
-.. _cn_parisc_index:
-
-====================
-PA-RISC体系架构
-====================
-
-.. toctree::
-   :maxdepth: 2
-
-   debugging
-   registers
-
-Todolist:
-
-   features
-
-.. only::  subproject and html
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/parisc/registers.rst b/Documentation/translations/zh_CN/parisc/registers.rst
deleted file mode 100644 (file)
index d2ab187..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-.. include:: ../disclaimer-zh_CN.rst
-
-:Original: Documentation/parisc/registers.rst
-
-:翻译:
-
- 司延腾 Yanteng Si <siyanteng@loongson.cn>
-
-.. _cn_parisc_registers:
-
-=========================
-Linux/PA-RISC的寄存器用法
-=========================
-
-[ 用星号表示目前尚未实现的计划用途。 ]
-
-ABI约定的通用寄存器
-===================
-
-控制寄存器
-----------
-
-============================    =================================
-CR 0 (恢复计数器)               用于ptrace
-CR 1-CR 7(无定义)               未使用
-CR 8 (Protection ID)            每进程值*
-CR 9, 12, 13 (PIDS)             未使用
-CR10 (CCR)                      FPU延迟保存*
-CR11                            按照ABI的规定(SAR)
-CR14 (中断向量)                 初始化为 fault_vector
-CR15 (EIEM)                     所有位初始化为1*
-CR16 (间隔计时器)               读取周期数/写入开始时间间隔计时器
-CR17-CR22                       中断参数
-CR19                            中断指令寄存器
-CR20                            中断空间寄存器
-CR21                            中断偏移量寄存器
-CR22                            中断 PSW
-CR23 (EIRR)                     读取未决中断/写入清除位
-CR24 (TR 0)                     内核空间页目录指针
-CR25 (TR 1)                     用户空间页目录指针
-CR26 (TR 2)                     不使用
-CR27 (TR 3)                     线程描述符指针
-CR28 (TR 4)                     不使用
-CR29 (TR 5)                     不使用
-CR30 (TR 6)                     当前 / 0
-CR31 (TR 7)                     临时寄存器,在不同地方使用
-============================    =================================
-
-空间寄存器(内核模式)
-----------------------
-
-========                        ==============================
-SR0                             临时空间寄存器
-SR4-SR7                         设置为0
-SR1                             临时空间寄存器
-SR2                             内核不应该破坏它
-SR3                             用于用户空间访问(当前进程)
-========                        ==============================
-
-空间寄存器(用户模式)
-----------------------
-
-========                        ============================
-SR0                             临时空间寄存器
-SR1                             临时空间寄存器
-SR2                             保存Linux gateway page的空间
-SR3                             在内核中保存用户地址空间的值
-SR4-SR7                         定义了用户/内核的短地址空间
-========                        ============================
-
-
-处理器状态字
-------------
-
-======================          ================================================
-W (64位地址)                  0
-E (小尾端)                    0
-S (安全间隔计时器)            0
-T (产生分支陷阱)              0
-H (高特权级陷阱)              0
-L (低特权级陷阱)              0
-N (撤销下一条指令)            被C代码使用
-X (数据存储中断禁用)          0
-B (产生分支)                  被C代码使用
-C (代码地址转译)              1, 在执行实模式代码时为0
-V (除法步长校正)              被C代码使用
-M (HPMC 掩码)                 0, 在执行HPMC操作*时为1
-C/B (进/借 位)                被C代码使用
-O (有序引用)                  1*
-F (性能监视器)                0
-R (回收计数器陷阱)            0
-Q (收集中断状态)              1 (在rfi之前的代码中为0)
-P (保护标识符)                1*
-D (数据地址转译)              1, 在执行实模式代码时为0
-I (外部中断掩码)              由cli()/sti()宏使用。
-======================          ================================================
-
-“隐形”寄存器(影子寄存器)
----------------------------
-
-=============                   ===================
-PSW W 默认值                    0
-PSW E 默认值                    0
-影子寄存器                      被中断处理代码使用
-TOC启用位                       1
-=============                   ===================
-
-----------------------------------------------------------
-
-PA-RISC架构定义了7个寄存器作为“影子寄存器”。这些寄存器在
-RETURN FROM INTERRUPTION AND RESTORE指令中使用,通过消
-除中断处理程序中对一般寄存器(GR)的保存和恢复的需要来减
-少状态保存和恢复时间。影子寄存器是GRs 1, 8, 9, 16, 17,
-24和25。
-
--------------------------------------------------------------------------
-
-寄存器使用说明,最初由John Marvin提供,并由Randolph Chung提供一些补充说明。
-
-对于通用寄存器:
-
-r1,r2,r19-r26,r28,r29 & r31可以在不保存它们的情况下被使用。当然,如果你
-关心它们,在调用另一个程序之前,你也需要保存它们。上面的一些寄存器确实
-有特殊的含义,你应该注意一下:
-
-    r1:
-       addil指令是硬性规定将其结果放在r1中,所以如果你使用这条指令要
-       注意这点。
-
-    r2:
-       这就是返回指针。一般来说,你不想使用它,因为你需要这个指针来返
-       回给你的调用者。然而,它与这组寄存器组合在一起,因为调用者不能
-       依赖你返回时的值是相同的,也就是说,你可以将r2复制到另一个寄存
-       器,并在作废r2后通过该寄存器返回,这应该不会给调用程序带来问题。
-
-    r19-r22:
-       这些通常被认为是临时寄存器。
-       请注意,在64位中它们是arg7-arg4。
-
-    r23-r26:
-       这些是arg3-arg0,也就是说,如果你不再关心传入的值,你可以使用
-       它们。
-
-    r28,r29:
-       这俩是ret0和ret1。它们是你传入返回值的地方。r28是主返回值。当返回
-       小结构体时,r29也可以用来将数据传回给调用程序。
-
-    r30:
-       栈指针
-
-    r31:
-       ble指令将返回指针放在这里。
-
-
-    r3-r18,r27,r30需要被保存和恢复。r3-r18只是一般用途的寄存器。
-    r27是数据指针,用来使对全局变量的引用更容易。r30是栈指针。
index 10254751df6a25457d5526995371a1c58213c7bd..cc47be356dd323956f6d6d24a62fad1ac3052d06 100644 (file)
@@ -125,7 +125,7 @@ Linux内核代码中包含有大量的文档。这些文档对于学习如何与
     这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系
     统转移到Linux的人来说也很重要。
 
-  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+  :ref:`Documentation/process/security-bugs.rst <securitybugs>`
     如果你认为自己发现了Linux内核的安全性问题,请根据这篇文档中的步骤来
     提醒其他内核开发者并帮助解决这个问题。
 
index e07ffdd391d32d97b0dda5c37b32da13b0d682c7..8cba135dcd1a6b4aa718f8cc215d8a84ed33f919 100644 (file)
@@ -231,7 +231,7 @@ CFS调度类基于实体负载跟踪机制(Per-Entity Load Tracking, PELT)
 当前,Linux无法凭自身算出CPU算力,因此必须要有把这个信息传递给Linux的方式。每个架构必须为此
 定义arch_scale_cpu_capacity()函数。
 
-arm和arm64架构直接把这个信息映射到arch_topology驱动的CPU scaling数据中(译注:参考
+arm、arm64和RISC-V架构直接把这个信息映射到arch_topology驱动的CPU scaling数据中(译注:参考
 arch_topology.h的percpu变量cpu_scale),它是从capacity-dmips-mhz CPU binding中衍生计算
 出来的。参见Documentation/devicetree/bindings/cpu/cpu-capacity.txt。
 
index eed260ef0c373a450f49b538d8e90793c35bc803..15f8e900507180c9a8dc2c1f012636ec8f6649aa 100644 (file)
@@ -2,7 +2,7 @@
 
 .. include:: ../disclaimer-zh_TW.rst
 
-:Original: :doc:`../../../admin-guide/security-bugs`
+:Original: :doc:`../../../process/security-bugs`
 
 :譯者:
 
index 8fb8edcaee66525d4cd140a6259d083ad2a65279..ea2f468d3e587df699abf8ca0abf322cc05c09a4 100644 (file)
@@ -128,7 +128,7 @@ Linux內核代碼中包含有大量的文檔。這些文檔對於學習如何與
     這篇文檔對於理解Linux的開發哲學至關重要。對於將開發平台從其他操作系
     統轉移到Linux的人來說也很重要。
 
-  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+  :ref:`Documentation/process/security-bugs.rst <securitybugs>`
     如果你認爲自己發現了Linux內核的安全性問題,請根據這篇文檔中的步驟來
     提醒其他內核開發者並幫助解決這個問題。
 
diff --git a/Documentation/usb/gadget_uvc.rst b/Documentation/usb/gadget_uvc.rst
new file mode 100644 (file)
index 0000000..6d22fac
--- /dev/null
@@ -0,0 +1,352 @@
+=======================
+Linux UVC Gadget Driver
+=======================
+
+Overview
+--------
+The UVC Gadget driver is a driver for hardware on the *device* side of a USB
+connection. It is intended to run on a Linux system that has USB device-side
+hardware such as boards with an OTG port.
+
+On the device system, once the driver is bound it appears as a V4L2 device with
+the output capability.
+
+On the host side (once connected via USB cable), a device running the UVC Gadget
+driver *and controlled by an appropriate userspace program* should appear as a UVC
+specification compliant camera, and function appropriately with any program
+designed to handle them. The userspace program running on the device system can
+queue image buffers from a variety of sources to be transmitted via the USB
+connection. Typically this would mean forwarding the buffers from a camera sensor
+peripheral, but the source of the buffer is entirely dependent on the userspace
+companion program.
+
+Configuring the device kernel
+-----------------------------
+The Kconfig options USB_CONFIGFS, USB_LIBCOMPOSITE, USB_CONFIGFS_F_UVC and
+USB_F_UVC must be selected to enable support for the UVC gadget.
+
+Configuring the gadget through configfs
+---------------------------------------
+The UVC Gadget expects to be configured through configfs using the UVC function.
+This allows a significant degree of flexibility, as many of a UVC device's
+settings can be controlled this way.
+
+Not all of the available attributes are described here. For a complete enumeration
+see Documentation/ABI/testing/configfs-usb-gadget-uvc
+
+Assumptions
+~~~~~~~~~~~
+This section assumes that you have mounted configfs at `/sys/kernel/config` and
+created a gadget as `/sys/kernel/config/usb_gadget/g1`.
+
+The UVC Function
+~~~~~~~~~~~~~~~~
+
+The first step is to create the UVC function:
+
+.. code-block:: bash
+
+       # These variables will be assumed throughout the rest of the document
+       CONFIGFS="/sys/kernel/config"
+       GADGET="$CONFIGFS/usb_gadget/g1"
+       FUNCTION="$GADGET/functions/uvc.0"
+
+       mkdir -p $FUNCTION
+
+Formats and Frames
+~~~~~~~~~~~~~~~~~~
+
+You must configure the gadget by telling it which formats you support, as well
+as the frame sizes and frame intervals that are supported for each format. In
+the current implementation there is no way for the gadget to refuse to set a
+format that the host instructs it to set, so it is important that this step is
+completed *accurately* to ensure that the host never asks for a format that
+can't be provided.
+
+Formats are created under the streaming/uncompressed and streaming/mjpeg configfs
+groups, with the framesizes created under the formats in the following
+structure:
+
+::
+
+       uvc.0 +
+             |
+             + streaming +
+                         |
+                         + mjpeg +
+                         |       |
+                         |       + mjpeg +
+                         |            |
+                         |            + 720p
+                         |            |
+                         |            + 1080p
+                         |
+                         + uncompressed +
+                                        |
+                                        + yuyv +
+                                               |
+                                               + 720p
+                                               |
+                                               + 1080p
+
+Each frame can then be configured with a width and height, plus the maximum
+buffer size required to store a single frame, and finally with the supported
+frame intervals for that format and framesize. Width and height are enumerated in
+units of pixels, frame interval in units of 100ns. To create the structure
+above with 2, 15 and 100 fps frameintervals for each framesize for example you
+might do:
+
+.. code-block:: bash
+
+       create_frame() {
+               # Example usage:
+               # create_frame <width> <height> <group> <format name>
+
+               WIDTH=$1
+               HEIGHT=$2
+               FORMAT=$3
+               NAME=$4
+
+               wdir=$FUNCTION/streaming/$FORMAT/$NAME/${HEIGHT}p
+
+               mkdir -p $wdir
+               echo $WIDTH > $wdir/wWidth
+               echo $HEIGHT > $wdir/wHeight
+               echo $(( $WIDTH * $HEIGHT * 2 )) > $wdir/dwMaxVideoFrameBufferSize
+               cat <<EOF > $wdir/dwFrameInterval
+       666666
+       100000
+       5000000
+       EOF
+       }
+
+       create_frame 1280 720 mjpeg mjpeg
+       create_frame 1920 1080 mjpeg mjpeg
+       create_frame 1280 720 uncompressed yuyv
+       create_frame 1920 1080 uncompressed yuyv
+
+The only uncompressed format currently supported is YUYV, which is detailed at
+Documentation/userspace-api/media/v4l/pixfmt-packed.yuv.rst.
+
+Color Matching Descriptors
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+It's possible to specify some colometry information for each format you create.
+This step is optional, and default information will be included if this step is
+skipped; those default values follow those defined in the Color Matching Descriptor
+section of the UVC specification.
+
+To create a Color Matching Descriptor, create a configfs item and set its three
+attributes to your desired settings and then link to it from the format you wish
+it to be associated with:
+
+.. code-block:: bash
+
+       # Create a new Color Matching Descriptor
+
+       mkdir $FUNCTION/streaming/color_matching/yuyv
+       pushd $FUNCTION/streaming/color_matching/yuyv
+
+       echo 1 > bColorPrimaries
+       echo 1 > bTransferCharacteristics
+       echo 4 > bMatrixCoefficients
+
+       popd
+
+       # Create a symlink to the Color Matching Descriptor from the format's config item
+       ln -s $FUNCTION/streaming/color_matching/yuyv $FUNCTION/streaming/uncompressed/yuyv
+
+For details about the valid values, consult the UVC specification. Note that a
+default color matching descriptor exists and is used by any format which does
+not have a link to a different Color Matching Descriptor. It's possible to
+change the attribute settings for the default descriptor, so bear in mind that if
+you do that you are altering the defaults for any format that does not link to
+a different one.
+
+
+Header linking
+~~~~~~~~~~~~~~
+
+The UVC specification requires that Format and Frame descriptors be preceded by
+Headers detailing things such as the number and cumulative size of the different
+Format descriptors that follow. This and similar operations are acheived in
+configfs by linking between the configfs item representing the header and the
+config items representing those other descriptors, in this manner:
+
+.. code-block:: bash
+
+       mkdir $FUNCTION/streaming/header/h
+
+       # This section links the format descriptors and their associated frames
+       # to the header
+       cd $FUNCTION/streaming/header/h
+       ln -s ../../uncompressed/yuyv
+       ln -s ../../mjpeg/mjpeg
+
+       # This section ensures that the header will be transmitted for each
+       # speed's set of descriptors. If support for a particular speed is not
+       # needed then it can be skipped here.
+       cd ../../class/fs
+       ln -s ../../header/h
+       cd ../../class/hs
+       ln -s ../../header/h
+       cd ../../class/ss
+       ln -s ../../header/h
+       cd ../../../control
+       mkdir header/h
+       ln -s header/h class/fs
+       ln -s header/h class/ss
+
+
+Extension Unit Support
+~~~~~~~~~~~~~~~~~~~~~~
+
+A UVC Extension Unit (XU) basically provides a distinct unit to which control set
+and get requests can be addressed. The meaning of those control requests is
+entirely implementation dependent, but may be used to control settings outside
+of the UVC specification (for example enabling or disabling video effects). An
+XU can be inserted into the UVC unit chain or left free-hanging.
+
+Configuring an extension unit involves creating an entry in the appropriate
+directory and setting its attributes appropriately, like so:
+
+.. code-block:: bash
+
+       mkdir $FUNCTION/control/extensions/xu.0
+       pushd $FUNCTION/control/extensions/xu.0
+
+       # Set the bUnitID of the Processing Unit as the source for this
+       # Extension Unit
+       echo 2 > baSourceID
+
+       # Set this XU as the source of the default output terminal. This inserts
+       # the XU into the UVC chain between the PU and OT such that the final
+       # chain is IT > PU > XU.0 > OT
+       cat bUnitID > ../../terminal/output/default/baSourceID
+
+       # Flag some controls as being available for use. The bmControl field is
+       # a bitmap with each bit denoting the availability of a particular
+       # control. For example to flag the 0th, 2nd and 3rd controls available:
+       echo 0x0d > bmControls
+
+       # Set the GUID; this is a vendor-specific code identifying the XU.
+       echo -e -n "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" > guidExtensionCode
+
+       popd
+
+The bmControls attribute and the baSourceID attribute are multi-value attributes.
+This means that you may write multiple newline separated values to them. For
+example to flag the 1st, 2nd, 9th and 10th controls as being available you would
+need to write two values to bmControls, like so:
+
+.. code-block:: bash
+
+       cat << EOF > bmControls
+       0x03
+       0x03
+       EOF
+
+The multi-value nature of the baSourceID attribute belies the fact that XUs can
+be multiple-input, though note that this currently has no significant effect.
+
+The bControlSize attribute reflects the size of the bmControls attribute, and
+similarly bNrInPins reflects the size of the baSourceID attributes. Both
+attributes are automatically increased / decreased as you set bmControls and
+baSourceID. It is also possible to manually increase or decrease bControlSize
+which has the effect of truncating entries to the new size, or padding entries
+out with 0x00, for example:
+
+::
+
+       $ cat bmControls
+       0x03
+       0x05
+
+       $ cat bControlSize
+       2
+
+       $ echo 1 > bControlSize
+       $ cat bmControls
+       0x03
+
+       $ echo 2 > bControlSize
+       $ cat bmControls
+       0x03
+       0x00
+
+bNrInPins and baSourceID function in the same way.
+
+Custom Strings Support
+~~~~~~~~~~~~~~~~~~~~~~
+
+String descriptors that provide a textual description for various parts of a
+USB device can be defined in the usual place within USB configfs, and may then
+be linked to from the UVC function root or from Extension Unit directories to
+assign those strings as descriptors:
+
+.. code-block:: bash
+
+       # Create a string descriptor in us-EN and link to it from the function
+       # root. The name of the link is significant here, as it declares this
+       # descriptor to be intended for the Interface Association Descriptor.
+       # Other significant link names at function root are vs0_desc and vs1_desc
+       # For the VideoStreaming Interface 0/1 Descriptors.
+
+       mkdir -p $GADGET/strings/0x409/iad_desc
+       echo -n "Interface Associaton Descriptor" > $GADGET/strings/0x409/iad_desc/s
+       ln -s $GADGET/strings/0x409/iad_desc $FUNCTION/iad_desc
+
+       # Because the link to a String Descriptor from an Extension Unit clearly
+       # associates the two, the name of this link is not significant and may
+       # be set freely.
+
+       mkdir -p $GADGET/strings/0x409/xu.0
+       echo -n "A Very Useful Extension Unit" > $GADGET/strings/0x409/xu.0/s
+       ln -s $GADGET/strings/0x409/xu.0 $FUNCTION/control/extensions/xu.0
+
+The interrupt endpoint
+~~~~~~~~~~~~~~~~~~~~~~
+
+The VideoControl interface has an optional interrupt endpoint which is by default
+disabled. This is intended to support delayed response control set requests for
+UVC (which should respond through the interrupt endpoint rather than tying up
+endpoint 0). At present support for sending data through this endpoint is missing
+and so it is left disabled to avoid confusion. If you wish to enable it you can
+do so through the configfs attribute:
+
+.. code-block:: bash
+
+       echo 1 > $FUNCTION/control/enable_interrupt_ep
+
+Bandwidth configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There are three attributes which control the bandwidth of the USB connection.
+These live in the function root and can be set within limits:
+
+.. code-block:: bash
+
+       # streaming_interval sets bInterval. Values range from 1..255
+       echo 1 > $FUNCTION/streaming_interval
+
+       # streaming_maxpacket sets wMaxPacketSize. Valid values are 1024/2048/3072
+       echo 3072 > $FUNCTION/streaming_maxpacket
+
+       # streaming_maxburst sets bMaxBurst. Valid values are 1..15
+       echo 1 > $FUNCTION/streaming_maxburst
+
+
+The values passed here will be clamped to valid values according to the UVC
+specification (which depend on the speed of the USB connection). To understand
+how the settings influence bandwidth you should consult the UVC specifications,
+but a rule of thumb is that increasing the streaming_maxpacket setting will
+improve bandwidth (and thus the maximum possible framerate), whilst the same is
+true for streaming_maxburst provided the USB connection is running at SuperSpeed.
+Increasing streaming_interval will reduce bandwidth and framerate.
+
+The userspace application
+-------------------------
+By itself, the UVC Gadget driver cannot do anything particularly interesting. It
+must be paired with a userspace program that responds to UVC control requests and
+fills buffers to be queued to the V4L2 device that the driver creates. How those
+things are achieved is implementation dependent and beyond the scope of this
+document, but a reference application can be found at https://gitlab.freedesktop.org/camera/uvc-gadget
index b656c9be23ed230af5b499ef68689a9bfdfa5094..27955dad95e12403fbae8dda7c64dd9771fec3bd 100644 (file)
@@ -16,6 +16,7 @@ USB support
     gadget_multi
     gadget_printer
     gadget_serial
+    gadget_uvc
     gadget-testing
     iuu_phoenix
     mass-storage
diff --git a/Documentation/userspace-api/ELF.rst b/Documentation/userspace-api/ELF.rst
new file mode 100644 (file)
index 0000000..ac8aeac
--- /dev/null
@@ -0,0 +1,34 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================================
+Linux-specific ELF idiosyncrasies
+=================================
+
+Definitions
+===========
+
+"First" program header is the one with the smallest offset in the file:
+e_phoff.
+
+"Last" program header is the one with the biggest offset in the file:
+e_phoff + (e_phnum - 1) * sizeof(Elf_Phdr).
+
+PT_INTERP
+=========
+
+First PT_INTERP program header is used to locate the filename of ELF
+interpreter. Other PT_INTERP headers are ignored (since Linux 2.4.11).
+
+PT_GNU_STACK
+============
+
+Last PT_GNU_STACK program header defines userspace stack executability
+(since Linux 2.6.6). Other PT_GNU_STACK headers are ignored.
+
+PT_GNU_PROPERTY
+===============
+
+ELF interpreter's last PT_GNU_PROPERTY program header is used (since
+Linux 5.8). If interpreter doesn't have one, then the last PT_GNU_PROPERTY
+program header of an executable is used. Other PT_GNU_PROPERTY headers
+are ignored.
index f16337bdb8520fac879bc4aee481bf7cfe8b0ce4..72a65db0c498898749d6e182e2e277ebd7647291 100644 (file)
@@ -23,6 +23,7 @@ place where this information is gathered.
    spec_ctrl
    accelerators/ocxl
    ebpf/index
+   ELF
    ioctl/index
    iommu
    iommufd
index d330aeb4d3ebf74af6e931d839c70fabf8e832d2..d9d7b7621d8cef4fb597122c30e7a4f856151fb9 100644 (file)
@@ -778,7 +778,7 @@ number of bits for each component.
     \tiny
     \setlength{\tabcolsep}{2pt}
 
-.. tabularcolumns:: |p{2.8cm}|p{2.0cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
+.. tabularcolumns:: |p{3.2cm}|p{0.8cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
 
 
 .. flat-table:: RGB Formats 10 Bits Per Color Component
@@ -868,7 +868,6 @@ number of bits for each component.
       - r\ :sub:`4`
       - r\ :sub:`3`
       - r\ :sub:`2`
-      -
     * .. _V4L2-PIX-FMT-RGBA1010102:
 
       - ``V4L2_PIX_FMT_RGBA1010102``
@@ -909,7 +908,6 @@ number of bits for each component.
       - r\ :sub:`4`
       - r\ :sub:`3`
       - r\ :sub:`2`
-      -
     * .. _V4L2-PIX-FMT-ARGB2101010:
 
       - ``V4L2_PIX_FMT_ARGB2101010``
@@ -950,7 +948,6 @@ number of bits for each component.
       - r\ :sub:`6`
       - r\ :sub:`5`
       - r\ :sub:`4`
-      -
 
 .. raw:: latex
 
index 2122e0c4a39987c4fdf86a1d4fbbcb954d1813ce..a22442ba1d30bb4bfeae33bf85a71458d235f7ba 100644 (file)
@@ -24,7 +24,8 @@ YAML specifications can be found under ``Documentation/netlink/specs/``
 This document describes details of the schema.
 See :doc:`intro-specs` for a practical starting guide.
 
-All specs must be licensed under ``GPL-2.0-only OR BSD-3-Clause``
+All specs must be licensed under
+``((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)``
 to allow for easy adoption in user space code.
 
 Compatibility levels
index bf593e88cfd9d737b62e1a82d66bf4f847594624..68b0d2363af820256c70ba2d5284244247ee979f 100644 (file)
@@ -37,11 +37,11 @@ along with a description:
       the return value.  General error numbers (-ENOMEM, -EINVAL)
       are not detailed, but errors with specific meanings are.
 
-The guest ioctl should be issued on a file descriptor of the /dev/sev-guest device.
-The ioctl accepts struct snp_user_guest_request. The input and output structure is
-specified through the req_data and resp_data field respectively. If the ioctl fails
-to execute due to a firmware error, then fw_err code will be set otherwise the
-fw_err will be set to 0x00000000000000ff.
+The guest ioctl should be issued on a file descriptor of the /dev/sev-guest
+device.  The ioctl accepts struct snp_user_guest_request. The input and
+output structure is specified through the req_data and resp_data field
+respectively. If the ioctl fails to execute due to a firmware error, then
+the fw_error code will be set, otherwise fw_error will be set to -1.
 
 The firmware checks that the message sequence counter is one greater than
 the guests message sequence counter. If guest driver fails to increment message
@@ -57,8 +57,14 @@ counter (e.g. counter overflow), then -EIO will be returned.
                 __u64 req_data;
                 __u64 resp_data;
 
-                /* firmware error code on failure (see psp-sev.h) */
-                __u64 fw_err;
+                /* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */
+                union {
+                        __u64 exitinfo2;
+                        struct {
+                                __u32 fw_error;
+                                __u32 vmm_error;
+                        };
+                };
         };
 
 2.1 SNP_GET_REPORT
index 62de0768d6aa5991a1054813eedc2e37b6e6ad1e..841e9d1987bde6f5132306cbe54722634b296433 100644 (file)
@@ -7456,7 +7456,7 @@ system fingerprint.  To prevent userspace from circumventing such restrictions
 by running an enclave in a VM, KVM prevents access to privileged attributes by
 default.
 
-See Documentation/x86/sgx.rst for more details.
+See Documentation/arch/x86/sgx.rst for more details.
 
 7.26 KVM_CAP_PPC_RPT_INVALIDATE
 -------------------------------
@@ -8296,11 +8296,11 @@ ENOSYS for the others.
 8.35 KVM_CAP_PMU_CAPABILITY
 ---------------------------
 
-:Capability KVM_CAP_PMU_CAPABILITY
+:Capability: KVM_CAP_PMU_CAPABILITY
 :Architectures: x86
 :Type: vm
 :Parameters: arg[0] is bitmask of PMU virtualization capabilities.
-:Returns 0 on success, -EINVAL when arg[0] contains invalid bits
+:Returns: 0 on success, -EINVAL when arg[0] contains invalid bits
 
 This capability alters PMU virtualization in KVM.
 
diff --git a/Documentation/x86/amd-memory-encryption.rst b/Documentation/x86/amd-memory-encryption.rst
deleted file mode 100644 (file)
index 934310c..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=====================
-AMD Memory Encryption
-=====================
-
-Secure Memory Encryption (SME) and Secure Encrypted Virtualization (SEV) are
-features found on AMD processors.
-
-SME provides the ability to mark individual pages of memory as encrypted using
-the standard x86 page tables.  A page that is marked encrypted will be
-automatically decrypted when read from DRAM and encrypted when written to
-DRAM.  SME can therefore be used to protect the contents of DRAM from physical
-attacks on the system.
-
-SEV enables running encrypted virtual machines (VMs) in which the code and data
-of the guest VM are secured so that a decrypted version is available only
-within the VM itself. SEV guest VMs have the concept of private and shared
-memory. Private memory is encrypted with the guest-specific key, while shared
-memory may be encrypted with hypervisor key. When SME is enabled, the hypervisor
-key is the same key which is used in SME.
-
-A page is encrypted when a page table entry has the encryption bit set (see
-below on how to determine its position).  The encryption bit can also be
-specified in the cr3 register, allowing the PGD table to be encrypted. Each
-successive level of page tables can also be encrypted by setting the encryption
-bit in the page table entry that points to the next table. This allows the full
-page table hierarchy to be encrypted. Note, this means that just because the
-encryption bit is set in cr3, doesn't imply the full hierarchy is encrypted.
-Each page table entry in the hierarchy needs to have the encryption bit set to
-achieve that. So, theoretically, you could have the encryption bit set in cr3
-so that the PGD is encrypted, but not set the encryption bit in the PGD entry
-for a PUD which results in the PUD pointed to by that entry to not be
-encrypted.
-
-When SEV is enabled, instruction pages and guest page tables are always treated
-as private. All the DMA operations inside the guest must be performed on shared
-memory. Since the memory encryption bit is controlled by the guest OS when it
-is operating in 64-bit or 32-bit PAE mode, in all other modes the SEV hardware
-forces the memory encryption bit to 1.
-
-Support for SME and SEV can be determined through the CPUID instruction. The
-CPUID function 0x8000001f reports information related to SME::
-
-       0x8000001f[eax]:
-               Bit[0] indicates support for SME
-               Bit[1] indicates support for SEV
-       0x8000001f[ebx]:
-               Bits[5:0]  pagetable bit number used to activate memory
-                          encryption
-               Bits[11:6] reduction in physical address space, in bits, when
-                          memory encryption is enabled (this only affects
-                          system physical addresses, not guest physical
-                          addresses)
-
-If support for SME is present, MSR 0xc00100010 (MSR_AMD64_SYSCFG) can be used to
-determine if SME is enabled and/or to enable memory encryption::
-
-       0xc0010010:
-               Bit[23]   0 = memory encryption features are disabled
-                         1 = memory encryption features are enabled
-
-If SEV is supported, MSR 0xc0010131 (MSR_AMD64_SEV) can be used to determine if
-SEV is active::
-
-       0xc0010131:
-               Bit[0]    0 = memory encryption is not active
-                         1 = memory encryption is active
-
-Linux relies on BIOS to set this bit if BIOS has determined that the reduction
-in the physical address space as a result of enabling memory encryption (see
-CPUID information above) will not conflict with the address space resource
-requirements for the system.  If this bit is not set upon Linux startup then
-Linux itself will not set it and memory encryption will not be possible.
-
-The state of SME in the Linux kernel can be documented as follows:
-
-       - Supported:
-         The CPU supports SME (determined through CPUID instruction).
-
-       - Enabled:
-         Supported and bit 23 of MSR_AMD64_SYSCFG is set.
-
-       - Active:
-         Supported, Enabled and the Linux kernel is actively applying
-         the encryption bit to page table entries (the SME mask in the
-         kernel is non-zero).
-
-SME can also be enabled and activated in the BIOS. If SME is enabled and
-activated in the BIOS, then all memory accesses will be encrypted and it will
-not be necessary to activate the Linux memory encryption support.  If the BIOS
-merely enables SME (sets bit 23 of the MSR_AMD64_SYSCFG), then Linux can activate
-memory encryption by default (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y) or
-by supplying mem_encrypt=on on the kernel command line.  However, if BIOS does
-not enable SME, then Linux will not be able to activate memory encryption, even
-if configured to do so by default or the mem_encrypt=on command line parameter
-is specified.
-
-Secure Nested Paging (SNP)
-==========================
-
-SEV-SNP introduces new features (SEV_FEATURES[1:63]) which can be enabled
-by the hypervisor for security enhancements. Some of these features need
-guest side implementation to function correctly. The below table lists the
-expected guest behavior with various possible scenarios of guest/hypervisor
-SNP feature support.
-
-+-----------------+---------------+---------------+------------------+
-| Feature Enabled | Guest needs   | Guest has     | Guest boot       |
-| by the HV       | implementation| implementation| behaviour        |
-+=================+===============+===============+==================+
-|      No         |      No       |      No       |     Boot         |
-|                 |               |               |                  |
-+-----------------+---------------+---------------+------------------+
-|      No         |      Yes      |      No       |     Boot         |
-|                 |               |               |                  |
-+-----------------+---------------+---------------+------------------+
-|      No         |      Yes      |      Yes      |     Boot         |
-|                 |               |               |                  |
-+-----------------+---------------+---------------+------------------+
-|      Yes        |      No       |      No       | Boot with        |
-|                 |               |               | feature enabled  |
-+-----------------+---------------+---------------+------------------+
-|      Yes        |      Yes      |      No       | Graceful boot    |
-|                 |               |               | failure          |
-+-----------------+---------------+---------------+------------------+
-|      Yes        |      Yes      |      Yes      | Boot with        |
-|                 |               |               | feature enabled  |
-+-----------------+---------------+---------------+------------------+
-
-More details in AMD64 APM[1] Vol 2: 15.34.10 SEV_STATUS MSR
-
-[1] https://www.amd.com/system/files/TechDocs/40332.pdf
diff --git a/Documentation/x86/amd_hsmp.rst b/Documentation/x86/amd_hsmp.rst
deleted file mode 100644 (file)
index 440e4b6..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============================================
-AMD HSMP interface
-============================================
-
-Newer Fam19h EPYC server line of processors from AMD support system
-management functionality via HSMP (Host System Management Port).
-
-The Host System Management Port (HSMP) is an interface to provide
-OS-level software with access to system management functions via a
-set of mailbox registers.
-
-More details on the interface can be found in chapter
-"7 Host System Management Port (HSMP)" of the family/model PPR
-Eg: https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
-
-HSMP interface is supported on EPYC server CPU models only.
-
-
-HSMP device
-============================================
-
-amd_hsmp driver under the drivers/platforms/x86/ creates miscdevice
-/dev/hsmp to let user space programs run hsmp mailbox commands.
-
-$ ls -al /dev/hsmp
-crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp
-
-Characteristics of the dev node:
- * Write mode is used for running set/configure commands
- * Read mode is used for running get/status monitor commands
-
-Access restrictions:
- * Only root user is allowed to open the file in write mode.
- * The file can be opened in read mode by all the users.
-
-In-kernel integration:
- * Other subsystems in the kernel can use the exported transport
-   function hsmp_send_message().
- * Locking across callers is taken care by the driver.
-
-
-An example
-==========
-
-To access hsmp device from a C program.
-First, you need to include the headers::
-
-  #include <linux/amd_hsmp.h>
-
-Which defines the supported messages/message IDs.
-
-Next thing, open the device file, as follows::
-
-  int file;
-
-  file = open("/dev/hsmp", O_RDWR);
-  if (file < 0) {
-    /* ERROR HANDLING; you can check errno to see what went wrong */
-    exit(1);
-  }
-
-The following IOCTL is defined:
-
-``ioctl(file, HSMP_IOCTL_CMD, struct hsmp_message *msg)``
-  The argument is a pointer to a::
-
-    struct hsmp_message {
-       __u32   msg_id;                         /* Message ID */
-       __u16   num_args;                       /* Number of input argument words in message */
-       __u16   response_sz;                    /* Number of expected output/response words */
-       __u32   args[HSMP_MAX_MSG_LEN];         /* argument/response buffer */
-       __u16   sock_ind;                       /* socket number */
-    };
-
-The ioctl would return a non-zero on failure; you can read errno to see
-what happened. The transaction returns 0 on success.
-
-More details on the interface and message definitions can be found in chapter
-"7 Host System Management Port (HSMP)" of the respective family/model PPR
-eg: https://www.amd.com/system/files/TechDocs/55898_B1_pub_0.50.zip
-
-User space C-APIs are made available by linking against the esmi library,
-which is provided by the E-SMS project https://developer.amd.com/e-sms/.
-See: https://github.com/amd/esmi_ib_library
diff --git a/Documentation/x86/boot.rst b/Documentation/x86/boot.rst
deleted file mode 100644 (file)
index 240d084..0000000
+++ /dev/null
@@ -1,1443 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===========================
-The Linux/x86 Boot Protocol
-===========================
-
-On the x86 platform, the Linux kernel uses a rather complicated boot
-convention.  This has evolved partially due to historical aspects, as
-well as the desire in the early days to have the kernel itself be a
-bootable image, the complicated PC memory model and due to changed
-expectations in the PC industry caused by the effective demise of
-real-mode DOS as a mainstream operating system.
-
-Currently, the following versions of the Linux/x86 boot protocol exist.
-
-=============  ============================================================
-Old kernels    zImage/Image support only.  Some very early kernels
-               may not even support a command line.
-
-Protocol 2.00  (Kernel 1.3.73) Added bzImage and initrd support, as
-               well as a formalized way to communicate between the
-               boot loader and the kernel.  setup.S made relocatable,
-               although the traditional setup area still assumed
-               writable.
-
-Protocol 2.01  (Kernel 1.3.76) Added a heap overrun warning.
-
-Protocol 2.02  (Kernel 2.4.0-test3-pre3) New command line protocol.
-               Lower the conventional memory ceiling.  No overwrite
-               of the traditional setup area, thus making booting
-               safe for systems which use the EBDA from SMM or 32-bit
-               BIOS entry points.  zImage deprecated but still
-               supported.
-
-Protocol 2.03  (Kernel 2.4.18-pre1) Explicitly makes the highest possible
-               initrd address available to the bootloader.
-
-Protocol 2.04  (Kernel 2.6.14) Extend the syssize field to four bytes.
-
-Protocol 2.05  (Kernel 2.6.20) Make protected mode kernel relocatable.
-               Introduce relocatable_kernel and kernel_alignment fields.
-
-Protocol 2.06  (Kernel 2.6.22) Added a field that contains the size of
-               the boot command line.
-
-Protocol 2.07  (Kernel 2.6.24) Added paravirtualised boot protocol.
-               Introduced hardware_subarch and hardware_subarch_data
-               and KEEP_SEGMENTS flag in load_flags.
-
-Protocol 2.08  (Kernel 2.6.26) Added crc32 checksum and ELF format
-               payload. Introduced payload_offset and payload_length
-               fields to aid in locating the payload.
-
-Protocol 2.09  (Kernel 2.6.26) Added a field of 64-bit physical
-               pointer to single linked list of struct setup_data.
-
-Protocol 2.10  (Kernel 2.6.31) Added a protocol for relaxed alignment
-               beyond the kernel_alignment added, new init_size and
-               pref_address fields.  Added extended boot loader IDs.
-
-Protocol 2.11  (Kernel 3.6) Added a field for offset of EFI handover
-               protocol entry point.
-
-Protocol 2.12  (Kernel 3.8) Added the xloadflags field and extension fields
-               to struct boot_params for loading bzImage and ramdisk
-               above 4G in 64bit.
-
-Protocol 2.13  (Kernel 3.14) Support 32- and 64-bit flags being set in
-               xloadflags to support booting a 64-bit kernel from 32-bit
-               EFI
-
-Protocol 2.14  BURNT BY INCORRECT COMMIT
-                ae7e1238e68f2a472a125673ab506d49158c1889
-               (x86/boot: Add ACPI RSDP address to setup_header)
-               DO NOT USE!!! ASSUME SAME AS 2.13.
-
-Protocol 2.15  (Kernel 5.5) Added the kernel_info and kernel_info.setup_type_max.
-=============  ============================================================
-
-.. note::
-     The protocol version number should be changed only if the setup header
-     is changed. There is no need to update the version number if boot_params
-     or kernel_info are changed. Additionally, it is recommended to use
-     xloadflags (in this case the protocol version number should not be
-     updated either) or kernel_info to communicate supported Linux kernel
-     features to the boot loader. Due to very limited space available in
-     the original setup header every update to it should be considered
-     with great care. Starting from the protocol 2.15 the primary way to
-     communicate things to the boot loader is the kernel_info.
-
-
-Memory Layout
-=============
-
-The traditional memory map for the kernel loader, used for Image or
-zImage kernels, typically looks like::
-
-               |                        |
-       0A0000  +------------------------+
-               |  Reserved for BIOS     |      Do not use.  Reserved for BIOS EBDA.
-       09A000  +------------------------+
-               |  Command line          |
-               |  Stack/heap            |      For use by the kernel real-mode code.
-       098000  +------------------------+
-               |  Kernel setup          |      The kernel real-mode code.
-       090200  +------------------------+
-               |  Kernel boot sector    |      The kernel legacy boot sector.
-       090000  +------------------------+
-               |  Protected-mode kernel |      The bulk of the kernel image.
-       010000  +------------------------+
-               |  Boot loader           |      <- Boot sector entry point 0000:7C00
-       001000  +------------------------+
-               |  Reserved for MBR/BIOS |
-       000800  +------------------------+
-               |  Typically used by MBR |
-       000600  +------------------------+
-               |  BIOS use only         |
-       000000  +------------------------+
-
-When using bzImage, the protected-mode kernel was relocated to
-0x100000 ("high memory"), and the kernel real-mode block (boot sector,
-setup, and stack/heap) was made relocatable to any address between
-0x10000 and end of low memory. Unfortunately, in protocols 2.00 and
-2.01 the 0x90000+ memory range is still used internally by the kernel;
-the 2.02 protocol resolves that problem.
-
-It is desirable to keep the "memory ceiling" -- the highest point in
-low memory touched by the boot loader -- as low as possible, since
-some newer BIOSes have begun to allocate some rather large amounts of
-memory, called the Extended BIOS Data Area, near the top of low
-memory.         The boot loader should use the "INT 12h" BIOS call to verify
-how much low memory is available.
-
-Unfortunately, if INT 12h reports that the amount of memory is too
-low, there is usually nothing the boot loader can do but to report an
-error to the user.  The boot loader should therefore be designed to
-take up as little space in low memory as it reasonably can.  For
-zImage or old bzImage kernels, which need data written into the
-0x90000 segment, the boot loader should make sure not to use memory
-above the 0x9A000 point; too many BIOSes will break above that point.
-
-For a modern bzImage kernel with boot protocol version >= 2.02, a
-memory layout like the following is suggested::
-
-               ~                        ~
-               |  Protected-mode kernel |
-       100000  +------------------------+
-               |  I/O memory hole       |
-       0A0000  +------------------------+
-               |  Reserved for BIOS     |      Leave as much as possible unused
-               ~                        ~
-               |  Command line          |      (Can also be below the X+10000 mark)
-       X+10000 +------------------------+
-               |  Stack/heap            |      For use by the kernel real-mode code.
-       X+08000 +------------------------+
-               |  Kernel setup          |      The kernel real-mode code.
-               |  Kernel boot sector    |      The kernel legacy boot sector.
-       X       +------------------------+
-               |  Boot loader           |      <- Boot sector entry point 0000:7C00
-       001000  +------------------------+
-               |  Reserved for MBR/BIOS |
-       000800  +------------------------+
-               |  Typically used by MBR |
-       000600  +------------------------+
-               |  BIOS use only         |
-       000000  +------------------------+
-
-  ... where the address X is as low as the design of the boot loader permits.
-
-
-The Real-Mode Kernel Header
-===========================
-
-In the following text, and anywhere in the kernel boot sequence, "a
-sector" refers to 512 bytes.  It is independent of the actual sector
-size of the underlying medium.
-
-The first step in loading a Linux kernel should be to load the
-real-mode code (boot sector and setup code) and then examine the
-following header at offset 0x01f1.  The real-mode code can total up to
-32K, although the boot loader may choose to load only the first two
-sectors (1K) and then examine the bootup sector size.
-
-The header looks like:
-
-===========    ========        =====================   ============================================
-Offset/Size    Proto           Name                    Meaning
-===========    ========        =====================   ============================================
-01F1/1         ALL(1)          setup_sects             The size of the setup in sectors
-01F2/2         ALL             root_flags              If set, the root is mounted readonly
-01F4/4         2.04+(2)        syssize                 The size of the 32-bit code in 16-byte paras
-01F8/2         ALL             ram_size                DO NOT USE - for bootsect.S use only
-01FA/2         ALL             vid_mode                Video mode control
-01FC/2         ALL             root_dev                Default root device number
-01FE/2         ALL             boot_flag               0xAA55 magic number
-0200/2         2.00+           jump                    Jump instruction
-0202/4         2.00+           header                  Magic signature "HdrS"
-0206/2         2.00+           version                 Boot protocol version supported
-0208/4         2.00+           realmode_swtch          Boot loader hook (see below)
-020C/2         2.00+           start_sys_seg           The load-low segment (0x1000) (obsolete)
-020E/2         2.00+           kernel_version          Pointer to kernel version string
-0210/1         2.00+           type_of_loader          Boot loader identifier
-0211/1         2.00+           loadflags               Boot protocol option flags
-0212/2         2.00+           setup_move_size         Move to high memory size (used with hooks)
-0214/4         2.00+           code32_start            Boot loader hook (see below)
-0218/4         2.00+           ramdisk_image           initrd load address (set by boot loader)
-021C/4         2.00+           ramdisk_size            initrd size (set by boot loader)
-0220/4         2.00+           bootsect_kludge         DO NOT USE - for bootsect.S use only
-0224/2         2.01+           heap_end_ptr            Free memory after setup end
-0226/1         2.02+(3)        ext_loader_ver          Extended boot loader version
-0227/1         2.02+(3)        ext_loader_type         Extended boot loader ID
-0228/4         2.02+           cmd_line_ptr            32-bit pointer to the kernel command line
-022C/4         2.03+           initrd_addr_max         Highest legal initrd address
-0230/4         2.05+           kernel_alignment        Physical addr alignment required for kernel
-0234/1         2.05+           relocatable_kernel      Whether kernel is relocatable or not
-0235/1         2.10+           min_alignment           Minimum alignment, as a power of two
-0236/2         2.12+           xloadflags              Boot protocol option flags
-0238/4         2.06+           cmdline_size            Maximum size of the kernel command line
-023C/4         2.07+           hardware_subarch        Hardware subarchitecture
-0240/8         2.07+           hardware_subarch_data   Subarchitecture-specific data
-0248/4         2.08+           payload_offset          Offset of kernel payload
-024C/4         2.08+           payload_length          Length of kernel payload
-0250/8         2.09+           setup_data              64-bit physical pointer to linked list
-                                                       of struct setup_data
-0258/8         2.10+           pref_address            Preferred loading address
-0260/4         2.10+           init_size               Linear memory required during initialization
-0264/4         2.11+           handover_offset         Offset of handover entry point
-0268/4         2.15+           kernel_info_offset      Offset of the kernel_info
-===========    ========        =====================   ============================================
-
-.. note::
-  (1) For backwards compatibility, if the setup_sects field contains 0, the
-      real value is 4.
-
-  (2) For boot protocol prior to 2.04, the upper two bytes of the syssize
-      field are unusable, which means the size of a bzImage kernel
-      cannot be determined.
-
-  (3) Ignored, but safe to set, for boot protocols 2.02-2.09.
-
-If the "HdrS" (0x53726448) magic number is not found at offset 0x202,
-the boot protocol version is "old".  Loading an old kernel, the
-following parameters should be assumed::
-
-       Image type = zImage
-       initrd not supported
-       Real-mode kernel must be located at 0x90000.
-
-Otherwise, the "version" field contains the protocol version,
-e.g. protocol version 2.01 will contain 0x0201 in this field.  When
-setting fields in the header, you must make sure only to set fields
-supported by the protocol version in use.
-
-
-Details of Header Fields
-========================
-
-For each field, some are information from the kernel to the bootloader
-("read"), some are expected to be filled out by the bootloader
-("write"), and some are expected to be read and modified by the
-bootloader ("modify").
-
-All general purpose boot loaders should write the fields marked
-(obligatory).  Boot loaders who want to load the kernel at a
-nonstandard address should fill in the fields marked (reloc); other
-boot loaders can ignore those fields.
-
-The byte order of all fields is littleendian (this is x86, after all.)
-
-============   ===========
-Field name:    setup_sects
-Type:          read
-Offset/size:   0x1f1/1
-Protocol:      ALL
-============   ===========
-
-  The size of the setup code in 512-byte sectors.  If this field is
-  0, the real value is 4.  The real-mode code consists of the boot
-  sector (always one 512-byte sector) plus the setup code.
-
-============   =================
-Field name:    root_flags
-Type:          modify (optional)
-Offset/size:   0x1f2/2
-Protocol:      ALL
-============   =================
-
-  If this field is nonzero, the root defaults to readonly.  The use of
-  this field is deprecated; use the "ro" or "rw" options on the
-  command line instead.
-
-============   ===============================================
-Field name:    syssize
-Type:          read
-Offset/size:   0x1f4/4 (protocol 2.04+) 0x1f4/2 (protocol ALL)
-Protocol:      2.04+
-============   ===============================================
-
-  The size of the protected-mode code in units of 16-byte paragraphs.
-  For protocol versions older than 2.04 this field is only two bytes
-  wide, and therefore cannot be trusted for the size of a kernel if
-  the LOAD_HIGH flag is set.
-
-============   ===============
-Field name:    ram_size
-Type:          kernel internal
-Offset/size:   0x1f8/2
-Protocol:      ALL
-============   ===============
-
-  This field is obsolete.
-
-============   ===================
-Field name:    vid_mode
-Type:          modify (obligatory)
-Offset/size:   0x1fa/2
-============   ===================
-
-  Please see the section on SPECIAL COMMAND LINE OPTIONS.
-
-============   =================
-Field name:    root_dev
-Type:          modify (optional)
-Offset/size:   0x1fc/2
-Protocol:      ALL
-============   =================
-
-  The default root device device number.  The use of this field is
-  deprecated, use the "root=" option on the command line instead.
-
-============   =========
-Field name:    boot_flag
-Type:          read
-Offset/size:   0x1fe/2
-Protocol:      ALL
-============   =========
-
-  Contains 0xAA55.  This is the closest thing old Linux kernels have
-  to a magic number.
-
-============   =======
-Field name:    jump
-Type:          read
-Offset/size:   0x200/2
-Protocol:      2.00+
-============   =======
-
-  Contains an x86 jump instruction, 0xEB followed by a signed offset
-  relative to byte 0x202.  This can be used to determine the size of
-  the header.
-
-============   =======
-Field name:    header
-Type:          read
-Offset/size:   0x202/4
-Protocol:      2.00+
-============   =======
-
-  Contains the magic number "HdrS" (0x53726448).
-
-============   =======
-Field name:    version
-Type:          read
-Offset/size:   0x206/2
-Protocol:      2.00+
-============   =======
-
-  Contains the boot protocol version, in (major << 8)+minor format,
-  e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
-  10.17.
-
-============   =================
-Field name:    realmode_swtch
-Type:          modify (optional)
-Offset/size:   0x208/4
-Protocol:      2.00+
-============   =================
-
-  Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
-
-============   =============
-Field name:    start_sys_seg
-Type:          read
-Offset/size:   0x20c/2
-Protocol:      2.00+
-============   =============
-
-  The load low segment (0x1000).  Obsolete.
-
-============   ==============
-Field name:    kernel_version
-Type:          read
-Offset/size:   0x20e/2
-Protocol:      2.00+
-============   ==============
-
-  If set to a nonzero value, contains a pointer to a NUL-terminated
-  human-readable kernel version number string, less 0x200.  This can
-  be used to display the kernel version to the user.  This value
-  should be less than (0x200*setup_sects).
-
-  For example, if this value is set to 0x1c00, the kernel version
-  number string can be found at offset 0x1e00 in the kernel file.
-  This is a valid value if and only if the "setup_sects" field
-  contains the value 15 or higher, as::
-
-       0x1c00  < 15*0x200 (= 0x1e00) but
-       0x1c00 >= 14*0x200 (= 0x1c00)
-
-       0x1c00 >> 9 = 14, So the minimum value for setup_secs is 15.
-
-============   ==================
-Field name:    type_of_loader
-Type:          write (obligatory)
-Offset/size:   0x210/1
-Protocol:      2.00+
-============   ==================
-
-  If your boot loader has an assigned id (see table below), enter
-  0xTV here, where T is an identifier for the boot loader and V is
-  a version number.  Otherwise, enter 0xFF here.
-
-  For boot loader IDs above T = 0xD, write T = 0xE to this field and
-  write the extended ID minus 0x10 to the ext_loader_type field.
-  Similarly, the ext_loader_ver field can be used to provide more than
-  four bits for the bootloader version.
-
-  For example, for T = 0x15, V = 0x234, write::
-
-       type_of_loader  <- 0xE4
-       ext_loader_type <- 0x05
-       ext_loader_ver  <- 0x23
-
-  Assigned boot loader ids (hexadecimal):
-
-       == =======================================
-       0  LILO
-          (0x00 reserved for pre-2.00 bootloader)
-       1  Loadlin
-       2  bootsect-loader
-          (0x20, all other values reserved)
-       3  Syslinux
-       4  Etherboot/gPXE/iPXE
-       5  ELILO
-       7  GRUB
-       8  U-Boot
-       9  Xen
-       A  Gujin
-       B  Qemu
-       C  Arcturus Networks uCbootloader
-       D  kexec-tools
-       E  Extended (see ext_loader_type)
-       F  Special (0xFF = undefined)
-       10 Reserved
-       11 Minimal Linux Bootloader
-          <http://sebastian-plotz.blogspot.de>
-       12 OVMF UEFI virtualization stack
-       13 barebox
-       == =======================================
-
-  Please contact <hpa@zytor.com> if you need a bootloader ID value assigned.
-
-============   ===================
-Field name:    loadflags
-Type:          modify (obligatory)
-Offset/size:   0x211/1
-Protocol:      2.00+
-============   ===================
-
-  This field is a bitmask.
-
-  Bit 0 (read):        LOADED_HIGH
-
-       - If 0, the protected-mode code is loaded at 0x10000.
-       - If 1, the protected-mode code is loaded at 0x100000.
-
-  Bit 1 (kernel internal): KASLR_FLAG
-
-       - Used internally by the compressed kernel to communicate
-         KASLR status to kernel proper.
-
-           - If 1, KASLR enabled.
-           - If 0, KASLR disabled.
-
-  Bit 5 (write): QUIET_FLAG
-
-       - If 0, print early messages.
-       - If 1, suppress early messages.
-
-               This requests to the kernel (decompressor and early
-               kernel) to not write early messages that require
-               accessing the display hardware directly.
-
-  Bit 6 (obsolete): KEEP_SEGMENTS
-
-       Protocol: 2.07+
-
-        - This flag is obsolete.
-
-  Bit 7 (write): CAN_USE_HEAP
-
-       Set this bit to 1 to indicate that the value entered in the
-       heap_end_ptr is valid.  If this field is clear, some setup code
-       functionality will be disabled.
-
-
-============   ===================
-Field name:    setup_move_size
-Type:          modify (obligatory)
-Offset/size:   0x212/2
-Protocol:      2.00-2.01
-============   ===================
-
-  When using protocol 2.00 or 2.01, if the real mode kernel is not
-  loaded at 0x90000, it gets moved there later in the loading
-  sequence.  Fill in this field if you want additional data (such as
-  the kernel command line) moved in addition to the real-mode kernel
-  itself.
-
-  The unit is bytes starting with the beginning of the boot sector.
-
-  This field is can be ignored when the protocol is 2.02 or higher, or
-  if the real-mode code is loaded at 0x90000.
-
-============   ========================
-Field name:    code32_start
-Type:          modify (optional, reloc)
-Offset/size:   0x214/4
-Protocol:      2.00+
-============   ========================
-
-  The address to jump to in protected mode.  This defaults to the load
-  address of the kernel, and can be used by the boot loader to
-  determine the proper load address.
-
-  This field can be modified for two purposes:
-
-    1. as a boot loader hook (see Advanced Boot Loader Hooks below.)
-
-    2. if a bootloader which does not install a hook loads a
-       relocatable kernel at a nonstandard address it will have to modify
-       this field to point to the load address.
-
-============   ==================
-Field name:    ramdisk_image
-Type:          write (obligatory)
-Offset/size:   0x218/4
-Protocol:      2.00+
-============   ==================
-
-  The 32-bit linear address of the initial ramdisk or ramfs.  Leave at
-  zero if there is no initial ramdisk/ramfs.
-
-============   ==================
-Field name:    ramdisk_size
-Type:          write (obligatory)
-Offset/size:   0x21c/4
-Protocol:      2.00+
-============   ==================
-
-  Size of the initial ramdisk or ramfs.  Leave at zero if there is no
-  initial ramdisk/ramfs.
-
-============   ===============
-Field name:    bootsect_kludge
-Type:          kernel internal
-Offset/size:   0x220/4
-Protocol:      2.00+
-============   ===============
-
-  This field is obsolete.
-
-============   ==================
-Field name:    heap_end_ptr
-Type:          write (obligatory)
-Offset/size:   0x224/2
-Protocol:      2.01+
-============   ==================
-
-  Set this field to the offset (from the beginning of the real-mode
-  code) of the end of the setup stack/heap, minus 0x0200.
-
-============   ================
-Field name:    ext_loader_ver
-Type:          write (optional)
-Offset/size:   0x226/1
-Protocol:      2.02+
-============   ================
-
-  This field is used as an extension of the version number in the
-  type_of_loader field.  The total version number is considered to be
-  (type_of_loader & 0x0f) + (ext_loader_ver << 4).
-
-  The use of this field is boot loader specific.  If not written, it
-  is zero.
-
-  Kernels prior to 2.6.31 did not recognize this field, but it is safe
-  to write for protocol version 2.02 or higher.
-
-============   =====================================================
-Field name:    ext_loader_type
-Type:          write (obligatory if (type_of_loader & 0xf0) == 0xe0)
-Offset/size:   0x227/1
-Protocol:      2.02+
-============   =====================================================
-
-  This field is used as an extension of the type number in
-  type_of_loader field.  If the type in type_of_loader is 0xE, then
-  the actual type is (ext_loader_type + 0x10).
-
-  This field is ignored if the type in type_of_loader is not 0xE.
-
-  Kernels prior to 2.6.31 did not recognize this field, but it is safe
-  to write for protocol version 2.02 or higher.
-
-============   ==================
-Field name:    cmd_line_ptr
-Type:          write (obligatory)
-Offset/size:   0x228/4
-Protocol:      2.02+
-============   ==================
-
-  Set this field to the linear address of the kernel command line.
-  The kernel command line can be located anywhere between the end of
-  the setup heap and 0xA0000; it does not have to be located in the
-  same 64K segment as the real-mode code itself.
-
-  Fill in this field even if your boot loader does not support a
-  command line, in which case you can point this to an empty string
-  (or better yet, to the string "auto".)  If this field is left at
-  zero, the kernel will assume that your boot loader does not support
-  the 2.02+ protocol.
-
-============   ===============
-Field name:    initrd_addr_max
-Type:          read
-Offset/size:   0x22c/4
-Protocol:      2.03+
-============   ===============
-
-  The maximum address that may be occupied by the initial
-  ramdisk/ramfs contents.  For boot protocols 2.02 or earlier, this
-  field is not present, and the maximum address is 0x37FFFFFF.  (This
-  address is defined as the address of the highest safe byte, so if
-  your ramdisk is exactly 131072 bytes long and this field is
-  0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
-
-============   ============================
-Field name:    kernel_alignment
-Type:          read/modify (reloc)
-Offset/size:   0x230/4
-Protocol:      2.05+ (read), 2.10+ (modify)
-============   ============================
-
-  Alignment unit required by the kernel (if relocatable_kernel is
-  true.)  A relocatable kernel that is loaded at an alignment
-  incompatible with the value in this field will be realigned during
-  kernel initialization.
-
-  Starting with protocol version 2.10, this reflects the kernel
-  alignment preferred for optimal performance; it is possible for the
-  loader to modify this field to permit a lesser alignment.  See the
-  min_alignment and pref_address field below.
-
-============   ==================
-Field name:    relocatable_kernel
-Type:          read (reloc)
-Offset/size:   0x234/1
-Protocol:      2.05+
-============   ==================
-
-  If this field is nonzero, the protected-mode part of the kernel can
-  be loaded at any address that satisfies the kernel_alignment field.
-  After loading, the boot loader must set the code32_start field to
-  point to the loaded code, or to a boot loader hook.
-
-============   =============
-Field name:    min_alignment
-Type:          read (reloc)
-Offset/size:   0x235/1
-Protocol:      2.10+
-============   =============
-
-  This field, if nonzero, indicates as a power of two the minimum
-  alignment required, as opposed to preferred, by the kernel to boot.
-  If a boot loader makes use of this field, it should update the
-  kernel_alignment field with the alignment unit desired; typically::
-
-       kernel_alignment = 1 << min_alignment
-
-  There may be a considerable performance cost with an excessively
-  misaligned kernel.  Therefore, a loader should typically try each
-  power-of-two alignment from kernel_alignment down to this alignment.
-
-============   ==========
-Field name:    xloadflags
-Type:          read
-Offset/size:   0x236/2
-Protocol:      2.12+
-============   ==========
-
-  This field is a bitmask.
-
-  Bit 0 (read):        XLF_KERNEL_64
-
-       - If 1, this kernel has the legacy 64-bit entry point at 0x200.
-
-  Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G
-
-        - If 1, kernel/boot_params/cmdline/ramdisk can be above 4G.
-
-  Bit 2 (read):        XLF_EFI_HANDOVER_32
-
-       - If 1, the kernel supports the 32-bit EFI handoff entry point
-          given at handover_offset.
-
-  Bit 3 (read): XLF_EFI_HANDOVER_64
-
-       - If 1, the kernel supports the 64-bit EFI handoff entry point
-          given at handover_offset + 0x200.
-
-  Bit 4 (read): XLF_EFI_KEXEC
-
-       - If 1, the kernel supports kexec EFI boot with EFI runtime support.
-
-
-============   ============
-Field name:    cmdline_size
-Type:          read
-Offset/size:   0x238/4
-Protocol:      2.06+
-============   ============
-
-  The maximum size of the command line without the terminating
-  zero. This means that the command line can contain at most
-  cmdline_size characters. With protocol version 2.05 and earlier, the
-  maximum size was 255.
-
-============   ====================================
-Field name:    hardware_subarch
-Type:          write (optional, defaults to x86/PC)
-Offset/size:   0x23c/4
-Protocol:      2.07+
-============   ====================================
-
-  In a paravirtualized environment the hardware low level architectural
-  pieces such as interrupt handling, page table handling, and
-  accessing process control registers needs to be done differently.
-
-  This field allows the bootloader to inform the kernel we are in one
-  one of those environments.
-
-  ==========   ==============================
-  0x00000000   The default x86/PC environment
-  0x00000001   lguest
-  0x00000002   Xen
-  0x00000003   Moorestown MID
-  0x00000004   CE4100 TV Platform
-  ==========   ==============================
-
-============   =========================
-Field name:    hardware_subarch_data
-Type:          write (subarch-dependent)
-Offset/size:   0x240/8
-Protocol:      2.07+
-============   =========================
-
-  A pointer to data that is specific to hardware subarch
-  This field is currently unused for the default x86/PC environment,
-  do not modify.
-
-============   ==============
-Field name:    payload_offset
-Type:          read
-Offset/size:   0x248/4
-Protocol:      2.08+
-============   ==============
-
-  If non-zero then this field contains the offset from the beginning
-  of the protected-mode code to the payload.
-
-  The payload may be compressed. The format of both the compressed and
-  uncompressed data should be determined using the standard magic
-  numbers.  The currently supported compression formats are gzip
-  (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA
-  (magic number 5D 00), XZ (magic number FD 37), LZ4 (magic number
-  02 21) and ZSTD (magic number 28 B5). The uncompressed payload is
-  currently always ELF (magic number 7F 45 4C 46).
-
-============   ==============
-Field name:    payload_length
-Type:          read
-Offset/size:   0x24c/4
-Protocol:      2.08+
-============   ==============
-
-  The length of the payload.
-
-============   ===============
-Field name:    setup_data
-Type:          write (special)
-Offset/size:   0x250/8
-Protocol:      2.09+
-============   ===============
-
-  The 64-bit physical pointer to NULL terminated single linked list of
-  struct setup_data. This is used to define a more extensible boot
-  parameters passing mechanism. The definition of struct setup_data is
-  as follow::
-
-       struct setup_data {
-               u64 next;
-               u32 type;
-               u32 len;
-               u8  data[0];
-       };
-
-  Where, the next is a 64-bit physical pointer to the next node of
-  linked list, the next field of the last node is 0; the type is used
-  to identify the contents of data; the len is the length of data
-  field; the data holds the real payload.
-
-  This list may be modified at a number of points during the bootup
-  process.  Therefore, when modifying this list one should always make
-  sure to consider the case where the linked list already contains
-  entries.
-
-  The setup_data is a bit awkward to use for extremely large data objects,
-  both because the setup_data header has to be adjacent to the data object
-  and because it has a 32-bit length field. However, it is important that
-  intermediate stages of the boot process have a way to identify which
-  chunks of memory are occupied by kernel data.
-
-  Thus setup_indirect struct and SETUP_INDIRECT type were introduced in
-  protocol 2.15::
-
-    struct setup_indirect {
-      __u32 type;
-      __u32 reserved;  /* Reserved, must be set to zero. */
-      __u64 len;
-      __u64 addr;
-    };
-
-  The type member is a SETUP_INDIRECT | SETUP_* type. However, it cannot be
-  SETUP_INDIRECT itself since making the setup_indirect a tree structure
-  could require a lot of stack space in something that needs to parse it
-  and stack space can be limited in boot contexts.
-
-  Let's give an example how to point to SETUP_E820_EXT data using setup_indirect.
-  In this case setup_data and setup_indirect will look like this::
-
-    struct setup_data {
-      __u64 next = 0 or <addr_of_next_setup_data_struct>;
-      __u32 type = SETUP_INDIRECT;
-      __u32 len = sizeof(setup_indirect);
-      __u8 data[sizeof(setup_indirect)] = struct setup_indirect {
-        __u32 type = SETUP_INDIRECT | SETUP_E820_EXT;
-        __u32 reserved = 0;
-        __u64 len = <len_of_SETUP_E820_EXT_data>;
-        __u64 addr = <addr_of_SETUP_E820_EXT_data>;
-      }
-    }
-
-.. note::
-     SETUP_INDIRECT | SETUP_NONE objects cannot be properly distinguished
-     from SETUP_INDIRECT itself. So, this kind of objects cannot be provided
-     by the bootloaders.
-
-============   ============
-Field name:    pref_address
-Type:          read (reloc)
-Offset/size:   0x258/8
-Protocol:      2.10+
-============   ============
-
-  This field, if nonzero, represents a preferred load address for the
-  kernel.  A relocating bootloader should attempt to load at this
-  address if possible.
-
-  A non-relocatable kernel will unconditionally move itself and to run
-  at this address.
-
-============   =======
-Field name:    init_size
-Type:          read
-Offset/size:   0x260/4
-============   =======
-
-  This field indicates the amount of linear contiguous memory starting
-  at the kernel runtime start address that the kernel needs before it
-  is capable of examining its memory map.  This is not the same thing
-  as the total amount of memory the kernel needs to boot, but it can
-  be used by a relocating boot loader to help select a safe load
-  address for the kernel.
-
-  The kernel runtime start address is determined by the following algorithm::
-
-       if (relocatable_kernel)
-       runtime_start = align_up(load_address, kernel_alignment)
-       else
-       runtime_start = pref_address
-
-============   ===============
-Field name:    handover_offset
-Type:          read
-Offset/size:   0x264/4
-============   ===============
-
-  This field is the offset from the beginning of the kernel image to
-  the EFI handover protocol entry point. Boot loaders using the EFI
-  handover protocol to boot the kernel should jump to this offset.
-
-  See EFI HANDOVER PROTOCOL below for more details.
-
-============   ==================
-Field name:    kernel_info_offset
-Type:          read
-Offset/size:   0x268/4
-Protocol:      2.15+
-============   ==================
-
-  This field is the offset from the beginning of the kernel image to the
-  kernel_info. The kernel_info structure is embedded in the Linux image
-  in the uncompressed protected mode region.
-
-
-The kernel_info
-===============
-
-The relationships between the headers are analogous to the various data
-sections:
-
-  setup_header = .data
-  boot_params/setup_data = .bss
-
-What is missing from the above list? That's right:
-
-  kernel_info = .rodata
-
-We have been (ab)using .data for things that could go into .rodata or .bss for
-a long time, for lack of alternatives and -- especially early on -- inertia.
-Also, the BIOS stub is responsible for creating boot_params, so it isn't
-available to a BIOS-based loader (setup_data is, though).
-
-setup_header is permanently limited to 144 bytes due to the reach of the
-2-byte jump field, which doubles as a length field for the structure, combined
-with the size of the "hole" in struct boot_params that a protected-mode loader
-or the BIOS stub has to copy it into. It is currently 119 bytes long, which
-leaves us with 25 very precious bytes. This isn't something that can be fixed
-without revising the boot protocol entirely, breaking backwards compatibility.
-
-boot_params proper is limited to 4096 bytes, but can be arbitrarily extended
-by adding setup_data entries. It cannot be used to communicate properties of
-the kernel image, because it is .bss and has no image-provided content.
-
-kernel_info solves this by providing an extensible place for information about
-the kernel image. It is readonly, because the kernel cannot rely on a
-bootloader copying its contents anywhere, but that is OK; if it becomes
-necessary it can still contain data items that an enabled bootloader would be
-expected to copy into a setup_data chunk.
-
-All kernel_info data should be part of this structure. Fixed size data have to
-be put before kernel_info_var_len_data label. Variable size data have to be put
-after kernel_info_var_len_data label. Each chunk of variable size data has to
-be prefixed with header/magic and its size, e.g.::
-
-  kernel_info:
-          .ascii  "LToP"          /* Header, Linux top (structure). */
-          .long   kernel_info_var_len_data - kernel_info
-          .long   kernel_info_end - kernel_info
-          .long   0x01234567      /* Some fixed size data for the bootloaders. */
-  kernel_info_var_len_data:
-  example_struct:                 /* Some variable size data for the bootloaders. */
-          .ascii  "0123"          /* Header/Magic. */
-          .long   example_struct_end - example_struct
-          .ascii  "Struct"
-          .long   0x89012345
-  example_struct_end:
-  example_strings:                /* Some variable size data for the bootloaders. */
-          .ascii  "ABCD"          /* Header/Magic. */
-          .long   example_strings_end - example_strings
-          .asciz  "String_0"
-          .asciz  "String_1"
-  example_strings_end:
-  kernel_info_end:
-
-This way the kernel_info is self-contained blob.
-
-.. note::
-     Each variable size data header/magic can be any 4-character string,
-     without \0 at the end of the string, which does not collide with
-     existing variable length data headers/magics.
-
-
-Details of the kernel_info Fields
-=================================
-
-============   ========
-Field name:    header
-Offset/size:   0x0000/4
-============   ========
-
-  Contains the magic number "LToP" (0x506f544c).
-
-============   ========
-Field name:    size
-Offset/size:   0x0004/4
-============   ========
-
-  This field contains the size of the kernel_info including kernel_info.header.
-  It does not count kernel_info.kernel_info_var_len_data size. This field should be
-  used by the bootloaders to detect supported fixed size fields in the kernel_info
-  and beginning of kernel_info.kernel_info_var_len_data.
-
-============   ========
-Field name:    size_total
-Offset/size:   0x0008/4
-============   ========
-
-  This field contains the size of the kernel_info including kernel_info.header
-  and kernel_info.kernel_info_var_len_data.
-
-============   ==============
-Field name:    setup_type_max
-Offset/size:   0x000c/4
-============   ==============
-
-  This field contains maximal allowed type for setup_data and setup_indirect structs.
-
-
-The Image Checksum
-==================
-
-From boot protocol version 2.08 onwards the CRC-32 is calculated over
-the entire file using the characteristic polynomial 0x04C11DB7 and an
-initial remainder of 0xffffffff.  The checksum is appended to the
-file; therefore the CRC of the file up to the limit specified in the
-syssize field of the header is always 0.
-
-
-The Kernel Command Line
-=======================
-
-The kernel command line has become an important way for the boot
-loader to communicate with the kernel.  Some of its options are also
-relevant to the boot loader itself, see "special command line options"
-below.
-
-The kernel command line is a null-terminated string. The maximum
-length can be retrieved from the field cmdline_size.  Before protocol
-version 2.06, the maximum was 255 characters.  A string that is too
-long will be automatically truncated by the kernel.
-
-If the boot protocol version is 2.02 or later, the address of the
-kernel command line is given by the header field cmd_line_ptr (see
-above.)  This address can be anywhere between the end of the setup
-heap and 0xA0000.
-
-If the protocol version is *not* 2.02 or higher, the kernel
-command line is entered using the following protocol:
-
-  - At offset 0x0020 (word), "cmd_line_magic", enter the magic
-    number 0xA33F.
-
-  - At offset 0x0022 (word), "cmd_line_offset", enter the offset
-    of the kernel command line (relative to the start of the
-    real-mode kernel).
-
-  - The kernel command line *must* be within the memory region
-    covered by setup_move_size, so you may need to adjust this
-    field.
-
-
-Memory Layout of The Real-Mode Code
-===================================
-
-The real-mode code requires a stack/heap to be set up, as well as
-memory allocated for the kernel command line.  This needs to be done
-in the real-mode accessible memory in bottom megabyte.
-
-It should be noted that modern machines often have a sizable Extended
-BIOS Data Area (EBDA).  As a result, it is advisable to use as little
-of the low megabyte as possible.
-
-Unfortunately, under the following circumstances the 0x90000 memory
-segment has to be used:
-
-       - When loading a zImage kernel ((loadflags & 0x01) == 0).
-       - When loading a 2.01 or earlier boot protocol kernel.
-
-.. note::
-     For the 2.00 and 2.01 boot protocols, the real-mode code
-     can be loaded at another address, but it is internally
-     relocated to 0x90000.  For the "old" protocol, the
-     real-mode code must be loaded at 0x90000.
-
-When loading at 0x90000, avoid using memory above 0x9a000.
-
-For boot protocol 2.02 or higher, the command line does not have to be
-located in the same 64K segment as the real-mode setup code; it is
-thus permitted to give the stack/heap the full 64K segment and locate
-the command line above it.
-
-The kernel command line should not be located below the real-mode
-code, nor should it be located in high memory.
-
-
-Sample Boot Configuartion
-=========================
-
-As a sample configuration, assume the following layout of the real
-mode segment.
-
-    When loading below 0x90000, use the entire segment:
-
-        =============  ===================
-       0x0000-0x7fff   Real mode kernel
-       0x8000-0xdfff   Stack and heap
-       0xe000-0xffff   Kernel command line
-       =============   ===================
-
-    When loading at 0x90000 OR the protocol version is 2.01 or earlier:
-
-       =============   ===================
-       0x0000-0x7fff   Real mode kernel
-       0x8000-0x97ff   Stack and heap
-       0x9800-0x9fff   Kernel command line
-       =============   ===================
-
-Such a boot loader should enter the following fields in the header::
-
-       unsigned long base_ptr; /* base address for real-mode segment */
-
-       if ( setup_sects == 0 ) {
-               setup_sects = 4;
-       }
-
-       if ( protocol >= 0x0200 ) {
-               type_of_loader = <type code>;
-               if ( loading_initrd ) {
-                       ramdisk_image = <initrd_address>;
-                       ramdisk_size = <initrd_size>;
-               }
-
-               if ( protocol >= 0x0202 && loadflags & 0x01 )
-                       heap_end = 0xe000;
-               else
-                       heap_end = 0x9800;
-
-               if ( protocol >= 0x0201 ) {
-                       heap_end_ptr = heap_end - 0x200;
-                       loadflags |= 0x80; /* CAN_USE_HEAP */
-               }
-
-               if ( protocol >= 0x0202 ) {
-                       cmd_line_ptr = base_ptr + heap_end;
-                       strcpy(cmd_line_ptr, cmdline);
-               } else {
-                       cmd_line_magic  = 0xA33F;
-                       cmd_line_offset = heap_end;
-                       setup_move_size = heap_end + strlen(cmdline)+1;
-                       strcpy(base_ptr+cmd_line_offset, cmdline);
-               }
-       } else {
-               /* Very old kernel */
-
-               heap_end = 0x9800;
-
-               cmd_line_magic  = 0xA33F;
-               cmd_line_offset = heap_end;
-
-               /* A very old kernel MUST have its real-mode code
-                  loaded at 0x90000 */
-
-               if ( base_ptr != 0x90000 ) {
-                       /* Copy the real-mode kernel */
-                       memcpy(0x90000, base_ptr, (setup_sects+1)*512);
-                       base_ptr = 0x90000;              /* Relocated */
-               }
-
-               strcpy(0x90000+cmd_line_offset, cmdline);
-
-               /* It is recommended to clear memory up to the 32K mark */
-               memset(0x90000 + (setup_sects+1)*512, 0,
-                      (64-(setup_sects+1))*512);
-       }
-
-
-Loading The Rest of The Kernel
-==============================
-
-The 32-bit (non-real-mode) kernel starts at offset (setup_sects+1)*512
-in the kernel file (again, if setup_sects == 0 the real value is 4.)
-It should be loaded at address 0x10000 for Image/zImage kernels and
-0x100000 for bzImage kernels.
-
-The kernel is a bzImage kernel if the protocol >= 2.00 and the 0x01
-bit (LOAD_HIGH) in the loadflags field is set::
-
-       is_bzImage = (protocol >= 0x0200) && (loadflags & 0x01);
-       load_address = is_bzImage ? 0x100000 : 0x10000;
-
-Note that Image/zImage kernels can be up to 512K in size, and thus use
-the entire 0x10000-0x90000 range of memory.  This means it is pretty
-much a requirement for these kernels to load the real-mode part at
-0x90000.  bzImage kernels allow much more flexibility.
-
-Special Command Line Options
-============================
-
-If the command line provided by the boot loader is entered by the
-user, the user may expect the following command line options to work.
-They should normally not be deleted from the kernel command line even
-though not all of them are actually meaningful to the kernel.  Boot
-loader authors who need additional command line options for the boot
-loader itself should get them registered in
-Documentation/admin-guide/kernel-parameters.rst to make sure they will not
-conflict with actual kernel options now or in the future.
-
-  vga=<mode>
-       <mode> here is either an integer (in C notation, either
-       decimal, octal, or hexadecimal) or one of the strings
-       "normal" (meaning 0xFFFF), "ext" (meaning 0xFFFE) or "ask"
-       (meaning 0xFFFD).  This value should be entered into the
-       vid_mode field, as it is used by the kernel before the command
-       line is parsed.
-
-  mem=<size>
-       <size> is an integer in C notation optionally followed by
-       (case insensitive) K, M, G, T, P or E (meaning << 10, << 20,
-       << 30, << 40, << 50 or << 60).  This specifies the end of
-       memory to the kernel. This affects the possible placement of
-       an initrd, since an initrd should be placed near end of
-       memory.  Note that this is an option to *both* the kernel and
-       the bootloader!
-
-  initrd=<file>
-       An initrd should be loaded.  The meaning of <file> is
-       obviously bootloader-dependent, and some boot loaders
-       (e.g. LILO) do not have such a command.
-
-In addition, some boot loaders add the following options to the
-user-specified command line:
-
-  BOOT_IMAGE=<file>
-       The boot image which was loaded.  Again, the meaning of <file>
-       is obviously bootloader-dependent.
-
-  auto
-       The kernel was booted without explicit user intervention.
-
-If these options are added by the boot loader, it is highly
-recommended that they are located *first*, before the user-specified
-or configuration-specified command line.  Otherwise, "init=/bin/sh"
-gets confused by the "auto" option.
-
-
-Running the Kernel
-==================
-
-The kernel is started by jumping to the kernel entry point, which is
-located at *segment* offset 0x20 from the start of the real mode
-kernel.  This means that if you loaded your real-mode kernel code at
-0x90000, the kernel entry point is 9020:0000.
-
-At entry, ds = es = ss should point to the start of the real-mode
-kernel code (0x9000 if the code is loaded at 0x90000), sp should be
-set up properly, normally pointing to the top of the heap, and
-interrupts should be disabled.  Furthermore, to guard against bugs in
-the kernel, it is recommended that the boot loader sets fs = gs = ds =
-es = ss.
-
-In our example from above, we would do::
-
-       /* Note: in the case of the "old" kernel protocol, base_ptr must
-          be == 0x90000 at this point; see the previous sample code */
-
-       seg = base_ptr >> 4;
-
-       cli();  /* Enter with interrupts disabled! */
-
-       /* Set up the real-mode kernel stack */
-       _SS = seg;
-       _SP = heap_end;
-
-       _DS = _ES = _FS = _GS = seg;
-       jmp_far(seg+0x20, 0);   /* Run the kernel */
-
-If your boot sector accesses a floppy drive, it is recommended to
-switch off the floppy motor before running the kernel, since the
-kernel boot leaves interrupts off and thus the motor will not be
-switched off, especially if the loaded kernel has the floppy driver as
-a demand-loaded module!
-
-
-Advanced Boot Loader Hooks
-==========================
-
-If the boot loader runs in a particularly hostile environment (such as
-LOADLIN, which runs under DOS) it may be impossible to follow the
-standard memory location requirements.  Such a boot loader may use the
-following hooks that, if set, are invoked by the kernel at the
-appropriate time.  The use of these hooks should probably be
-considered an absolutely last resort!
-
-IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
-%edi across invocation.
-
-  realmode_swtch:
-       A 16-bit real mode far subroutine invoked immediately before
-       entering protected mode.  The default routine disables NMI, so
-       your routine should probably do so, too.
-
-  code32_start:
-       A 32-bit flat-mode routine *jumped* to immediately after the
-       transition to protected mode, but before the kernel is
-       uncompressed.  No segments, except CS, are guaranteed to be
-       set up (current kernels do, but older ones do not); you should
-       set them up to BOOT_DS (0x18) yourself.
-
-       After completing your hook, you should jump to the address
-       that was in this field before your boot loader overwrote it
-       (relocated, if appropriate.)
-
-
-32-bit Boot Protocol
-====================
-
-For machine with some new BIOS other than legacy BIOS, such as EFI,
-LinuxBIOS, etc, and kexec, the 16-bit real mode setup code in kernel
-based on legacy BIOS can not be used, so a 32-bit boot protocol needs
-to be defined.
-
-In 32-bit boot protocol, the first step in loading a Linux kernel
-should be to setup the boot parameters (struct boot_params,
-traditionally known as "zero page"). The memory for struct boot_params
-should be allocated and initialized to all zero. Then the setup header
-from offset 0x01f1 of kernel image on should be loaded into struct
-boot_params and examined. The end of setup header can be calculated as
-follow::
-
-       0x0202 + byte value at offset 0x0201
-
-In addition to read/modify/write the setup header of the struct
-boot_params as that of 16-bit boot protocol, the boot loader should
-also fill the additional fields of the struct boot_params as
-described in chapter Documentation/x86/zero-page.rst.
-
-After setting up the struct boot_params, the boot loader can load the
-32/64-bit kernel in the same way as that of 16-bit boot protocol.
-
-In 32-bit boot protocol, the kernel is started by jumping to the
-32-bit kernel entry point, which is the start address of loaded
-32/64-bit kernel.
-
-At entry, the CPU must be in 32-bit protected mode with paging
-disabled; a GDT must be loaded with the descriptors for selectors
-__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat
-segment; __BOOT_CS must have execute/read permission, and __BOOT_DS
-must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
-must be __BOOT_DS; interrupt must be disabled; %esi must hold the base
-address of the struct boot_params; %ebp, %edi and %ebx must be zero.
-
-64-bit Boot Protocol
-====================
-
-For machine with 64bit cpus and 64bit kernel, we could use 64bit bootloader
-and we need a 64-bit boot protocol.
-
-In 64-bit boot protocol, the first step in loading a Linux kernel
-should be to setup the boot parameters (struct boot_params,
-traditionally known as "zero page"). The memory for struct boot_params
-could be allocated anywhere (even above 4G) and initialized to all zero.
-Then, the setup header at offset 0x01f1 of kernel image on should be
-loaded into struct boot_params and examined. The end of setup header
-can be calculated as follows::
-
-       0x0202 + byte value at offset 0x0201
-
-In addition to read/modify/write the setup header of the struct
-boot_params as that of 16-bit boot protocol, the boot loader should
-also fill the additional fields of the struct boot_params as described
-in chapter Documentation/x86/zero-page.rst.
-
-After setting up the struct boot_params, the boot loader can load
-64-bit kernel in the same way as that of 16-bit boot protocol, but
-kernel could be loaded above 4G.
-
-In 64-bit boot protocol, the kernel is started by jumping to the
-64-bit kernel entry point, which is the start address of loaded
-64-bit kernel plus 0x200.
-
-At entry, the CPU must be in 64-bit mode with paging enabled.
-The range with setup_header.init_size from start address of loaded
-kernel and zero page and command line buffer get ident mapping;
-a GDT must be loaded with the descriptors for selectors
-__BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G flat
-segment; __BOOT_CS must have execute/read permission, and __BOOT_DS
-must have read/write permission; CS must be __BOOT_CS and DS, ES, SS
-must be __BOOT_DS; interrupt must be disabled; %rsi must hold the base
-address of the struct boot_params.
-
-EFI Handover Protocol (deprecated)
-==================================
-
-This protocol allows boot loaders to defer initialisation to the EFI
-boot stub. The boot loader is required to load the kernel/initrd(s)
-from the boot media and jump to the EFI handover protocol entry point
-which is hdr->handover_offset bytes from the beginning of
-startup_{32,64}.
-
-The boot loader MUST respect the kernel's PE/COFF metadata when it comes
-to section alignment, the memory footprint of the executable image beyond
-the size of the file itself, and any other aspect of the PE/COFF header
-that may affect correct operation of the image as a PE/COFF binary in the
-execution context provided by the EFI firmware.
-
-The function prototype for the handover entry point looks like this::
-
-    efi_main(void *handle, efi_system_table_t *table, struct boot_params *bp)
-
-'handle' is the EFI image handle passed to the boot loader by the EFI
-firmware, 'table' is the EFI system table - these are the first two
-arguments of the "handoff state" as described in section 2.3 of the
-UEFI specification. 'bp' is the boot loader-allocated boot params.
-
-The boot loader *must* fill out the following fields in bp::
-
-  - hdr.cmd_line_ptr
-  - hdr.ramdisk_image (if applicable)
-  - hdr.ramdisk_size  (if applicable)
-
-All other fields should be zero.
-
-NOTE: The EFI Handover Protocol is deprecated in favour of the ordinary PE/COFF
-      entry point, combined with the LINUX_EFI_INITRD_MEDIA_GUID based initrd
-      loading protocol (refer to [0] for an example of the bootloader side of
-      this), which removes the need for any knowledge on the part of the EFI
-      bootloader regarding the internal representation of boot_params or any
-      requirements/limitations regarding the placement of the command line
-      and ramdisk in memory, or the placement of the kernel image itself.
-
-[0] https://github.com/u-boot/u-boot/commit/ec80b4735a593961fe701cc3a5d717d4739b0fd0
diff --git a/Documentation/x86/booting-dt.rst b/Documentation/x86/booting-dt.rst
deleted file mode 100644 (file)
index 965a374..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-DeviceTree Booting
-------------------
-
-  There is one single 32bit entry point to the kernel at code32_start,
-  the decompressor (the real mode entry point goes to the same  32bit
-  entry point once it switched into protected mode). That entry point
-  supports one calling convention which is documented in
-  Documentation/x86/boot.rst
-  The physical pointer to the device-tree block is passed via setup_data
-  which requires at least boot protocol 2.09.
-  The type filed is defined as
-
-  #define SETUP_DTB                      2
-
-  This device-tree is used as an extension to the "boot page". As such it
-  does not parse / consider data which is already covered by the boot
-  page. This includes memory size, reserved ranges, command line arguments
-  or initrd address. It simply holds information which can not be retrieved
-  otherwise like interrupt routing or a list of devices behind an I2C bus.
diff --git a/Documentation/x86/buslock.rst b/Documentation/x86/buslock.rst
deleted file mode 100644 (file)
index 7c051e7..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. include:: <isonum.txt>
-
-===============================
-Bus lock detection and handling
-===============================
-
-:Copyright: |copy| 2021 Intel Corporation
-:Authors: - Fenghua Yu <fenghua.yu@intel.com>
-          - Tony Luck <tony.luck@intel.com>
-
-Problem
-=======
-
-A split lock is any atomic operation whose operand crosses two cache lines.
-Since the operand spans two cache lines and the operation must be atomic,
-the system locks the bus while the CPU accesses the two cache lines.
-
-A bus lock is acquired through either split locked access to writeback (WB)
-memory or any locked access to non-WB memory. This is typically thousands of
-cycles slower than an atomic operation within a cache line. It also disrupts
-performance on other cores and brings the whole system to its knees.
-
-Detection
-=========
-
-Intel processors may support either or both of the following hardware
-mechanisms to detect split locks and bus locks.
-
-#AC exception for split lock detection
---------------------------------------
-
-Beginning with the Tremont Atom CPU split lock operations may raise an
-Alignment Check (#AC) exception when a split lock operation is attemped.
-
-#DB exception for bus lock detection
-------------------------------------
-
-Some CPUs have the ability to notify the kernel by an #DB trap after a user
-instruction acquires a bus lock and is executed. This allows the kernel to
-terminate the application or to enforce throttling.
-
-Software handling
-=================
-
-The kernel #AC and #DB handlers handle bus lock based on the kernel
-parameter "split_lock_detect". Here is a summary of different options:
-
-+------------------+----------------------------+-----------------------+
-|split_lock_detect=|#AC for split lock         |#DB for bus lock       |
-+------------------+----------------------------+-----------------------+
-|off              |Do nothing                  |Do nothing             |
-+------------------+----------------------------+-----------------------+
-|warn             |Kernel OOPs                 |Warn once per task and |
-|(default)        |Warn once per task and      |and continues to run.  |
-|                 |disable future checking     |                       |
-|                 |When both features are      |                       |
-|                 |supported, warn in #AC      |                       |
-+------------------+----------------------------+-----------------------+
-|fatal            |Kernel OOPs                 |Send SIGBUS to user.   |
-|                 |Send SIGBUS to user         |                       |
-|                 |When both features are      |                       |
-|                 |supported, fatal in #AC     |                       |
-+------------------+----------------------------+-----------------------+
-|ratelimit:N      |Do nothing                  |Limit bus lock rate to |
-|(0 < N <= 1000)   |                           |N bus locks per second |
-|                 |                            |system wide and warn on|
-|                 |                            |bus locks.             |
-+------------------+----------------------------+-----------------------+
-
-Usages
-======
-
-Detecting and handling bus lock may find usages in various areas:
-
-It is critical for real time system designers who build consolidated real
-time systems. These systems run hard real time code on some cores and run
-"untrusted" user processes on other cores. The hard real time cannot afford
-to have any bus lock from the untrusted processes to hurt real time
-performance. To date the designers have been unable to deploy these
-solutions as they have no way to prevent the "untrusted" user code from
-generating split lock and bus lock to block the hard real time code to
-access memory during bus locking.
-
-It's also useful for general computing to prevent guests or user
-applications from slowing down the overall system by executing instructions
-with bus lock.
-
-
-Guidance
-========
-off
----
-
-Disable checking for split lock and bus lock. This option can be useful if
-there are legacy applications that trigger these events at a low rate so
-that mitigation is not needed.
-
-warn
-----
-
-A warning is emitted when a bus lock is detected which allows to identify
-the offending application. This is the default behavior.
-
-fatal
------
-
-In this case, the bus lock is not tolerated and the process is killed.
-
-ratelimit
----------
-
-A system wide bus lock rate limit N is specified where 0 < N <= 1000. This
-allows a bus lock rate up to N bus locks per second. When the bus lock rate
-is exceeded then any task which is caught via the buslock #DB exception is
-throttled by enforced sleeps until the rate goes under the limit again.
-
-This is an effective mitigation in cases where a minimal impact can be
-tolerated, but an eventual Denial of Service attack has to be prevented. It
-allows to identify the offending processes and analyze whether they are
-malicious or just badly written.
-
-Selecting a rate limit of 1000 allows the bus to be locked for up to about
-seven million cycles each second (assuming 7000 cycles for each bus
-lock). On a 2 GHz processor that would be about 0.35% system slowdown.
diff --git a/Documentation/x86/cpuinfo.rst b/Documentation/x86/cpuinfo.rst
deleted file mode 100644 (file)
index 08246e8..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=================
-x86 Feature Flags
-=================
-
-Introduction
-============
-
-On x86, flags appearing in /proc/cpuinfo have an X86_FEATURE definition
-in arch/x86/include/asm/cpufeatures.h. If the kernel cares about a feature
-or KVM want to expose the feature to a KVM guest, it can and should have
-an X86_FEATURE_* defined. These flags represent hardware features as
-well as software features.
-
-If users want to know if a feature is available on a given system, they
-try to find the flag in /proc/cpuinfo. If a given flag is present, it
-means that the kernel supports it and is currently making it available.
-If such flag represents a hardware feature, it also means that the
-hardware supports it.
-
-If the expected flag does not appear in /proc/cpuinfo, things are murkier.
-Users need to find out the reason why the flag is missing and find the way
-how to enable it, which is not always easy. There are several factors that
-can explain missing flags: the expected feature failed to enable, the feature
-is missing in hardware, platform firmware did not enable it, the feature is
-disabled at build or run time, an old kernel is in use, or the kernel does
-not support the feature and thus has not enabled it. In general, /proc/cpuinfo
-shows features which the kernel supports. For a full list of CPUID flags
-which the CPU supports, use tools/arch/x86/kcpuid.
-
-How are feature flags created?
-==============================
-
-a: Feature flags can be derived from the contents of CPUID leaves.
-------------------------------------------------------------------
-These feature definitions are organized mirroring the layout of CPUID
-leaves and grouped in words with offsets as mapped in enum cpuid_leafs
-in cpufeatures.h (see arch/x86/include/asm/cpufeatures.h for details).
-If a feature is defined with a X86_FEATURE_<name> definition in
-cpufeatures.h, and if it is detected at run time, the flags will be
-displayed accordingly in /proc/cpuinfo. For example, the flag "avx2"
-comes from X86_FEATURE_AVX2 in cpufeatures.h.
-
-b: Flags can be from scattered CPUID-based features.
-----------------------------------------------------
-Hardware features enumerated in sparsely populated CPUID leaves get
-software-defined values. Still, CPUID needs to be queried to determine
-if a given feature is present. This is done in init_scattered_cpuid_features().
-For instance, X86_FEATURE_CQM_LLC is defined as 11*32 + 0 and its presence is
-checked at runtime in the respective CPUID leaf [EAX=f, ECX=0] bit EDX[1].
-
-The intent of scattering CPUID leaves is to not bloat struct
-cpuinfo_x86.x86_capability[] unnecessarily. For instance, the CPUID leaf
-[EAX=7, ECX=0] has 30 features and is dense, but the CPUID leaf [EAX=7, EAX=1]
-has only one feature and would waste 31 bits of space in the x86_capability[]
-array. Since there is a struct cpuinfo_x86 for each possible CPU, the wasted
-memory is not trivial.
-
-c: Flags can be created synthetically under certain conditions for hardware features.
--------------------------------------------------------------------------------------
-Examples of conditions include whether certain features are present in
-MSR_IA32_CORE_CAPS or specific CPU models are identified. If the needed
-conditions are met, the features are enabled by the set_cpu_cap or
-setup_force_cpu_cap macros. For example, if bit 5 is set in MSR_IA32_CORE_CAPS,
-the feature X86_FEATURE_SPLIT_LOCK_DETECT will be enabled and
-"split_lock_detect" will be displayed. The flag "ring3mwait" will be
-displayed only when running on INTEL_FAM6_XEON_PHI_[KNL|KNM] processors.
-
-d: Flags can represent purely software features.
-------------------------------------------------
-These flags do not represent hardware features. Instead, they represent a
-software feature implemented in the kernel. For example, Kernel Page Table
-Isolation is purely software feature and its feature flag X86_FEATURE_PTI is
-also defined in cpufeatures.h.
-
-Naming of Flags
-===============
-
-The script arch/x86/kernel/cpu/mkcapflags.sh processes the
-#define X86_FEATURE_<name> from cpufeatures.h and generates the
-x86_cap/bug_flags[] arrays in kernel/cpu/capflags.c. The names in the
-resulting x86_cap/bug_flags[] are used to populate /proc/cpuinfo. The naming
-of flags in the x86_cap/bug_flags[] are as follows:
-
-a: The name of the flag is from the string in X86_FEATURE_<name> by default.
-----------------------------------------------------------------------------
-By default, the flag <name> in /proc/cpuinfo is extracted from the respective
-X86_FEATURE_<name> in cpufeatures.h. For example, the flag "avx2" is from
-X86_FEATURE_AVX2.
-
-b: The naming can be overridden.
---------------------------------
-If the comment on the line for the #define X86_FEATURE_* starts with a
-double-quote character (""), the string inside the double-quote characters
-will be the name of the flags. For example, the flag "sse4_1" comes from
-the comment "sse4_1" following the X86_FEATURE_XMM4_1 definition.
-
-There are situations in which overriding the displayed name of the flag is
-needed. For instance, /proc/cpuinfo is a userspace interface and must remain
-constant. If, for some reason, the naming of X86_FEATURE_<name> changes, one
-shall override the new naming with the name already used in /proc/cpuinfo.
-
-c: The naming override can be "", which means it will not appear in /proc/cpuinfo.
-----------------------------------------------------------------------------------
-The feature shall be omitted from /proc/cpuinfo if it does not make sense for
-the feature to be exposed to userspace. For example, X86_FEATURE_ALWAYS is
-defined in cpufeatures.h but that flag is an internal kernel feature used
-in the alternative runtime patching functionality. So, its name is overridden
-with "". Its flag will not appear in /proc/cpuinfo.
-
-Flags are missing when one or more of these happen
-==================================================
-
-a: The hardware does not enumerate support for it.
---------------------------------------------------
-For example, when a new kernel is running on old hardware or the feature is
-not enabled by boot firmware. Even if the hardware is new, there might be a
-problem enabling the feature at run time, the flag will not be displayed.
-
-b: The kernel does not know about the flag.
--------------------------------------------
-For example, when an old kernel is running on new hardware.
-
-c: The kernel disabled support for it at compile-time.
-------------------------------------------------------
-For example, if 5-level-paging is not enabled when building (i.e.,
-CONFIG_X86_5LEVEL is not selected) the flag "la57" will not show up [#f1]_.
-Even though the feature will still be detected via CPUID, the kernel disables
-it by clearing via setup_clear_cpu_cap(X86_FEATURE_LA57).
-
-d: The feature is disabled at boot-time.
-----------------------------------------
-A feature can be disabled either using a command-line parameter or because
-it failed to be enabled. The command-line parameter clearcpuid= can be used
-to disable features using the feature number as defined in
-/arch/x86/include/asm/cpufeatures.h. For instance, User Mode Instruction
-Protection can be disabled using clearcpuid=514. The number 514 is calculated
-from #define X86_FEATURE_UMIP (16*32 + 2).
-
-In addition, there exists a variety of custom command-line parameters that
-disable specific features. The list of parameters includes, but is not limited
-to, nofsgsbase, nosgx, noxsave, etc. 5-level paging can also be disabled using
-"no5lvl".
-
-e: The feature was known to be non-functional.
-----------------------------------------------
-The feature was known to be non-functional because a dependency was
-missing at runtime. For example, AVX flags will not show up if XSAVE feature
-is disabled since they depend on XSAVE feature. Another example would be broken
-CPUs and them missing microcode patches. Due to that, the kernel decides not to
-enable a feature.
-
-.. [#f1] 5-level paging uses linear address of 57 bits.
diff --git a/Documentation/x86/earlyprintk.rst b/Documentation/x86/earlyprintk.rst
deleted file mode 100644 (file)
index 51ef11e..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============
-Early Printk
-============
-
-Mini-HOWTO for using the earlyprintk=dbgp boot option with a
-USB2 Debug port key and a debug cable, on x86 systems.
-
-You need two computers, the 'USB debug key' special gadget and
-two USB cables, connected like this::
-
-  [host/target] <-------> [USB debug key] <-------> [client/console]
-
-Hardware requirements
-=====================
-
-  a) Host/target system needs to have USB debug port capability.
-
-     You can check this capability by looking at a 'Debug port' bit in
-     the lspci -vvv output::
-
-       # lspci -vvv
-       ...
-       00:1d.7 USB Controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #1 (rev 03) (prog-if 20 [EHCI])
-               Subsystem: Lenovo ThinkPad T61
-               Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
-               Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
-               Latency: 0
-               Interrupt: pin D routed to IRQ 19
-               Region 0: Memory at fe227000 (32-bit, non-prefetchable) [size=1K]
-               Capabilities: [50] Power Management version 2
-                       Flags: PMEClk- DSI- D1- D2- AuxCurrent=375mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
-                       Status: D0 PME-Enable- DSel=0 DScale=0 PME+
-               Capabilities: [58] Debug port: BAR=1 offset=00a0
-                            ^^^^^^^^^^^ <==================== [ HERE ]
-               Kernel driver in use: ehci_hcd
-               Kernel modules: ehci-hcd
-       ...
-
-     .. note::
-       If your system does not list a debug port capability then you probably
-       won't be able to use the USB debug key.
-
-  b) You also need a NetChip USB debug cable/key:
-
-        http://www.plxtech.com/products/NET2000/NET20DC/default.asp
-
-     This is a small blue plastic connector with two USB connections;
-     it draws power from its USB connections.
-
-  c) You need a second client/console system with a high speed USB 2.0 port.
-
-  d) The NetChip device must be plugged directly into the physical
-     debug port on the "host/target" system. You cannot use a USB hub in
-     between the physical debug port and the "host/target" system.
-
-     The EHCI debug controller is bound to a specific physical USB
-     port and the NetChip device will only work as an early printk
-     device in this port.  The EHCI host controllers are electrically
-     wired such that the EHCI debug controller is hooked up to the
-     first physical port and there is no way to change this via software.
-     You can find the physical port through experimentation by trying
-     each physical port on the system and rebooting.  Or you can try
-     and use lsusb or look at the kernel info messages emitted by the
-     usb stack when you plug a usb device into various ports on the
-     "host/target" system.
-
-     Some hardware vendors do not expose the usb debug port with a
-     physical connector and if you find such a device send a complaint
-     to the hardware vendor, because there is no reason not to wire
-     this port into one of the physically accessible ports.
-
-  e) It is also important to note, that many versions of the NetChip
-     device require the "client/console" system to be plugged into the
-     right hand side of the device (with the product logo facing up and
-     readable left to right).  The reason being is that the 5 volt
-     power supply is taken from only one side of the device and it
-     must be the side that does not get rebooted.
-
-Software requirements
-=====================
-
-  a) On the host/target system:
-
-    You need to enable the following kernel config option::
-
-      CONFIG_EARLY_PRINTK_DBGP=y
-
-    And you need to add the boot command line: "earlyprintk=dbgp".
-
-    .. note::
-      If you are using Grub, append it to the 'kernel' line in
-      /etc/grub.conf.  If you are using Grub2 on a BIOS firmware system,
-      append it to the 'linux' line in /boot/grub2/grub.cfg. If you are
-      using Grub2 on an EFI firmware system, append it to the 'linux'
-      or 'linuxefi' line in /boot/grub2/grub.cfg or
-      /boot/efi/EFI/<distro>/grub.cfg.
-
-    On systems with more than one EHCI debug controller you must
-    specify the correct EHCI debug controller number.  The ordering
-    comes from the PCI bus enumeration of the EHCI controllers.  The
-    default with no number argument is "0" or the first EHCI debug
-    controller.  To use the second EHCI debug controller, you would
-    use the command line: "earlyprintk=dbgp1"
-
-    .. note::
-      normally earlyprintk console gets turned off once the
-      regular console is alive - use "earlyprintk=dbgp,keep" to keep
-      this channel open beyond early bootup. This can be useful for
-      debugging crashes under Xorg, etc.
-
-  b) On the client/console system:
-
-    You should enable the following kernel config option::
-
-      CONFIG_USB_SERIAL_DEBUG=y
-
-    On the next bootup with the modified kernel you should
-    get a /dev/ttyUSBx device(s).
-
-    Now this channel of kernel messages is ready to be used: start
-    your favorite terminal emulator (minicom, etc.) and set
-    it up to use /dev/ttyUSB0 - or use a raw 'cat /dev/ttyUSBx' to
-    see the raw output.
-
-  c) On Nvidia Southbridge based systems: the kernel will try to probe
-     and find out which port has a debug device connected.
-
-Testing
-=======
-
-You can test the output by using earlyprintk=dbgp,keep and provoking
-kernel messages on the host/target system. You can provoke a harmless
-kernel message by for example doing::
-
-     echo h > /proc/sysrq-trigger
-
-On the host/target system you should see this help line in "dmesg" output::
-
-     SysRq : HELP : loglevel(0-9) reBoot Crashdump terminate-all-tasks(E) memory-full-oom-kill(F) kill-all-tasks(I) saK show-backtrace-all-active-cpus(L) show-memory-usage(M) nice-all-RT-tasks(N) powerOff show-registers(P) show-all-timers(Q) unRaw Sync show-task-states(T) Unmount show-blocked-tasks(W) dump-ftrace-buffer(Z)
-
-On the client/console system do::
-
-       cat /dev/ttyUSB0
-
-And you should see the help line above displayed shortly after you've
-provoked it on the host system.
-
-If it does not work then please ask about it on the linux-kernel@vger.kernel.org
-mailing list or contact the x86 maintainers.
diff --git a/Documentation/x86/elf_auxvec.rst b/Documentation/x86/elf_auxvec.rst
deleted file mode 100644 (file)
index 18e4744..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==================================
-x86-specific ELF Auxiliary Vectors
-==================================
-
-This document describes the semantics of the x86 auxiliary vectors.
-
-Introduction
-============
-
-ELF Auxiliary vectors enable the kernel to efficiently provide
-configuration-specific parameters to userspace. In this example, a program
-allocates an alternate stack based on the kernel-provided size::
-
-   #include <sys/auxv.h>
-   #include <elf.h>
-   #include <signal.h>
-   #include <stdlib.h>
-   #include <assert.h>
-   #include <err.h>
-
-   #ifndef AT_MINSIGSTKSZ
-   #define AT_MINSIGSTKSZ      51
-   #endif
-
-   ....
-   stack_t ss;
-
-   ss.ss_sp = malloc(ss.ss_size);
-   assert(ss.ss_sp);
-
-   ss.ss_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ;
-   ss.ss_flags = 0;
-
-   if (sigaltstack(&ss, NULL))
-        err(1, "sigaltstack");
-
-
-The exposed auxiliary vectors
-=============================
-
-AT_SYSINFO is used for locating the vsyscall entry point.  It is not
-exported on 64-bit mode.
-
-AT_SYSINFO_EHDR is the start address of the page containing the vDSO.
-
-AT_MINSIGSTKSZ denotes the minimum stack size required by the kernel to
-deliver a signal to user-space.  AT_MINSIGSTKSZ comprehends the space
-consumed by the kernel to accommodate the user context for the current
-hardware configuration.  It does not comprehend subsequent user-space stack
-consumption, which must be added by the user.  (e.g. Above, user-space adds
-SIGSTKSZ to AT_MINSIGSTKSZ.)
diff --git a/Documentation/x86/entry_64.rst b/Documentation/x86/entry_64.rst
deleted file mode 100644 (file)
index 0afdce3..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==============
-Kernel Entries
-==============
-
-This file documents some of the kernel entries in
-arch/x86/entry/entry_64.S.  A lot of this explanation is adapted from
-an email from Ingo Molnar:
-
-https://lore.kernel.org/r/20110529191055.GC9835%40elte.hu
-
-The x86 architecture has quite a few different ways to jump into
-kernel code.  Most of these entry points are registered in
-arch/x86/kernel/traps.c and implemented in arch/x86/entry/entry_64.S
-for 64-bit, arch/x86/entry/entry_32.S for 32-bit and finally
-arch/x86/entry/entry_64_compat.S which implements the 32-bit compatibility
-syscall entry points and thus provides for 32-bit processes the
-ability to execute syscalls when running on 64-bit kernels.
-
-The IDT vector assignments are listed in arch/x86/include/asm/irq_vectors.h.
-
-Some of these entries are:
-
- - system_call: syscall instruction from 64-bit code.
-
- - entry_INT80_compat: int 0x80 from 32-bit or 64-bit code; compat syscall
-   either way.
-
- - entry_INT80_compat, ia32_sysenter: syscall and sysenter from 32-bit
-   code
-
- - interrupt: An array of entries.  Every IDT vector that doesn't
-   explicitly point somewhere else gets set to the corresponding
-   value in interrupts.  These point to a whole array of
-   magically-generated functions that make their way to common_interrupt()
-   with the interrupt number as a parameter.
-
- - APIC interrupts: Various special-purpose interrupts for things
-   like TLB shootdown.
-
- - Architecturally-defined exceptions like divide_error.
-
-There are a few complexities here.  The different x86-64 entries
-have different calling conventions.  The syscall and sysenter
-instructions have their own peculiar calling conventions.  Some of
-the IDT entries push an error code onto the stack; others don't.
-IDT entries using the IST alternative stack mechanism need their own
-magic to get the stack frames right.  (You can find some
-documentation in the AMD APM, Volume 2, Chapter 8 and the Intel SDM,
-Volume 3, Chapter 6.)
-
-Dealing with the swapgs instruction is especially tricky.  Swapgs
-toggles whether gs is the kernel gs or the user gs.  The swapgs
-instruction is rather fragile: it must nest perfectly and only in
-single depth, it should only be used if entering from user mode to
-kernel mode and then when returning to user-space, and precisely
-so. If we mess that up even slightly, we crash.
-
-So when we have a secondary entry, already in kernel mode, we *must
-not* use SWAPGS blindly - nor must we forget doing a SWAPGS when it's
-not switched/swapped yet.
-
-Now, there's a secondary complication: there's a cheap way to test
-which mode the CPU is in and an expensive way.
-
-The cheap way is to pick this info off the entry frame on the kernel
-stack, from the CS of the ptregs area of the kernel stack::
-
-       xorl %ebx,%ebx
-       testl $3,CS+8(%rsp)
-       je error_kernelspace
-       SWAPGS
-
-The expensive (paranoid) way is to read back the MSR_GS_BASE value
-(which is what SWAPGS modifies)::
-
-       movl $1,%ebx
-       movl $MSR_GS_BASE,%ecx
-       rdmsr
-       testl %edx,%edx
-       js 1f   /* negative -> in kernel */
-       SWAPGS
-       xorl %ebx,%ebx
-  1:   ret
-
-If we are at an interrupt or user-trap/gate-alike boundary then we can
-use the faster check: the stack will be a reliable indicator of
-whether SWAPGS was already done: if we see that we are a secondary
-entry interrupting kernel mode execution, then we know that the GS
-base has already been switched. If it says that we interrupted
-user-space execution then we must do the SWAPGS.
-
-But if we are in an NMI/MCE/DEBUG/whatever super-atomic entry context,
-which might have triggered right after a normal entry wrote CS to the
-stack but before we executed SWAPGS, then the only safe way to check
-for GS is the slower method: the RDMSR.
-
-Therefore, super-atomic entries (except NMI, which is handled separately)
-must use idtentry with paranoid=1 to handle gsbase correctly.  This
-triggers three main behavior changes:
-
- - Interrupt entry will use the slower gsbase check.
- - Interrupt entry from user mode will switch off the IST stack.
- - Interrupt exit to kernel mode will not attempt to reschedule.
-
-We try to only use IST entries and the paranoid entry code for vectors
-that absolutely need the more expensive check for the GS base - and we
-generate all 'normal' entry points with the regular (faster) paranoid=0
-variant.
diff --git a/Documentation/x86/exception-tables.rst b/Documentation/x86/exception-tables.rst
deleted file mode 100644 (file)
index efde1fe..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===============================
-Kernel level exception handling
-===============================
-
-Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>
-
-When a process runs in kernel mode, it often has to access user
-mode memory whose address has been passed by an untrusted program.
-To protect itself the kernel has to verify this address.
-
-In older versions of Linux this was done with the
-int verify_area(int type, const void * addr, unsigned long size)
-function (which has since been replaced by access_ok()).
-
-This function verified that the memory area starting at address
-'addr' and of size 'size' was accessible for the operation specified
-in type (read or write). To do this, verify_read had to look up the
-virtual memory area (vma) that contained the address addr. In the
-normal case (correctly working program), this test was successful.
-It only failed for a few buggy programs. In some kernel profiling
-tests, this normally unneeded verification used up a considerable
-amount of time.
-
-To overcome this situation, Linus decided to let the virtual memory
-hardware present in every Linux-capable CPU handle this test.
-
-How does this work?
-
-Whenever the kernel tries to access an address that is currently not
-accessible, the CPU generates a page fault exception and calls the
-page fault handler::
-
-  void exc_page_fault(struct pt_regs *regs, unsigned long error_code)
-
-in arch/x86/mm/fault.c. The parameters on the stack are set up by
-the low level assembly glue in arch/x86/entry/entry_32.S. The parameter
-regs is a pointer to the saved registers on the stack, error_code
-contains a reason code for the exception.
-
-exc_page_fault() first obtains the inaccessible address from the CPU
-control register CR2. If the address is within the virtual address
-space of the process, the fault probably occurred, because the page
-was not swapped in, write protected or something similar. However,
-we are interested in the other case: the address is not valid, there
-is no vma that contains this address. In this case, the kernel jumps
-to the bad_area label.
-
-There it uses the address of the instruction that caused the exception
-(i.e. regs->eip) to find an address where the execution can continue
-(fixup). If this search is successful, the fault handler modifies the
-return address (again regs->eip) and returns. The execution will
-continue at the address in fixup.
-
-Where does fixup point to?
-
-Since we jump to the contents of fixup, fixup obviously points
-to executable code. This code is hidden inside the user access macros.
-I have picked the get_user() macro defined in arch/x86/include/asm/uaccess.h
-as an example. The definition is somewhat hard to follow, so let's peek at
-the code generated by the preprocessor and the compiler. I selected
-the get_user() call in drivers/char/sysrq.c for a detailed examination.
-
-The original code in sysrq.c line 587::
-
-        get_user(c, buf);
-
-The preprocessor output (edited to become somewhat readable)::
-
-  (
-    {
-      long __gu_err = - 14 , __gu_val = 0;
-      const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));
-      if (((((0 + current_set[0])->tss.segment) == 0x18 )  ||
-        (((sizeof(*(buf))) <= 0xC0000000UL) &&
-        ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
-        do {
-          __gu_err  = 0;
-          switch ((sizeof(*(buf)))) {
-            case 1:
-              __asm__ __volatile__(
-                "1:      mov" "b" " %2,%" "b" "1\n"
-                "2:\n"
-                ".section .fixup,\"ax\"\n"
-                "3:      movl %3,%0\n"
-                "        xor" "b" " %" "b" "1,%" "b" "1\n"
-                "        jmp 2b\n"
-                ".section __ex_table,\"a\"\n"
-                "        .align 4\n"
-                "        .long 1b,3b\n"
-                ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
-                              (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ;
-                break;
-            case 2:
-              __asm__ __volatile__(
-                "1:      mov" "w" " %2,%" "w" "1\n"
-                "2:\n"
-                ".section .fixup,\"ax\"\n"
-                "3:      movl %3,%0\n"
-                "        xor" "w" " %" "w" "1,%" "w" "1\n"
-                "        jmp 2b\n"
-                ".section __ex_table,\"a\"\n"
-                "        .align 4\n"
-                "        .long 1b,3b\n"
-                ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
-                              (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  ));
-                break;
-            case 4:
-              __asm__ __volatile__(
-                "1:      mov" "l" " %2,%" "" "1\n"
-                "2:\n"
-                ".section .fixup,\"ax\"\n"
-                "3:      movl %3,%0\n"
-                "        xor" "l" " %" "" "1,%" "" "1\n"
-                "        jmp 2b\n"
-                ".section __ex_table,\"a\"\n"
-                "        .align 4\n"        "        .long 1b,3b\n"
-                ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
-                              (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err));
-                break;
-            default:
-              (__gu_val) = __get_user_bad();
-          }
-        } while (0) ;
-      ((c)) = (__typeof__(*((buf))))__gu_val;
-      __gu_err;
-    }
-  );
-
-WOW! Black GCC/assembly magic. This is impossible to follow, so let's
-see what code gcc generates::
-
- >         xorl %edx,%edx
- >         movl current_set,%eax
- >         cmpl $24,788(%eax)
- >         je .L1424
- >         cmpl $-1073741825,64(%esp)
- >         ja .L1423
- > .L1424:
- >         movl %edx,%eax
- >         movl 64(%esp),%ebx
- > #APP
- > 1:      movb (%ebx),%dl                /* this is the actual user access */
- > 2:
- > .section .fixup,"ax"
- > 3:      movl $-14,%eax
- >         xorb %dl,%dl
- >         jmp 2b
- > .section __ex_table,"a"
- >         .align 4
- >         .long 1b,3b
- > .text
- > #NO_APP
- > .L1423:
- >         movzbl %dl,%esi
-
-The optimizer does a good job and gives us something we can actually
-understand. Can we? The actual user access is quite obvious. Thanks
-to the unified address space we can just access the address in user
-memory. But what does the .section stuff do?????
-
-To understand this we have to look at the final kernel::
-
- > objdump --section-headers vmlinux
- >
- > vmlinux:     file format elf32-i386
- >
- > Sections:
- > Idx Name          Size      VMA       LMA       File off  Algn
- >   0 .text         00098f40  c0100000  c0100000  00001000  2**4
- >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
- >   1 .fixup        000016bc  c0198f40  c0198f40  00099f40  2**0
- >                   CONTENTS, ALLOC, LOAD, READONLY, CODE
- >   2 .rodata       0000f127  c019a5fc  c019a5fc  0009b5fc  2**2
- >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
- >   3 __ex_table    000015c0  c01a9724  c01a9724  000aa724  2**2
- >                   CONTENTS, ALLOC, LOAD, READONLY, DATA
- >   4 .data         0000ea58  c01abcf0  c01abcf0  000abcf0  2**4
- >                   CONTENTS, ALLOC, LOAD, DATA
- >   5 .bss          00018e21  c01ba748  c01ba748  000ba748  2**2
- >                   ALLOC
- >   6 .comment      00000ec4  00000000  00000000  000ba748  2**0
- >                   CONTENTS, READONLY
- >   7 .note         00001068  00000ec4  00000ec4  000bb60c  2**0
- >                   CONTENTS, READONLY
-
-There are obviously 2 non standard ELF sections in the generated object
-file. But first we want to find out what happened to our code in the
-final kernel executable::
-
- > objdump --disassemble --section=.text vmlinux
- >
- > c017e785 <do_con_write+c1> xorl   %edx,%edx
- > c017e787 <do_con_write+c3> movl   0xc01c7bec,%eax
- > c017e78c <do_con_write+c8> cmpl   $0x18,0x314(%eax)
- > c017e793 <do_con_write+cf> je     c017e79f <do_con_write+db>
- > c017e795 <do_con_write+d1> cmpl   $0xbfffffff,0x40(%esp,1)
- > c017e79d <do_con_write+d9> ja     c017e7a7 <do_con_write+e3>
- > c017e79f <do_con_write+db> movl   %edx,%eax
- > c017e7a1 <do_con_write+dd> movl   0x40(%esp,1),%ebx
- > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
- > c017e7a7 <do_con_write+e3> movzbl %dl,%esi
-
-The whole user memory access is reduced to 10 x86 machine instructions.
-The instructions bracketed in the .section directives are no longer
-in the normal execution path. They are located in a different section
-of the executable file::
-
- > objdump --disassemble --section=.fixup vmlinux
- >
- > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
- > c0199ffa <.fixup+10ba> xorb   %dl,%dl
- > c0199ffc <.fixup+10bc> jmp    c017e7a7 <do_con_write+e3>
-
-And finally::
-
- > objdump --full-contents --section=__ex_table vmlinux
- >
- >  c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0  ................
- >  c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0  ................
- >  c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0  ................
-
-or in human readable byte order::
-
- >  c01aa7c4 c017c093 c0199fe0 c017c097 c017c099  ................
- >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
-                               ^^^^^^^^^^^^^^^^^
-                               this is the interesting part!
- >  c01aa7e4 c0180a08 c019a001 c0180a0a c019a004  ................
-
-What happened? The assembly directives::
-
-  .section .fixup,"ax"
-  .section __ex_table,"a"
-
-told the assembler to move the following code to the specified
-sections in the ELF object file. So the instructions::
-
-  3:      movl $-14,%eax
-          xorb %dl,%dl
-          jmp 2b
-
-ended up in the .fixup section of the object file and the addresses::
-
-        .long 1b,3b
-
-ended up in the __ex_table section of the object file. 1b and 3b
-are local labels. The local label 1b (1b stands for next label 1
-backward) is the address of the instruction that might fault, i.e.
-in our case the address of the label 1 is c017e7a5:
-the original assembly code: > 1:      movb (%ebx),%dl
-and linked in vmlinux     : > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
-
-The local label 3 (backwards again) is the address of the code to handle
-the fault, in our case the actual value is c0199ff5:
-the original assembly code: > 3:      movl $-14,%eax
-and linked in vmlinux     : > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
-
-If the fixup was able to handle the exception, control flow may be returned
-to the instruction after the one that triggered the fault, ie. local label 2b.
-
-The assembly code::
-
- > .section __ex_table,"a"
- >         .align 4
- >         .long 1b,3b
-
-becomes the value pair::
-
- >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
-                               ^this is ^this is
-                               1b       3b
-
-c017e7a5,c0199ff5 in the exception table of the kernel.
-
-So, what actually happens if a fault from kernel mode with no suitable
-vma occurs?
-
-#. access to invalid address::
-
-    > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
-#. MMU generates exception
-#. CPU calls exc_page_fault()
-#. exc_page_fault() calls do_user_addr_fault()
-#. do_user_addr_fault() calls kernelmode_fixup_or_oops()
-#. kernelmode_fixup_or_oops() calls fixup_exception() (regs->eip == c017e7a5);
-#. fixup_exception() calls search_exception_tables()
-#. search_exception_tables() looks up the address c017e7a5 in the
-   exception table (i.e. the contents of the ELF section __ex_table)
-   and returns the address of the associated fault handle code c0199ff5.
-#. fixup_exception() modifies its own return address to point to the fault
-   handle code and returns.
-#. execution continues in the fault handling code.
-#. a) EAX becomes -EFAULT (== -14)
-   b) DL  becomes zero (the value we "read" from user space)
-   c) execution continues at local label 2 (address of the
-      instruction immediately after the faulting user access).
-
-The steps 8a to 8c in a certain way emulate the faulting instruction.
-
-That's it, mostly. If you look at our example, you might ask why
-we set EAX to -EFAULT in the exception handler code. Well, the
-get_user() macro actually returns a value: 0, if the user access was
-successful, -EFAULT on failure. Our original code did not test this
-return value, however the inline assembly code in get_user() tries to
-return -EFAULT. GCC selected EAX to return this value.
-
-NOTE:
-Due to the way that the exception table is built and needs to be ordered,
-only use exceptions for code in the .text section.  Any other section
-will cause the exception table to not be sorted correctly, and the
-exceptions will fail.
-
-Things changed when 64-bit support was added to x86 Linux. Rather than
-double the size of the exception table by expanding the two entries
-from 32-bits to 64 bits, a clever trick was used to store addresses
-as relative offsets from the table itself. The assembly code changed
-from::
-
-    .long 1b,3b
-  to:
-          .long (from) - .
-          .long (to) - .
-
-and the C-code that uses these values converts back to absolute addresses
-like this::
-
-       ex_insn_addr(const struct exception_table_entry *x)
-       {
-               return (unsigned long)&x->insn + x->insn;
-       }
-
-In v4.6 the exception table entry was expanded with a new field "handler".
-This is also 32-bits wide and contains a third relative function
-pointer which points to one of:
-
-1) ``int ex_handler_default(const struct exception_table_entry *fixup)``
-     This is legacy case that just jumps to the fixup code
-
-2) ``int ex_handler_fault(const struct exception_table_entry *fixup)``
-     This case provides the fault number of the trap that occurred at
-     entry->insn. It is used to distinguish page faults from machine
-     check.
-
-More functions can easily be added.
-
-CONFIG_BUILDTIME_TABLE_SORT allows the __ex_table section to be sorted post
-link of the kernel image, via a host utility scripts/sorttable. It will set the
-symbol main_extable_sort_needed to 0, avoiding sorting the __ex_table section
-at boot time. With the exception table sorted, at runtime when an exception
-occurs we can quickly lookup the __ex_table entry via binary search.
-
-This is not just a boot time optimization, some architectures require this
-table to be sorted in order to handle exceptions relatively early in the boot
-process. For example, i386 makes use of this form of exception handling before
-paging support is even enabled!
diff --git a/Documentation/x86/features.rst b/Documentation/x86/features.rst
deleted file mode 100644 (file)
index b663f15..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features x86
diff --git a/Documentation/x86/i386/IO-APIC.rst b/Documentation/x86/i386/IO-APIC.rst
deleted file mode 100644 (file)
index ce4d8df..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=======
-IO-APIC
-=======
-
-:Author: Ingo Molnar <mingo@kernel.org>
-
-Most (all) Intel-MP compliant SMP boards have the so-called 'IO-APIC',
-which is an enhanced interrupt controller. It enables us to route
-hardware interrupts to multiple CPUs, or to CPU groups. Without an
-IO-APIC, interrupts from hardware will be delivered only to the
-CPU which boots the operating system (usually CPU#0).
-
-Linux supports all variants of compliant SMP boards, including ones with
-multiple IO-APICs. Multiple IO-APICs are used in high-end servers to
-distribute IRQ load further.
-
-There are (a few) known breakages in certain older boards, such bugs are
-usually worked around by the kernel. If your MP-compliant SMP board does
-not boot Linux, then consult the linux-smp mailing list archives first.
-
-If your box boots fine with enabled IO-APIC IRQs, then your
-/proc/interrupts will look like this one::
-
-  hell:~> cat /proc/interrupts
-             CPU0
-    0:    1360293    IO-APIC-edge  timer
-    1:          4    IO-APIC-edge  keyboard
-    2:          0          XT-PIC  cascade
-   13:          1          XT-PIC  fpu
-   14:       1448    IO-APIC-edge  ide0
-   16:      28232   IO-APIC-level  Intel EtherExpress Pro 10/100 Ethernet
-   17:      51304   IO-APIC-level  eth0
-  NMI:          0
-  ERR:          0
-  hell:~>
-
-Some interrupts are still listed as 'XT PIC', but this is not a problem;
-none of those IRQ sources is performance-critical.
-
-
-In the unlikely case that your board does not create a working mp-table,
-you can use the pirq= boot parameter to 'hand-construct' IRQ entries. This
-is non-trivial though and cannot be automated. One sample /etc/lilo.conf
-entry::
-
-       append="pirq=15,11,10"
-
-The actual numbers depend on your system, on your PCI cards and on their
-PCI slot position. Usually PCI slots are 'daisy chained' before they are
-connected to the PCI chipset IRQ routing facility (the incoming PIRQ1-4
-lines)::
-
-               ,-.        ,-.        ,-.        ,-.        ,-.
-     PIRQ4 ----| |-.    ,-| |-.    ,-| |-.    ,-| |--------| |
-               |S|  \  /  |S|  \  /  |S|  \  /  |S|        |S|
-     PIRQ3 ----|l|-. `/---|l|-. `/---|l|-. `/---|l|--------|l|
-               |o|  \/    |o|  \/    |o|  \/    |o|        |o|
-     PIRQ2 ----|t|-./`----|t|-./`----|t|-./`----|t|--------|t|
-               |1| /\     |2| /\     |3| /\     |4|        |5|
-     PIRQ1 ----| |-  `----| |-  `----| |-  `----| |--------| |
-               `-'        `-'        `-'        `-'        `-'
-
-Every PCI card emits a PCI IRQ, which can be INTA, INTB, INTC or INTD::
-
-                               ,-.
-                         INTD--| |
-                               |S|
-                         INTC--|l|
-                               |o|
-                         INTB--|t|
-                               |x|
-                         INTA--| |
-                               `-'
-
-These INTA-D PCI IRQs are always 'local to the card', their real meaning
-depends on which slot they are in. If you look at the daisy chaining diagram,
-a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ4 of
-the PCI chipset. Most cards issue INTA, this creates optimal distribution
-between the PIRQ lines. (distributing IRQ sources properly is not a
-necessity, PCI IRQs can be shared at will, but it's a good for performance
-to have non shared interrupts). Slot5 should be used for videocards, they
-do not use interrupts normally, thus they are not daisy chained either.
-
-so if you have your SCSI card (IRQ11) in Slot1, Tulip card (IRQ9) in
-Slot2, then you'll have to specify this pirq= line::
-
-       append="pirq=11,9"
-
-the following script tries to figure out such a default pirq= line from
-your PCI configuration::
-
-       echo -n pirq=; echo `scanpci | grep T_L | cut -c56-` | sed 's/ /,/g'
-
-note that this script won't work if you have skipped a few slots or if your
-board does not do default daisy-chaining. (or the IO-APIC has the PIRQ pins
-connected in some strange way). E.g. if in the above case you have your SCSI
-card (IRQ11) in Slot3, and have Slot1 empty::
-
-       append="pirq=0,9,11"
-
-[value '0' is a generic 'placeholder', reserved for empty (or non-IRQ emitting)
-slots.]
-
-Generally, it's always possible to find out the correct pirq= settings, just
-permute all IRQ numbers properly ... it will take some time though. An
-'incorrect' pirq line will cause the booting process to hang, or a device
-won't function properly (e.g. if it's inserted as a module).
-
-If you have 2 PCI buses, then you can use up to 8 pirq values, although such
-boards tend to have a good configuration.
-
-Be prepared that it might happen that you need some strange pirq line::
-
-       append="pirq=0,0,0,0,0,0,9,11"
-
-Use smart trial-and-error techniques to find out the correct pirq line ...
-
-Good luck and mail to linux-smp@vger.kernel.org or
-linux-kernel@vger.kernel.org if you have any problems that are not covered
-by this document.
-
diff --git a/Documentation/x86/i386/index.rst b/Documentation/x86/i386/index.rst
deleted file mode 100644 (file)
index 8747cf5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============
-i386 Support
-============
-
-.. toctree::
-   :maxdepth: 2
-
-   IO-APIC
diff --git a/Documentation/x86/ifs.rst b/Documentation/x86/ifs.rst
deleted file mode 100644 (file)
index 97abb69..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-.. kernel-doc:: drivers/platform/x86/intel/ifs/ifs.h
diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst
deleted file mode 100644 (file)
index c73d133..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==========================
-x86-specific Documentation
-==========================
-
-.. toctree::
-   :maxdepth: 2
-   :numbered:
-
-   boot
-   booting-dt
-   cpuinfo
-   topology
-   exception-tables
-   kernel-stacks
-   entry_64
-   earlyprintk
-   orc-unwinder
-   zero-page
-   tlb
-   mtrr
-   pat
-   intel-hfi
-   iommu
-   intel_txt
-   amd-memory-encryption
-   amd_hsmp
-   tdx
-   pti
-   mds
-   microcode
-   resctrl
-   tsx_async_abort
-   buslock
-   usb-legacy-support
-   i386/index
-   x86_64/index
-   ifs
-   sva
-   sgx
-   features
-   elf_auxvec
-   xstate
diff --git a/Documentation/x86/intel-hfi.rst b/Documentation/x86/intel-hfi.rst
deleted file mode 100644 (file)
index 49dea58..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============================================================
-Hardware-Feedback Interface for scheduling on Intel Hardware
-============================================================
-
-Overview
---------
-
-Intel has described the Hardware Feedback Interface (HFI) in the Intel 64 and
-IA-32 Architectures Software Developer's Manual (Intel SDM) Volume 3 Section
-14.6 [1]_.
-
-The HFI gives the operating system a performance and energy efficiency
-capability data for each CPU in the system. Linux can use the information from
-the HFI to influence task placement decisions.
-
-The Hardware Feedback Interface
--------------------------------
-
-The Hardware Feedback Interface provides to the operating system information
-about the performance and energy efficiency of each CPU in the system. Each
-capability is given as a unit-less quantity in the range [0-255]. Higher values
-indicate higher capability. Energy efficiency and performance are reported in
-separate capabilities. Even though on some systems these two metrics may be
-related, they are specified as independent capabilities in the Intel SDM.
-
-These capabilities may change at runtime as a result of changes in the
-operating conditions of the system or the action of external factors. The rate
-at which these capabilities are updated is specific to each processor model. On
-some models, capabilities are set at boot time and never change. On others,
-capabilities may change every tens of milliseconds. For instance, a remote
-mechanism may be used to lower Thermal Design Power. Such change can be
-reflected in the HFI. Likewise, if the system needs to be throttled due to
-excessive heat, the HFI may reflect reduced performance on specific CPUs.
-
-The kernel or a userspace policy daemon can use these capabilities to modify
-task placement decisions. For instance, if either the performance or energy
-capabilities of a given logical processor becomes zero, it is an indication that
-the hardware recommends to the operating system to not schedule any tasks on
-that processor for performance or energy efficiency reasons, respectively.
-
-Implementation details for Linux
---------------------------------
-
-The infrastructure to handle thermal event interrupts has two parts. In the
-Local Vector Table of a CPU's local APIC, there exists a register for the
-Thermal Monitor Register. This register controls how interrupts are delivered
-to a CPU when the thermal monitor generates and interrupt. Further details
-can be found in the Intel SDM Vol. 3 Section 10.5 [1]_.
-
-The thermal monitor may generate interrupts per CPU or per package. The HFI
-generates package-level interrupts. This monitor is configured and initialized
-via a set of machine-specific registers. Specifically, the HFI interrupt and
-status are controlled via designated bits in the IA32_PACKAGE_THERM_INTERRUPT
-and IA32_PACKAGE_THERM_STATUS registers, respectively. There exists one HFI
-table per package. Further details can be found in the Intel SDM Vol. 3
-Section 14.9 [1]_.
-
-The hardware issues an HFI interrupt after updating the HFI table and is ready
-for the operating system to consume it. CPUs receive such interrupt via the
-thermal entry in the Local APIC's Local Vector Table.
-
-When servicing such interrupt, the HFI driver parses the updated table and
-relays the update to userspace using the thermal notification framework. Given
-that there may be many HFI updates every second, the updates relayed to
-userspace are throttled at a rate of CONFIG_HZ jiffies.
-
-References
-----------
-
-.. [1] https://www.intel.com/sdm
diff --git a/Documentation/x86/intel_txt.rst b/Documentation/x86/intel_txt.rst
deleted file mode 100644 (file)
index d83c1a2..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-=====================
-Intel(R) TXT Overview
-=====================
-
-Intel's technology for safer computing, Intel(R) Trusted Execution
-Technology (Intel(R) TXT), defines platform-level enhancements that
-provide the building blocks for creating trusted platforms.
-
-Intel TXT was formerly known by the code name LaGrande Technology (LT).
-
-Intel TXT in Brief:
-
--  Provides dynamic root of trust for measurement (DRTM)
--  Data protection in case of improper shutdown
--  Measurement and verification of launched environment
-
-Intel TXT is part of the vPro(TM) brand and is also available some
-non-vPro systems.  It is currently available on desktop systems
-based on the Q35, X38, Q45, and Q43 Express chipsets (e.g. Dell
-Optiplex 755, HP dc7800, etc.) and mobile systems based on the GM45,
-PM45, and GS45 Express chipsets.
-
-For more information, see http://www.intel.com/technology/security/.
-This site also has a link to the Intel TXT MLE Developers Manual,
-which has been updated for the new released platforms.
-
-Intel TXT has been presented at various events over the past few
-years, some of which are:
-
-      - LinuxTAG 2008:
-          http://www.linuxtag.org/2008/en/conf/events/vp-donnerstag.html
-
-      - TRUST2008:
-          http://www.trust-conference.eu/downloads/Keynote-Speakers/
-          3_David-Grawrock_The-Front-Door-of-Trusted-Computing.pdf
-
-      - IDF, Shanghai:
-          http://www.prcidf.com.cn/index_en.html
-
-      - IDFs 2006, 2007
-         (I'm not sure if/where they are online)
-
-Trusted Boot Project Overview
-=============================
-
-Trusted Boot (tboot) is an open source, pre-kernel/VMM module that
-uses Intel TXT to perform a measured and verified launch of an OS
-kernel/VMM.
-
-It is hosted on SourceForge at http://sourceforge.net/projects/tboot.
-The mercurial source repo is available at http://www.bughost.org/
-repos.hg/tboot.hg.
-
-Tboot currently supports launching Xen (open source VMM/hypervisor
-w/ TXT support since v3.2), and now Linux kernels.
-
-
-Value Proposition for Linux or "Why should you care?"
-=====================================================
-
-While there are many products and technologies that attempt to
-measure or protect the integrity of a running kernel, they all
-assume the kernel is "good" to begin with.  The Integrity
-Measurement Architecture (IMA) and Linux Integrity Module interface
-are examples of such solutions.
-
-To get trust in the initial kernel without using Intel TXT, a
-static root of trust must be used.  This bases trust in BIOS
-starting at system reset and requires measurement of all code
-executed between system reset through the completion of the kernel
-boot as well as data objects used by that code.  In the case of a
-Linux kernel, this means all of BIOS, any option ROMs, the
-bootloader and the boot config.  In practice, this is a lot of
-code/data, much of which is subject to change from boot to boot
-(e.g. changing NICs may change option ROMs).  Without reference
-hashes, these measurement changes are difficult to assess or
-confirm as benign.  This process also does not provide DMA
-protection, memory configuration/alias checks and locks, crash
-protection, or policy support.
-
-By using the hardware-based root of trust that Intel TXT provides,
-many of these issues can be mitigated.  Specifically: many
-pre-launch components can be removed from the trust chain, DMA
-protection is provided to all launched components, a large number
-of platform configuration checks are performed and values locked,
-protection is provided for any data in the event of an improper
-shutdown, and there is support for policy-based execution/verification.
-This provides a more stable measurement and a higher assurance of
-system configuration and initial state than would be otherwise
-possible.  Since the tboot project is open source, source code for
-almost all parts of the trust chain is available (excepting SMM and
-Intel-provided firmware).
-
-How Does it Work?
-=================
-
--  Tboot is an executable that is launched by the bootloader as
-   the "kernel" (the binary the bootloader executes).
--  It performs all of the work necessary to determine if the
-   platform supports Intel TXT and, if so, executes the GETSEC[SENTER]
-   processor instruction that initiates the dynamic root of trust.
-
-   -  If tboot determines that the system does not support Intel TXT
-      or is not configured correctly (e.g. the SINIT AC Module was
-      incorrect), it will directly launch the kernel with no changes
-      to any state.
-   -  Tboot will output various information about its progress to the
-      terminal, serial port, and/or an in-memory log; the output
-      locations can be configured with a command line switch.
-
--  The GETSEC[SENTER] instruction will return control to tboot and
-   tboot then verifies certain aspects of the environment (e.g. TPM NV
-   lock, e820 table does not have invalid entries, etc.).
--  It will wake the APs from the special sleep state the GETSEC[SENTER]
-   instruction had put them in and place them into a wait-for-SIPI
-   state.
-
-   -  Because the processors will not respond to an INIT or SIPI when
-      in the TXT environment, it is necessary to create a small VT-x
-      guest for the APs.  When they run in this guest, they will
-      simply wait for the INIT-SIPI-SIPI sequence, which will cause
-      VMEXITs, and then disable VT and jump to the SIPI vector.  This
-      approach seemed like a better choice than having to insert
-      special code into the kernel's MP wakeup sequence.
-
--  Tboot then applies an (optional) user-defined launch policy to
-   verify the kernel and initrd.
-
-   -  This policy is rooted in TPM NV and is described in the tboot
-      project.  The tboot project also contains code for tools to
-      create and provision the policy.
-   -  Policies are completely under user control and if not present
-      then any kernel will be launched.
-   -  Policy action is flexible and can include halting on failures
-      or simply logging them and continuing.
-
--  Tboot adjusts the e820 table provided by the bootloader to reserve
-   its own location in memory as well as to reserve certain other
-   TXT-related regions.
--  As part of its launch, tboot DMA protects all of RAM (using the
-   VT-d PMRs).  Thus, the kernel must be booted with 'intel_iommu=on'
-   in order to remove this blanket protection and use VT-d's
-   page-level protection.
--  Tboot will populate a shared page with some data about itself and
-   pass this to the Linux kernel as it transfers control.
-
-   -  The location of the shared page is passed via the boot_params
-      struct as a physical address.
-
--  The kernel will look for the tboot shared page address and, if it
-   exists, map it.
--  As one of the checks/protections provided by TXT, it makes a copy
-   of the VT-d DMARs in a DMA-protected region of memory and verifies
-   them for correctness.  The VT-d code will detect if the kernel was
-   launched with tboot and use this copy instead of the one in the
-   ACPI table.
--  At this point, tboot and TXT are out of the picture until a
-   shutdown (S<n>)
--  In order to put a system into any of the sleep states after a TXT
-   launch, TXT must first be exited.  This is to prevent attacks that
-   attempt to crash the system to gain control on reboot and steal
-   data left in memory.
-
-   -  The kernel will perform all of its sleep preparation and
-      populate the shared page with the ACPI data needed to put the
-      platform in the desired sleep state.
-   -  Then the kernel jumps into tboot via the vector specified in the
-      shared page.
-   -  Tboot will clean up the environment and disable TXT, then use the
-      kernel-provided ACPI information to actually place the platform
-      into the desired sleep state.
-   -  In the case of S3, tboot will also register itself as the resume
-      vector.  This is necessary because it must re-establish the
-      measured environment upon resume.  Once the TXT environment
-      has been restored, it will restore the TPM PCRs and then
-      transfer control back to the kernel's S3 resume vector.
-      In order to preserve system integrity across S3, the kernel
-      provides tboot with a set of memory ranges (RAM and RESERVED_KERN
-      in the e820 table, but not any memory that BIOS might alter over
-      the S3 transition) that tboot will calculate a MAC (message
-      authentication code) over and then seal with the TPM. On resume
-      and once the measured environment has been re-established, tboot
-      will re-calculate the MAC and verify it against the sealed value.
-      Tboot's policy determines what happens if the verification fails.
-      Note that the c/s 194 of tboot which has the new MAC code supports
-      this.
-
-That's pretty much it for TXT support.
-
-
-Configuring the System
-======================
-
-This code works with 32bit, 32bit PAE, and 64bit (x86_64) kernels.
-
-In BIOS, the user must enable:  TPM, TXT, VT-x, VT-d.  Not all BIOSes
-allow these to be individually enabled/disabled and the screens in
-which to find them are BIOS-specific.
-
-grub.conf needs to be modified as follows::
-
-        title Linux 2.6.29-tip w/ tboot
-          root (hd0,0)
-                kernel /tboot.gz logging=serial,vga,memory
-                module /vmlinuz-2.6.29-tip intel_iommu=on ro
-                       root=LABEL=/ rhgb console=ttyS0,115200 3
-                module /initrd-2.6.29-tip.img
-                module /Q35_SINIT_17.BIN
-
-The kernel option for enabling Intel TXT support is found under the
-Security top-level menu and is called "Enable Intel(R) Trusted
-Execution Technology (TXT)".  It is considered EXPERIMENTAL and
-depends on the generic x86 support (to allow maximum flexibility in
-kernel build options), since the tboot code will detect whether the
-platform actually supports Intel TXT and thus whether any of the
-kernel code is executed.
-
-The Q35_SINIT_17.BIN file is what Intel TXT refers to as an
-Authenticated Code Module.  It is specific to the chipset in the
-system and can also be found on the Trusted Boot site.  It is an
-(unencrypted) module signed by Intel that is used as part of the
-DRTM process to verify and configure the system.  It is signed
-because it operates at a higher privilege level in the system than
-any other macrocode and its correct operation is critical to the
-establishment of the DRTM.  The process for determining the correct
-SINIT ACM for a system is documented in the SINIT-guide.txt file
-that is on the tboot SourceForge site under the SINIT ACM downloads.
diff --git a/Documentation/x86/iommu.rst b/Documentation/x86/iommu.rst
deleted file mode 100644 (file)
index 42c7a6f..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-=================
-x86 IOMMU Support
-=================
-
-The architecture specs can be obtained from the below locations.
-
-- Intel: http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/vt-directed-io-spec.pdf
-- AMD: https://www.amd.com/system/files/TechDocs/48882_IOMMU.pdf
-
-This guide gives a quick cheat sheet for some basic understanding.
-
-Basic stuff
------------
-
-ACPI enumerates and lists the different IOMMUs on the platform, and
-device scope relationships between devices and which IOMMU controls
-them.
-
-Some ACPI Keywords:
-
-- DMAR - Intel DMA Remapping table
-- DRHD - Intel DMA Remapping Hardware Unit Definition
-- RMRR - Intel Reserved Memory Region Reporting Structure
-- IVRS - AMD I/O Virtualization Reporting Structure
-- IVDB - AMD I/O Virtualization Definition Block
-- IVHD - AMD I/O Virtualization Hardware Definition
-
-What is Intel RMRR?
-^^^^^^^^^^^^^^^^^^^
-
-There are some devices the BIOS controls, for e.g USB devices to perform
-PS2 emulation. The regions of memory used for these devices are marked
-reserved in the e820 map. When we turn on DMA translation, DMA to those
-regions will fail. Hence BIOS uses RMRR to specify these regions along with
-devices that need to access these regions. OS is expected to setup
-unity mappings for these regions for these devices to access these regions.
-
-What is AMD IVRS?
-^^^^^^^^^^^^^^^^^
-
-The architecture defines an ACPI-compatible data structure called an I/O
-Virtualization Reporting Structure (IVRS) that is used to convey information
-related to I/O virtualization to system software.  The IVRS describes the
-configuration and capabilities of the IOMMUs contained in the platform as
-well as information about the devices that each IOMMU virtualizes.
-
-The IVRS provides information about the following:
-
-- IOMMUs present in the platform including their capabilities and proper configuration
-- System I/O topology relevant to each IOMMU
-- Peripheral devices that cannot be otherwise enumerated
-- Memory regions used by SMI/SMM, platform firmware, and platform hardware. These are generally exclusion ranges to be configured by system software.
-
-How is an I/O Virtual Address (IOVA) generated?
------------------------------------------------
-
-Well behaved drivers call dma_map_*() calls before sending command to device
-that needs to perform DMA. Once DMA is completed and mapping is no longer
-required, driver performs dma_unmap_*() calls to unmap the region.
-
-Intel Specific Notes
---------------------
-
-Graphics Problems?
-^^^^^^^^^^^^^^^^^^
-
-If you encounter issues with graphics devices, you can try adding
-option intel_iommu=igfx_off to turn off the integrated graphics engine.
-If this fixes anything, please ensure you file a bug reporting the problem.
-
-Some exceptions to IOVA
-^^^^^^^^^^^^^^^^^^^^^^^
-
-Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff).
-The same is true for peer to peer transactions. Hence we reserve the
-address from PCI MMIO ranges so they are not allocated for IOVA addresses.
-
-AMD Specific Notes
-------------------
-
-Graphics Problems?
-^^^^^^^^^^^^^^^^^^
-
-If you encounter issues with integrated graphics devices, you can try adding
-option iommu=pt to the kernel command line use a 1:1 mapping for the IOMMU.  If
-this fixes anything, please ensure you file a bug reporting the problem.
-
-Fault reporting
----------------
-When errors are reported, the IOMMU signals via an interrupt. The fault
-reason and device that caused it is printed on the console.
-
-
-Kernel Log Samples
-------------------
-
-Intel Boot Messages
-^^^^^^^^^^^^^^^^^^^
-
-Something like this gets printed indicating presence of DMAR tables
-in ACPI:
-
-::
-
-       ACPI: DMAR (v001 A M I  OEMDMAR  0x00000001 MSFT 0x00000097) @ 0x000000007f5b5ef0
-
-When DMAR is being processed and initialized by ACPI, prints DMAR locations
-and any RMRR's processed:
-
-::
-
-       ACPI DMAR:Host address width 36
-       ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000
-       ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000
-       ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000
-       ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff
-       ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff
-
-When DMAR is enabled for use, you will notice:
-
-::
-
-       PCI-DMA: Using DMAR IOMMU
-
-Intel Fault reporting
-^^^^^^^^^^^^^^^^^^^^^
-
-::
-
-       DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
-       DMAR:[fault reason 05] PTE Write access is not set
-       DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
-       DMAR:[fault reason 05] PTE Write access is not set
-
-AMD Boot Messages
-^^^^^^^^^^^^^^^^^
-
-Something like this gets printed indicating presence of the IOMMU:
-
-::
-
-       iommu: Default domain type: Translated
-       iommu: DMA domain TLB invalidation policy: lazy mode
-
-AMD Fault reporting
-^^^^^^^^^^^^^^^^^^^
-
-::
-
-       AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0007 address=0xffffc02000 flags=0x0000]
-       AMD-Vi: Event logged [IO_PAGE_FAULT device=07:00.0 domain=0x0007 address=0xffffc02000 flags=0x0000]
diff --git a/Documentation/x86/kernel-stacks.rst b/Documentation/x86/kernel-stacks.rst
deleted file mode 100644 (file)
index 6b0bcf0..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=============
-Kernel Stacks
-=============
-
-Kernel stacks on x86-64 bit
-===========================
-
-Most of the text from Keith Owens, hacked by AK
-
-x86_64 page size (PAGE_SIZE) is 4K.
-
-Like all other architectures, x86_64 has a kernel stack for every
-active thread.  These thread stacks are THREAD_SIZE (2*PAGE_SIZE) big.
-These stacks contain useful data as long as a thread is alive or a
-zombie. While the thread is in user space the kernel stack is empty
-except for the thread_info structure at the bottom.
-
-In addition to the per thread stacks, there are specialized stacks
-associated with each CPU.  These stacks are only used while the kernel
-is in control on that CPU; when a CPU returns to user space the
-specialized stacks contain no useful data.  The main CPU stacks are:
-
-* Interrupt stack.  IRQ_STACK_SIZE
-
-  Used for external hardware interrupts.  If this is the first external
-  hardware interrupt (i.e. not a nested hardware interrupt) then the
-  kernel switches from the current task to the interrupt stack.  Like
-  the split thread and interrupt stacks on i386, this gives more room
-  for kernel interrupt processing without having to increase the size
-  of every per thread stack.
-
-  The interrupt stack is also used when processing a softirq.
-
-Switching to the kernel interrupt stack is done by software based on a
-per CPU interrupt nest counter. This is needed because x86-64 "IST"
-hardware stacks cannot nest without races.
-
-x86_64 also has a feature which is not available on i386, the ability
-to automatically switch to a new stack for designated events such as
-double fault or NMI, which makes it easier to handle these unusual
-events on x86_64.  This feature is called the Interrupt Stack Table
-(IST).  There can be up to 7 IST entries per CPU. The IST code is an
-index into the Task State Segment (TSS). The IST entries in the TSS
-point to dedicated stacks; each stack can be a different size.
-
-An IST is selected by a non-zero value in the IST field of an
-interrupt-gate descriptor.  When an interrupt occurs and the hardware
-loads such a descriptor, the hardware automatically sets the new stack
-pointer based on the IST value, then invokes the interrupt handler.  If
-the interrupt came from user mode, then the interrupt handler prologue
-will switch back to the per-thread stack.  If software wants to allow
-nested IST interrupts then the handler must adjust the IST values on
-entry to and exit from the interrupt handler.  (This is occasionally
-done, e.g. for debug exceptions.)
-
-Events with different IST codes (i.e. with different stacks) can be
-nested.  For example, a debug interrupt can safely be interrupted by an
-NMI.  arch/x86_64/kernel/entry.S::paranoidentry adjusts the stack
-pointers on entry to and exit from all IST events, in theory allowing
-IST events with the same code to be nested.  However in most cases, the
-stack size allocated to an IST assumes no nesting for the same code.
-If that assumption is ever broken then the stacks will become corrupt.
-
-The currently assigned IST stacks are:
-
-* ESTACK_DF.  EXCEPTION_STKSZ (PAGE_SIZE).
-
-  Used for interrupt 8 - Double Fault Exception (#DF).
-
-  Invoked when handling one exception causes another exception. Happens
-  when the kernel is very confused (e.g. kernel stack pointer corrupt).
-  Using a separate stack allows the kernel to recover from it well enough
-  in many cases to still output an oops.
-
-* ESTACK_NMI.  EXCEPTION_STKSZ (PAGE_SIZE).
-
-  Used for non-maskable interrupts (NMI).
-
-  NMI can be delivered at any time, including when the kernel is in the
-  middle of switching stacks.  Using IST for NMI events avoids making
-  assumptions about the previous state of the kernel stack.
-
-* ESTACK_DB.  EXCEPTION_STKSZ (PAGE_SIZE).
-
-  Used for hardware debug interrupts (interrupt 1) and for software
-  debug interrupts (INT3).
-
-  When debugging a kernel, debug interrupts (both hardware and
-  software) can occur at any time.  Using IST for these interrupts
-  avoids making assumptions about the previous state of the kernel
-  stack.
-
-  To handle nested #DB correctly there exist two instances of DB stacks. On
-  #DB entry the IST stackpointer for #DB is switched to the second instance
-  so a nested #DB starts from a clean stack. The nested #DB switches
-  the IST stackpointer to a guard hole to catch triple nesting.
-
-* ESTACK_MCE.  EXCEPTION_STKSZ (PAGE_SIZE).
-
-  Used for interrupt 18 - Machine Check Exception (#MC).
-
-  MCE can be delivered at any time, including when the kernel is in the
-  middle of switching stacks.  Using IST for MCE events avoids making
-  assumptions about the previous state of the kernel stack.
-
-For more details see the Intel IA32 or AMD AMD64 architecture manuals.
-
-
-Printing backtraces on x86
-==========================
-
-The question about the '?' preceding function names in an x86 stacktrace
-keeps popping up, here's an indepth explanation. It helps if the reader
-stares at print_context_stack() and the whole machinery in and around
-arch/x86/kernel/dumpstack.c.
-
-Adapted from Ingo's mail, Message-ID: <20150521101614.GA10889@gmail.com>:
-
-We always scan the full kernel stack for return addresses stored on
-the kernel stack(s) [1]_, from stack top to stack bottom, and print out
-anything that 'looks like' a kernel text address.
-
-If it fits into the frame pointer chain, we print it without a question
-mark, knowing that it's part of the real backtrace.
-
-If the address does not fit into our expected frame pointer chain we
-still print it, but we print a '?'. It can mean two things:
-
- - either the address is not part of the call chain: it's just stale
-   values on the kernel stack, from earlier function calls. This is
-   the common case.
-
- - or it is part of the call chain, but the frame pointer was not set
-   up properly within the function, so we don't recognize it.
-
-This way we will always print out the real call chain (plus a few more
-entries), regardless of whether the frame pointer was set up correctly
-or not - but in most cases we'll get the call chain right as well. The
-entries printed are strictly in stack order, so you can deduce more
-information from that as well.
-
-The most important property of this method is that we _never_ lose
-information: we always strive to print _all_ addresses on the stack(s)
-that look like kernel text addresses, so if debug information is wrong,
-we still print out the real call chain as well - just with more question
-marks than ideal.
-
-.. [1] For things like IRQ and IST stacks, we also scan those stacks, in
-       the right order, and try to cross from one stack into another
-       reconstructing the call chain. This works most of the time.
diff --git a/Documentation/x86/mds.rst b/Documentation/x86/mds.rst
deleted file mode 100644 (file)
index 5d4330b..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-Microarchitectural Data Sampling (MDS) mitigation
-=================================================
-
-.. _mds:
-
-Overview
---------
-
-Microarchitectural Data Sampling (MDS) is a family of side channel attacks
-on internal buffers in Intel CPUs. The variants are:
-
- - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126)
- - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130)
- - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127)
- - Microarchitectural Data Sampling Uncacheable Memory (MDSUM) (CVE-2019-11091)
-
-MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a
-dependent load (store-to-load forwarding) as an optimization. The forward
-can also happen to a faulting or assisting load operation for a different
-memory address, which can be exploited under certain conditions. Store
-buffers are partitioned between Hyper-Threads so cross thread forwarding is
-not possible. But if a thread enters or exits a sleep state the store
-buffer is repartitioned which can expose data from one thread to the other.
-
-MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage
-L1 miss situations and to hold data which is returned or sent in response
-to a memory or I/O operation. Fill buffers can forward data to a load
-operation and also write data to the cache. When the fill buffer is
-deallocated it can retain the stale data of the preceding operations which
-can then be forwarded to a faulting or assisting load operation, which can
-be exploited under certain conditions. Fill buffers are shared between
-Hyper-Threads so cross thread leakage is possible.
-
-MLPDS leaks Load Port Data. Load ports are used to perform load operations
-from memory or I/O. The received data is then forwarded to the register
-file or a subsequent operation. In some implementations the Load Port can
-contain stale data from a previous operation which can be forwarded to
-faulting or assisting loads under certain conditions, which again can be
-exploited eventually. Load ports are shared between Hyper-Threads so cross
-thread leakage is possible.
-
-MDSUM is a special case of MSBDS, MFBDS and MLPDS. An uncacheable load from
-memory that takes a fault or assist can leave data in a microarchitectural
-structure that may later be observed using one of the same methods used by
-MSBDS, MFBDS or MLPDS.
-
-Exposure assumptions
---------------------
-
-It is assumed that attack code resides in user space or in a guest with one
-exception. The rationale behind this assumption is that the code construct
-needed for exploiting MDS requires:
-
- - to control the load to trigger a fault or assist
-
- - to have a disclosure gadget which exposes the speculatively accessed
-   data for consumption through a side channel.
-
- - to control the pointer through which the disclosure gadget exposes the
-   data
-
-The existence of such a construct in the kernel cannot be excluded with
-100% certainty, but the complexity involved makes it extremly unlikely.
-
-There is one exception, which is untrusted BPF. The functionality of
-untrusted BPF is limited, but it needs to be thoroughly investigated
-whether it can be used to create such a construct.
-
-
-Mitigation strategy
--------------------
-
-All variants have the same mitigation strategy at least for the single CPU
-thread case (SMT off): Force the CPU to clear the affected buffers.
-
-This is achieved by using the otherwise unused and obsolete VERW
-instruction in combination with a microcode update. The microcode clears
-the affected CPU buffers when the VERW instruction is executed.
-
-For virtualization there are two ways to achieve CPU buffer
-clearing. Either the modified VERW instruction or via the L1D Flush
-command. The latter is issued when L1TF mitigation is enabled so the extra
-VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to
-be issued.
-
-If the VERW instruction with the supplied segment selector argument is
-executed on a CPU without the microcode update there is no side effect
-other than a small number of pointlessly wasted CPU cycles.
-
-This does not protect against cross Hyper-Thread attacks except for MSBDS
-which is only exploitable cross Hyper-thread when one of the Hyper-Threads
-enters a C-state.
-
-The kernel provides a function to invoke the buffer clearing:
-
-    mds_clear_cpu_buffers()
-
-The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state
-(idle) transitions.
-
-As a special quirk to address virtualization scenarios where the host has
-the microcode updated, but the hypervisor does not (yet) expose the
-MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the
-hope that it might actually clear the buffers. The state is reflected
-accordingly.
-
-According to current knowledge additional mitigations inside the kernel
-itself are not required because the necessary gadgets to expose the leaked
-data cannot be controlled in a way which allows exploitation from malicious
-user space or VM guests.
-
-Kernel internal mitigation modes
---------------------------------
-
- ======= ============================================================
- off      Mitigation is disabled. Either the CPU is not affected or
-          mds=off is supplied on the kernel command line
-
- full     Mitigation is enabled. CPU is affected and MD_CLEAR is
-          advertised in CPUID.
-
- vmwerv          Mitigation is enabled. CPU is affected and MD_CLEAR is not
-         advertised in CPUID. That is mainly for virtualization
-         scenarios where the host has the updated microcode but the
-         hypervisor does not expose MD_CLEAR in CPUID. It's a best
-         effort approach without guarantee.
- ======= ============================================================
-
-If the CPU is affected and mds=off is not supplied on the kernel command
-line then the kernel selects the appropriate mitigation mode depending on
-the availability of the MD_CLEAR CPUID bit.
-
-Mitigation points
------------------
-
-1. Return to user space
-^^^^^^^^^^^^^^^^^^^^^^^
-
-   When transitioning from kernel to user space the CPU buffers are flushed
-   on affected CPUs when the mitigation is not disabled on the kernel
-   command line. The migitation is enabled through the static key
-   mds_user_clear.
-
-   The mitigation is invoked in prepare_exit_to_usermode() which covers
-   all but one of the kernel to user space transitions.  The exception
-   is when we return from a Non Maskable Interrupt (NMI), which is
-   handled directly in do_nmi().
-
-   (The reason that NMI is special is that prepare_exit_to_usermode() can
-    enable IRQs.  In NMI context, NMIs are blocked, and we don't want to
-    enable IRQs with NMIs blocked.)
-
-
-2. C-State transition
-^^^^^^^^^^^^^^^^^^^^^
-
-   When a CPU goes idle and enters a C-State the CPU buffers need to be
-   cleared on affected CPUs when SMT is active. This addresses the
-   repartitioning of the store buffer when one of the Hyper-Threads enters
-   a C-State.
-
-   When SMT is inactive, i.e. either the CPU does not support it or all
-   sibling threads are offline CPU buffer clearing is not required.
-
-   The idle clearing is enabled on CPUs which are only affected by MSBDS
-   and not by any other MDS variant. The other MDS variants cannot be
-   protected against cross Hyper-Thread attacks because the Fill Buffer and
-   the Load Ports are shared. So on CPUs affected by other variants, the
-   idle clearing would be a window dressing exercise and is therefore not
-   activated.
-
-   The invocation is controlled by the static key mds_idle_clear which is
-   switched depending on the chosen mitigation mode and the SMT state of
-   the system.
-
-   The buffer clear is only invoked before entering the C-State to prevent
-   that stale data from the idling CPU from spilling to the Hyper-Thread
-   sibling after the store buffer got repartitioned and all entries are
-   available to the non idle sibling.
-
-   When coming out of idle the store buffer is partitioned again so each
-   sibling has half of it available. The back from idle CPU could be then
-   speculatively exposed to contents of the sibling. The buffers are
-   flushed either on exit to user space or on VMENTER so malicious code
-   in user space or the guest cannot speculatively access them.
-
-   The mitigation is hooked into all variants of halt()/mwait(), but does
-   not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver
-   has been superseded by the intel_idle driver around 2010 and is
-   preferred on all affected CPUs which are expected to gain the MD_CLEAR
-   functionality in microcode. Aside of that the IO-Port mechanism is a
-   legacy interface which is only used on older systems which are either
-   not affected or do not receive microcode updates anymore.
diff --git a/Documentation/x86/microcode.rst b/Documentation/x86/microcode.rst
deleted file mode 100644 (file)
index b627c6f..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==========================
-The Linux Microcode Loader
-==========================
-
-:Authors: - Fenghua Yu <fenghua.yu@intel.com>
-          - Borislav Petkov <bp@suse.de>
-         - Ashok Raj <ashok.raj@intel.com>
-
-The kernel has a x86 microcode loading facility which is supposed to
-provide microcode loading methods in the OS. Potential use cases are
-updating the microcode on platforms beyond the OEM End-Of-Life support,
-and updating the microcode on long-running systems without rebooting.
-
-The loader supports three loading methods:
-
-Early load microcode
-====================
-
-The kernel can update microcode very early during boot. Loading
-microcode early can fix CPU issues before they are observed during
-kernel boot time.
-
-The microcode is stored in an initrd file. During boot, it is read from
-it and loaded into the CPU cores.
-
-The format of the combined initrd image is microcode in (uncompressed)
-cpio format followed by the (possibly compressed) initrd image. The
-loader parses the combined initrd image during boot.
-
-The microcode files in cpio name space are:
-
-on Intel:
-  kernel/x86/microcode/GenuineIntel.bin
-on AMD  :
-  kernel/x86/microcode/AuthenticAMD.bin
-
-During BSP (BootStrapping Processor) boot (pre-SMP), the kernel
-scans the microcode file in the initrd. If microcode matching the
-CPU is found, it will be applied in the BSP and later on in all APs
-(Application Processors).
-
-The loader also saves the matching microcode for the CPU in memory.
-Thus, the cached microcode patch is applied when CPUs resume from a
-sleep state.
-
-Here's a crude example how to prepare an initrd with microcode (this is
-normally done automatically by the distribution, when recreating the
-initrd, so you don't really have to do it yourself. It is documented
-here for future reference only).
-::
-
-  #!/bin/bash
-
-  if [ -z "$1" ]; then
-      echo "You need to supply an initrd file"
-      exit 1
-  fi
-
-  INITRD="$1"
-
-  DSTDIR=kernel/x86/microcode
-  TMPDIR=/tmp/initrd
-
-  rm -rf $TMPDIR
-
-  mkdir $TMPDIR
-  cd $TMPDIR
-  mkdir -p $DSTDIR
-
-  if [ -d /lib/firmware/amd-ucode ]; then
-          cat /lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin
-  fi
-
-  if [ -d /lib/firmware/intel-ucode ]; then
-          cat /lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin
-  fi
-
-  find . | cpio -o -H newc >../ucode.cpio
-  cd ..
-  mv $INITRD $INITRD.orig
-  cat ucode.cpio $INITRD.orig > $INITRD
-
-  rm -rf $TMPDIR
-
-
-The system needs to have the microcode packages installed into
-/lib/firmware or you need to fixup the paths above if yours are
-somewhere else and/or you've downloaded them directly from the processor
-vendor's site.
-
-Late loading
-============
-
-You simply install the microcode packages your distro supplies and
-run::
-
-  # echo 1 > /sys/devices/system/cpu/microcode/reload
-
-as root.
-
-The loading mechanism looks for microcode blobs in
-/lib/firmware/{intel-ucode,amd-ucode}. The default distro installation
-packages already put them there.
-
-Since kernel 5.19, late loading is not enabled by default.
-
-The /dev/cpu/microcode method has been removed in 5.19.
-
-Why is late loading dangerous?
-==============================
-
-Synchronizing all CPUs
-----------------------
-
-The microcode engine which receives the microcode update is shared
-between the two logical threads in a SMT system. Therefore, when
-the update is executed on one SMT thread of the core, the sibling
-"automatically" gets the update.
-
-Since the microcode can "simulate" MSRs too, while the microcode update
-is in progress, those simulated MSRs transiently cease to exist. This
-can result in unpredictable results if the SMT sibling thread happens to
-be in the middle of an access to such an MSR. The usual observation is
-that such MSR accesses cause #GPs to be raised to signal that former are
-not present.
-
-The disappearing MSRs are just one common issue which is being observed.
-Any other instruction that's being patched and gets concurrently
-executed by the other SMT sibling, can also result in similar,
-unpredictable behavior.
-
-To eliminate this case, a stop_machine()-based CPU synchronization was
-introduced as a way to guarantee that all logical CPUs will not execute
-any code but just wait in a spin loop, polling an atomic variable.
-
-While this took care of device or external interrupts, IPIs including
-LVT ones, such as CMCI etc, it cannot address other special interrupts
-that can't be shut off. Those are Machine Check (#MC), System Management
-(#SMI) and Non-Maskable interrupts (#NMI).
-
-Machine Checks
---------------
-
-Machine Checks (#MC) are non-maskable. There are two kinds of MCEs.
-Fatal un-recoverable MCEs and recoverable MCEs. While un-recoverable
-errors are fatal, recoverable errors can also happen in kernel context
-are also treated as fatal by the kernel.
-
-On certain Intel machines, MCEs are also broadcast to all threads in a
-system. If one thread is in the middle of executing WRMSR, a MCE will be
-taken at the end of the flow. Either way, they will wait for the thread
-performing the wrmsr(0x79) to rendezvous in the MCE handler and shutdown
-eventually if any of the threads in the system fail to check in to the
-MCE rendezvous.
-
-To be paranoid and get predictable behavior, the OS can choose to set
-MCG_STATUS.MCIP. Since MCEs can be at most one in a system, if an
-MCE was signaled, the above condition will promote to a system reset
-automatically. OS can turn off MCIP at the end of the update for that
-core.
-
-System Management Interrupt
----------------------------
-
-SMIs are also broadcast to all CPUs in the platform. Microcode update
-requests exclusive access to the core before writing to MSR 0x79. So if
-it does happen such that, one thread is in WRMSR flow, and the 2nd got
-an SMI, that thread will be stopped in the first instruction in the SMI
-handler.
-
-Since the secondary thread is stopped in the first instruction in SMI,
-there is very little chance that it would be in the middle of executing
-an instruction being patched. Plus OS has no way to stop SMIs from
-happening.
-
-Non-Maskable Interrupts
------------------------
-
-When thread0 of a core is doing the microcode update, if thread1 is
-pulled into NMI, that can cause unpredictable behavior due to the
-reasons above.
-
-OS can choose a variety of methods to avoid running into this situation.
-
-
-Is the microcode suitable for late loading?
--------------------------------------------
-
-Late loading is done when the system is fully operational and running
-real workloads. Late loading behavior depends on what the base patch on
-the CPU is before upgrading to the new patch.
-
-This is true for Intel CPUs.
-
-Consider, for example, a CPU has patch level 1 and the update is to
-patch level 3.
-
-Between patch1 and patch3, patch2 might have deprecated a software-visible
-feature.
-
-This is unacceptable if software is even potentially using that feature.
-For instance, say MSR_X is no longer available after an update,
-accessing that MSR will cause a #GP fault.
-
-Basically there is no way to declare a new microcode update suitable
-for late-loading. This is another one of the problems that caused late
-loading to be not enabled by default.
-
-Builtin microcode
-=================
-
-The loader supports also loading of a builtin microcode supplied through
-the regular builtin firmware method CONFIG_EXTRA_FIRMWARE. Only 64-bit is
-currently supported.
-
-Here's an example::
-
-  CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin"
-  CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"
-
-This basically means, you have the following tree structure locally::
-
-  /lib/firmware/
-  |-- amd-ucode
-  ...
-  |   |-- microcode_amd_fam15h.bin
-  ...
-  |-- intel-ucode
-  ...
-  |   |-- 06-3a-09
-  ...
-
-so that the build system can find those files and integrate them into
-the final kernel image. The early loader finds them and applies them.
-
-Needless to say, this method is not the most flexible one because it
-requires rebuilding the kernel each time updated microcode from the CPU
-vendor is available.
diff --git a/Documentation/x86/mtrr.rst b/Documentation/x86/mtrr.rst
deleted file mode 100644 (file)
index 9f0b185..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=========================================
-MTRR (Memory Type Range Register) control
-=========================================
-
-:Authors: - Richard Gooch <rgooch@atnf.csiro.au> - 3 Jun 1999
-          - Luis R. Rodriguez <mcgrof@do-not-panic.com> - April 9, 2015
-
-
-Phasing out MTRR use
-====================
-
-MTRR use is replaced on modern x86 hardware with PAT. Direct MTRR use by
-drivers on Linux is now completely phased out, device drivers should use
-arch_phys_wc_add() in combination with ioremap_wc() to make MTRR effective on
-non-PAT systems while a no-op but equally effective on PAT enabled systems.
-
-Even if Linux does not use MTRRs directly, some x86 platform firmware may still
-set up MTRRs early before booting the OS. They do this as some platform
-firmware may still have implemented access to MTRRs which would be controlled
-and handled by the platform firmware directly. An example of platform use of
-MTRRs is through the use of SMI handlers, one case could be for fan control,
-the platform code would need uncachable access to some of its fan control
-registers. Such platform access does not need any Operating System MTRR code in
-place other than mtrr_type_lookup() to ensure any OS specific mapping requests
-are aligned with platform MTRR setup. If MTRRs are only set up by the platform
-firmware code though and the OS does not make any specific MTRR mapping
-requests mtrr_type_lookup() should always return MTRR_TYPE_INVALID.
-
-For details refer to Documentation/x86/pat.rst.
-
-.. tip::
-  On Intel P6 family processors (Pentium Pro, Pentium II and later)
-  the Memory Type Range Registers (MTRRs) may be used to control
-  processor access to memory ranges. This is most useful when you have
-  a video (VGA) card on a PCI or AGP bus. Enabling write-combining
-  allows bus write transfers to be combined into a larger transfer
-  before bursting over the PCI/AGP bus. This can increase performance
-  of image write operations 2.5 times or more.
-
-  The Cyrix 6x86, 6x86MX and M II processors have Address Range
-  Registers (ARRs) which provide a similar functionality to MTRRs. For
-  these, the ARRs are used to emulate the MTRRs.
-
-  The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
-  MTRRs. These are supported.  The AMD Athlon family provide 8 Intel
-  style MTRRs.
-
-  The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
-  are supported.
-
-  The VIA Cyrix III and VIA C3 CPUs offer 8 Intel style MTRRs.
-
-  The CONFIG_MTRR option creates a /proc/mtrr file which may be used
-  to manipulate your MTRRs. Typically the X server should use
-  this. This should have a reasonably generic interface so that
-  similar control registers on other processors can be easily
-  supported.
-
-There are two interfaces to /proc/mtrr: one is an ASCII interface
-which allows you to read and write. The other is an ioctl()
-interface. The ASCII interface is meant for administration. The
-ioctl() interface is meant for C programs (i.e. the X server). The
-interfaces are described below, with sample commands and C code.
-
-
-Reading MTRRs from the shell
-============================
-::
-
-  % cat /proc/mtrr
-  reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
-  reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1
-
-Creating MTRRs from the C-shell::
-
-  # echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr
-
-or if you use bash::
-
-  # echo "base=0xf8000000 size=0x400000 type=write-combining" >| /proc/mtrr
-
-And the result thereof::
-
-  % cat /proc/mtrr
-  reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
-  reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1
-  reg02: base=0xf8000000 (3968MB), size=   4MB: write-combining, count=1
-
-This is for video RAM at base address 0xf8000000 and size 4 megabytes. To
-find out your base address, you need to look at the output of your X
-server, which tells you where the linear framebuffer address is. A
-typical line that you may get is::
-
-  (--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000
-
-Note that you should only use the value from the X server, as it may
-move the framebuffer base address, so the only value you can trust is
-that reported by the X server.
-
-To find out the size of your framebuffer (what, you don't actually
-know?), the following line will tell you::
-
-  (--) S3: videoram:  4096k
-
-That's 4 megabytes, which is 0x400000 bytes (in hexadecimal).
-A patch is being written for XFree86 which will make this automatic:
-in other words the X server will manipulate /proc/mtrr using the
-ioctl() interface, so users won't have to do anything. If you use a
-commercial X server, lobby your vendor to add support for MTRRs.
-
-
-Creating overlapping MTRRs
-==========================
-::
-
-  %echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr
-  %echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr
-
-And the results::
-
-  % cat /proc/mtrr
-  reg00: base=0x00000000 (   0MB), size=  64MB: write-back, count=1
-  reg01: base=0xfb000000 (4016MB), size=  16MB: write-combining, count=1
-  reg02: base=0xfb000000 (4016MB), size=   4kB: uncachable, count=1
-
-Some cards (especially Voodoo Graphics boards) need this 4 kB area
-excluded from the beginning of the region because it is used for
-registers.
-
-NOTE: You can only create type=uncachable region, if the first
-region that you created is type=write-combining.
-
-
-Removing MTRRs from the C-shel
-==============================
-::
-
-  % echo "disable=2" >! /proc/mtrr
-
-or using bash::
-
-  % echo "disable=2" >| /proc/mtrr
-
-
-Reading MTRRs from a C program using ioctl()'s
-==============================================
-::
-
-  /*  mtrr-show.c
-
-      Source file for mtrr-show (example program to show MTRRs using ioctl()'s)
-
-      Copyright (C) 1997-1998  Richard Gooch
-
-      This program is free software; you can redistribute it and/or modify
-      it under the terms of the GNU General Public License as published by
-      the Free Software Foundation; either version 2 of the License, or
-      (at your option) any later version.
-
-      This program is distributed in the hope that it will be useful,
-      but WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-      GNU General Public License for more details.
-
-      You should have received a copy of the GNU General Public License
-      along with this program; if not, write to the Free Software
-      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-      Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
-      The postal address is:
-        Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
-  */
-
-  /*
-      This program will use an ioctl() on /proc/mtrr to show the current MTRR
-      settings. This is an alternative to reading /proc/mtrr.
-
-
-      Written by      Richard Gooch   17-DEC-1997
-
-      Last updated by Richard Gooch   2-MAY-1998
-
-
-  */
-  #include <stdio.h>
-  #include <stdlib.h>
-  #include <string.h>
-  #include <sys/types.h>
-  #include <sys/stat.h>
-  #include <fcntl.h>
-  #include <sys/ioctl.h>
-  #include <errno.h>
-  #include <asm/mtrr.h>
-
-  #define TRUE 1
-  #define FALSE 0
-  #define ERRSTRING strerror (errno)
-
-  static char *mtrr_strings[MTRR_NUM_TYPES] =
-  {
-      "uncachable",               /* 0 */
-      "write-combining",          /* 1 */
-      "?",                        /* 2 */
-      "?",                        /* 3 */
-      "write-through",            /* 4 */
-      "write-protect",            /* 5 */
-      "write-back",               /* 6 */
-  };
-
-  int main ()
-  {
-      int fd;
-      struct mtrr_gentry gentry;
-
-      if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) == -1 )
-      {
-    if (errno == ENOENT)
-    {
-        fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
-        stderr);
-        exit (1);
-    }
-    fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
-    exit (2);
-      }
-      for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0;
-    ++gentry.regnum)
-      {
-    if (gentry.size < 1)
-    {
-        fprintf (stderr, "Register: %u disabled\n", gentry.regnum);
-        continue;
-    }
-    fprintf (stderr, "Register: %u base: 0x%lx size: 0x%lx type: %s\n",
-      gentry.regnum, gentry.base, gentry.size,
-      mtrr_strings[gentry.type]);
-      }
-      if (errno == EINVAL) exit (0);
-      fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
-      exit (3);
-  }   /*  End Function main  */
-
-
-Creating MTRRs from a C programme using ioctl()'s
-=================================================
-::
-
-  /*  mtrr-add.c
-
-      Source file for mtrr-add (example programme to add an MTRRs using ioctl())
-
-      Copyright (C) 1997-1998  Richard Gooch
-
-      This program is free software; you can redistribute it and/or modify
-      it under the terms of the GNU General Public License as published by
-      the Free Software Foundation; either version 2 of the License, or
-      (at your option) any later version.
-
-      This program is distributed in the hope that it will be useful,
-      but WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-      GNU General Public License for more details.
-
-      You should have received a copy of the GNU General Public License
-      along with this program; if not, write to the Free Software
-      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-      Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
-      The postal address is:
-        Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
-  */
-
-  /*
-      This programme will use an ioctl() on /proc/mtrr to add an entry. The first
-      available mtrr is used. This is an alternative to writing /proc/mtrr.
-
-
-      Written by      Richard Gooch   17-DEC-1997
-
-      Last updated by Richard Gooch   2-MAY-1998
-
-
-  */
-  #include <stdio.h>
-  #include <string.h>
-  #include <stdlib.h>
-  #include <unistd.h>
-  #include <sys/types.h>
-  #include <sys/stat.h>
-  #include <fcntl.h>
-  #include <sys/ioctl.h>
-  #include <errno.h>
-  #include <asm/mtrr.h>
-
-  #define TRUE 1
-  #define FALSE 0
-  #define ERRSTRING strerror (errno)
-
-  static char *mtrr_strings[MTRR_NUM_TYPES] =
-  {
-      "uncachable",               /* 0 */
-      "write-combining",          /* 1 */
-      "?",                        /* 2 */
-      "?",                        /* 3 */
-      "write-through",            /* 4 */
-      "write-protect",            /* 5 */
-      "write-back",               /* 6 */
-  };
-
-  int main (int argc, char **argv)
-  {
-      int fd;
-      struct mtrr_sentry sentry;
-
-      if (argc != 4)
-      {
-    fprintf (stderr, "Usage:\tmtrr-add base size type\n");
-    exit (1);
-      }
-      sentry.base = strtoul (argv[1], NULL, 0);
-      sentry.size = strtoul (argv[2], NULL, 0);
-      for (sentry.type = 0; sentry.type < MTRR_NUM_TYPES; ++sentry.type)
-      {
-    if (strcmp (argv[3], mtrr_strings[sentry.type]) == 0) break;
-      }
-      if (sentry.type >= MTRR_NUM_TYPES)
-      {
-    fprintf (stderr, "Illegal type: \"%s\"\n", argv[3]);
-    exit (2);
-      }
-      if ( ( fd = open ("/proc/mtrr", O_WRONLY, 0) ) == -1 )
-      {
-    if (errno == ENOENT)
-    {
-        fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
-        stderr);
-        exit (3);
-    }
-    fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
-    exit (4);
-      }
-      if (ioctl (fd, MTRRIOC_ADD_ENTRY, &sentry) == -1)
-      {
-    fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
-    exit (5);
-      }
-      fprintf (stderr, "Sleeping for 5 seconds so you can see the new entry\n");
-      sleep (5);
-      close (fd);
-      fputs ("I've just closed /proc/mtrr so now the new entry should be gone\n",
-      stderr);
-  }   /*  End Function main  */
diff --git a/Documentation/x86/orc-unwinder.rst b/Documentation/x86/orc-unwinder.rst
deleted file mode 100644 (file)
index cdb2570..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============
-ORC unwinder
-============
-
-Overview
-========
-
-The kernel CONFIG_UNWINDER_ORC option enables the ORC unwinder, which is
-similar in concept to a DWARF unwinder.  The difference is that the
-format of the ORC data is much simpler than DWARF, which in turn allows
-the ORC unwinder to be much simpler and faster.
-
-The ORC data consists of unwind tables which are generated by objtool.
-They contain out-of-band data which is used by the in-kernel ORC
-unwinder.  Objtool generates the ORC data by first doing compile-time
-stack metadata validation (CONFIG_STACK_VALIDATION).  After analyzing
-all the code paths of a .o file, it determines information about the
-stack state at each instruction address in the file and outputs that
-information to the .orc_unwind and .orc_unwind_ip sections.
-
-The per-object ORC sections are combined at link time and are sorted and
-post-processed at boot time.  The unwinder uses the resulting data to
-correlate instruction addresses with their stack states at run time.
-
-
-ORC vs frame pointers
-=====================
-
-With frame pointers enabled, GCC adds instrumentation code to every
-function in the kernel.  The kernel's .text size increases by about
-3.2%, resulting in a broad kernel-wide slowdown.  Measurements by Mel
-Gorman [1]_ have shown a slowdown of 5-10% for some workloads.
-
-In contrast, the ORC unwinder has no effect on text size or runtime
-performance, because the debuginfo is out of band.  So if you disable
-frame pointers and enable the ORC unwinder, you get a nice performance
-improvement across the board, and still have reliable stack traces.
-
-Ingo Molnar says:
-
-  "Note that it's not just a performance improvement, but also an
-  instruction cache locality improvement: 3.2% .text savings almost
-  directly transform into a similarly sized reduction in cache
-  footprint. That can transform to even higher speedups for workloads
-  whose cache locality is borderline."
-
-Another benefit of ORC compared to frame pointers is that it can
-reliably unwind across interrupts and exceptions.  Frame pointer based
-unwinds can sometimes skip the caller of the interrupted function, if it
-was a leaf function or if the interrupt hit before the frame pointer was
-saved.
-
-The main disadvantage of the ORC unwinder compared to frame pointers is
-that it needs more memory to store the ORC unwind tables: roughly 2-4MB
-depending on the kernel config.
-
-
-ORC vs DWARF
-============
-
-ORC debuginfo's advantage over DWARF itself is that it's much simpler.
-It gets rid of the complex DWARF CFI state machine and also gets rid of
-the tracking of unnecessary registers.  This allows the unwinder to be
-much simpler, meaning fewer bugs, which is especially important for
-mission critical oops code.
-
-The simpler debuginfo format also enables the unwinder to be much faster
-than DWARF, which is important for perf and lockdep.  In a basic
-performance test by Jiri Slaby [2]_, the ORC unwinder was about 20x
-faster than an out-of-tree DWARF unwinder.  (Note: That measurement was
-taken before some performance tweaks were added, which doubled
-performance, so the speedup over DWARF may be closer to 40x.)
-
-The ORC data format does have a few downsides compared to DWARF.  ORC
-unwind tables take up ~50% more RAM (+1.3MB on an x86 defconfig kernel)
-than DWARF-based eh_frame tables.
-
-Another potential downside is that, as GCC evolves, it's conceivable
-that the ORC data may end up being *too* simple to describe the state of
-the stack for certain optimizations.  But IMO this is unlikely because
-GCC saves the frame pointer for any unusual stack adjustments it does,
-so I suspect we'll really only ever need to keep track of the stack
-pointer and the frame pointer between call frames.  But even if we do
-end up having to track all the registers DWARF tracks, at least we will
-still be able to control the format, e.g. no complex state machines.
-
-
-ORC unwind table generation
-===========================
-
-The ORC data is generated by objtool.  With the existing compile-time
-stack metadata validation feature, objtool already follows all code
-paths, and so it already has all the information it needs to be able to
-generate ORC data from scratch.  So it's an easy step to go from stack
-validation to ORC data generation.
-
-It should be possible to instead generate the ORC data with a simple
-tool which converts DWARF to ORC data.  However, such a solution would
-be incomplete due to the kernel's extensive use of asm, inline asm, and
-special sections like exception tables.
-
-That could be rectified by manually annotating those special code paths
-using GNU assembler .cfi annotations in .S files, and homegrown
-annotations for inline asm in .c files.  But asm annotations were tried
-in the past and were found to be unmaintainable.  They were often
-incorrect/incomplete and made the code harder to read and keep updated.
-And based on looking at glibc code, annotating inline asm in .c files
-might be even worse.
-
-Objtool still needs a few annotations, but only in code which does
-unusual things to the stack like entry code.  And even then, far fewer
-annotations are needed than what DWARF would need, so they're much more
-maintainable than DWARF CFI annotations.
-
-So the advantages of using objtool to generate ORC data are that it
-gives more accurate debuginfo, with very few annotations.  It also
-insulates the kernel from toolchain bugs which can be very painful to
-deal with in the kernel since we often have to workaround issues in
-older versions of the toolchain for years.
-
-The downside is that the unwinder now becomes dependent on objtool's
-ability to reverse engineer GCC code flow.  If GCC optimizations become
-too complicated for objtool to follow, the ORC data generation might
-stop working or become incomplete.  (It's worth noting that livepatch
-already has such a dependency on objtool's ability to follow GCC code
-flow.)
-
-If newer versions of GCC come up with some optimizations which break
-objtool, we may need to revisit the current implementation.  Some
-possible solutions would be asking GCC to make the optimizations more
-palatable, or having objtool use DWARF as an additional input, or
-creating a GCC plugin to assist objtool with its analysis.  But for now,
-objtool follows GCC code quite well.
-
-
-Unwinder implementation details
-===============================
-
-Objtool generates the ORC data by integrating with the compile-time
-stack metadata validation feature, which is described in detail in
-tools/objtool/Documentation/objtool.txt.  After analyzing all
-the code paths of a .o file, it creates an array of orc_entry structs,
-and a parallel array of instruction addresses associated with those
-structs, and writes them to the .orc_unwind and .orc_unwind_ip sections
-respectively.
-
-The ORC data is split into the two arrays for performance reasons, to
-make the searchable part of the data (.orc_unwind_ip) more compact.  The
-arrays are sorted in parallel at boot time.
-
-Performance is further improved by the use of a fast lookup table which
-is created at runtime.  The fast lookup table associates a given address
-with a range of indices for the .orc_unwind table, so that only a small
-subset of the table needs to be searched.
-
-
-Etymology
-=========
-
-Orcs, fearsome creatures of medieval folklore, are the Dwarves' natural
-enemies.  Similarly, the ORC unwinder was created in opposition to the
-complexity and slowness of DWARF.
-
-"Although Orcs rarely consider multiple solutions to a problem, they do
-excel at getting things done because they are creatures of action, not
-thought." [3]_  Similarly, unlike the esoteric DWARF unwinder, the
-veracious ORC unwinder wastes no time or siloconic effort decoding
-variable-length zero-extended unsigned-integer byte-coded
-state-machine-based debug information entries.
-
-Similar to how Orcs frequently unravel the well-intentioned plans of
-their adversaries, the ORC unwinder frequently unravels stacks with
-brutal, unyielding efficiency.
-
-ORC stands for Oops Rewind Capability.
-
-
-.. [1] https://lore.kernel.org/r/20170602104048.jkkzssljsompjdwy@suse.de
-.. [2] https://lore.kernel.org/r/d2ca5435-6386-29b8-db87-7f227c2b713a@suse.cz
-.. [3] http://dustin.wikidot.com/half-orcs-and-orcs
diff --git a/Documentation/x86/pat.rst b/Documentation/x86/pat.rst
deleted file mode 100644 (file)
index 5d90177..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==========================
-PAT (Page Attribute Table)
-==========================
-
-x86 Page Attribute Table (PAT) allows for setting the memory attribute at the
-page level granularity. PAT is complementary to the MTRR settings which allows
-for setting of memory types over physical address ranges. However, PAT is
-more flexible than MTRR due to its capability to set attributes at page level
-and also due to the fact that there are no hardware limitations on number of
-such attribute settings allowed. Added flexibility comes with guidelines for
-not having memory type aliasing for the same physical memory with multiple
-virtual addresses.
-
-PAT allows for different types of memory attributes. The most commonly used
-ones that will be supported at this time are:
-
-===  ==============
-WB   Write-back
-UC   Uncached
-WC   Write-combined
-WT   Write-through
-UC-  Uncached Minus
-===  ==============
-
-
-PAT APIs
-========
-
-There are many different APIs in the kernel that allows setting of memory
-attributes at the page level. In order to avoid aliasing, these interfaces
-should be used thoughtfully. Below is a table of interfaces available,
-their intended usage and their memory attribute relationships. Internally,
-these APIs use a reserve_memtype()/free_memtype() interface on the physical
-address range to avoid any aliasing.
-
-+------------------------+----------+--------------+------------------+
-| API                    |    RAM   |  ACPI,...    |  Reserved/Holes  |
-+------------------------+----------+--------------+------------------+
-| ioremap                |    --    |    UC-       |       UC-        |
-+------------------------+----------+--------------+------------------+
-| ioremap_cache          |    --    |    WB        |       WB         |
-+------------------------+----------+--------------+------------------+
-| ioremap_uc             |    --    |    UC        |       UC         |
-+------------------------+----------+--------------+------------------+
-| ioremap_wc             |    --    |    --        |       WC         |
-+------------------------+----------+--------------+------------------+
-| ioremap_wt             |    --    |    --        |       WT         |
-+------------------------+----------+--------------+------------------+
-| set_memory_uc,         |    UC-   |    --        |       --         |
-| set_memory_wb          |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| set_memory_wc,         |    WC    |    --        |       --         |
-| set_memory_wb          |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| set_memory_wt,         |    WT    |    --        |       --         |
-| set_memory_wb          |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| pci sysfs resource     |    --    |    --        |       UC-        |
-+------------------------+----------+--------------+------------------+
-| pci sysfs resource_wc  |    --    |    --        |       WC         |
-| is IORESOURCE_PREFETCH |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| pci proc               |    --    |    --        |       UC-        |
-| !PCIIOC_WRITE_COMBINE  |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| pci proc               |    --    |    --        |       WC         |
-| PCIIOC_WRITE_COMBINE   |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| /dev/mem               |    --    |   WB/WC/UC-  |    WB/WC/UC-     |
-| read-write             |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| /dev/mem               |    --    |    UC-       |       UC-        |
-| mmap SYNC flag         |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| /dev/mem               |    --    |   WB/WC/UC-  |  WB/WC/UC-       |
-| mmap !SYNC flag        |          |              |                  |
-| and                    |          |(from existing|  (from existing  |
-| any alias to this area |          |alias)        |  alias)          |
-+------------------------+----------+--------------+------------------+
-| /dev/mem               |    --    |    WB        |       WB         |
-| mmap !SYNC flag        |          |              |                  |
-| no alias to this area  |          |              |                  |
-| and                    |          |              |                  |
-| MTRR says WB           |          |              |                  |
-+------------------------+----------+--------------+------------------+
-| /dev/mem               |    --    |    --        |       UC-        |
-| mmap !SYNC flag        |          |              |                  |
-| no alias to this area  |          |              |                  |
-| and                    |          |              |                  |
-| MTRR says !WB          |          |              |                  |
-+------------------------+----------+--------------+------------------+
-
-
-Advanced APIs for drivers
-=========================
-
-A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range,
-vmf_insert_pfn.
-
-Drivers wanting to export some pages to userspace do it by using mmap
-interface and a combination of:
-
-  1) pgprot_noncached()
-  2) io_remap_pfn_range() or remap_pfn_range() or vmf_insert_pfn()
-
-With PAT support, a new API pgprot_writecombine is being added. So, drivers can
-continue to use the above sequence, with either pgprot_noncached() or
-pgprot_writecombine() in step 1, followed by step 2.
-
-In addition, step 2 internally tracks the region as UC or WC in memtype
-list in order to ensure no conflicting mapping.
-
-Note that this set of APIs only works with IO (non RAM) regions. If driver
-wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
-as step 0 above and also track the usage of those pages and use set_memory_wb()
-before the page is freed to free pool.
-
-MTRR effects on PAT / non-PAT systems
-=====================================
-
-The following table provides the effects of using write-combining MTRRs when
-using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
-mtrr_add() usage will be phased out in favor of arch_phys_wc_add() which will
-be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
-is made, should already have been ioremapped with WC attributes or PAT entries,
-this can be done by using ioremap_wc() / set_memory_wc().  Devices which
-combine areas of IO memory desired to remain uncacheable with areas where
-write-combining is desirable should consider use of ioremap_uc() followed by
-set_memory_wc() to white-list effective write-combined areas.  Such use is
-nevertheless discouraged as the effective memory type is considered
-implementation defined, yet this strategy can be used as last resort on devices
-with size-constrained regions where otherwise MTRR write-combining would
-otherwise not be effective.
-::
-
-  ====  =======  ===  =========================  =====================
-  MTRR  Non-PAT  PAT  Linux ioremap value        Effective memory type
-  ====  =======  ===  =========================  =====================
-        PAT                                        Non-PAT |  PAT
-        |PCD                                               |
-        ||PWT                                              |
-        |||                                                |
-  WC    000      WB   _PAGE_CACHE_MODE_WB             WC   |   WC
-  WC    001      WC   _PAGE_CACHE_MODE_WC             WC*  |   WC
-  WC    010      UC-  _PAGE_CACHE_MODE_UC_MINUS       WC*  |   UC
-  WC    011      UC   _PAGE_CACHE_MODE_UC             UC   |   UC
-  ====  =======  ===  =========================  =====================
-
-  (*) denotes implementation defined and is discouraged
-
-.. note:: -- in the above table mean "Not suggested usage for the API". Some
-  of the --'s are strictly enforced by the kernel. Some others are not really
-  enforced today, but may be enforced in future.
-
-For ioremap and pci access through /sys or /proc - The actual type returned
-can be more restrictive, in case of any existing aliasing for that address.
-For example: If there is an existing uncached mapping, a new ioremap_wc can
-return uncached mapping in place of write-combine requested.
-
-set_memory_[uc|wc|wt] and set_memory_wb should be used in pairs, where driver
-will first make a region uc, wc or wt and switch it back to wb after use.
-
-Over time writes to /proc/mtrr will be deprecated in favor of using PAT based
-interfaces. Users writing to /proc/mtrr are suggested to use above interfaces.
-
-Drivers should use ioremap_[uc|wc] to access PCI BARs with [uc|wc] access
-types.
-
-Drivers should use set_memory_[uc|wc|wt] to set access type for RAM ranges.
-
-
-PAT debugging
-=============
-
-With CONFIG_DEBUG_FS enabled, PAT memtype list can be examined by::
-
-  # mount -t debugfs debugfs /sys/kernel/debug
-  # cat /sys/kernel/debug/x86/pat_memtype_list
-  PAT memtype list:
-  uncached-minus @ 0x7fadf000-0x7fae0000
-  uncached-minus @ 0x7fb19000-0x7fb1a000
-  uncached-minus @ 0x7fb1a000-0x7fb1b000
-  uncached-minus @ 0x7fb1b000-0x7fb1c000
-  uncached-minus @ 0x7fb1c000-0x7fb1d000
-  uncached-minus @ 0x7fb1d000-0x7fb1e000
-  uncached-minus @ 0x7fb1e000-0x7fb25000
-  uncached-minus @ 0x7fb25000-0x7fb26000
-  uncached-minus @ 0x7fb26000-0x7fb27000
-  uncached-minus @ 0x7fb27000-0x7fb28000
-  uncached-minus @ 0x7fb28000-0x7fb2e000
-  uncached-minus @ 0x7fb2e000-0x7fb2f000
-  uncached-minus @ 0x7fb2f000-0x7fb30000
-  uncached-minus @ 0x7fb31000-0x7fb32000
-  uncached-minus @ 0x80000000-0x90000000
-
-This list shows physical address ranges and various PAT settings used to
-access those physical address ranges.
-
-Another, more verbose way of getting PAT related debug messages is with
-"debugpat" boot parameter. With this parameter, various debug messages are
-printed to dmesg log.
-
-PAT Initialization
-==================
-
-The following table describes how PAT is initialized under various
-configurations. The PAT MSR must be updated by Linux in order to support WC
-and WT attributes. Otherwise, the PAT MSR has the value programmed in it
-by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests.
-
- ==== ===== ==========================  =========  =======
- MTRR PAT   Call Sequence               PAT State  PAT MSR
- ==== ===== ==========================  =========  =======
- E    E     MTRR -> PAT init            Enabled    OS
- E    D     MTRR -> PAT init            Disabled    -
- D    E     MTRR -> PAT disable         Disabled   BIOS
- D    D     MTRR -> PAT disable         Disabled    -
- -    np/E  PAT  -> PAT disable         Disabled   BIOS
- -    np/D  PAT  -> PAT disable         Disabled    -
- E    !P/E  MTRR -> PAT init            Disabled   BIOS
- D    !P/E  MTRR -> PAT disable         Disabled   BIOS
- !M   !P/E  MTRR stub -> PAT disable    Disabled   BIOS
- ==== ===== ==========================  =========  =======
-
-  Legend
-
- ========= =======================================
- E         Feature enabled in CPU
- D        Feature disabled/unsupported in CPU
- np       "nopat" boot option specified
- !P       CONFIG_X86_PAT option unset
- !M       CONFIG_MTRR option unset
- Enabled   PAT state set to enabled
- Disabled  PAT state set to disabled
- OS        PAT initializes PAT MSR with OS setting
- BIOS      PAT keeps PAT MSR with BIOS setting
- ========= =======================================
-
diff --git a/Documentation/x86/pti.rst b/Documentation/x86/pti.rst
deleted file mode 100644 (file)
index 4b858a9..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==========================
-Page Table Isolation (PTI)
-==========================
-
-Overview
-========
-
-Page Table Isolation (pti, previously known as KAISER [1]_) is a
-countermeasure against attacks on the shared user/kernel address
-space such as the "Meltdown" approach [2]_.
-
-To mitigate this class of attacks, we create an independent set of
-page tables for use only when running userspace applications.  When
-the kernel is entered via syscalls, interrupts or exceptions, the
-page tables are switched to the full "kernel" copy.  When the system
-switches back to user mode, the user copy is used again.
-
-The userspace page tables contain only a minimal amount of kernel
-data: only what is needed to enter/exit the kernel such as the
-entry/exit functions themselves and the interrupt descriptor table
-(IDT).  There are a few strictly unnecessary things that get mapped
-such as the first C function when entering an interrupt (see
-comments in pti.c).
-
-This approach helps to ensure that side-channel attacks leveraging
-the paging structures do not function when PTI is enabled.  It can be
-enabled by setting CONFIG_PAGE_TABLE_ISOLATION=y at compile time.
-Once enabled at compile-time, it can be disabled at boot with the
-'nopti' or 'pti=' kernel parameters (see kernel-parameters.txt).
-
-Page Table Management
-=====================
-
-When PTI is enabled, the kernel manages two sets of page tables.
-The first set is very similar to the single set which is present in
-kernels without PTI.  This includes a complete mapping of userspace
-that the kernel can use for things like copy_to_user().
-
-Although _complete_, the user portion of the kernel page tables is
-crippled by setting the NX bit in the top level.  This ensures
-that any missed kernel->user CR3 switch will immediately crash
-userspace upon executing its first instruction.
-
-The userspace page tables map only the kernel data needed to enter
-and exit the kernel.  This data is entirely contained in the 'struct
-cpu_entry_area' structure which is placed in the fixmap which gives
-each CPU's copy of the area a compile-time-fixed virtual address.
-
-For new userspace mappings, the kernel makes the entries in its
-page tables like normal.  The only difference is when the kernel
-makes entries in the top (PGD) level.  In addition to setting the
-entry in the main kernel PGD, a copy of the entry is made in the
-userspace page tables' PGD.
-
-This sharing at the PGD level also inherently shares all the lower
-layers of the page tables.  This leaves a single, shared set of
-userspace page tables to manage.  One PTE to lock, one set of
-accessed bits, dirty bits, etc...
-
-Overhead
-========
-
-Protection against side-channel attacks is important.  But,
-this protection comes at a cost:
-
-1. Increased Memory Use
-
-  a. Each process now needs an order-1 PGD instead of order-0.
-     (Consumes an additional 4k per process).
-  b. The 'cpu_entry_area' structure must be 2MB in size and 2MB
-     aligned so that it can be mapped by setting a single PMD
-     entry.  This consumes nearly 2MB of RAM once the kernel
-     is decompressed, but no space in the kernel image itself.
-
-2. Runtime Cost
-
-  a. CR3 manipulation to switch between the page table copies
-     must be done at interrupt, syscall, and exception entry
-     and exit (it can be skipped when the kernel is interrupted,
-     though.)  Moves to CR3 are on the order of a hundred
-     cycles, and are required at every entry and exit.
-  b. A "trampoline" must be used for SYSCALL entry.  This
-     trampoline depends on a smaller set of resources than the
-     non-PTI SYSCALL entry code, so requires mapping fewer
-     things into the userspace page tables.  The downside is
-     that stacks must be switched at entry time.
-  c. Global pages are disabled for all kernel structures not
-     mapped into both kernel and userspace page tables.  This
-     feature of the MMU allows different processes to share TLB
-     entries mapping the kernel.  Losing the feature means more
-     TLB misses after a context switch.  The actual loss of
-     performance is very small, however, never exceeding 1%.
-  d. Process Context IDentifiers (PCID) is a CPU feature that
-     allows us to skip flushing the entire TLB when switching page
-     tables by setting a special bit in CR3 when the page tables
-     are changed.  This makes switching the page tables (at context
-     switch, or kernel entry/exit) cheaper.  But, on systems with
-     PCID support, the context switch code must flush both the user
-     and kernel entries out of the TLB.  The user PCID TLB flush is
-     deferred until the exit to userspace, minimizing the cost.
-     See intel.com/sdm for the gory PCID/INVPCID details.
-  e. The userspace page tables must be populated for each new
-     process.  Even without PTI, the shared kernel mappings
-     are created by copying top-level (PGD) entries into each
-     new process.  But, with PTI, there are now *two* kernel
-     mappings: one in the kernel page tables that maps everything
-     and one for the entry/exit structures.  At fork(), we need to
-     copy both.
-  f. In addition to the fork()-time copying, there must also
-     be an update to the userspace PGD any time a set_pgd() is done
-     on a PGD used to map userspace.  This ensures that the kernel
-     and userspace copies always map the same userspace
-     memory.
-  g. On systems without PCID support, each CR3 write flushes
-     the entire TLB.  That means that each syscall, interrupt
-     or exception flushes the TLB.
-  h. INVPCID is a TLB-flushing instruction which allows flushing
-     of TLB entries for non-current PCIDs.  Some systems support
-     PCIDs, but do not support INVPCID.  On these systems, addresses
-     can only be flushed from the TLB for the current PCID.  When
-     flushing a kernel address, we need to flush all PCIDs, so a
-     single kernel address flush will require a TLB-flushing CR3
-     write upon the next use of every PCID.
-
-Possible Future Work
-====================
-1. We can be more careful about not actually writing to CR3
-   unless its value is actually changed.
-2. Allow PTI to be enabled/disabled at runtime in addition to the
-   boot-time switching.
-
-Testing
-========
-
-To test stability of PTI, the following test procedure is recommended,
-ideally doing all of these in parallel:
-
-1. Set CONFIG_DEBUG_ENTRY=y
-2. Run several copies of all of the tools/testing/selftests/x86/ tests
-   (excluding MPX and protection_keys) in a loop on multiple CPUs for
-   several minutes.  These tests frequently uncover corner cases in the
-   kernel entry code.  In general, old kernels might cause these tests
-   themselves to crash, but they should never crash the kernel.
-3. Run the 'perf' tool in a mode (top or record) that generates many
-   frequent performance monitoring non-maskable interrupts (see "NMI"
-   in /proc/interrupts).  This exercises the NMI entry/exit code which
-   is known to trigger bugs in code paths that did not expect to be
-   interrupted, including nested NMIs.  Using "-c" boosts the rate of
-   NMIs, and using two -c with separate counters encourages nested NMIs
-   and less deterministic behavior.
-   ::
-
-       while true; do perf record -c 10000 -e instructions,cycles -a sleep 10; done
-
-4. Launch a KVM virtual machine.
-5. Run 32-bit binaries on systems supporting the SYSCALL instruction.
-   This has been a lightly-tested code path and needs extra scrutiny.
-
-Debugging
-=========
-
-Bugs in PTI cause a few different signatures of crashes
-that are worth noting here.
-
- * Failures of the selftests/x86 code.  Usually a bug in one of the
-   more obscure corners of entry_64.S
- * Crashes in early boot, especially around CPU bringup.  Bugs
-   in the trampoline code or mappings cause these.
- * Crashes at the first interrupt.  Caused by bugs in entry_64.S,
-   like screwing up a page table switch.  Also caused by
-   incorrectly mapping the IRQ handler entry code.
- * Crashes at the first NMI.  The NMI code is separate from main
-   interrupt handlers and can have bugs that do not affect
-   normal interrupts.  Also caused by incorrectly mapping NMI
-   code.  NMIs that interrupt the entry code must be very
-   careful and can be the cause of crashes that show up when
-   running perf.
- * Kernel crashes at the first exit to userspace.  entry_64.S
-   bugs, or failing to map some of the exit code.
- * Crashes at first interrupt that interrupts userspace. The paths
-   in entry_64.S that return to userspace are sometimes separate
-   from the ones that return to the kernel.
- * Double faults: overflowing the kernel stack because of page
-   faults upon page faults.  Caused by touching non-pti-mapped
-   data in the entry code, or forgetting to switch to kernel
-   CR3 before calling into C functions which are not pti-mapped.
- * Userspace segfaults early in boot, sometimes manifesting
-   as mount(8) failing to mount the rootfs.  These have
-   tended to be TLB invalidation issues.  Usually invalidating
-   the wrong PCID, or otherwise missing an invalidation.
-
-.. [1] https://gruss.cc/files/kaiser.pdf
-.. [2] https://meltdownattack.com/meltdown.pdf
diff --git a/Documentation/x86/resctrl.rst b/Documentation/x86/resctrl.rst
deleted file mode 100644 (file)
index 387ccbc..0000000
+++ /dev/null
@@ -1,1447 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-.. include:: <isonum.txt>
-
-===========================================
-User Interface for Resource Control feature
-===========================================
-
-:Copyright: |copy| 2016 Intel Corporation
-:Authors: - Fenghua Yu <fenghua.yu@intel.com>
-          - Tony Luck <tony.luck@intel.com>
-          - Vikas Shivappa <vikas.shivappa@intel.com>
-
-
-Intel refers to this feature as Intel Resource Director Technology(Intel(R) RDT).
-AMD refers to this feature as AMD Platform Quality of Service(AMD QoS).
-
-This feature is enabled by the CONFIG_X86_CPU_RESCTRL and the x86 /proc/cpuinfo
-flag bits:
-
-===============================================        ================================
-RDT (Resource Director Technology) Allocation  "rdt_a"
-CAT (Cache Allocation Technology)              "cat_l3", "cat_l2"
-CDP (Code and Data Prioritization)             "cdp_l3", "cdp_l2"
-CQM (Cache QoS Monitoring)                     "cqm_llc", "cqm_occup_llc"
-MBM (Memory Bandwidth Monitoring)              "cqm_mbm_total", "cqm_mbm_local"
-MBA (Memory Bandwidth Allocation)              "mba"
-SMBA (Slow Memory Bandwidth Allocation)         ""
-BMEC (Bandwidth Monitoring Event Configuration) ""
-===============================================        ================================
-
-Historically, new features were made visible by default in /proc/cpuinfo. This
-resulted in the feature flags becoming hard to parse by humans. Adding a new
-flag to /proc/cpuinfo should be avoided if user space can obtain information
-about the feature from resctrl's info directory.
-
-To use the feature mount the file system::
-
- # mount -t resctrl resctrl [-o cdp[,cdpl2][,mba_MBps]] /sys/fs/resctrl
-
-mount options are:
-
-"cdp":
-       Enable code/data prioritization in L3 cache allocations.
-"cdpl2":
-       Enable code/data prioritization in L2 cache allocations.
-"mba_MBps":
-       Enable the MBA Software Controller(mba_sc) to specify MBA
-       bandwidth in MBps
-
-L2 and L3 CDP are controlled separately.
-
-RDT features are orthogonal. A particular system may support only
-monitoring, only control, or both monitoring and control.  Cache
-pseudo-locking is a unique way of using cache control to "pin" or
-"lock" data in the cache. Details can be found in
-"Cache Pseudo-Locking".
-
-
-The mount succeeds if either of allocation or monitoring is present, but
-only those files and directories supported by the system will be created.
-For more details on the behavior of the interface during monitoring
-and allocation, see the "Resource alloc and monitor groups" section.
-
-Info directory
-==============
-
-The 'info' directory contains information about the enabled
-resources. Each resource has its own subdirectory. The subdirectory
-names reflect the resource names.
-
-Each subdirectory contains the following files with respect to
-allocation:
-
-Cache resource(L3/L2)  subdirectory contains the following files
-related to allocation:
-
-"num_closids":
-               The number of CLOSIDs which are valid for this
-               resource. The kernel uses the smallest number of
-               CLOSIDs of all enabled resources as limit.
-"cbm_mask":
-               The bitmask which is valid for this resource.
-               This mask is equivalent to 100%.
-"min_cbm_bits":
-               The minimum number of consecutive bits which
-               must be set when writing a mask.
-
-"shareable_bits":
-               Bitmask of shareable resource with other executing
-               entities (e.g. I/O). User can use this when
-               setting up exclusive cache partitions. Note that
-               some platforms support devices that have their
-               own settings for cache use which can over-ride
-               these bits.
-"bit_usage":
-               Annotated capacity bitmasks showing how all
-               instances of the resource are used. The legend is:
-
-                       "0":
-                             Corresponding region is unused. When the system's
-                             resources have been allocated and a "0" is found
-                             in "bit_usage" it is a sign that resources are
-                             wasted.
-
-                       "H":
-                             Corresponding region is used by hardware only
-                             but available for software use. If a resource
-                             has bits set in "shareable_bits" but not all
-                             of these bits appear in the resource groups'
-                             schematas then the bits appearing in
-                             "shareable_bits" but no resource group will
-                             be marked as "H".
-                       "X":
-                             Corresponding region is available for sharing and
-                             used by hardware and software. These are the
-                             bits that appear in "shareable_bits" as
-                             well as a resource group's allocation.
-                       "S":
-                             Corresponding region is used by software
-                             and available for sharing.
-                       "E":
-                             Corresponding region is used exclusively by
-                             one resource group. No sharing allowed.
-                       "P":
-                             Corresponding region is pseudo-locked. No
-                             sharing allowed.
-
-Memory bandwidth(MB) subdirectory contains the following files
-with respect to allocation:
-
-"min_bandwidth":
-               The minimum memory bandwidth percentage which
-               user can request.
-
-"bandwidth_gran":
-               The granularity in which the memory bandwidth
-               percentage is allocated. The allocated
-               b/w percentage is rounded off to the next
-               control step available on the hardware. The
-               available bandwidth control steps are:
-               min_bandwidth + N * bandwidth_gran.
-
-"delay_linear":
-               Indicates if the delay scale is linear or
-               non-linear. This field is purely informational
-               only.
-
-"thread_throttle_mode":
-               Indicator on Intel systems of how tasks running on threads
-               of a physical core are throttled in cases where they
-               request different memory bandwidth percentages:
-
-               "max":
-                       the smallest percentage is applied
-                       to all threads
-               "per-thread":
-                       bandwidth percentages are directly applied to
-                       the threads running on the core
-
-If RDT monitoring is available there will be an "L3_MON" directory
-with the following files:
-
-"num_rmids":
-               The number of RMIDs available. This is the
-               upper bound for how many "CTRL_MON" + "MON"
-               groups can be created.
-
-"mon_features":
-               Lists the monitoring events if
-               monitoring is enabled for the resource.
-               Example::
-
-                       # cat /sys/fs/resctrl/info/L3_MON/mon_features
-                       llc_occupancy
-                       mbm_total_bytes
-                       mbm_local_bytes
-
-               If the system supports Bandwidth Monitoring Event
-               Configuration (BMEC), then the bandwidth events will
-               be configurable. The output will be::
-
-                       # cat /sys/fs/resctrl/info/L3_MON/mon_features
-                       llc_occupancy
-                       mbm_total_bytes
-                       mbm_total_bytes_config
-                       mbm_local_bytes
-                       mbm_local_bytes_config
-
-"mbm_total_bytes_config", "mbm_local_bytes_config":
-       Read/write files containing the configuration for the mbm_total_bytes
-       and mbm_local_bytes events, respectively, when the Bandwidth
-       Monitoring Event Configuration (BMEC) feature is supported.
-       The event configuration settings are domain specific and affect
-       all the CPUs in the domain. When either event configuration is
-       changed, the bandwidth counters for all RMIDs of both events
-       (mbm_total_bytes as well as mbm_local_bytes) are cleared for that
-       domain. The next read for every RMID will report "Unavailable"
-       and subsequent reads will report the valid value.
-
-       Following are the types of events supported:
-
-       ====    ========================================================
-       Bits    Description
-       ====    ========================================================
-       6       Dirty Victims from the QOS domain to all types of memory
-       5       Reads to slow memory in the non-local NUMA domain
-       4       Reads to slow memory in the local NUMA domain
-       3       Non-temporal writes to non-local NUMA domain
-       2       Non-temporal writes to local NUMA domain
-       1       Reads to memory in the non-local NUMA domain
-       0       Reads to memory in the local NUMA domain
-       ====    ========================================================
-
-       By default, the mbm_total_bytes configuration is set to 0x7f to count
-       all the event types and the mbm_local_bytes configuration is set to
-       0x15 to count all the local memory events.
-
-       Examples:
-
-       * To view the current configuration::
-         ::
-
-           # cat /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
-           0=0x7f;1=0x7f;2=0x7f;3=0x7f
-
-           # cat /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config
-           0=0x15;1=0x15;3=0x15;4=0x15
-
-       * To change the mbm_total_bytes to count only reads on domain 0,
-         the bits 0, 1, 4 and 5 needs to be set, which is 110011b in binary
-         (in hexadecimal 0x33):
-         ::
-
-           # echo  "0=0x33" > /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
-
-           # cat /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config
-           0=0x33;1=0x7f;2=0x7f;3=0x7f
-
-       * To change the mbm_local_bytes to count all the slow memory reads on
-         domain 0 and 1, the bits 4 and 5 needs to be set, which is 110000b
-         in binary (in hexadecimal 0x30):
-         ::
-
-           # echo  "0=0x30;1=0x30" > /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config
-
-           # cat /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config
-           0=0x30;1=0x30;3=0x15;4=0x15
-
-"max_threshold_occupancy":
-               Read/write file provides the largest value (in
-               bytes) at which a previously used LLC_occupancy
-               counter can be considered for re-use.
-
-Finally, in the top level of the "info" directory there is a file
-named "last_cmd_status". This is reset with every "command" issued
-via the file system (making new directories or writing to any of the
-control files). If the command was successful, it will read as "ok".
-If the command failed, it will provide more information that can be
-conveyed in the error returns from file operations. E.g.
-::
-
-       # echo L3:0=f7 > schemata
-       bash: echo: write error: Invalid argument
-       # cat info/last_cmd_status
-       mask f7 has non-consecutive 1-bits
-
-Resource alloc and monitor groups
-=================================
-
-Resource groups are represented as directories in the resctrl file
-system.  The default group is the root directory which, immediately
-after mounting, owns all the tasks and cpus in the system and can make
-full use of all resources.
-
-On a system with RDT control features additional directories can be
-created in the root directory that specify different amounts of each
-resource (see "schemata" below). The root and these additional top level
-directories are referred to as "CTRL_MON" groups below.
-
-On a system with RDT monitoring the root directory and other top level
-directories contain a directory named "mon_groups" in which additional
-directories can be created to monitor subsets of tasks in the CTRL_MON
-group that is their ancestor. These are called "MON" groups in the rest
-of this document.
-
-Removing a directory will move all tasks and cpus owned by the group it
-represents to the parent. Removing one of the created CTRL_MON groups
-will automatically remove all MON groups below it.
-
-All groups contain the following files:
-
-"tasks":
-       Reading this file shows the list of all tasks that belong to
-       this group. Writing a task id to the file will add a task to the
-       group. If the group is a CTRL_MON group the task is removed from
-       whichever previous CTRL_MON group owned the task and also from
-       any MON group that owned the task. If the group is a MON group,
-       then the task must already belong to the CTRL_MON parent of this
-       group. The task is removed from any previous MON group.
-
-
-"cpus":
-       Reading this file shows a bitmask of the logical CPUs owned by
-       this group. Writing a mask to this file will add and remove
-       CPUs to/from this group. As with the tasks file a hierarchy is
-       maintained where MON groups may only include CPUs owned by the
-       parent CTRL_MON group.
-       When the resource group is in pseudo-locked mode this file will
-       only be readable, reflecting the CPUs associated with the
-       pseudo-locked region.
-
-
-"cpus_list":
-       Just like "cpus", only using ranges of CPUs instead of bitmasks.
-
-
-When control is enabled all CTRL_MON groups will also contain:
-
-"schemata":
-       A list of all the resources available to this group.
-       Each resource has its own line and format - see below for details.
-
-"size":
-       Mirrors the display of the "schemata" file to display the size in
-       bytes of each allocation instead of the bits representing the
-       allocation.
-
-"mode":
-       The "mode" of the resource group dictates the sharing of its
-       allocations. A "shareable" resource group allows sharing of its
-       allocations while an "exclusive" resource group does not. A
-       cache pseudo-locked region is created by first writing
-       "pseudo-locksetup" to the "mode" file before writing the cache
-       pseudo-locked region's schemata to the resource group's "schemata"
-       file. On successful pseudo-locked region creation the mode will
-       automatically change to "pseudo-locked".
-
-When monitoring is enabled all MON groups will also contain:
-
-"mon_data":
-       This contains a set of files organized by L3 domain and by
-       RDT event. E.g. on a system with two L3 domains there will
-       be subdirectories "mon_L3_00" and "mon_L3_01".  Each of these
-       directories have one file per event (e.g. "llc_occupancy",
-       "mbm_total_bytes", and "mbm_local_bytes"). In a MON group these
-       files provide a read out of the current value of the event for
-       all tasks in the group. In CTRL_MON groups these files provide
-       the sum for all tasks in the CTRL_MON group and all tasks in
-       MON groups. Please see example section for more details on usage.
-
-Resource allocation rules
--------------------------
-
-When a task is running the following rules define which resources are
-available to it:
-
-1) If the task is a member of a non-default group, then the schemata
-   for that group is used.
-
-2) Else if the task belongs to the default group, but is running on a
-   CPU that is assigned to some specific group, then the schemata for the
-   CPU's group is used.
-
-3) Otherwise the schemata for the default group is used.
-
-Resource monitoring rules
--------------------------
-1) If a task is a member of a MON group, or non-default CTRL_MON group
-   then RDT events for the task will be reported in that group.
-
-2) If a task is a member of the default CTRL_MON group, but is running
-   on a CPU that is assigned to some specific group, then the RDT events
-   for the task will be reported in that group.
-
-3) Otherwise RDT events for the task will be reported in the root level
-   "mon_data" group.
-
-
-Notes on cache occupancy monitoring and control
-===============================================
-When moving a task from one group to another you should remember that
-this only affects *new* cache allocations by the task. E.g. you may have
-a task in a monitor group showing 3 MB of cache occupancy. If you move
-to a new group and immediately check the occupancy of the old and new
-groups you will likely see that the old group is still showing 3 MB and
-the new group zero. When the task accesses locations still in cache from
-before the move, the h/w does not update any counters. On a busy system
-you will likely see the occupancy in the old group go down as cache lines
-are evicted and re-used while the occupancy in the new group rises as
-the task accesses memory and loads into the cache are counted based on
-membership in the new group.
-
-The same applies to cache allocation control. Moving a task to a group
-with a smaller cache partition will not evict any cache lines. The
-process may continue to use them from the old partition.
-
-Hardware uses CLOSid(Class of service ID) and an RMID(Resource monitoring ID)
-to identify a control group and a monitoring group respectively. Each of
-the resource groups are mapped to these IDs based on the kind of group. The
-number of CLOSid and RMID are limited by the hardware and hence the creation of
-a "CTRL_MON" directory may fail if we run out of either CLOSID or RMID
-and creation of "MON" group may fail if we run out of RMIDs.
-
-max_threshold_occupancy - generic concepts
-------------------------------------------
-
-Note that an RMID once freed may not be immediately available for use as
-the RMID is still tagged the cache lines of the previous user of RMID.
-Hence such RMIDs are placed on limbo list and checked back if the cache
-occupancy has gone down. If there is a time when system has a lot of
-limbo RMIDs but which are not ready to be used, user may see an -EBUSY
-during mkdir.
-
-max_threshold_occupancy is a user configurable value to determine the
-occupancy at which an RMID can be freed.
-
-Schemata files - general concepts
----------------------------------
-Each line in the file describes one resource. The line starts with
-the name of the resource, followed by specific values to be applied
-in each of the instances of that resource on the system.
-
-Cache IDs
----------
-On current generation systems there is one L3 cache per socket and L2
-caches are generally just shared by the hyperthreads on a core, but this
-isn't an architectural requirement. We could have multiple separate L3
-caches on a socket, multiple cores could share an L2 cache. So instead
-of using "socket" or "core" to define the set of logical cpus sharing
-a resource we use a "Cache ID". At a given cache level this will be a
-unique number across the whole system (but it isn't guaranteed to be a
-contiguous sequence, there may be gaps).  To find the ID for each logical
-CPU look in /sys/devices/system/cpu/cpu*/cache/index*/id
-
-Cache Bit Masks (CBM)
----------------------
-For cache resources we describe the portion of the cache that is available
-for allocation using a bitmask. The maximum value of the mask is defined
-by each cpu model (and may be different for different cache levels). It
-is found using CPUID, but is also provided in the "info" directory of
-the resctrl file system in "info/{resource}/cbm_mask". Intel hardware
-requires that these masks have all the '1' bits in a contiguous block. So
-0x3, 0x6 and 0xC are legal 4-bit masks with two bits set, but 0x5, 0x9
-and 0xA are not.  On a system with a 20-bit mask each bit represents 5%
-of the capacity of the cache. You could partition the cache into four
-equal parts with masks: 0x1f, 0x3e0, 0x7c00, 0xf8000.
-
-Memory bandwidth Allocation and monitoring
-==========================================
-
-For Memory bandwidth resource, by default the user controls the resource
-by indicating the percentage of total memory bandwidth.
-
-The minimum bandwidth percentage value for each cpu model is predefined
-and can be looked up through "info/MB/min_bandwidth". The bandwidth
-granularity that is allocated is also dependent on the cpu model and can
-be looked up at "info/MB/bandwidth_gran". The available bandwidth
-control steps are: min_bw + N * bw_gran. Intermediate values are rounded
-to the next control step available on the hardware.
-
-The bandwidth throttling is a core specific mechanism on some of Intel
-SKUs. Using a high bandwidth and a low bandwidth setting on two threads
-sharing a core may result in both threads being throttled to use the
-low bandwidth (see "thread_throttle_mode").
-
-The fact that Memory bandwidth allocation(MBA) may be a core
-specific mechanism where as memory bandwidth monitoring(MBM) is done at
-the package level may lead to confusion when users try to apply control
-via the MBA and then monitor the bandwidth to see if the controls are
-effective. Below are such scenarios:
-
-1. User may *not* see increase in actual bandwidth when percentage
-   values are increased:
-
-This can occur when aggregate L2 external bandwidth is more than L3
-external bandwidth. Consider an SKL SKU with 24 cores on a package and
-where L2 external  is 10GBps (hence aggregate L2 external bandwidth is
-240GBps) and L3 external bandwidth is 100GBps. Now a workload with '20
-threads, having 50% bandwidth, each consuming 5GBps' consumes the max L3
-bandwidth of 100GBps although the percentage value specified is only 50%
-<< 100%. Hence increasing the bandwidth percentage will not yield any
-more bandwidth. This is because although the L2 external bandwidth still
-has capacity, the L3 external bandwidth is fully used. Also note that
-this would be dependent on number of cores the benchmark is run on.
-
-2. Same bandwidth percentage may mean different actual bandwidth
-   depending on # of threads:
-
-For the same SKU in #1, a 'single thread, with 10% bandwidth' and '4
-thread, with 10% bandwidth' can consume upto 10GBps and 40GBps although
-they have same percentage bandwidth of 10%. This is simply because as
-threads start using more cores in an rdtgroup, the actual bandwidth may
-increase or vary although user specified bandwidth percentage is same.
-
-In order to mitigate this and make the interface more user friendly,
-resctrl added support for specifying the bandwidth in MBps as well.  The
-kernel underneath would use a software feedback mechanism or a "Software
-Controller(mba_sc)" which reads the actual bandwidth using MBM counters
-and adjust the memory bandwidth percentages to ensure::
-
-       "actual bandwidth < user specified bandwidth".
-
-By default, the schemata would take the bandwidth percentage values
-where as user can switch to the "MBA software controller" mode using
-a mount option 'mba_MBps'. The schemata format is specified in the below
-sections.
-
-L3 schemata file details (code and data prioritization disabled)
-----------------------------------------------------------------
-With CDP disabled the L3 schemata format is::
-
-       L3:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
-
-L3 schemata file details (CDP enabled via mount option to resctrl)
-------------------------------------------------------------------
-When CDP is enabled L3 control is split into two separate resources
-so you can specify independent masks for code and data like this::
-
-       L3DATA:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
-       L3CODE:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
-
-L2 schemata file details
-------------------------
-CDP is supported at L2 using the 'cdpl2' mount option. The schemata
-format is either::
-
-       L2:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
-
-or
-
-       L2DATA:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
-       L2CODE:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
-
-
-Memory bandwidth Allocation (default mode)
-------------------------------------------
-
-Memory b/w domain is L3 cache.
-::
-
-       MB:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;...
-
-Memory bandwidth Allocation specified in MBps
----------------------------------------------
-
-Memory bandwidth domain is L3 cache.
-::
-
-       MB:<cache_id0>=bw_MBps0;<cache_id1>=bw_MBps1;...
-
-Slow Memory Bandwidth Allocation (SMBA)
----------------------------------------
-AMD hardware supports Slow Memory Bandwidth Allocation (SMBA).
-CXL.memory is the only supported "slow" memory device. With the
-support of SMBA, the hardware enables bandwidth allocation on
-the slow memory devices. If there are multiple such devices in
-the system, the throttling logic groups all the slow sources
-together and applies the limit on them as a whole.
-
-The presence of SMBA (with CXL.memory) is independent of slow memory
-devices presence. If there are no such devices on the system, then
-configuring SMBA will have no impact on the performance of the system.
-
-The bandwidth domain for slow memory is L3 cache. Its schemata file
-is formatted as:
-::
-
-       SMBA:<cache_id0>=bandwidth0;<cache_id1>=bandwidth1;...
-
-Reading/writing the schemata file
----------------------------------
-Reading the schemata file will show the state of all resources
-on all domains. When writing you only need to specify those values
-which you wish to change.  E.g.
-::
-
-  # cat schemata
-  L3DATA:0=fffff;1=fffff;2=fffff;3=fffff
-  L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
-  # echo "L3DATA:2=3c0;" > schemata
-  # cat schemata
-  L3DATA:0=fffff;1=fffff;2=3c0;3=fffff
-  L3CODE:0=fffff;1=fffff;2=fffff;3=fffff
-
-Reading/writing the schemata file (on AMD systems)
---------------------------------------------------
-Reading the schemata file will show the current bandwidth limit on all
-domains. The allocated resources are in multiples of one eighth GB/s.
-When writing to the file, you need to specify what cache id you wish to
-configure the bandwidth limit.
-
-For example, to allocate 2GB/s limit on the first cache id:
-
-::
-
-  # cat schemata
-    MB:0=2048;1=2048;2=2048;3=2048
-    L3:0=ffff;1=ffff;2=ffff;3=ffff
-
-  # echo "MB:1=16" > schemata
-  # cat schemata
-    MB:0=2048;1=  16;2=2048;3=2048
-    L3:0=ffff;1=ffff;2=ffff;3=ffff
-
-Reading/writing the schemata file (on AMD systems) with SMBA feature
---------------------------------------------------------------------
-Reading and writing the schemata file is the same as without SMBA in
-above section.
-
-For example, to allocate 8GB/s limit on the first cache id:
-
-::
-
-  # cat schemata
-    SMBA:0=2048;1=2048;2=2048;3=2048
-      MB:0=2048;1=2048;2=2048;3=2048
-      L3:0=ffff;1=ffff;2=ffff;3=ffff
-
-  # echo "SMBA:1=64" > schemata
-  # cat schemata
-    SMBA:0=2048;1=  64;2=2048;3=2048
-      MB:0=2048;1=2048;2=2048;3=2048
-      L3:0=ffff;1=ffff;2=ffff;3=ffff
-
-Cache Pseudo-Locking
-====================
-CAT enables a user to specify the amount of cache space that an
-application can fill. Cache pseudo-locking builds on the fact that a
-CPU can still read and write data pre-allocated outside its current
-allocated area on a cache hit. With cache pseudo-locking, data can be
-preloaded into a reserved portion of cache that no application can
-fill, and from that point on will only serve cache hits. The cache
-pseudo-locked memory is made accessible to user space where an
-application can map it into its virtual address space and thus have
-a region of memory with reduced average read latency.
-
-The creation of a cache pseudo-locked region is triggered by a request
-from the user to do so that is accompanied by a schemata of the region
-to be pseudo-locked. The cache pseudo-locked region is created as follows:
-
-- Create a CAT allocation CLOSNEW with a CBM matching the schemata
-  from the user of the cache region that will contain the pseudo-locked
-  memory. This region must not overlap with any current CAT allocation/CLOS
-  on the system and no future overlap with this cache region is allowed
-  while the pseudo-locked region exists.
-- Create a contiguous region of memory of the same size as the cache
-  region.
-- Flush the cache, disable hardware prefetchers, disable preemption.
-- Make CLOSNEW the active CLOS and touch the allocated memory to load
-  it into the cache.
-- Set the previous CLOS as active.
-- At this point the closid CLOSNEW can be released - the cache
-  pseudo-locked region is protected as long as its CBM does not appear in
-  any CAT allocation. Even though the cache pseudo-locked region will from
-  this point on not appear in any CBM of any CLOS an application running with
-  any CLOS will be able to access the memory in the pseudo-locked region since
-  the region continues to serve cache hits.
-- The contiguous region of memory loaded into the cache is exposed to
-  user-space as a character device.
-
-Cache pseudo-locking increases the probability that data will remain
-in the cache via carefully configuring the CAT feature and controlling
-application behavior. There is no guarantee that data is placed in
-cache. Instructions like INVD, WBINVD, CLFLUSH, etc. can still evict
-“locked” data from cache. Power management C-states may shrink or
-power off cache. Deeper C-states will automatically be restricted on
-pseudo-locked region creation.
-
-It is required that an application using a pseudo-locked region runs
-with affinity to the cores (or a subset of the cores) associated
-with the cache on which the pseudo-locked region resides. A sanity check
-within the code will not allow an application to map pseudo-locked memory
-unless it runs with affinity to cores associated with the cache on which the
-pseudo-locked region resides. The sanity check is only done during the
-initial mmap() handling, there is no enforcement afterwards and the
-application self needs to ensure it remains affine to the correct cores.
-
-Pseudo-locking is accomplished in two stages:
-
-1) During the first stage the system administrator allocates a portion
-   of cache that should be dedicated to pseudo-locking. At this time an
-   equivalent portion of memory is allocated, loaded into allocated
-   cache portion, and exposed as a character device.
-2) During the second stage a user-space application maps (mmap()) the
-   pseudo-locked memory into its address space.
-
-Cache Pseudo-Locking Interface
-------------------------------
-A pseudo-locked region is created using the resctrl interface as follows:
-
-1) Create a new resource group by creating a new directory in /sys/fs/resctrl.
-2) Change the new resource group's mode to "pseudo-locksetup" by writing
-   "pseudo-locksetup" to the "mode" file.
-3) Write the schemata of the pseudo-locked region to the "schemata" file. All
-   bits within the schemata should be "unused" according to the "bit_usage"
-   file.
-
-On successful pseudo-locked region creation the "mode" file will contain
-"pseudo-locked" and a new character device with the same name as the resource
-group will exist in /dev/pseudo_lock. This character device can be mmap()'ed
-by user space in order to obtain access to the pseudo-locked memory region.
-
-An example of cache pseudo-locked region creation and usage can be found below.
-
-Cache Pseudo-Locking Debugging Interface
-----------------------------------------
-The pseudo-locking debugging interface is enabled by default (if
-CONFIG_DEBUG_FS is enabled) and can be found in /sys/kernel/debug/resctrl.
-
-There is no explicit way for the kernel to test if a provided memory
-location is present in the cache. The pseudo-locking debugging interface uses
-the tracing infrastructure to provide two ways to measure cache residency of
-the pseudo-locked region:
-
-1) Memory access latency using the pseudo_lock_mem_latency tracepoint. Data
-   from these measurements are best visualized using a hist trigger (see
-   example below). In this test the pseudo-locked region is traversed at
-   a stride of 32 bytes while hardware prefetchers and preemption
-   are disabled. This also provides a substitute visualization of cache
-   hits and misses.
-2) Cache hit and miss measurements using model specific precision counters if
-   available. Depending on the levels of cache on the system the pseudo_lock_l2
-   and pseudo_lock_l3 tracepoints are available.
-
-When a pseudo-locked region is created a new debugfs directory is created for
-it in debugfs as /sys/kernel/debug/resctrl/<newdir>. A single
-write-only file, pseudo_lock_measure, is present in this directory. The
-measurement of the pseudo-locked region depends on the number written to this
-debugfs file:
-
-1:
-     writing "1" to the pseudo_lock_measure file will trigger the latency
-     measurement captured in the pseudo_lock_mem_latency tracepoint. See
-     example below.
-2:
-     writing "2" to the pseudo_lock_measure file will trigger the L2 cache
-     residency (cache hits and misses) measurement captured in the
-     pseudo_lock_l2 tracepoint. See example below.
-3:
-     writing "3" to the pseudo_lock_measure file will trigger the L3 cache
-     residency (cache hits and misses) measurement captured in the
-     pseudo_lock_l3 tracepoint.
-
-All measurements are recorded with the tracing infrastructure. This requires
-the relevant tracepoints to be enabled before the measurement is triggered.
-
-Example of latency debugging interface
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In this example a pseudo-locked region named "newlock" was created. Here is
-how we can measure the latency in cycles of reading from this region and
-visualize this data with a histogram that is available if CONFIG_HIST_TRIGGERS
-is set::
-
-  # :> /sys/kernel/tracing/trace
-  # echo 'hist:keys=latency' > /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/trigger
-  # echo 1 > /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/enable
-  # echo 1 > /sys/kernel/debug/resctrl/newlock/pseudo_lock_measure
-  # echo 0 > /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/enable
-  # cat /sys/kernel/tracing/events/resctrl/pseudo_lock_mem_latency/hist
-
-  # event histogram
-  #
-  # trigger info: hist:keys=latency:vals=hitcount:sort=hitcount:size=2048 [active]
-  #
-
-  { latency:        456 } hitcount:          1
-  { latency:         50 } hitcount:         83
-  { latency:         36 } hitcount:         96
-  { latency:         44 } hitcount:        174
-  { latency:         48 } hitcount:        195
-  { latency:         46 } hitcount:        262
-  { latency:         42 } hitcount:        693
-  { latency:         40 } hitcount:       3204
-  { latency:         38 } hitcount:       3484
-
-  Totals:
-      Hits: 8192
-      Entries: 9
-    Dropped: 0
-
-Example of cache hits/misses debugging
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In this example a pseudo-locked region named "newlock" was created on the L2
-cache of a platform. Here is how we can obtain details of the cache hits
-and misses using the platform's precision counters.
-::
-
-  # :> /sys/kernel/tracing/trace
-  # echo 1 > /sys/kernel/tracing/events/resctrl/pseudo_lock_l2/enable
-  # echo 2 > /sys/kernel/debug/resctrl/newlock/pseudo_lock_measure
-  # echo 0 > /sys/kernel/tracing/events/resctrl/pseudo_lock_l2/enable
-  # cat /sys/kernel/tracing/trace
-
-  # tracer: nop
-  #
-  #                              _-----=> irqs-off
-  #                             / _----=> need-resched
-  #                            | / _---=> hardirq/softirq
-  #                            || / _--=> preempt-depth
-  #                            ||| /     delay
-  #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
-  #              | |       |   ||||       |         |
-  pseudo_lock_mea-1672  [002] ....  3132.860500: pseudo_lock_l2: hits=4097 miss=0
-
-
-Examples for RDT allocation usage
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1) Example 1
-
-On a two socket machine (one L3 cache per socket) with just four bits
-for cache bit masks, minimum b/w of 10% with a memory bandwidth
-granularity of 10%.
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-  # mkdir p0 p1
-  # echo "L3:0=3;1=c\nMB:0=50;1=50" > /sys/fs/resctrl/p0/schemata
-  # echo "L3:0=3;1=3\nMB:0=50;1=50" > /sys/fs/resctrl/p1/schemata
-
-The default resource group is unmodified, so we have access to all parts
-of all caches (its schemata file reads "L3:0=f;1=f").
-
-Tasks that are under the control of group "p0" may only allocate from the
-"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
-Tasks in group "p1" use the "lower" 50% of cache on both sockets.
-
-Similarly, tasks that are under the control of group "p0" may use a
-maximum memory b/w of 50% on socket0 and 50% on socket 1.
-Tasks in group "p1" may also use 50% memory b/w on both sockets.
-Note that unlike cache masks, memory b/w cannot specify whether these
-allocations can overlap or not. The allocations specifies the maximum
-b/w that the group may be able to use and the system admin can configure
-the b/w accordingly.
-
-If resctrl is using the software controller (mba_sc) then user can enter the
-max b/w in MB rather than the percentage values.
-::
-
-  # echo "L3:0=3;1=c\nMB:0=1024;1=500" > /sys/fs/resctrl/p0/schemata
-  # echo "L3:0=3;1=3\nMB:0=1024;1=500" > /sys/fs/resctrl/p1/schemata
-
-In the above example the tasks in "p1" and "p0" on socket 0 would use a max b/w
-of 1024MB where as on socket 1 they would use 500MB.
-
-2) Example 2
-
-Again two sockets, but this time with a more realistic 20-bit mask.
-
-Two real time tasks pid=1234 running on processor 0 and pid=5678 running on
-processor 1 on socket 0 on a 2-socket and dual core machine. To avoid noisy
-neighbors, each of the two real-time tasks exclusively occupies one quarter
-of L3 cache on socket 0.
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-
-First we reset the schemata for the default group so that the "upper"
-50% of the L3 cache on socket 0 and 50% of memory b/w cannot be used by
-ordinary tasks::
-
-  # echo "L3:0=3ff;1=fffff\nMB:0=50;1=100" > schemata
-
-Next we make a resource group for our first real time task and give
-it access to the "top" 25% of the cache on socket 0.
-::
-
-  # mkdir p0
-  # echo "L3:0=f8000;1=fffff" > p0/schemata
-
-Finally we move our first real time task into this resource group. We
-also use taskset(1) to ensure the task always runs on a dedicated CPU
-on socket 0. Most uses of resource groups will also constrain which
-processors tasks run on.
-::
-
-  # echo 1234 > p0/tasks
-  # taskset -cp 1 1234
-
-Ditto for the second real time task (with the remaining 25% of cache)::
-
-  # mkdir p1
-  # echo "L3:0=7c00;1=fffff" > p1/schemata
-  # echo 5678 > p1/tasks
-  # taskset -cp 2 5678
-
-For the same 2 socket system with memory b/w resource and CAT L3 the
-schemata would look like(Assume min_bandwidth 10 and bandwidth_gran is
-10):
-
-For our first real time task this would request 20% memory b/w on socket 0.
-::
-
-  # echo -e "L3:0=f8000;1=fffff\nMB:0=20;1=100" > p0/schemata
-
-For our second real time task this would request an other 20% memory b/w
-on socket 0.
-::
-
-  # echo -e "L3:0=f8000;1=fffff\nMB:0=20;1=100" > p0/schemata
-
-3) Example 3
-
-A single socket system which has real-time tasks running on core 4-7 and
-non real-time workload assigned to core 0-3. The real-time tasks share text
-and data, so a per task association is not required and due to interaction
-with the kernel it's desired that the kernel on these cores shares L3 with
-the tasks.
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-
-First we reset the schemata for the default group so that the "upper"
-50% of the L3 cache on socket 0, and 50% of memory bandwidth on socket 0
-cannot be used by ordinary tasks::
-
-  # echo "L3:0=3ff\nMB:0=50" > schemata
-
-Next we make a resource group for our real time cores and give it access
-to the "top" 50% of the cache on socket 0 and 50% of memory bandwidth on
-socket 0.
-::
-
-  # mkdir p0
-  # echo "L3:0=ffc00\nMB:0=50" > p0/schemata
-
-Finally we move core 4-7 over to the new group and make sure that the
-kernel and the tasks running there get 50% of the cache. They should
-also get 50% of memory bandwidth assuming that the cores 4-7 are SMT
-siblings and only the real time threads are scheduled on the cores 4-7.
-::
-
-  # echo F0 > p0/cpus
-
-4) Example 4
-
-The resource groups in previous examples were all in the default "shareable"
-mode allowing sharing of their cache allocations. If one resource group
-configures a cache allocation then nothing prevents another resource group
-to overlap with that allocation.
-
-In this example a new exclusive resource group will be created on a L2 CAT
-system with two L2 cache instances that can be configured with an 8-bit
-capacity bitmask. The new exclusive resource group will be configured to use
-25% of each cache instance.
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl/
-  # cd /sys/fs/resctrl
-
-First, we observe that the default group is configured to allocate to all L2
-cache::
-
-  # cat schemata
-  L2:0=ff;1=ff
-
-We could attempt to create the new resource group at this point, but it will
-fail because of the overlap with the schemata of the default group::
-
-  # mkdir p0
-  # echo 'L2:0=0x3;1=0x3' > p0/schemata
-  # cat p0/mode
-  shareable
-  # echo exclusive > p0/mode
-  -sh: echo: write error: Invalid argument
-  # cat info/last_cmd_status
-  schemata overlaps
-
-To ensure that there is no overlap with another resource group the default
-resource group's schemata has to change, making it possible for the new
-resource group to become exclusive.
-::
-
-  # echo 'L2:0=0xfc;1=0xfc' > schemata
-  # echo exclusive > p0/mode
-  # grep . p0/*
-  p0/cpus:0
-  p0/mode:exclusive
-  p0/schemata:L2:0=03;1=03
-  p0/size:L2:0=262144;1=262144
-
-A new resource group will on creation not overlap with an exclusive resource
-group::
-
-  # mkdir p1
-  # grep . p1/*
-  p1/cpus:0
-  p1/mode:shareable
-  p1/schemata:L2:0=fc;1=fc
-  p1/size:L2:0=786432;1=786432
-
-The bit_usage will reflect how the cache is used::
-
-  # cat info/L2/bit_usage
-  0=SSSSSSEE;1=SSSSSSEE
-
-A resource group cannot be forced to overlap with an exclusive resource group::
-
-  # echo 'L2:0=0x1;1=0x1' > p1/schemata
-  -sh: echo: write error: Invalid argument
-  # cat info/last_cmd_status
-  overlaps with exclusive group
-
-Example of Cache Pseudo-Locking
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Lock portion of L2 cache from cache id 1 using CBM 0x3. Pseudo-locked
-region is exposed at /dev/pseudo_lock/newlock that can be provided to
-application for argument to mmap().
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl/
-  # cd /sys/fs/resctrl
-
-Ensure that there are bits available that can be pseudo-locked, since only
-unused bits can be pseudo-locked the bits to be pseudo-locked needs to be
-removed from the default resource group's schemata::
-
-  # cat info/L2/bit_usage
-  0=SSSSSSSS;1=SSSSSSSS
-  # echo 'L2:1=0xfc' > schemata
-  # cat info/L2/bit_usage
-  0=SSSSSSSS;1=SSSSSS00
-
-Create a new resource group that will be associated with the pseudo-locked
-region, indicate that it will be used for a pseudo-locked region, and
-configure the requested pseudo-locked region capacity bitmask::
-
-  # mkdir newlock
-  # echo pseudo-locksetup > newlock/mode
-  # echo 'L2:1=0x3' > newlock/schemata
-
-On success the resource group's mode will change to pseudo-locked, the
-bit_usage will reflect the pseudo-locked region, and the character device
-exposing the pseudo-locked region will exist::
-
-  # cat newlock/mode
-  pseudo-locked
-  # cat info/L2/bit_usage
-  0=SSSSSSSS;1=SSSSSSPP
-  # ls -l /dev/pseudo_lock/newlock
-  crw------- 1 root root 243, 0 Apr  3 05:01 /dev/pseudo_lock/newlock
-
-::
-
-  /*
-  * Example code to access one page of pseudo-locked cache region
-  * from user space.
-  */
-  #define _GNU_SOURCE
-  #include <fcntl.h>
-  #include <sched.h>
-  #include <stdio.h>
-  #include <stdlib.h>
-  #include <unistd.h>
-  #include <sys/mman.h>
-
-  /*
-  * It is required that the application runs with affinity to only
-  * cores associated with the pseudo-locked region. Here the cpu
-  * is hardcoded for convenience of example.
-  */
-  static int cpuid = 2;
-
-  int main(int argc, char *argv[])
-  {
-    cpu_set_t cpuset;
-    long page_size;
-    void *mapping;
-    int dev_fd;
-    int ret;
-
-    page_size = sysconf(_SC_PAGESIZE);
-
-    CPU_ZERO(&cpuset);
-    CPU_SET(cpuid, &cpuset);
-    ret = sched_setaffinity(0, sizeof(cpuset), &cpuset);
-    if (ret < 0) {
-      perror("sched_setaffinity");
-      exit(EXIT_FAILURE);
-    }
-
-    dev_fd = open("/dev/pseudo_lock/newlock", O_RDWR);
-    if (dev_fd < 0) {
-      perror("open");
-      exit(EXIT_FAILURE);
-    }
-
-    mapping = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
-            dev_fd, 0);
-    if (mapping == MAP_FAILED) {
-      perror("mmap");
-      close(dev_fd);
-      exit(EXIT_FAILURE);
-    }
-
-    /* Application interacts with pseudo-locked memory @mapping */
-
-    ret = munmap(mapping, page_size);
-    if (ret < 0) {
-      perror("munmap");
-      close(dev_fd);
-      exit(EXIT_FAILURE);
-    }
-
-    close(dev_fd);
-    exit(EXIT_SUCCESS);
-  }
-
-Locking between applications
-----------------------------
-
-Certain operations on the resctrl filesystem, composed of read/writes
-to/from multiple files, must be atomic.
-
-As an example, the allocation of an exclusive reservation of L3 cache
-involves:
-
-  1. Read the cbmmasks from each directory or the per-resource "bit_usage"
-  2. Find a contiguous set of bits in the global CBM bitmask that is clear
-     in any of the directory cbmmasks
-  3. Create a new directory
-  4. Set the bits found in step 2 to the new directory "schemata" file
-
-If two applications attempt to allocate space concurrently then they can
-end up allocating the same bits so the reservations are shared instead of
-exclusive.
-
-To coordinate atomic operations on the resctrlfs and to avoid the problem
-above, the following locking procedure is recommended:
-
-Locking is based on flock, which is available in libc and also as a shell
-script command
-
-Write lock:
-
- A) Take flock(LOCK_EX) on /sys/fs/resctrl
- B) Read/write the directory structure.
- C) funlock
-
-Read lock:
-
- A) Take flock(LOCK_SH) on /sys/fs/resctrl
- B) If success read the directory structure.
- C) funlock
-
-Example with bash::
-
-  # Atomically read directory structure
-  $ flock -s /sys/fs/resctrl/ find /sys/fs/resctrl
-
-  # Read directory contents and create new subdirectory
-
-  $ cat create-dir.sh
-  find /sys/fs/resctrl/ > output.txt
-  mask = function-of(output.txt)
-  mkdir /sys/fs/resctrl/newres/
-  echo mask > /sys/fs/resctrl/newres/schemata
-
-  $ flock /sys/fs/resctrl/ ./create-dir.sh
-
-Example with C::
-
-  /*
-  * Example code do take advisory locks
-  * before accessing resctrl filesystem
-  */
-  #include <sys/file.h>
-  #include <stdlib.h>
-
-  void resctrl_take_shared_lock(int fd)
-  {
-    int ret;
-
-    /* take shared lock on resctrl filesystem */
-    ret = flock(fd, LOCK_SH);
-    if (ret) {
-      perror("flock");
-      exit(-1);
-    }
-  }
-
-  void resctrl_take_exclusive_lock(int fd)
-  {
-    int ret;
-
-    /* release lock on resctrl filesystem */
-    ret = flock(fd, LOCK_EX);
-    if (ret) {
-      perror("flock");
-      exit(-1);
-    }
-  }
-
-  void resctrl_release_lock(int fd)
-  {
-    int ret;
-
-    /* take shared lock on resctrl filesystem */
-    ret = flock(fd, LOCK_UN);
-    if (ret) {
-      perror("flock");
-      exit(-1);
-    }
-  }
-
-  void main(void)
-  {
-    int fd, ret;
-
-    fd = open("/sys/fs/resctrl", O_DIRECTORY);
-    if (fd == -1) {
-      perror("open");
-      exit(-1);
-    }
-    resctrl_take_shared_lock(fd);
-    /* code to read directory contents */
-    resctrl_release_lock(fd);
-
-    resctrl_take_exclusive_lock(fd);
-    /* code to read and write directory contents */
-    resctrl_release_lock(fd);
-  }
-
-Examples for RDT Monitoring along with allocation usage
-=======================================================
-Reading monitored data
-----------------------
-Reading an event file (for ex: mon_data/mon_L3_00/llc_occupancy) would
-show the current snapshot of LLC occupancy of the corresponding MON
-group or CTRL_MON group.
-
-
-Example 1 (Monitor CTRL_MON group and subset of tasks in CTRL_MON group)
-------------------------------------------------------------------------
-On a two socket machine (one L3 cache per socket) with just four bits
-for cache bit masks::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-  # mkdir p0 p1
-  # echo "L3:0=3;1=c" > /sys/fs/resctrl/p0/schemata
-  # echo "L3:0=3;1=3" > /sys/fs/resctrl/p1/schemata
-  # echo 5678 > p1/tasks
-  # echo 5679 > p1/tasks
-
-The default resource group is unmodified, so we have access to all parts
-of all caches (its schemata file reads "L3:0=f;1=f").
-
-Tasks that are under the control of group "p0" may only allocate from the
-"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
-Tasks in group "p1" use the "lower" 50% of cache on both sockets.
-
-Create monitor groups and assign a subset of tasks to each monitor group.
-::
-
-  # cd /sys/fs/resctrl/p1/mon_groups
-  # mkdir m11 m12
-  # echo 5678 > m11/tasks
-  # echo 5679 > m12/tasks
-
-fetch data (data shown in bytes)
-::
-
-  # cat m11/mon_data/mon_L3_00/llc_occupancy
-  16234000
-  # cat m11/mon_data/mon_L3_01/llc_occupancy
-  14789000
-  # cat m12/mon_data/mon_L3_00/llc_occupancy
-  16789000
-
-The parent ctrl_mon group shows the aggregated data.
-::
-
-  # cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
-  31234000
-
-Example 2 (Monitor a task from its creation)
---------------------------------------------
-On a two socket machine (one L3 cache per socket)::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-  # mkdir p0 p1
-
-An RMID is allocated to the group once its created and hence the <cmd>
-below is monitored from its creation.
-::
-
-  # echo $$ > /sys/fs/resctrl/p1/tasks
-  # <cmd>
-
-Fetch the data::
-
-  # cat /sys/fs/resctrl/p1/mon_data/mon_l3_00/llc_occupancy
-  31789000
-
-Example 3 (Monitor without CAT support or before creating CAT groups)
----------------------------------------------------------------------
-
-Assume a system like HSW has only CQM and no CAT support. In this case
-the resctrl will still mount but cannot create CTRL_MON directories.
-But user can create different MON groups within the root group thereby
-able to monitor all tasks including kernel threads.
-
-This can also be used to profile jobs cache size footprint before being
-able to allocate them to different allocation groups.
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-  # mkdir mon_groups/m01
-  # mkdir mon_groups/m02
-
-  # echo 3478 > /sys/fs/resctrl/mon_groups/m01/tasks
-  # echo 2467 > /sys/fs/resctrl/mon_groups/m02/tasks
-
-Monitor the groups separately and also get per domain data. From the
-below its apparent that the tasks are mostly doing work on
-domain(socket) 0.
-::
-
-  # cat /sys/fs/resctrl/mon_groups/m01/mon_L3_00/llc_occupancy
-  31234000
-  # cat /sys/fs/resctrl/mon_groups/m01/mon_L3_01/llc_occupancy
-  34555
-  # cat /sys/fs/resctrl/mon_groups/m02/mon_L3_00/llc_occupancy
-  31234000
-  # cat /sys/fs/resctrl/mon_groups/m02/mon_L3_01/llc_occupancy
-  32789
-
-
-Example 4 (Monitor real time tasks)
------------------------------------
-
-A single socket system which has real time tasks running on cores 4-7
-and non real time tasks on other cpus. We want to monitor the cache
-occupancy of the real time threads on these cores.
-::
-
-  # mount -t resctrl resctrl /sys/fs/resctrl
-  # cd /sys/fs/resctrl
-  # mkdir p1
-
-Move the cpus 4-7 over to p1::
-
-  # echo f0 > p1/cpus
-
-View the llc occupancy snapshot::
-
-  # cat /sys/fs/resctrl/p1/mon_data/mon_L3_00/llc_occupancy
-  11234000
-
-Intel RDT Errata
-================
-
-Intel MBM Counters May Report System Memory Bandwidth Incorrectly
------------------------------------------------------------------
-
-Errata SKX99 for Skylake server and BDF102 for Broadwell server.
-
-Problem: Intel Memory Bandwidth Monitoring (MBM) counters track metrics
-according to the assigned Resource Monitor ID (RMID) for that logical
-core. The IA32_QM_CTR register (MSR 0xC8E), used to report these
-metrics, may report incorrect system bandwidth for certain RMID values.
-
-Implication: Due to the errata, system memory bandwidth may not match
-what is reported.
-
-Workaround: MBM total and local readings are corrected according to the
-following correction factor table:
-
-+---------------+---------------+---------------+-----------------+
-|core count    |rmid count     |rmid threshold |correction factor|
-+---------------+---------------+---------------+-----------------+
-|1             |8              |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|2             |16             |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|3             |24             |15             |0.969650         |
-+---------------+---------------+---------------+-----------------+
-|4             |32             |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|6             |48             |31             |0.969650         |
-+---------------+---------------+---------------+-----------------+
-|7             |56             |47             |1.142857         |
-+---------------+---------------+---------------+-----------------+
-|8             |64             |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|9             |72             |63             |1.185115         |
-+---------------+---------------+---------------+-----------------+
-|10            |80             |63             |1.066553         |
-+---------------+---------------+---------------+-----------------+
-|11            |88             |79             |1.454545         |
-+---------------+---------------+---------------+-----------------+
-|12            |96             |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|13            |104            |95             |1.230769         |
-+---------------+---------------+---------------+-----------------+
-|14            |112            |95             |1.142857         |
-+---------------+---------------+---------------+-----------------+
-|15            |120            |95             |1.066667         |
-+---------------+---------------+---------------+-----------------+
-|16            |128            |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|17            |136            |127            |1.254863         |
-+---------------+---------------+---------------+-----------------+
-|18            |144            |127            |1.185255         |
-+---------------+---------------+---------------+-----------------+
-|19            |152            |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|20            |160            |127            |1.066667         |
-+---------------+---------------+---------------+-----------------+
-|21            |168            |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|22            |176            |159            |1.454334         |
-+---------------+---------------+---------------+-----------------+
-|23            |184            |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|24            |192            |127            |0.969744         |
-+---------------+---------------+---------------+-----------------+
-|25            |200            |191            |1.280246         |
-+---------------+---------------+---------------+-----------------+
-|26            |208            |191            |1.230921         |
-+---------------+---------------+---------------+-----------------+
-|27            |216            |0              |1.000000         |
-+---------------+---------------+---------------+-----------------+
-|28            |224            |191            |1.143118         |
-+---------------+---------------+---------------+-----------------+
-
-If rmid > rmid threshold, MBM total and local values should be multiplied
-by the correction factor.
-
-See:
-
-1. Erratum SKX99 in Intel Xeon Processor Scalable Family Specification Update:
-http://web.archive.org/web/20200716124958/https://www.intel.com/content/www/us/en/processors/xeon/scalable/xeon-scalable-spec-update.html
-
-2. Erratum BDF102 in Intel Xeon E5-2600 v4 Processor Product Family Specification Update:
-http://web.archive.org/web/20191125200531/https://www.intel.com/content/dam/www/public/us/en/documents/specification-updates/xeon-e5-v4-spec-update.pdf
-
-3. The errata in Intel Resource Director Technology (Intel RDT) on 2nd Generation Intel Xeon Scalable Processors Reference Manual:
-https://software.intel.com/content/www/us/en/develop/articles/intel-resource-director-technology-rdt-reference-manual.html
-
-for further information.
diff --git a/Documentation/x86/sgx.rst b/Documentation/x86/sgx.rst
deleted file mode 100644 (file)
index 2bcbffa..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===============================
-Software Guard eXtensions (SGX)
-===============================
-
-Overview
-========
-
-Software Guard eXtensions (SGX) hardware enables for user space applications
-to set aside private memory regions of code and data:
-
-* Privileged (ring-0) ENCLS functions orchestrate the construction of the
-  regions.
-* Unprivileged (ring-3) ENCLU functions allow an application to enter and
-  execute inside the regions.
-
-These memory regions are called enclaves. An enclave can be only entered at a
-fixed set of entry points. Each entry point can hold a single hardware thread
-at a time.  While the enclave is loaded from a regular binary file by using
-ENCLS functions, only the threads inside the enclave can access its memory. The
-region is denied from outside access by the CPU, and encrypted before it leaves
-from LLC.
-
-The support can be determined by
-
-       ``grep sgx /proc/cpuinfo``
-
-SGX must both be supported in the processor and enabled by the BIOS.  If SGX
-appears to be unsupported on a system which has hardware support, ensure
-support is enabled in the BIOS.  If a BIOS presents a choice between "Enabled"
-and "Software Enabled" modes for SGX, choose "Enabled".
-
-Enclave Page Cache
-==================
-
-SGX utilizes an *Enclave Page Cache (EPC)* to store pages that are associated
-with an enclave. It is contained in a BIOS-reserved region of physical memory.
-Unlike pages used for regular memory, pages can only be accessed from outside of
-the enclave during enclave construction with special, limited SGX instructions.
-
-Only a CPU executing inside an enclave can directly access enclave memory.
-However, a CPU executing inside an enclave may access normal memory outside the
-enclave.
-
-The kernel manages enclave memory similar to how it treats device memory.
-
-Enclave Page Types
-------------------
-
-**SGX Enclave Control Structure (SECS)**
-   Enclave's address range, attributes and other global data are defined
-   by this structure.
-
-**Regular (REG)**
-   Regular EPC pages contain the code and data of an enclave.
-
-**Thread Control Structure (TCS)**
-   Thread Control Structure pages define the entry points to an enclave and
-   track the execution state of an enclave thread.
-
-**Version Array (VA)**
-   Version Array pages contain 512 slots, each of which can contain a version
-   number for a page evicted from the EPC.
-
-Enclave Page Cache Map
-----------------------
-
-The processor tracks EPC pages in a hardware metadata structure called the
-*Enclave Page Cache Map (EPCM)*.  The EPCM contains an entry for each EPC page
-which describes the owning enclave, access rights and page type among the other
-things.
-
-EPCM permissions are separate from the normal page tables.  This prevents the
-kernel from, for instance, allowing writes to data which an enclave wishes to
-remain read-only.  EPCM permissions may only impose additional restrictions on
-top of normal x86 page permissions.
-
-For all intents and purposes, the SGX architecture allows the processor to
-invalidate all EPCM entries at will.  This requires that software be prepared to
-handle an EPCM fault at any time.  In practice, this can happen on events like
-power transitions when the ephemeral key that encrypts enclave memory is lost.
-
-Application interface
-=====================
-
-Enclave build functions
------------------------
-
-In addition to the traditional compiler and linker build process, SGX has a
-separate enclave “build” process.  Enclaves must be built before they can be
-executed (entered). The first step in building an enclave is opening the
-**/dev/sgx_enclave** device.  Since enclave memory is protected from direct
-access, special privileged instructions are then used to copy data into enclave
-pages and establish enclave page permissions.
-
-.. kernel-doc:: arch/x86/kernel/cpu/sgx/ioctl.c
-   :functions: sgx_ioc_enclave_create
-               sgx_ioc_enclave_add_pages
-               sgx_ioc_enclave_init
-               sgx_ioc_enclave_provision
-
-Enclave runtime management
---------------------------
-
-Systems supporting SGX2 additionally support changes to initialized
-enclaves: modifying enclave page permissions and type, and dynamically
-adding and removing of enclave pages. When an enclave accesses an address
-within its address range that does not have a backing page then a new
-regular page will be dynamically added to the enclave. The enclave is
-still required to run EACCEPT on the new page before it can be used.
-
-.. kernel-doc:: arch/x86/kernel/cpu/sgx/ioctl.c
-   :functions: sgx_ioc_enclave_restrict_permissions
-               sgx_ioc_enclave_modify_types
-               sgx_ioc_enclave_remove_pages
-
-Enclave vDSO
-------------
-
-Entering an enclave can only be done through SGX-specific EENTER and ERESUME
-functions, and is a non-trivial process.  Because of the complexity of
-transitioning to and from an enclave, enclaves typically utilize a library to
-handle the actual transitions.  This is roughly analogous to how glibc
-implementations are used by most applications to wrap system calls.
-
-Another crucial characteristic of enclaves is that they can generate exceptions
-as part of their normal operation that need to be handled in the enclave or are
-unique to SGX.
-
-Instead of the traditional signal mechanism to handle these exceptions, SGX
-can leverage special exception fixup provided by the vDSO.  The kernel-provided
-vDSO function wraps low-level transitions to/from the enclave like EENTER and
-ERESUME.  The vDSO function intercepts exceptions that would otherwise generate
-a signal and return the fault information directly to its caller.  This avoids
-the need to juggle signal handlers.
-
-.. kernel-doc:: arch/x86/include/uapi/asm/sgx.h
-   :functions: vdso_sgx_enter_enclave_t
-
-ksgxd
-=====
-
-SGX support includes a kernel thread called *ksgxd*.
-
-EPC sanitization
-----------------
-
-ksgxd is started when SGX initializes.  Enclave memory is typically ready
-for use when the processor powers on or resets.  However, if SGX has been in
-use since the reset, enclave pages may be in an inconsistent state.  This might
-occur after a crash and kexec() cycle, for instance.  At boot, ksgxd
-reinitializes all enclave pages so that they can be allocated and re-used.
-
-The sanitization is done by going through EPC address space and applying the
-EREMOVE function to each physical page. Some enclave pages like SECS pages have
-hardware dependencies on other pages which prevents EREMOVE from functioning.
-Executing two EREMOVE passes removes the dependencies.
-
-Page reclaimer
---------------
-
-Similar to the core kswapd, ksgxd, is responsible for managing the
-overcommitment of enclave memory.  If the system runs out of enclave memory,
-*ksgxd* “swaps” enclave memory to normal memory.
-
-Launch Control
-==============
-
-SGX provides a launch control mechanism. After all enclave pages have been
-copied, kernel executes EINIT function, which initializes the enclave. Only after
-this the CPU can execute inside the enclave.
-
-EINIT function takes an RSA-3072 signature of the enclave measurement.  The function
-checks that the measurement is correct and signature is signed with the key
-hashed to the four **IA32_SGXLEPUBKEYHASH{0, 1, 2, 3}** MSRs representing the
-SHA256 of a public key.
-
-Those MSRs can be configured by the BIOS to be either readable or writable.
-Linux supports only writable configuration in order to give full control to the
-kernel on launch control policy. Before calling EINIT function, the driver sets
-the MSRs to match the enclave's signing key.
-
-Encryption engines
-==================
-
-In order to conceal the enclave data while it is out of the CPU package, the
-memory controller has an encryption engine to transparently encrypt and decrypt
-enclave memory.
-
-In CPUs prior to Ice Lake, the Memory Encryption Engine (MEE) is used to
-encrypt pages leaving the CPU caches. MEE uses a n-ary Merkle tree with root in
-SRAM to maintain integrity of the encrypted data. This provides integrity and
-anti-replay protection but does not scale to large memory sizes because the time
-required to update the Merkle tree grows logarithmically in relation to the
-memory size.
-
-CPUs starting from Icelake use Total Memory Encryption (TME) in the place of
-MEE. TME-based SGX implementations do not have an integrity Merkle tree, which
-means integrity and replay-attacks are not mitigated.  B, it includes
-additional changes to prevent cipher text from being returned and SW memory
-aliases from being created.
-
-DMA to enclave memory is blocked by range registers on both MEE and TME systems
-(SDM section 41.10).
-
-Usage Models
-============
-
-Shared Library
---------------
-
-Sensitive data and the code that acts on it is partitioned from the application
-into a separate library. The library is then linked as a DSO which can be loaded
-into an enclave. The application can then make individual function calls into
-the enclave through special SGX instructions. A run-time within the enclave is
-configured to marshal function parameters into and out of the enclave and to
-call the correct library function.
-
-Application Container
----------------------
-
-An application may be loaded into a container enclave which is specially
-configured with a library OS and run-time which permits the application to run.
-The enclave run-time and library OS work together to execute the application
-when a thread enters the enclave.
-
-Impact of Potential Kernel SGX Bugs
-===================================
-
-EPC leaks
----------
-
-When EPC page leaks happen, a WARNING like this is shown in dmesg:
-
-"EREMOVE returned ... and an EPC page was leaked.  SGX may become unusable..."
-
-This is effectively a kernel use-after-free of an EPC page, and due
-to the way SGX works, the bug is detected at freeing. Rather than
-adding the page back to the pool of available EPC pages, the kernel
-intentionally leaks the page to avoid additional errors in the future.
-
-When this happens, the kernel will likely soon leak more EPC pages, and
-SGX will likely become unusable because the memory available to SGX is
-limited. However, while this may be fatal to SGX, the rest of the kernel
-is unlikely to be impacted and should continue to work.
-
-As a result, when this happpens, user should stop running any new
-SGX workloads, (or just any new workloads), and migrate all valuable
-workloads. Although a machine reboot can recover all EPC memory, the bug
-should be reported to Linux developers.
-
-
-Virtual EPC
-===========
-
-The implementation has also a virtual EPC driver to support SGX enclaves
-in guests. Unlike the SGX driver, an EPC page allocated by the virtual
-EPC driver doesn't have a specific enclave associated with it. This is
-because KVM doesn't track how a guest uses EPC pages.
-
-As a result, the SGX core page reclaimer doesn't support reclaiming EPC
-pages allocated to KVM guests through the virtual EPC driver. If the
-user wants to deploy SGX applications both on the host and in guests
-on the same machine, the user should reserve enough EPC (by taking out
-total virtual EPC size of all SGX VMs from the physical EPC size) for
-host SGX applications so they can run with acceptable performance.
-
-Architectural behavior is to restore all EPC pages to an uninitialized
-state also after a guest reboot.  Because this state can be reached only
-through the privileged ``ENCLS[EREMOVE]`` instruction, ``/dev/sgx_vepc``
-provides the ``SGX_IOC_VEPC_REMOVE_ALL`` ioctl to execute the instruction
-on all pages in the virtual EPC.
-
-``EREMOVE`` can fail for three reasons.  Userspace must pay attention
-to expected failures and handle them as follows:
-
-1. Page removal will always fail when any thread is running in the
-   enclave to which the page belongs.  In this case the ioctl will
-   return ``EBUSY`` independent of whether it has successfully removed
-   some pages; userspace can avoid these failures by preventing execution
-   of any vcpu which maps the virtual EPC.
-
-2. Page removal will cause a general protection fault if two calls to
-   ``EREMOVE`` happen concurrently for pages that refer to the same
-   "SECS" metadata pages.  This can happen if there are concurrent
-   invocations to ``SGX_IOC_VEPC_REMOVE_ALL``, or if a ``/dev/sgx_vepc``
-   file descriptor in the guest is closed at the same time as
-   ``SGX_IOC_VEPC_REMOVE_ALL``; it will also be reported as ``EBUSY``.
-   This can be avoided in userspace by serializing calls to the ioctl()
-   and to close(), but in general it should not be a problem.
-
-3. Finally, page removal will fail for SECS metadata pages which still
-   have child pages.  Child pages can be removed by executing
-   ``SGX_IOC_VEPC_REMOVE_ALL`` on all ``/dev/sgx_vepc`` file descriptors
-   mapped into the guest.  This means that the ioctl() must be called
-   twice: an initial set of calls to remove child pages and a subsequent
-   set of calls to remove SECS pages.  The second set of calls is only
-   required for those mappings that returned a nonzero value from the
-   first call.  It indicates a bug in the kernel or the userspace client
-   if any of the second round of ``SGX_IOC_VEPC_REMOVE_ALL`` calls has
-   a return code other than 0.
diff --git a/Documentation/x86/sva.rst b/Documentation/x86/sva.rst
deleted file mode 100644 (file)
index 2e9b8b0..0000000
+++ /dev/null
@@ -1,286 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===========================================
-Shared Virtual Addressing (SVA) with ENQCMD
-===========================================
-
-Background
-==========
-
-Shared Virtual Addressing (SVA) allows the processor and device to use the
-same virtual addresses avoiding the need for software to translate virtual
-addresses to physical addresses. SVA is what PCIe calls Shared Virtual
-Memory (SVM).
-
-In addition to the convenience of using application virtual addresses
-by the device, it also doesn't require pinning pages for DMA.
-PCIe Address Translation Services (ATS) along with Page Request Interface
-(PRI) allow devices to function much the same way as the CPU handling
-application page-faults. For more information please refer to the PCIe
-specification Chapter 10: ATS Specification.
-
-Use of SVA requires IOMMU support in the platform. IOMMU is also
-required to support the PCIe features ATS and PRI. ATS allows devices
-to cache translations for virtual addresses. The IOMMU driver uses the
-mmu_notifier() support to keep the device TLB cache and the CPU cache in
-sync. When an ATS lookup fails for a virtual address, the device should
-use the PRI in order to request the virtual address to be paged into the
-CPU page tables. The device must use ATS again in order the fetch the
-translation before use.
-
-Shared Hardware Workqueues
-==========================
-
-Unlike Single Root I/O Virtualization (SR-IOV), Scalable IOV (SIOV) permits
-the use of Shared Work Queues (SWQ) by both applications and Virtual
-Machines (VM's). This allows better hardware utilization vs. hard
-partitioning resources that could result in under utilization. In order to
-allow the hardware to distinguish the context for which work is being
-executed in the hardware by SWQ interface, SIOV uses Process Address Space
-ID (PASID), which is a 20-bit number defined by the PCIe SIG.
-
-PASID value is encoded in all transactions from the device. This allows the
-IOMMU to track I/O on a per-PASID granularity in addition to using the PCIe
-Resource Identifier (RID) which is the Bus/Device/Function.
-
-
-ENQCMD
-======
-
-ENQCMD is a new instruction on Intel platforms that atomically submits a
-work descriptor to a device. The descriptor includes the operation to be
-performed, virtual addresses of all parameters, virtual address of a completion
-record, and the PASID (process address space ID) of the current process.
-
-ENQCMD works with non-posted semantics and carries a status back if the
-command was accepted by hardware. This allows the submitter to know if the
-submission needs to be retried or other device specific mechanisms to
-implement fairness or ensure forward progress should be provided.
-
-ENQCMD is the glue that ensures applications can directly submit commands
-to the hardware and also permits hardware to be aware of application context
-to perform I/O operations via use of PASID.
-
-Process Address Space Tagging
-=============================
-
-A new thread-scoped MSR (IA32_PASID) provides the connection between
-user processes and the rest of the hardware. When an application first
-accesses an SVA-capable device, this MSR is initialized with a newly
-allocated PASID. The driver for the device calls an IOMMU-specific API
-that sets up the routing for DMA and page-requests.
-
-For example, the Intel Data Streaming Accelerator (DSA) uses
-iommu_sva_bind_device(), which will do the following:
-
-- Allocate the PASID, and program the process page-table (%cr3 register) in the
-  PASID context entries.
-- Register for mmu_notifier() to track any page-table invalidations to keep
-  the device TLB in sync. For example, when a page-table entry is invalidated,
-  the IOMMU propagates the invalidation to the device TLB. This will force any
-  future access by the device to this virtual address to participate in
-  ATS. If the IOMMU responds with proper response that a page is not
-  present, the device would request the page to be paged in via the PCIe PRI
-  protocol before performing I/O.
-
-This MSR is managed with the XSAVE feature set as "supervisor state" to
-ensure the MSR is updated during context switch.
-
-PASID Management
-================
-
-The kernel must allocate a PASID on behalf of each process which will use
-ENQCMD and program it into the new MSR to communicate the process identity to
-platform hardware.  ENQCMD uses the PASID stored in this MSR to tag requests
-from this process.  When a user submits a work descriptor to a device using the
-ENQCMD instruction, the PASID field in the descriptor is auto-filled with the
-value from MSR_IA32_PASID. Requests for DMA from the device are also tagged
-with the same PASID. The platform IOMMU uses the PASID in the transaction to
-perform address translation. The IOMMU APIs setup the corresponding PASID
-entry in IOMMU with the process address used by the CPU (e.g. %cr3 register in
-x86).
-
-The MSR must be configured on each logical CPU before any application
-thread can interact with a device. Threads that belong to the same
-process share the same page tables, thus the same MSR value.
-
-PASID Life Cycle Management
-===========================
-
-PASID is initialized as INVALID_IOASID (-1) when a process is created.
-
-Only processes that access SVA-capable devices need to have a PASID
-allocated. This allocation happens when a process opens/binds an SVA-capable
-device but finds no PASID for this process. Subsequent binds of the same, or
-other devices will share the same PASID.
-
-Although the PASID is allocated to the process by opening a device,
-it is not active in any of the threads of that process. It's loaded to the
-IA32_PASID MSR lazily when a thread tries to submit a work descriptor
-to a device using the ENQCMD.
-
-That first access will trigger a #GP fault because the IA32_PASID MSR
-has not been initialized with the PASID value assigned to the process
-when the device was opened. The Linux #GP handler notes that a PASID has
-been allocated for the process, and so initializes the IA32_PASID MSR
-and returns so that the ENQCMD instruction is re-executed.
-
-On fork(2) or exec(2) the PASID is removed from the process as it no
-longer has the same address space that it had when the device was opened.
-
-On clone(2) the new task shares the same address space, so will be
-able to use the PASID allocated to the process. The IA32_PASID is not
-preemptively initialized as the PASID value might not be allocated yet or
-the kernel does not know whether this thread is going to access the device
-and the cleared IA32_PASID MSR reduces context switch overhead by xstate
-init optimization. Since #GP faults have to be handled on any threads that
-were created before the PASID was assigned to the mm of the process, newly
-created threads might as well be treated in a consistent way.
-
-Due to complexity of freeing the PASID and clearing all IA32_PASID MSRs in
-all threads in unbind, free the PASID lazily only on mm exit.
-
-If a process does a close(2) of the device file descriptor and munmap(2)
-of the device MMIO portal, then the driver will unbind the device. The
-PASID is still marked VALID in the PASID_MSR for any threads in the
-process that accessed the device. But this is harmless as without the
-MMIO portal they cannot submit new work to the device.
-
-Relationships
-=============
-
- * Each process has many threads, but only one PASID.
- * Devices have a limited number (~10's to 1000's) of hardware workqueues.
-   The device driver manages allocating hardware workqueues.
- * A single mmap() maps a single hardware workqueue as a "portal" and
-   each portal maps down to a single workqueue.
- * For each device with which a process interacts, there must be
-   one or more mmap()'d portals.
- * Many threads within a process can share a single portal to access
-   a single device.
- * Multiple processes can separately mmap() the same portal, in
-   which case they still share one device hardware workqueue.
- * The single process-wide PASID is used by all threads to interact
-   with all devices.  There is not, for instance, a PASID for each
-   thread or each thread<->device pair.
-
-FAQ
-===
-
-* What is SVA/SVM?
-
-Shared Virtual Addressing (SVA) permits I/O hardware and the processor to
-work in the same address space, i.e., to share it. Some call it Shared
-Virtual Memory (SVM), but Linux community wanted to avoid confusing it with
-POSIX Shared Memory and Secure Virtual Machines which were terms already in
-circulation.
-
-* What is a PASID?
-
-A Process Address Space ID (PASID) is a PCIe-defined Transaction Layer Packet
-(TLP) prefix. A PASID is a 20-bit number allocated and managed by the OS.
-PASID is included in all transactions between the platform and the device.
-
-* How are shared workqueues different?
-
-Traditionally, in order for userspace applications to interact with hardware,
-there is a separate hardware instance required per process. For example,
-consider doorbells as a mechanism of informing hardware about work to process.
-Each doorbell is required to be spaced 4k (or page-size) apart for process
-isolation. This requires hardware to provision that space and reserve it in
-MMIO. This doesn't scale as the number of threads becomes quite large. The
-hardware also manages the queue depth for Shared Work Queues (SWQ), and
-consumers don't need to track queue depth. If there is no space to accept
-a command, the device will return an error indicating retry.
-
-A user should check Deferrable Memory Write (DMWr) capability on the device
-and only submits ENQCMD when the device supports it. In the new DMWr PCIe
-terminology, devices need to support DMWr completer capability. In addition,
-it requires all switch ports to support DMWr routing and must be enabled by
-the PCIe subsystem, much like how PCIe atomic operations are managed for
-instance.
-
-SWQ allows hardware to provision just a single address in the device. When
-used with ENQCMD to submit work, the device can distinguish the process
-submitting the work since it will include the PASID assigned to that
-process. This helps the device scale to a large number of processes.
-
-* Is this the same as a user space device driver?
-
-Communicating with the device via the shared workqueue is much simpler
-than a full blown user space driver. The kernel driver does all the
-initialization of the hardware. User space only needs to worry about
-submitting work and processing completions.
-
-* Is this the same as SR-IOV?
-
-Single Root I/O Virtualization (SR-IOV) focuses on providing independent
-hardware interfaces for virtualizing hardware. Hence, it's required to be
-almost fully functional interface to software supporting the traditional
-BARs, space for interrupts via MSI-X, its own register layout.
-Virtual Functions (VFs) are assisted by the Physical Function (PF)
-driver.
-
-Scalable I/O Virtualization builds on the PASID concept to create device
-instances for virtualization. SIOV requires host software to assist in
-creating virtual devices; each virtual device is represented by a PASID
-along with the bus/device/function of the device.  This allows device
-hardware to optimize device resource creation and can grow dynamically on
-demand. SR-IOV creation and management is very static in nature. Consult
-references below for more details.
-
-* Why not just create a virtual function for each app?
-
-Creating PCIe SR-IOV type Virtual Functions (VF) is expensive. VFs require
-duplicated hardware for PCI config space and interrupts such as MSI-X.
-Resources such as interrupts have to be hard partitioned between VFs at
-creation time, and cannot scale dynamically on demand. The VFs are not
-completely independent from the Physical Function (PF). Most VFs require
-some communication and assistance from the PF driver. SIOV, in contrast,
-creates a software-defined device where all the configuration and control
-aspects are mediated via the slow path. The work submission and completion
-happen without any mediation.
-
-* Does this support virtualization?
-
-ENQCMD can be used from within a guest VM. In these cases, the VMM helps
-with setting up a translation table to translate from Guest PASID to Host
-PASID. Please consult the ENQCMD instruction set reference for more
-details.
-
-* Does memory need to be pinned?
-
-When devices support SVA along with platform hardware such as IOMMU
-supporting such devices, there is no need to pin memory for DMA purposes.
-Devices that support SVA also support other PCIe features that remove the
-pinning requirement for memory.
-
-Device TLB support - Device requests the IOMMU to lookup an address before
-use via Address Translation Service (ATS) requests.  If the mapping exists
-but there is no page allocated by the OS, IOMMU hardware returns that no
-mapping exists.
-
-Device requests the virtual address to be mapped via Page Request
-Interface (PRI). Once the OS has successfully completed the mapping, it
-returns the response back to the device. The device requests again for
-a translation and continues.
-
-IOMMU works with the OS in managing consistency of page-tables with the
-device. When removing pages, it interacts with the device to remove any
-device TLB entry that might have been cached before removing the mappings from
-the OS.
-
-References
-==========
-
-VT-D:
-https://01.org/blogs/ashokraj/2018/recent-enhancements-intel-virtualization-technology-directed-i/o-intel-vt-d
-
-SIOV:
-https://01.org/blogs/2019/assignable-interfaces-intel-scalable-i/o-virtualization-linux
-
-ENQCMD in ISE:
-https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf
-
-DSA spec:
-https://software.intel.com/sites/default/files/341204-intel-data-streaming-accelerator-spec.pdf
diff --git a/Documentation/x86/tdx.rst b/Documentation/x86/tdx.rst
deleted file mode 100644 (file)
index dc8d9fd..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=====================================
-Intel Trust Domain Extensions (TDX)
-=====================================
-
-Intel's Trust Domain Extensions (TDX) protect confidential guest VMs from
-the host and physical attacks by isolating the guest register state and by
-encrypting the guest memory. In TDX, a special module running in a special
-mode sits between the host and the guest and manages the guest/host
-separation.
-
-Since the host cannot directly access guest registers or memory, much
-normal functionality of a hypervisor must be moved into the guest. This is
-implemented using a Virtualization Exception (#VE) that is handled by the
-guest kernel. A #VE is handled entirely inside the guest kernel, but some
-require the hypervisor to be consulted.
-
-TDX includes new hypercall-like mechanisms for communicating from the
-guest to the hypervisor or the TDX module.
-
-New TDX Exceptions
-==================
-
-TDX guests behave differently from bare-metal and traditional VMX guests.
-In TDX guests, otherwise normal instructions or memory accesses can cause
-#VE or #GP exceptions.
-
-Instructions marked with an '*' conditionally cause exceptions.  The
-details for these instructions are discussed below.
-
-Instruction-based #VE
----------------------
-
-- Port I/O (INS, OUTS, IN, OUT)
-- HLT
-- MONITOR, MWAIT
-- WBINVD, INVD
-- VMCALL
-- RDMSR*,WRMSR*
-- CPUID*
-
-Instruction-based #GP
----------------------
-
-- All VMX instructions: INVEPT, INVVPID, VMCLEAR, VMFUNC, VMLAUNCH,
-  VMPTRLD, VMPTRST, VMREAD, VMRESUME, VMWRITE, VMXOFF, VMXON
-- ENCLS, ENCLU
-- GETSEC
-- RSM
-- ENQCMD
-- RDMSR*,WRMSR*
-
-RDMSR/WRMSR Behavior
---------------------
-
-MSR access behavior falls into three categories:
-
-- #GP generated
-- #VE generated
-- "Just works"
-
-In general, the #GP MSRs should not be used in guests.  Their use likely
-indicates a bug in the guest.  The guest may try to handle the #GP with a
-hypercall but it is unlikely to succeed.
-
-The #VE MSRs are typically able to be handled by the hypervisor.  Guests
-can make a hypercall to the hypervisor to handle the #VE.
-
-The "just works" MSRs do not need any special guest handling.  They might
-be implemented by directly passing through the MSR to the hardware or by
-trapping and handling in the TDX module.  Other than possibly being slow,
-these MSRs appear to function just as they would on bare metal.
-
-CPUID Behavior
---------------
-
-For some CPUID leaves and sub-leaves, the virtualized bit fields of CPUID
-return values (in guest EAX/EBX/ECX/EDX) are configurable by the
-hypervisor. For such cases, the Intel TDX module architecture defines two
-virtualization types:
-
-- Bit fields for which the hypervisor controls the value seen by the guest
-  TD.
-
-- Bit fields for which the hypervisor configures the value such that the
-  guest TD either sees their native value or a value of 0.  For these bit
-  fields, the hypervisor can mask off the native values, but it can not
-  turn *on* values.
-
-A #VE is generated for CPUID leaves and sub-leaves that the TDX module does
-not know how to handle. The guest kernel may ask the hypervisor for the
-value with a hypercall.
-
-#VE on Memory Accesses
-======================
-
-There are essentially two classes of TDX memory: private and shared.
-Private memory receives full TDX protections.  Its content is protected
-against access from the hypervisor.  Shared memory is expected to be
-shared between guest and hypervisor and does not receive full TDX
-protections.
-
-A TD guest is in control of whether its memory accesses are treated as
-private or shared.  It selects the behavior with a bit in its page table
-entries.  This helps ensure that a guest does not place sensitive
-information in shared memory, exposing it to the untrusted hypervisor.
-
-#VE on Shared Memory
---------------------
-
-Access to shared mappings can cause a #VE.  The hypervisor ultimately
-controls whether a shared memory access causes a #VE, so the guest must be
-careful to only reference shared pages it can safely handle a #VE.  For
-instance, the guest should be careful not to access shared memory in the
-#VE handler before it reads the #VE info structure (TDG.VP.VEINFO.GET).
-
-Shared mapping content is entirely controlled by the hypervisor. The guest
-should only use shared mappings for communicating with the hypervisor.
-Shared mappings must never be used for sensitive memory content like kernel
-stacks.  A good rule of thumb is that hypervisor-shared memory should be
-treated the same as memory mapped to userspace.  Both the hypervisor and
-userspace are completely untrusted.
-
-MMIO for virtual devices is implemented as shared memory.  The guest must
-be careful not to access device MMIO regions unless it is also prepared to
-handle a #VE.
-
-#VE on Private Pages
---------------------
-
-An access to private mappings can also cause a #VE.  Since all kernel
-memory is also private memory, the kernel might theoretically need to
-handle a #VE on arbitrary kernel memory accesses.  This is not feasible, so
-TDX guests ensure that all guest memory has been "accepted" before memory
-is used by the kernel.
-
-A modest amount of memory (typically 512M) is pre-accepted by the firmware
-before the kernel runs to ensure that the kernel can start up without
-being subjected to a #VE.
-
-The hypervisor is permitted to unilaterally move accepted pages to a
-"blocked" state. However, if it does this, page access will not generate a
-#VE.  It will, instead, cause a "TD Exit" where the hypervisor is required
-to handle the exception.
-
-Linux #VE handler
-=================
-
-Just like page faults or #GP's, #VE exceptions can be either handled or be
-fatal.  Typically, an unhandled userspace #VE results in a SIGSEGV.
-An unhandled kernel #VE results in an oops.
-
-Handling nested exceptions on x86 is typically nasty business.  A #VE
-could be interrupted by an NMI which triggers another #VE and hilarity
-ensues.  The TDX #VE architecture anticipated this scenario and includes a
-feature to make it slightly less nasty.
-
-During #VE handling, the TDX module ensures that all interrupts (including
-NMIs) are blocked.  The block remains in place until the guest makes a
-TDG.VP.VEINFO.GET TDCALL.  This allows the guest to control when interrupts
-or a new #VE can be delivered.
-
-However, the guest kernel must still be careful to avoid potential
-#VE-triggering actions (discussed above) while this block is in place.
-While the block is in place, any #VE is elevated to a double fault (#DF)
-which is not recoverable.
-
-MMIO handling
-=============
-
-In non-TDX VMs, MMIO is usually implemented by giving a guest access to a
-mapping which will cause a VMEXIT on access, and then the hypervisor
-emulates the access.  That is not possible in TDX guests because VMEXIT
-will expose the register state to the host. TDX guests don't trust the host
-and can't have their state exposed to the host.
-
-In TDX, MMIO regions typically trigger a #VE exception in the guest.  The
-guest #VE handler then emulates the MMIO instruction inside the guest and
-converts it into a controlled TDCALL to the host, rather than exposing
-guest state to the host.
-
-MMIO addresses on x86 are just special physical addresses. They can
-theoretically be accessed with any instruction that accesses memory.
-However, the kernel instruction decoding method is limited. It is only
-designed to decode instructions like those generated by io.h macros.
-
-MMIO access via other means (like structure overlays) may result in an
-oops.
-
-Shared Memory Conversions
-=========================
-
-All TDX guest memory starts out as private at boot.  This memory can not
-be accessed by the hypervisor.  However, some kernel users like device
-drivers might have a need to share data with the hypervisor.  To do this,
-memory must be converted between shared and private.  This can be
-accomplished using some existing memory encryption helpers:
-
- * set_memory_decrypted() converts a range of pages to shared.
- * set_memory_encrypted() converts memory back to private.
-
-Device drivers are the primary user of shared memory, but there's no need
-to touch every driver. DMA buffers and ioremap() do the conversions
-automatically.
-
-TDX uses SWIOTLB for most DMA allocations. The SWIOTLB buffer is
-converted to shared on boot.
-
-For coherent DMA allocation, the DMA buffer gets converted on the
-allocation. Check force_dma_unencrypted() for details.
-
-Attestation
-===========
-
-Attestation is used to verify the TDX guest trustworthiness to other
-entities before provisioning secrets to the guest. For example, a key
-server may want to use attestation to verify that the guest is the
-desired one before releasing the encryption keys to mount the encrypted
-rootfs or a secondary drive.
-
-The TDX module records the state of the TDX guest in various stages of
-the guest boot process using the build time measurement register (MRTD)
-and runtime measurement registers (RTMR). Measurements related to the
-guest initial configuration and firmware image are recorded in the MRTD
-register. Measurements related to initial state, kernel image, firmware
-image, command line options, initrd, ACPI tables, etc are recorded in
-RTMR registers. For more details, as an example, please refer to TDX
-Virtual Firmware design specification, section titled "TD Measurement".
-At TDX guest runtime, the attestation process is used to attest to these
-measurements.
-
-The attestation process consists of two steps: TDREPORT generation and
-Quote generation.
-
-TDX guest uses TDCALL[TDG.MR.REPORT] to get the TDREPORT (TDREPORT_STRUCT)
-from the TDX module. TDREPORT is a fixed-size data structure generated by
-the TDX module which contains guest-specific information (such as build
-and boot measurements), platform security version, and the MAC to protect
-the integrity of the TDREPORT. A user-provided 64-Byte REPORTDATA is used
-as input and included in the TDREPORT. Typically it can be some nonce
-provided by attestation service so the TDREPORT can be verified uniquely.
-More details about the TDREPORT can be found in Intel TDX Module
-specification, section titled "TDG.MR.REPORT Leaf".
-
-After getting the TDREPORT, the second step of the attestation process
-is to send it to the Quoting Enclave (QE) to generate the Quote. TDREPORT
-by design can only be verified on the local platform as the MAC key is
-bound to the platform. To support remote verification of the TDREPORT,
-TDX leverages Intel SGX Quoting Enclave to verify the TDREPORT locally
-and convert it to a remotely verifiable Quote. Method of sending TDREPORT
-to QE is implementation specific. Attestation software can choose
-whatever communication channel available (i.e. vsock or TCP/IP) to
-send the TDREPORT to QE and receive the Quote.
-
-References
-==========
-
-TDX reference material is collected here:
-
-https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html
diff --git a/Documentation/x86/tlb.rst b/Documentation/x86/tlb.rst
deleted file mode 100644 (file)
index 82ec58a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=======
-The TLB
-=======
-
-When the kernel unmaps or modified the attributes of a range of
-memory, it has two choices:
-
- 1. Flush the entire TLB with a two-instruction sequence.  This is
-    a quick operation, but it causes collateral damage: TLB entries
-    from areas other than the one we are trying to flush will be
-    destroyed and must be refilled later, at some cost.
- 2. Use the invlpg instruction to invalidate a single page at a
-    time.  This could potentially cost many more instructions, but
-    it is a much more precise operation, causing no collateral
-    damage to other TLB entries.
-
-Which method to do depends on a few things:
-
- 1. The size of the flush being performed.  A flush of the entire
-    address space is obviously better performed by flushing the
-    entire TLB than doing 2^48/PAGE_SIZE individual flushes.
- 2. The contents of the TLB.  If the TLB is empty, then there will
-    be no collateral damage caused by doing the global flush, and
-    all of the individual flush will have ended up being wasted
-    work.
- 3. The size of the TLB.  The larger the TLB, the more collateral
-    damage we do with a full flush.  So, the larger the TLB, the
-    more attractive an individual flush looks.  Data and
-    instructions have separate TLBs, as do different page sizes.
- 4. The microarchitecture.  The TLB has become a multi-level
-    cache on modern CPUs, and the global flushes have become more
-    expensive relative to single-page flushes.
-
-There is obviously no way the kernel can know all these things,
-especially the contents of the TLB during a given flush.  The
-sizes of the flush will vary greatly depending on the workload as
-well.  There is essentially no "right" point to choose.
-
-You may be doing too many individual invalidations if you see the
-invlpg instruction (or instructions _near_ it) show up high in
-profiles.  If you believe that individual invalidations being
-called too often, you can lower the tunable::
-
-       /sys/kernel/debug/x86/tlb_single_page_flush_ceiling
-
-This will cause us to do the global flush for more cases.
-Lowering it to 0 will disable the use of the individual flushes.
-Setting it to 1 is a very conservative setting and it should
-never need to be 0 under normal circumstances.
-
-Despite the fact that a single individual flush on x86 is
-guaranteed to flush a full 2MB [1]_, hugetlbfs always uses the full
-flushes.  THP is treated exactly the same as normal memory.
-
-You might see invlpg inside of flush_tlb_mm_range() show up in
-profiles, or you can use the trace_tlb_flush() tracepoints. to
-determine how long the flush operations are taking.
-
-Essentially, you are balancing the cycles you spend doing invlpg
-with the cycles that you spend refilling the TLB later.
-
-You can measure how expensive TLB refills are by using
-performance counters and 'perf stat', like this::
-
-  perf stat -e
-    cpu/event=0x8,umask=0x84,name=dtlb_load_misses_walk_duration/,
-    cpu/event=0x8,umask=0x82,name=dtlb_load_misses_walk_completed/,
-    cpu/event=0x49,umask=0x4,name=dtlb_store_misses_walk_duration/,
-    cpu/event=0x49,umask=0x2,name=dtlb_store_misses_walk_completed/,
-    cpu/event=0x85,umask=0x4,name=itlb_misses_walk_duration/,
-    cpu/event=0x85,umask=0x2,name=itlb_misses_walk_completed/
-
-That works on an IvyBridge-era CPU (i5-3320M).  Different CPUs
-may have differently-named counters, but they should at least
-be there in some form.  You can use pmu-tools 'ocperf list'
-(https://github.com/andikleen/pmu-tools) to find the right
-counters for a given CPU.
-
-.. [1] A footnote in Intel's SDM "4.10.4.2 Recommended Invalidation"
-   says: "One execution of INVLPG is sufficient even for a page
-   with size greater than 4 KBytes."
diff --git a/Documentation/x86/topology.rst b/Documentation/x86/topology.rst
deleted file mode 100644 (file)
index 7f58010..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============
-x86 Topology
-============
-
-This documents and clarifies the main aspects of x86 topology modelling and
-representation in the kernel. Update/change when doing changes to the
-respective code.
-
-The architecture-agnostic topology definitions are in
-Documentation/admin-guide/cputopology.rst. This file holds x86-specific
-differences/specialities which must not necessarily apply to the generic
-definitions. Thus, the way to read up on Linux topology on x86 is to start
-with the generic one and look at this one in parallel for the x86 specifics.
-
-Needless to say, code should use the generic functions - this file is *only*
-here to *document* the inner workings of x86 topology.
-
-Started by Thomas Gleixner <tglx@linutronix.de> and Borislav Petkov <bp@alien8.de>.
-
-The main aim of the topology facilities is to present adequate interfaces to
-code which needs to know/query/use the structure of the running system wrt
-threads, cores, packages, etc.
-
-The kernel does not care about the concept of physical sockets because a
-socket has no relevance to software. It's an electromechanical component. In
-the past a socket always contained a single package (see below), but with the
-advent of Multi Chip Modules (MCM) a socket can hold more than one package. So
-there might be still references to sockets in the code, but they are of
-historical nature and should be cleaned up.
-
-The topology of a system is described in the units of:
-
-    - packages
-    - cores
-    - threads
-
-Package
-=======
-Packages contain a number of cores plus shared resources, e.g. DRAM
-controller, shared caches etc.
-
-Modern systems may also use the term 'Die' for package.
-
-AMD nomenclature for package is 'Node'.
-
-Package-related topology information in the kernel:
-
-  - cpuinfo_x86.x86_max_cores:
-
-    The number of cores in a package. This information is retrieved via CPUID.
-
-  - cpuinfo_x86.x86_max_dies:
-
-    The number of dies in a package. This information is retrieved via CPUID.
-
-  - cpuinfo_x86.cpu_die_id:
-
-    The physical ID of the die. This information is retrieved via CPUID.
-
-  - cpuinfo_x86.phys_proc_id:
-
-    The physical ID of the package. This information is retrieved via CPUID
-    and deduced from the APIC IDs of the cores in the package.
-
-    Modern systems use this value for the socket. There may be multiple
-    packages within a socket. This value may differ from cpu_die_id.
-
-  - cpuinfo_x86.logical_proc_id:
-
-    The logical ID of the package. As we do not trust BIOSes to enumerate the
-    packages in a consistent way, we introduced the concept of logical package
-    ID so we can sanely calculate the number of maximum possible packages in
-    the system and have the packages enumerated linearly.
-
-  - topology_max_packages():
-
-    The maximum possible number of packages in the system. Helpful for per
-    package facilities to preallocate per package information.
-
-  - cpu_llc_id:
-
-    A per-CPU variable containing:
-
-      - On Intel, the first APIC ID of the list of CPUs sharing the Last Level
-        Cache
-
-      - On AMD, the Node ID or Core Complex ID containing the Last Level
-        Cache. In general, it is a number identifying an LLC uniquely on the
-        system.
-
-Cores
-=====
-A core consists of 1 or more threads. It does not matter whether the threads
-are SMT- or CMT-type threads.
-
-AMDs nomenclature for a CMT core is "Compute Unit". The kernel always uses
-"core".
-
-Core-related topology information in the kernel:
-
-  - smp_num_siblings:
-
-    The number of threads in a core. The number of threads in a package can be
-    calculated by::
-
-       threads_per_package = cpuinfo_x86.x86_max_cores * smp_num_siblings
-
-
-Threads
-=======
-A thread is a single scheduling unit. It's the equivalent to a logical Linux
-CPU.
-
-AMDs nomenclature for CMT threads is "Compute Unit Core". The kernel always
-uses "thread".
-
-Thread-related topology information in the kernel:
-
-  - topology_core_cpumask():
-
-    The cpumask contains all online threads in the package to which a thread
-    belongs.
-
-    The number of online threads is also printed in /proc/cpuinfo "siblings."
-
-  - topology_sibling_cpumask():
-
-    The cpumask contains all online threads in the core to which a thread
-    belongs.
-
-  - topology_logical_package_id():
-
-    The logical package ID to which a thread belongs.
-
-  - topology_physical_package_id():
-
-    The physical package ID to which a thread belongs.
-
-  - topology_core_id();
-
-    The ID of the core to which a thread belongs. It is also printed in /proc/cpuinfo
-    "core_id."
-
-
-
-System topology examples
-========================
-
-.. note::
-  The alternative Linux CPU enumeration depends on how the BIOS enumerates the
-  threads. Many BIOSes enumerate all threads 0 first and then all threads 1.
-  That has the "advantage" that the logical Linux CPU numbers of threads 0 stay
-  the same whether threads are enabled or not. That's merely an implementation
-  detail and has no practical impact.
-
-1) Single Package, Single Core::
-
-   [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-
-2) Single Package, Dual Core
-
-   a) One thread per core::
-
-       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-                   -> [core 1] -> [thread 0] -> Linux CPU 1
-
-   b) Two threads per core::
-
-       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-                               -> [thread 1] -> Linux CPU 1
-                   -> [core 1] -> [thread 0] -> Linux CPU 2
-                               -> [thread 1] -> Linux CPU 3
-
-      Alternative enumeration::
-
-       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-                               -> [thread 1] -> Linux CPU 2
-                   -> [core 1] -> [thread 0] -> Linux CPU 1
-                               -> [thread 1] -> Linux CPU 3
-
-      AMD nomenclature for CMT systems::
-
-       [node 0] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 0
-                                    -> [Compute Unit Core 1] -> Linux CPU 1
-                -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 2
-                                    -> [Compute Unit Core 1] -> Linux CPU 3
-
-4) Dual Package, Dual Core
-
-   a) One thread per core::
-
-       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-                   -> [core 1] -> [thread 0] -> Linux CPU 1
-
-       [package 1] -> [core 0] -> [thread 0] -> Linux CPU 2
-                   -> [core 1] -> [thread 0] -> Linux CPU 3
-
-   b) Two threads per core::
-
-       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-                               -> [thread 1] -> Linux CPU 1
-                   -> [core 1] -> [thread 0] -> Linux CPU 2
-                               -> [thread 1] -> Linux CPU 3
-
-       [package 1] -> [core 0] -> [thread 0] -> Linux CPU 4
-                               -> [thread 1] -> Linux CPU 5
-                   -> [core 1] -> [thread 0] -> Linux CPU 6
-                               -> [thread 1] -> Linux CPU 7
-
-      Alternative enumeration::
-
-       [package 0] -> [core 0] -> [thread 0] -> Linux CPU 0
-                               -> [thread 1] -> Linux CPU 4
-                   -> [core 1] -> [thread 0] -> Linux CPU 1
-                               -> [thread 1] -> Linux CPU 5
-
-       [package 1] -> [core 0] -> [thread 0] -> Linux CPU 2
-                               -> [thread 1] -> Linux CPU 6
-                   -> [core 1] -> [thread 0] -> Linux CPU 3
-                               -> [thread 1] -> Linux CPU 7
-
-      AMD nomenclature for CMT systems::
-
-       [node 0] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 0
-                                    -> [Compute Unit Core 1] -> Linux CPU 1
-                -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 2
-                                    -> [Compute Unit Core 1] -> Linux CPU 3
-
-       [node 1] -> [Compute Unit 0] -> [Compute Unit Core 0] -> Linux CPU 4
-                                    -> [Compute Unit Core 1] -> Linux CPU 5
-                -> [Compute Unit 1] -> [Compute Unit Core 0] -> Linux CPU 6
-                                    -> [Compute Unit Core 1] -> Linux CPU 7
diff --git a/Documentation/x86/tsx_async_abort.rst b/Documentation/x86/tsx_async_abort.rst
deleted file mode 100644 (file)
index 583ddc1..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-TSX Async Abort (TAA) mitigation
-================================
-
-.. _tsx_async_abort:
-
-Overview
---------
-
-TSX Async Abort (TAA) is a side channel attack on internal buffers in some
-Intel processors similar to Microachitectural Data Sampling (MDS).  In this
-case certain loads may speculatively pass invalid data to dependent operations
-when an asynchronous abort condition is pending in a Transactional
-Synchronization Extensions (TSX) transaction.  This includes loads with no
-fault or assist condition. Such loads may speculatively expose stale data from
-the same uarch data structures as in MDS, with same scope of exposure i.e.
-same-thread and cross-thread. This issue affects all current processors that
-support TSX.
-
-Mitigation strategy
--------------------
-
-a) TSX disable - one of the mitigations is to disable TSX. A new MSR
-IA32_TSX_CTRL will be available in future and current processors after
-microcode update which can be used to disable TSX. In addition, it
-controls the enumeration of the TSX feature bits (RTM and HLE) in CPUID.
-
-b) Clear CPU buffers - similar to MDS, clearing the CPU buffers mitigates this
-vulnerability. More details on this approach can be found in
-:ref:`Documentation/admin-guide/hw-vuln/mds.rst <mds>`.
-
-Kernel internal mitigation modes
---------------------------------
-
- =============    ============================================================
- off              Mitigation is disabled. Either the CPU is not affected or
-                  tsx_async_abort=off is supplied on the kernel command line.
-
- tsx disabled     Mitigation is enabled. TSX feature is disabled by default at
-                  bootup on processors that support TSX control.
-
- verw             Mitigation is enabled. CPU is affected and MD_CLEAR is
-                  advertised in CPUID.
-
- ucode needed     Mitigation is enabled. CPU is affected and MD_CLEAR is not
-                  advertised in CPUID. That is mainly for virtualization
-                  scenarios where the host has the updated microcode but the
-                  hypervisor does not expose MD_CLEAR in CPUID. It's a best
-                  effort approach without guarantee.
- =============    ============================================================
-
-If the CPU is affected and the "tsx_async_abort" kernel command line parameter is
-not provided then the kernel selects an appropriate mitigation depending on the
-status of RTM and MD_CLEAR CPUID bits.
-
-Below tables indicate the impact of tsx=on|off|auto cmdline options on state of
-TAA mitigation, VERW behavior and TSX feature for various combinations of
-MSR_IA32_ARCH_CAPABILITIES bits.
-
-1. "tsx=off"
-
-=========  =========  ============  ============  ==============  ===================  ======================
-MSR_IA32_ARCH_CAPABILITIES bits     Result with cmdline tsx=off
-----------------------------------  -------------------------------------------------------------------------
-TAA_NO     MDS_NO     TSX_CTRL_MSR  TSX state     VERW can clear  TAA mitigation       TAA mitigation
-                                    after bootup  CPU buffers     tsx_async_abort=off  tsx_async_abort=full
-=========  =========  ============  ============  ==============  ===================  ======================
-    0          0           0         HW default         Yes           Same as MDS           Same as MDS
-    0          0           1        Invalid case   Invalid case       Invalid case          Invalid case
-    0          1           0         HW default         No         Need ucode update     Need ucode update
-    0          1           1          Disabled          Yes           TSX disabled          TSX disabled
-    1          X           1          Disabled           X             None needed           None needed
-=========  =========  ============  ============  ==============  ===================  ======================
-
-2. "tsx=on"
-
-=========  =========  ============  ============  ==============  ===================  ======================
-MSR_IA32_ARCH_CAPABILITIES bits     Result with cmdline tsx=on
-----------------------------------  -------------------------------------------------------------------------
-TAA_NO     MDS_NO     TSX_CTRL_MSR  TSX state     VERW can clear  TAA mitigation       TAA mitigation
-                                    after bootup  CPU buffers     tsx_async_abort=off  tsx_async_abort=full
-=========  =========  ============  ============  ==============  ===================  ======================
-    0          0           0         HW default        Yes            Same as MDS          Same as MDS
-    0          0           1        Invalid case   Invalid case       Invalid case         Invalid case
-    0          1           0         HW default        No          Need ucode update     Need ucode update
-    0          1           1          Enabled          Yes               None              Same as MDS
-    1          X           1          Enabled          X              None needed          None needed
-=========  =========  ============  ============  ==============  ===================  ======================
-
-3. "tsx=auto"
-
-=========  =========  ============  ============  ==============  ===================  ======================
-MSR_IA32_ARCH_CAPABILITIES bits     Result with cmdline tsx=auto
-----------------------------------  -------------------------------------------------------------------------
-TAA_NO     MDS_NO     TSX_CTRL_MSR  TSX state     VERW can clear  TAA mitigation       TAA mitigation
-                                    after bootup  CPU buffers     tsx_async_abort=off  tsx_async_abort=full
-=========  =========  ============  ============  ==============  ===================  ======================
-    0          0           0         HW default    Yes                Same as MDS           Same as MDS
-    0          0           1        Invalid case  Invalid case        Invalid case          Invalid case
-    0          1           0         HW default    No              Need ucode update     Need ucode update
-    0          1           1          Disabled      Yes               TSX disabled          TSX disabled
-    1          X           1          Enabled       X                 None needed           None needed
-=========  =========  ============  ============  ==============  ===================  ======================
-
-In the tables, TSX_CTRL_MSR is a new bit in MSR_IA32_ARCH_CAPABILITIES that
-indicates whether MSR_IA32_TSX_CTRL is supported.
-
-There are two control bits in IA32_TSX_CTRL MSR:
-
-      Bit 0: When set it disables the Restricted Transactional Memory (RTM)
-             sub-feature of TSX (will force all transactions to abort on the
-             XBEGIN instruction).
-
-      Bit 1: When set it disables the enumeration of the RTM and HLE feature
-             (i.e. it will make CPUID(EAX=7).EBX{bit4} and
-             CPUID(EAX=7).EBX{bit11} read as 0).
diff --git a/Documentation/x86/usb-legacy-support.rst b/Documentation/x86/usb-legacy-support.rst
deleted file mode 100644 (file)
index e01c08b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-
-.. SPDX-License-Identifier: GPL-2.0
-
-==================
-USB Legacy support
-==================
-
-:Author: Vojtech Pavlik <vojtech@suse.cz>, January 2004
-
-
-Also known as "USB Keyboard" or "USB Mouse support" in the BIOS Setup is a
-feature that allows one to use the USB mouse and keyboard as if they were
-their classic PS/2 counterparts.  This means one can use an USB keyboard to
-type in LILO for example.
-
-It has several drawbacks, though:
-
-1) On some machines, the emulated PS/2 mouse takes over even when no USB
-   mouse is present and a real PS/2 mouse is present.  In that case the extra
-   features (wheel, extra buttons, touchpad mode) of the real PS/2 mouse may
-   not be available.
-
-2) If CONFIG_HIGHMEM64G is enabled, the PS/2 mouse emulation can cause
-   system crashes, because the SMM BIOS is not expecting to be in PAE mode.
-   The Intel E7505 is a typical machine where this happens.
-
-3) If AMD64 64-bit mode is enabled, again system crashes often happen,
-   because the SMM BIOS isn't expecting the CPU to be in 64-bit mode.  The
-   BIOS manufacturers only test with Windows, and Windows doesn't do 64-bit
-   yet.
-
-Solutions:
-
-Problem 1)
-  can be solved by loading the USB drivers prior to loading the
-  PS/2 mouse driver. Since the PS/2 mouse driver is in 2.6 compiled into
-  the kernel unconditionally, this means the USB drivers need to be
-  compiled-in, too.
-
-Problem 2)
-  can currently only be solved by either disabling HIGHMEM64G
-  in the kernel config or USB Legacy support in the BIOS. A BIOS update
-  could help, but so far no such update exists.
-
-Problem 3)
-  is usually fixed by a BIOS update. Check the board
-  manufacturers web site. If an update is not available, disable USB
-  Legacy support in the BIOS. If this alone doesn't help, try also adding
-  idle=poll on the kernel command line. The BIOS may be entering the SMM
-  on the HLT instruction as well.
diff --git a/Documentation/x86/x86_64/5level-paging.rst b/Documentation/x86/x86_64/5level-paging.rst
deleted file mode 100644 (file)
index b792bbd..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==============
-5-level paging
-==============
-
-Overview
-========
-Original x86-64 was limited by 4-level paging to 256 TiB of virtual address
-space and 64 TiB of physical address space. We are already bumping into
-this limit: some vendors offer servers with 64 TiB of memory today.
-
-To overcome the limitation upcoming hardware will introduce support for
-5-level paging. It is a straight-forward extension of the current page
-table structure adding one more layer of translation.
-
-It bumps the limits to 128 PiB of virtual address space and 4 PiB of
-physical address space. This "ought to be enough for anybody" ©.
-
-QEMU 2.9 and later support 5-level paging.
-
-Virtual memory layout for 5-level paging is described in
-Documentation/x86/x86_64/mm.rst
-
-
-Enabling 5-level paging
-=======================
-CONFIG_X86_5LEVEL=y enables the feature.
-
-Kernel with CONFIG_X86_5LEVEL=y still able to boot on 4-level hardware.
-In this case additional page table level -- p4d -- will be folded at
-runtime.
-
-User-space and large virtual address space
-==========================================
-On x86, 5-level paging enables 56-bit userspace virtual address space.
-Not all user space is ready to handle wide addresses. It's known that
-at least some JIT compilers use higher bits in pointers to encode their
-information. It collides with valid pointers with 5-level paging and
-leads to crashes.
-
-To mitigate this, we are not going to allocate virtual address space
-above 47-bit by default.
-
-But userspace can ask for allocation from full address space by
-specifying hint address (with or without MAP_FIXED) above 47-bits.
-
-If hint address set above 47-bit, but MAP_FIXED is not specified, we try
-to look for unmapped area by specified address. If it's already
-occupied, we look for unmapped area in *full* address space, rather than
-from 47-bit window.
-
-A high hint address would only affect the allocation in question, but not
-any future mmap()s.
-
-Specifying high hint address on older kernel or on machine without 5-level
-paging support is safe. The hint will be ignored and kernel will fall back
-to allocation from 47-bit address space.
-
-This approach helps to easily make application's memory allocator aware
-about large address space without manually tracking allocated virtual
-address space.
-
-One important case we need to handle here is interaction with MPX.
-MPX (without MAWA extension) cannot handle addresses above 47-bit, so we
-need to make sure that MPX cannot be enabled we already have VMA above
-the boundary and forbid creating such VMAs once MPX is enabled.
diff --git a/Documentation/x86/x86_64/boot-options.rst b/Documentation/x86/x86_64/boot-options.rst
deleted file mode 100644 (file)
index cbd1412..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===========================
-AMD64 Specific Boot Options
-===========================
-
-There are many others (usually documented in driver documentation), but
-only the AMD64 specific ones are listed here.
-
-Machine check
-=============
-Please see Documentation/x86/x86_64/machinecheck.rst for sysfs runtime tunables.
-
-   mce=off
-               Disable machine check
-   mce=no_cmci
-               Disable CMCI(Corrected Machine Check Interrupt) that
-               Intel processor supports.  Usually this disablement is
-               not recommended, but it might be handy if your hardware
-               is misbehaving.
-               Note that you'll get more problems without CMCI than with
-               due to the shared banks, i.e. you might get duplicated
-               error logs.
-   mce=dont_log_ce
-               Don't make logs for corrected errors.  All events reported
-               as corrected are silently cleared by OS.
-               This option will be useful if you have no interest in any
-               of corrected errors.
-   mce=ignore_ce
-               Disable features for corrected errors, e.g. polling timer
-               and CMCI.  All events reported as corrected are not cleared
-               by OS and remained in its error banks.
-               Usually this disablement is not recommended, however if
-               there is an agent checking/clearing corrected errors
-               (e.g. BIOS or hardware monitoring applications), conflicting
-               with OS's error handling, and you cannot deactivate the agent,
-               then this option will be a help.
-   mce=no_lmce
-               Do not opt-in to Local MCE delivery. Use legacy method
-               to broadcast MCEs.
-   mce=bootlog
-               Enable logging of machine checks left over from booting.
-               Disabled by default on AMD Fam10h and older because some BIOS
-               leave bogus ones.
-               If your BIOS doesn't do that it's a good idea to enable though
-               to make sure you log even machine check events that result
-               in a reboot. On Intel systems it is enabled by default.
-   mce=nobootlog
-               Disable boot machine check logging.
-   mce=monarchtimeout (number)
-               monarchtimeout:
-               Sets the time in us to wait for other CPUs on machine checks. 0
-               to disable.
-   mce=bios_cmci_threshold
-               Don't overwrite the bios-set CMCI threshold. This boot option
-               prevents Linux from overwriting the CMCI threshold set by the
-               bios. Without this option, Linux always sets the CMCI
-               threshold to 1. Enabling this may make memory predictive failure
-               analysis less effective if the bios sets thresholds for memory
-               errors since we will not see details for all errors.
-   mce=recovery
-               Force-enable recoverable machine check code paths
-
-   nomce (for compatibility with i386)
-               same as mce=off
-
-   Everything else is in sysfs now.
-
-APICs
-=====
-
-   apic
-       Use IO-APIC. Default
-
-   noapic
-       Don't use the IO-APIC.
-
-   disableapic
-       Don't use the local APIC
-
-   nolapic
-     Don't use the local APIC (alias for i386 compatibility)
-
-   pirq=...
-       See Documentation/x86/i386/IO-APIC.rst
-
-   noapictimer
-       Don't set up the APIC timer
-
-   no_timer_check
-       Don't check the IO-APIC timer. This can work around
-       problems with incorrect timer initialization on some boards.
-
-   apicpmtimer
-       Do APIC timer calibration using the pmtimer. Implies
-       apicmaintimer. Useful when your PIT timer is totally broken.
-
-Timing
-======
-
-  notsc
-    Deprecated, use tsc=unstable instead.
-
-  nohpet
-    Don't use the HPET timer.
-
-Idle loop
-=========
-
-  idle=poll
-    Don't do power saving in the idle loop using HLT, but poll for rescheduling
-    event. This will make the CPUs eat a lot more power, but may be useful
-    to get slightly better performance in multiprocessor benchmarks. It also
-    makes some profiling using performance counters more accurate.
-    Please note that on systems with MONITOR/MWAIT support (like Intel EM64T
-    CPUs) this option has no performance advantage over the normal idle loop.
-    It may also interact badly with hyperthreading.
-
-Rebooting
-=========
-
-   reboot=b[ios] | t[riple] | k[bd] | a[cpi] | e[fi] | p[ci] [, [w]arm | [c]old]
-      bios
-        Use the CPU reboot vector for warm reset
-      warm
-        Don't set the cold reboot flag
-      cold
-        Set the cold reboot flag
-      triple
-        Force a triple fault (init)
-      kbd
-        Use the keyboard controller. cold reset (default)
-      acpi
-        Use the ACPI RESET_REG in the FADT. If ACPI is not configured or
-        the ACPI reset does not work, the reboot path attempts the reset
-        using the keyboard controller.
-      efi
-        Use efi reset_system runtime service. If EFI is not configured or
-        the EFI reset does not work, the reboot path attempts the reset using
-        the keyboard controller.
-      pci
-        Use a write to the PCI config space register 0xcf9 to trigger reboot.
-
-   Using warm reset will be much faster especially on big memory
-   systems because the BIOS will not go through the memory check.
-   Disadvantage is that not all hardware will be completely reinitialized
-   on reboot so there may be boot problems on some systems.
-
-   reboot=force
-     Don't stop other CPUs on reboot. This can make reboot more reliable
-     in some cases.
-
-   reboot=default
-     There are some built-in platform specific "quirks" - you may see:
-     "reboot: <name> series board detected. Selecting <type> for reboots."
-     In the case where you think the quirk is in error (e.g. you have
-     newer BIOS, or newer board) using this option will ignore the built-in
-     quirk table, and use the generic default reboot actions.
-
-NUMA
-====
-
-  numa=off
-    Only set up a single NUMA node spanning all memory.
-
-  numa=noacpi
-    Don't parse the SRAT table for NUMA setup
-
-  numa=nohmat
-    Don't parse the HMAT table for NUMA setup, or soft-reserved memory
-    partitioning.
-
-  numa=fake=<size>[MG]
-    If given as a memory unit, fills all system RAM with nodes of
-    size interleaved over physical nodes.
-
-  numa=fake=<N>
-    If given as an integer, fills all system RAM with N fake nodes
-    interleaved over physical nodes.
-
-  numa=fake=<N>U
-    If given as an integer followed by 'U', it will divide each
-    physical node into N emulated nodes.
-
-ACPI
-====
-
-  acpi=off
-    Don't enable ACPI
-  acpi=ht
-    Use ACPI boot table parsing, but don't enable ACPI interpreter
-  acpi=force
-    Force ACPI on (currently not needed)
-  acpi=strict
-    Disable out of spec ACPI workarounds.
-  acpi_sci={edge,level,high,low}
-    Set up ACPI SCI interrupt.
-  acpi=noirq
-    Don't route interrupts
-  acpi=nocmcff
-    Disable firmware first mode for corrected errors. This
-    disables parsing the HEST CMC error source to check if
-    firmware has set the FF flag. This may result in
-    duplicate corrected error reports.
-
-PCI
-===
-
-  pci=off
-    Don't use PCI
-  pci=conf1
-    Use conf1 access.
-  pci=conf2
-    Use conf2 access.
-  pci=rom
-    Assign ROMs.
-  pci=assign-busses
-    Assign busses
-  pci=irqmask=MASK
-    Set PCI interrupt mask to MASK
-  pci=lastbus=NUMBER
-    Scan up to NUMBER busses, no matter what the mptable says.
-  pci=noacpi
-    Don't use ACPI to set up PCI interrupt routing.
-
-IOMMU (input/output memory management unit)
-===========================================
-Multiple x86-64 PCI-DMA mapping implementations exist, for example:
-
-   1. <kernel/dma/direct.c>: use no hardware/software IOMMU at all
-      (e.g. because you have < 3 GB memory).
-      Kernel boot message: "PCI-DMA: Disabling IOMMU"
-
-   2. <arch/x86/kernel/amd_gart_64.c>: AMD GART based hardware IOMMU.
-      Kernel boot message: "PCI-DMA: using GART IOMMU"
-
-   3. <arch/x86_64/kernel/pci-swiotlb.c> : Software IOMMU implementation. Used
-      e.g. if there is no hardware IOMMU in the system and it is need because
-      you have >3GB memory or told the kernel to us it (iommu=soft))
-      Kernel boot message: "PCI-DMA: Using software bounce buffering
-      for IO (SWIOTLB)"
-
-::
-
-  iommu=[<size>][,noagp][,off][,force][,noforce]
-  [,memaper[=<order>]][,merge][,fullflush][,nomerge]
-  [,noaperture]
-
-General iommu options:
-
-    off
-      Don't initialize and use any kind of IOMMU.
-    noforce
-      Don't force hardware IOMMU usage when it is not needed. (default).
-    force
-      Force the use of the hardware IOMMU even when it is
-      not actually needed (e.g. because < 3 GB memory).
-    soft
-      Use software bounce buffering (SWIOTLB) (default for
-      Intel machines). This can be used to prevent the usage
-      of an available hardware IOMMU.
-
-iommu options only relevant to the AMD GART hardware IOMMU:
-
-    <size>
-      Set the size of the remapping area in bytes.
-    allowed
-      Overwrite iommu off workarounds for specific chipsets.
-    fullflush
-      Flush IOMMU on each allocation (default).
-    nofullflush
-      Don't use IOMMU fullflush.
-    memaper[=<order>]
-      Allocate an own aperture over RAM with size 32MB<<order.
-      (default: order=1, i.e. 64MB)
-    merge
-      Do scatter-gather (SG) merging. Implies "force" (experimental).
-    nomerge
-      Don't do scatter-gather (SG) merging.
-    noaperture
-      Ask the IOMMU not to touch the aperture for AGP.
-    noagp
-      Don't initialize the AGP driver and use full aperture.
-    panic
-      Always panic when IOMMU overflows.
-
-iommu options only relevant to the software bounce buffering (SWIOTLB) IOMMU
-implementation:
-
-    swiotlb=<slots>[,force,noforce]
-      <slots>
-        Prereserve that many 2K slots for the software IO bounce buffering.
-      force
-        Force all IO through the software TLB.
-      noforce
-        Do not initialize the software TLB.
-
-
-Miscellaneous
-=============
-
-  nogbpages
-    Do not use GB pages for kernel direct mappings.
-  gbpages
-    Use GB pages for kernel direct mappings.
-
-
-AMD SEV (Secure Encrypted Virtualization)
-=========================================
-Options relating to AMD SEV, specified via the following format:
-
-::
-
-   sev=option1[,option2]
-
-The available options are:
-
-   debug
-     Enable debug messages.
diff --git a/Documentation/x86/x86_64/cpu-hotplug-spec.rst b/Documentation/x86/x86_64/cpu-hotplug-spec.rst
deleted file mode 100644 (file)
index 8d1c91f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===================================================
-Firmware support for CPU hotplug under Linux/x86-64
-===================================================
-
-Linux/x86-64 supports CPU hotplug now. For various reasons Linux wants to
-know in advance of boot time the maximum number of CPUs that could be plugged
-into the system. ACPI 3.0 currently has no official way to supply
-this information from the firmware to the operating system.
-
-In ACPI each CPU needs an LAPIC object in the MADT table (5.2.11.5 in the
-ACPI 3.0 specification).  ACPI already has the concept of disabled LAPIC
-objects by setting the Enabled bit in the LAPIC object to zero.
-
-For CPU hotplug Linux/x86-64 expects now that any possible future hotpluggable
-CPU is already available in the MADT. If the CPU is not available yet
-it should have its LAPIC Enabled bit set to 0. Linux will use the number
-of disabled LAPICs to compute the maximum number of future CPUs.
-
-In the worst case the user can overwrite this choice using a command line
-option (additional_cpus=...), but it is recommended to supply the correct
-number (or a reasonable approximation of it, with erring towards more not less)
-in the MADT to avoid manual configuration.
diff --git a/Documentation/x86/x86_64/fake-numa-for-cpusets.rst b/Documentation/x86/x86_64/fake-numa-for-cpusets.rst
deleted file mode 100644 (file)
index ff9bcfd..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=====================
-Fake NUMA For CPUSets
-=====================
-
-:Author: David Rientjes <rientjes@cs.washington.edu>
-
-Using numa=fake and CPUSets for Resource Management
-
-This document describes how the numa=fake x86_64 command-line option can be used
-in conjunction with cpusets for coarse memory management.  Using this feature,
-you can create fake NUMA nodes that represent contiguous chunks of memory and
-assign them to cpusets and their attached tasks.  This is a way of limiting the
-amount of system memory that are available to a certain class of tasks.
-
-For more information on the features of cpusets, see
-Documentation/admin-guide/cgroup-v1/cpusets.rst.
-There are a number of different configurations you can use for your needs.  For
-more information on the numa=fake command line option and its various ways of
-configuring fake nodes, see Documentation/x86/x86_64/boot-options.rst.
-
-For the purposes of this introduction, we'll assume a very primitive NUMA
-emulation setup of "numa=fake=4*512,".  This will split our system memory into
-four equal chunks of 512M each that we can now use to assign to cpusets.  As
-you become more familiar with using this combination for resource control,
-you'll determine a better setup to minimize the number of nodes you have to deal
-with.
-
-A machine may be split as follows with "numa=fake=4*512," as reported by dmesg::
-
-       Faking node 0 at 0000000000000000-0000000020000000 (512MB)
-       Faking node 1 at 0000000020000000-0000000040000000 (512MB)
-       Faking node 2 at 0000000040000000-0000000060000000 (512MB)
-       Faking node 3 at 0000000060000000-0000000080000000 (512MB)
-       ...
-       On node 0 totalpages: 130975
-       On node 1 totalpages: 131072
-       On node 2 totalpages: 131072
-       On node 3 totalpages: 131072
-
-Now following the instructions for mounting the cpusets filesystem from
-Documentation/admin-guide/cgroup-v1/cpusets.rst, you can assign fake nodes (i.e. contiguous memory
-address spaces) to individual cpusets::
-
-       [root@xroads /]# mkdir exampleset
-       [root@xroads /]# mount -t cpuset none exampleset
-       [root@xroads /]# mkdir exampleset/ddset
-       [root@xroads /]# cd exampleset/ddset
-       [root@xroads /exampleset/ddset]# echo 0-1 > cpus
-       [root@xroads /exampleset/ddset]# echo 0-1 > mems
-
-Now this cpuset, 'ddset', will only allowed access to fake nodes 0 and 1 for
-memory allocations (1G).
-
-You can now assign tasks to these cpusets to limit the memory resources
-available to them according to the fake nodes assigned as mems::
-
-       [root@xroads /exampleset/ddset]# echo $$ > tasks
-       [root@xroads /exampleset/ddset]# dd if=/dev/zero of=tmp bs=1024 count=1G
-       [1] 13425
-
-Notice the difference between the system memory usage as reported by
-/proc/meminfo between the restricted cpuset case above and the unrestricted
-case (i.e. running the same 'dd' command without assigning it to a fake NUMA
-cpuset):
-
-       ========        ============    ==========
-       Name            Unrestricted    Restricted
-       ========        ============    ==========
-       MemTotal        3091900 kB      3091900 kB
-       MemFree         42113 kB        1513236 kB
-       ========        ============    ==========
-
-This allows for coarse memory management for the tasks you assign to particular
-cpusets.  Since cpusets can form a hierarchy, you can create some pretty
-interesting combinations of use-cases for various classes of tasks for your
-memory management needs.
diff --git a/Documentation/x86/x86_64/fsgs.rst b/Documentation/x86/x86_64/fsgs.rst
deleted file mode 100644 (file)
index 50960e0..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-Using FS and GS segments in user space applications
-===================================================
-
-The x86 architecture supports segmentation. Instructions which access
-memory can use segment register based addressing mode. The following
-notation is used to address a byte within a segment:
-
-  Segment-register:Byte-address
-
-The segment base address is added to the Byte-address to compute the
-resulting virtual address which is accessed. This allows to access multiple
-instances of data with the identical Byte-address, i.e. the same code. The
-selection of a particular instance is purely based on the base-address in
-the segment register.
-
-In 32-bit mode the CPU provides 6 segments, which also support segment
-limits. The limits can be used to enforce address space protections.
-
-In 64-bit mode the CS/SS/DS/ES segments are ignored and the base address is
-always 0 to provide a full 64bit address space. The FS and GS segments are
-still functional in 64-bit mode.
-
-Common FS and GS usage
-------------------------------
-
-The FS segment is commonly used to address Thread Local Storage (TLS). FS
-is usually managed by runtime code or a threading library. Variables
-declared with the '__thread' storage class specifier are instantiated per
-thread and the compiler emits the FS: address prefix for accesses to these
-variables. Each thread has its own FS base address so common code can be
-used without complex address offset calculations to access the per thread
-instances. Applications should not use FS for other purposes when they use
-runtimes or threading libraries which manage the per thread FS.
-
-The GS segment has no common use and can be used freely by
-applications. GCC and Clang support GS based addressing via address space
-identifiers.
-
-Reading and writing the FS/GS base address
-------------------------------------------
-
-There exist two mechanisms to read and write the FS/GS base address:
-
- - the arch_prctl() system call
-
- - the FSGSBASE instruction family
-
-Accessing FS/GS base with arch_prctl()
---------------------------------------
-
- The arch_prctl(2) based mechanism is available on all 64-bit CPUs and all
- kernel versions.
-
- Reading the base:
-
-   arch_prctl(ARCH_GET_FS, &fsbase);
-   arch_prctl(ARCH_GET_GS, &gsbase);
-
- Writing the base:
-
-   arch_prctl(ARCH_SET_FS, fsbase);
-   arch_prctl(ARCH_SET_GS, gsbase);
-
- The ARCH_SET_GS prctl may be disabled depending on kernel configuration
- and security settings.
-
-Accessing FS/GS base with the FSGSBASE instructions
----------------------------------------------------
-
- With the Ivy Bridge CPU generation Intel introduced a new set of
- instructions to access the FS and GS base registers directly from user
- space. These instructions are also supported on AMD Family 17H CPUs. The
- following instructions are available:
-
-  =============== ===========================
-  RDFSBASE %reg   Read the FS base register
-  RDGSBASE %reg   Read the GS base register
-  WRFSBASE %reg   Write the FS base register
-  WRGSBASE %reg   Write the GS base register
-  =============== ===========================
-
- The instructions avoid the overhead of the arch_prctl() syscall and allow
- more flexible usage of the FS/GS addressing modes in user space
- applications. This does not prevent conflicts between threading libraries
- and runtimes which utilize FS and applications which want to use it for
- their own purpose.
-
-FSGSBASE instructions enablement
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The instructions are enumerated in CPUID leaf 7, bit 0 of EBX. If
- available /proc/cpuinfo shows 'fsgsbase' in the flag entry of the CPUs.
-
- The availability of the instructions does not enable them
- automatically. The kernel has to enable them explicitly in CR4. The
- reason for this is that older kernels make assumptions about the values in
- the GS register and enforce them when GS base is set via
- arch_prctl(). Allowing user space to write arbitrary values to GS base
- would violate these assumptions and cause malfunction.
-
- On kernels which do not enable FSGSBASE the execution of the FSGSBASE
- instructions will fault with a #UD exception.
-
- The kernel provides reliable information about the enabled state in the
- ELF AUX vector. If the HWCAP2_FSGSBASE bit is set in the AUX vector, the
- kernel has FSGSBASE instructions enabled and applications can use them.
- The following code example shows how this detection works::
-
-   #include <sys/auxv.h>
-   #include <elf.h>
-
-   /* Will be eventually in asm/hwcap.h */
-   #ifndef HWCAP2_FSGSBASE
-   #define HWCAP2_FSGSBASE        (1 << 1)
-   #endif
-
-   ....
-
-   unsigned val = getauxval(AT_HWCAP2);
-
-   if (val & HWCAP2_FSGSBASE)
-        printf("FSGSBASE enabled\n");
-
-FSGSBASE instructions compiler support
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-GCC version 4.6.4 and newer provide instrinsics for the FSGSBASE
-instructions. Clang 5 supports them as well.
-
-  =================== ===========================
-  _readfsbase_u64()   Read the FS base register
-  _readfsbase_u64()   Read the GS base register
-  _writefsbase_u64()  Write the FS base register
-  _writegsbase_u64()  Write the GS base register
-  =================== ===========================
-
-To utilize these instrinsics <immintrin.h> must be included in the source
-code and the compiler option -mfsgsbase has to be added.
-
-Compiler support for FS/GS based addressing
--------------------------------------------
-
-GCC version 6 and newer provide support for FS/GS based addressing via
-Named Address Spaces. GCC implements the following address space
-identifiers for x86:
-
-  ========= ====================================
-  __seg_fs  Variable is addressed relative to FS
-  __seg_gs  Variable is addressed relative to GS
-  ========= ====================================
-
-The preprocessor symbols __SEG_FS and __SEG_GS are defined when these
-address spaces are supported. Code which implements fallback modes should
-check whether these symbols are defined. Usage example::
-
-  #ifdef __SEG_GS
-
-  long data0 = 0;
-  long data1 = 1;
-
-  long __seg_gs *ptr;
-
-  /* Check whether FSGSBASE is enabled by the kernel (HWCAP2_FSGSBASE) */
-  ....
-
-  /* Set GS base to point to data0 */
-  _writegsbase_u64(&data0);
-
-  /* Access offset 0 of GS */
-  ptr = 0;
-  printf("data0 = %ld\n", *ptr);
-
-  /* Set GS base to point to data1 */
-  _writegsbase_u64(&data1);
-  /* ptr still addresses offset 0! */
-  printf("data1 = %ld\n", *ptr);
-
-
-Clang does not provide the GCC address space identifiers, but it provides
-address spaces via an attribute based mechanism in Clang 2.6 and newer
-versions:
-
- ==================================== =====================================
-  __attribute__((address_space(256))  Variable is addressed relative to GS
-  __attribute__((address_space(257))  Variable is addressed relative to FS
- ==================================== =====================================
-
-FS/GS based addressing with inline assembly
--------------------------------------------
-
-In case the compiler does not support address spaces, inline assembly can
-be used for FS/GS based addressing mode::
-
-       mov %fs:offset, %reg
-       mov %gs:offset, %reg
-
-       mov %reg, %fs:offset
-       mov %reg, %gs:offset
diff --git a/Documentation/x86/x86_64/index.rst b/Documentation/x86/x86_64/index.rst
deleted file mode 100644 (file)
index a56070f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-==============
-x86_64 Support
-==============
-
-.. toctree::
-   :maxdepth: 2
-
-   boot-options
-   uefi
-   mm
-   5level-paging
-   fake-numa-for-cpusets
-   cpu-hotplug-spec
-   machinecheck
-   fsgs
diff --git a/Documentation/x86/x86_64/machinecheck.rst b/Documentation/x86/x86_64/machinecheck.rst
deleted file mode 100644 (file)
index cea12ee..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===============================================================
-Configurable sysfs parameters for the x86-64 machine check code
-===============================================================
-
-Machine checks report internal hardware error conditions detected
-by the CPU. Uncorrected errors typically cause a machine check
-(often with panic), corrected ones cause a machine check log entry.
-
-Machine checks are organized in banks (normally associated with
-a hardware subsystem) and subevents in a bank. The exact meaning
-of the banks and subevent is CPU specific.
-
-mcelog knows how to decode them.
-
-When you see the "Machine check errors logged" message in the system
-log then mcelog should run to collect and decode machine check entries
-from /dev/mcelog. Normally mcelog should be run regularly from a cronjob.
-
-Each CPU has a directory in /sys/devices/system/machinecheck/machinecheckN
-(N = CPU number).
-
-The directory contains some configurable entries. See
-Documentation/ABI/testing/sysfs-mce for more details.
-
-TBD document entries for AMD threshold interrupt configuration
-
-For more details about the x86 machine check architecture
-see the Intel and AMD architecture manuals from their developer websites.
-
-For more details about the architecture
-see http://one.firstfloor.org/~andi/mce.pdf
diff --git a/Documentation/x86/x86_64/mm.rst b/Documentation/x86/x86_64/mm.rst
deleted file mode 100644 (file)
index 35e5e18..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=================
-Memory Management
-=================
-
-Complete virtual memory map with 4-level page tables
-====================================================
-
-.. note::
-
- - Negative addresses such as "-23 TB" are absolute addresses in bytes, counted down
-   from the top of the 64-bit address space. It's easier to understand the layout
-   when seen both in absolute addresses and in distance-from-top notation.
-
-   For example 0xffffe90000000000 == -23 TB, it's 23 TB lower than the top of the
-   64-bit address space (ffffffffffffffff).
-
-   Note that as we get closer to the top of the address space, the notation changes
-   from TB to GB and then MB/KB.
-
- - "16M TB" might look weird at first sight, but it's an easier way to visualize size
-   notation than "16 EB", which few will recognize at first sight as 16 exabytes.
-   It also shows it nicely how incredibly large 64-bit address space is.
-
-::
-
-  ========================================================================================================================
-      Start addr    |   Offset   |     End addr     |  Size   | VM area description
-  ========================================================================================================================
-                    |            |                  |         |
-   0000000000000000 |    0       | 00007fffffffffff |  128 TB | user-space virtual memory, different per mm
-  __________________|____________|__________________|_________|___________________________________________________________
-                    |            |                  |         |
-   0000800000000000 | +128    TB | ffff7fffffffffff | ~16M TB | ... huge, almost 64 bits wide hole of non-canonical
-                    |            |                  |         |     virtual memory addresses up to the -128 TB
-                    |            |                  |         |     starting offset of kernel mappings.
-  __________________|____________|__________________|_________|___________________________________________________________
-                                                              |
-                                                              | Kernel-space virtual memory, shared between all processes:
-  ____________________________________________________________|___________________________________________________________
-                    |            |                  |         |
-   ffff800000000000 | -128    TB | ffff87ffffffffff |    8 TB | ... guard hole, also reserved for hypervisor
-   ffff880000000000 | -120    TB | ffff887fffffffff |  0.5 TB | LDT remap for PTI
-   ffff888000000000 | -119.5  TB | ffffc87fffffffff |   64 TB | direct mapping of all physical memory (page_offset_base)
-   ffffc88000000000 |  -55.5  TB | ffffc8ffffffffff |  0.5 TB | ... unused hole
-   ffffc90000000000 |  -55    TB | ffffe8ffffffffff |   32 TB | vmalloc/ioremap space (vmalloc_base)
-   ffffe90000000000 |  -23    TB | ffffe9ffffffffff |    1 TB | ... unused hole
-   ffffea0000000000 |  -22    TB | ffffeaffffffffff |    1 TB | virtual memory map (vmemmap_base)
-   ffffeb0000000000 |  -21    TB | ffffebffffffffff |    1 TB | ... unused hole
-   ffffec0000000000 |  -20    TB | fffffbffffffffff |   16 TB | KASAN shadow memory
-  __________________|____________|__________________|_________|____________________________________________________________
-                                                              |
-                                                              | Identical layout to the 56-bit one from here on:
-  ____________________________________________________________|____________________________________________________________
-                    |            |                  |         |
-   fffffc0000000000 |   -4    TB | fffffdffffffffff |    2 TB | ... unused hole
-                    |            |                  |         | vaddr_end for KASLR
-   fffffe0000000000 |   -2    TB | fffffe7fffffffff |  0.5 TB | cpu_entry_area mapping
-   fffffe8000000000 |   -1.5  TB | fffffeffffffffff |  0.5 TB | ... unused hole
-   ffffff0000000000 |   -1    TB | ffffff7fffffffff |  0.5 TB | %esp fixup stacks
-   ffffff8000000000 | -512    GB | ffffffeeffffffff |  444 GB | ... unused hole
-   ffffffef00000000 |  -68    GB | fffffffeffffffff |   64 GB | EFI region mapping space
-   ffffffff00000000 |   -4    GB | ffffffff7fffffff |    2 GB | ... unused hole
-   ffffffff80000000 |   -2    GB | ffffffff9fffffff |  512 MB | kernel text mapping, mapped to physical address 0
-   ffffffff80000000 |-2048    MB |                  |         |
-   ffffffffa0000000 |-1536    MB | fffffffffeffffff | 1520 MB | module mapping space
-   ffffffffff000000 |  -16    MB |                  |         |
-      FIXADDR_START | ~-11    MB | ffffffffff5fffff | ~0.5 MB | kernel-internal fixmap range, variable size and offset
-   ffffffffff600000 |  -10    MB | ffffffffff600fff |    4 kB | legacy vsyscall ABI
-   ffffffffffe00000 |   -2    MB | ffffffffffffffff |    2 MB | ... unused hole
-  __________________|____________|__________________|_________|___________________________________________________________
-
-
-Complete virtual memory map with 5-level page tables
-====================================================
-
-.. note::
-
- - With 56-bit addresses, user-space memory gets expanded by a factor of 512x,
-   from 0.125 PB to 64 PB. All kernel mappings shift down to the -64 PB starting
-   offset and many of the regions expand to support the much larger physical
-   memory supported.
-
-::
-
-  ========================================================================================================================
-      Start addr    |   Offset   |     End addr     |  Size   | VM area description
-  ========================================================================================================================
-                    |            |                  |         |
-   0000000000000000 |    0       | 00ffffffffffffff |   64 PB | user-space virtual memory, different per mm
-  __________________|____________|__________________|_________|___________________________________________________________
-                    |            |                  |         |
-   0100000000000000 |  +64    PB | feffffffffffffff | ~16K PB | ... huge, still almost 64 bits wide hole of non-canonical
-                    |            |                  |         |     virtual memory addresses up to the -64 PB
-                    |            |                  |         |     starting offset of kernel mappings.
-  __________________|____________|__________________|_________|___________________________________________________________
-                                                              |
-                                                              | Kernel-space virtual memory, shared between all processes:
-  ____________________________________________________________|___________________________________________________________
-                    |            |                  |         |
-   ff00000000000000 |  -64    PB | ff0fffffffffffff |    4 PB | ... guard hole, also reserved for hypervisor
-   ff10000000000000 |  -60    PB | ff10ffffffffffff | 0.25 PB | LDT remap for PTI
-   ff11000000000000 |  -59.75 PB | ff90ffffffffffff |   32 PB | direct mapping of all physical memory (page_offset_base)
-   ff91000000000000 |  -27.75 PB | ff9fffffffffffff | 3.75 PB | ... unused hole
-   ffa0000000000000 |  -24    PB | ffd1ffffffffffff | 12.5 PB | vmalloc/ioremap space (vmalloc_base)
-   ffd2000000000000 |  -11.5  PB | ffd3ffffffffffff |  0.5 PB | ... unused hole
-   ffd4000000000000 |  -11    PB | ffd5ffffffffffff |  0.5 PB | virtual memory map (vmemmap_base)
-   ffd6000000000000 |  -10.5  PB | ffdeffffffffffff | 2.25 PB | ... unused hole
-   ffdf000000000000 |   -8.25 PB | fffffbffffffffff |   ~8 PB | KASAN shadow memory
-  __________________|____________|__________________|_________|____________________________________________________________
-                                                              |
-                                                              | Identical layout to the 47-bit one from here on:
-  ____________________________________________________________|____________________________________________________________
-                    |            |                  |         |
-   fffffc0000000000 |   -4    TB | fffffdffffffffff |    2 TB | ... unused hole
-                    |            |                  |         | vaddr_end for KASLR
-   fffffe0000000000 |   -2    TB | fffffe7fffffffff |  0.5 TB | cpu_entry_area mapping
-   fffffe8000000000 |   -1.5  TB | fffffeffffffffff |  0.5 TB | ... unused hole
-   ffffff0000000000 |   -1    TB | ffffff7fffffffff |  0.5 TB | %esp fixup stacks
-   ffffff8000000000 | -512    GB | ffffffeeffffffff |  444 GB | ... unused hole
-   ffffffef00000000 |  -68    GB | fffffffeffffffff |   64 GB | EFI region mapping space
-   ffffffff00000000 |   -4    GB | ffffffff7fffffff |    2 GB | ... unused hole
-   ffffffff80000000 |   -2    GB | ffffffff9fffffff |  512 MB | kernel text mapping, mapped to physical address 0
-   ffffffff80000000 |-2048    MB |                  |         |
-   ffffffffa0000000 |-1536    MB | fffffffffeffffff | 1520 MB | module mapping space
-   ffffffffff000000 |  -16    MB |                  |         |
-      FIXADDR_START | ~-11    MB | ffffffffff5fffff | ~0.5 MB | kernel-internal fixmap range, variable size and offset
-   ffffffffff600000 |  -10    MB | ffffffffff600fff |    4 kB | legacy vsyscall ABI
-   ffffffffffe00000 |   -2    MB | ffffffffffffffff |    2 MB | ... unused hole
-  __________________|____________|__________________|_________|___________________________________________________________
-
-Architecture defines a 64-bit virtual address. Implementations can support
-less. Currently supported are 48- and 57-bit virtual addresses. Bits 63
-through to the most-significant implemented bit are sign extended.
-This causes hole between user space and kernel addresses if you interpret them
-as unsigned.
-
-The direct mapping covers all memory in the system up to the highest
-memory address (this means in some cases it can also include PCI memory
-holes).
-
-We map EFI runtime services in the 'efi_pgd' PGD in a 64GB large virtual
-memory window (this size is arbitrary, it can be raised later if needed).
-The mappings are not part of any other kernel PGD and are only available
-during EFI runtime calls.
-
-Note that if CONFIG_RANDOMIZE_MEMORY is enabled, the direct mapping of all
-physical memory, vmalloc/ioremap space and virtual memory map are randomized.
-Their order is preserved but their base will be offset early at boot time.
-
-Be very careful vs. KASLR when changing anything here. The KASLR address
-range must not overlap with anything except the KASAN shadow area, which is
-correct as KASAN disables KASLR.
-
-For both 4- and 5-level layouts, the STACKLEAK_POISON value in the last 2MB
-hole: ffffffffffff4111
diff --git a/Documentation/x86/x86_64/uefi.rst b/Documentation/x86/x86_64/uefi.rst
deleted file mode 100644 (file)
index fbc30c9..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=====================================
-General note on [U]EFI x86_64 support
-=====================================
-
-The nomenclature EFI and UEFI are used interchangeably in this document.
-
-Although the tools below are _not_ needed for building the kernel,
-the needed bootloader support and associated tools for x86_64 platforms
-with EFI firmware and specifications are listed below.
-
-1. UEFI specification:  http://www.uefi.org
-
-2. Booting Linux kernel on UEFI x86_64 platform requires bootloader
-   support. Elilo with x86_64 support can be used.
-
-3. x86_64 platform with EFI/UEFI firmware.
-
-Mechanics
----------
-
-- Build the kernel with the following configuration::
-
-       CONFIG_FB_EFI=y
-       CONFIG_FRAMEBUFFER_CONSOLE=y
-
-  If EFI runtime services are expected, the following configuration should
-  be selected::
-
-       CONFIG_EFI=y
-       CONFIG_EFIVAR_FS=y or m         # optional
-
-- Create a VFAT partition on the disk
-- Copy the following to the VFAT partition:
-
-       elilo bootloader with x86_64 support, elilo configuration file,
-       kernel image built in first step and corresponding
-       initrd. Instructions on building elilo and its dependencies
-       can be found in the elilo sourceforge project.
-
-- Boot to EFI shell and invoke elilo choosing the kernel image built
-  in first step.
-- If some or all EFI runtime services don't work, you can try following
-  kernel command line parameters to turn off some or all EFI runtime
-  services.
-
-       noefi
-               turn off all EFI runtime services
-       reboot_type=k
-               turn off EFI reboot runtime service
-
-- If the EFI memory map has additional entries not in the E820 map,
-  you can include those entries in the kernels memory map of available
-  physical RAM by using the following kernel command line parameter.
-
-       add_efi_memmap
-               include EFI memory map of available physical RAM
diff --git a/Documentation/x86/xstate.rst b/Documentation/x86/xstate.rst
deleted file mode 100644 (file)
index 5cec7fb..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-Using XSTATE features in user space applications
-================================================
-
-The x86 architecture supports floating-point extensions which are
-enumerated via CPUID. Applications consult CPUID and use XGETBV to
-evaluate which features have been enabled by the kernel XCR0.
-
-Up to AVX-512 and PKRU states, these features are automatically enabled by
-the kernel if available. Features like AMX TILE_DATA (XSTATE component 18)
-are enabled by XCR0 as well, but the first use of related instruction is
-trapped by the kernel because by default the required large XSTATE buffers
-are not allocated automatically.
-
-Using dynamically enabled XSTATE features in user space applications
---------------------------------------------------------------------
-
-The kernel provides an arch_prctl(2) based mechanism for applications to
-request the usage of such features. The arch_prctl(2) options related to
-this are:
-
--ARCH_GET_XCOMP_SUPP
-
- arch_prctl(ARCH_GET_XCOMP_SUPP, &features);
-
- ARCH_GET_XCOMP_SUPP stores the supported features in userspace storage of
- type uint64_t. The second argument is a pointer to that storage.
-
--ARCH_GET_XCOMP_PERM
-
- arch_prctl(ARCH_GET_XCOMP_PERM, &features);
-
- ARCH_GET_XCOMP_PERM stores the features for which the userspace process
- has permission in userspace storage of type uint64_t. The second argument
- is a pointer to that storage.
-
--ARCH_REQ_XCOMP_PERM
-
- arch_prctl(ARCH_REQ_XCOMP_PERM, feature_nr);
-
- ARCH_REQ_XCOMP_PERM allows to request permission for a dynamically enabled
- feature or a feature set. A feature set can be mapped to a facility, e.g.
- AMX, and can require one or more XSTATE components to be enabled.
-
- The feature argument is the number of the highest XSTATE component which
- is required for a facility to work.
-
-When requesting permission for a feature, the kernel checks the
-availability. The kernel ensures that sigaltstacks in the process's tasks
-are large enough to accommodate the resulting large signal frame. It
-enforces this both during ARCH_REQ_XCOMP_SUPP and during any subsequent
-sigaltstack(2) calls. If an installed sigaltstack is smaller than the
-resulting sigframe size, ARCH_REQ_XCOMP_SUPP results in -ENOSUPP. Also,
-sigaltstack(2) results in -ENOMEM if the requested altstack is too small
-for the permitted features.
-
-Permission, when granted, is valid per process. Permissions are inherited
-on fork(2) and cleared on exec(3).
-
-The first use of an instruction related to a dynamically enabled feature is
-trapped by the kernel. The trap handler checks whether the process has
-permission to use the feature. If the process has no permission then the
-kernel sends SIGILL to the application. If the process has permission then
-the handler allocates a larger xstate buffer for the task so the large
-state can be context switched. In the unlikely cases that the allocation
-fails, the kernel sends SIGSEGV.
-
-Dynamic features in signal frames
----------------------------------
-
-Dynamcally enabled features are not written to the signal frame upon signal
-entry if the feature is in its initial configuration.  This differs from
-non-dynamic features which are always written regardless of their
-configuration.  Signal handlers can examine the XSAVE buffer's XSTATE_BV
-field to determine if a features was written.
diff --git a/Documentation/x86/zero-page.rst b/Documentation/x86/zero-page.rst
deleted file mode 100644 (file)
index 45aa9cc..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=========
-Zero Page
-=========
-The additional fields in struct boot_params as a part of 32-bit boot
-protocol of kernel. These should be filled by bootloader or 16-bit
-real-mode setup code of the kernel. References/settings to it mainly
-are in::
-
-  arch/x86/include/uapi/asm/bootparam.h
-
-===========    =====   ======================= =================================================
-Offset/Size    Proto   Name                    Meaning
-
-000/040                ALL     screen_info             Text mode or frame buffer information
-                                               (struct screen_info)
-040/014                ALL     apm_bios_info           APM BIOS information (struct apm_bios_info)
-058/008                ALL     tboot_addr              Physical address of tboot shared page
-060/010                ALL     ist_info                Intel SpeedStep (IST) BIOS support information
-                                               (struct ist_info)
-070/008                ALL     acpi_rsdp_addr          Physical address of ACPI RSDP table
-080/010                ALL     hd0_info                hd0 disk parameter, OBSOLETE!!
-090/010                ALL     hd1_info                hd1 disk parameter, OBSOLETE!!
-0A0/010                ALL     sys_desc_table          System description table (struct sys_desc_table),
-                                               OBSOLETE!!
-0B0/010                ALL     olpc_ofw_header         OLPC's OpenFirmware CIF and friends
-0C0/004                ALL     ext_ramdisk_image       ramdisk_image high 32bits
-0C4/004                ALL     ext_ramdisk_size        ramdisk_size high 32bits
-0C8/004                ALL     ext_cmd_line_ptr        cmd_line_ptr high 32bits
-13C/004                ALL     cc_blob_address         Physical address of Confidential Computing blob
-140/080                ALL     edid_info               Video mode setup (struct edid_info)
-1C0/020                ALL     efi_info                EFI 32 information (struct efi_info)
-1E0/004                ALL     alt_mem_k               Alternative mem check, in KB
-1E4/004                ALL     scratch                 Scratch field for the kernel setup code
-1E8/001                ALL     e820_entries            Number of entries in e820_table (below)
-1E9/001                ALL     eddbuf_entries          Number of entries in eddbuf (below)
-1EA/001                ALL     edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer
-                                               (below)
-1EB/001                ALL     kbd_status              Numlock is enabled
-1EC/001                ALL     secure_boot             Secure boot is enabled in the firmware
-1EF/001                ALL     sentinel                Used to detect broken bootloaders
-290/040                ALL     edd_mbr_sig_buffer      EDD MBR signatures
-2D0/A00                ALL     e820_table              E820 memory map table
-                                               (array of struct e820_entry)
-D00/1EC                ALL     eddbuf                  EDD data (array of struct edd_info)
-===========    =====   ======================= =================================================
diff --git a/Documentation/xtensa/atomctl.rst b/Documentation/xtensa/atomctl.rst
deleted file mode 100644 (file)
index 1ecbd0b..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-===========================================
-Atomic Operation Control (ATOMCTL) Register
-===========================================
-
-We Have Atomic Operation Control (ATOMCTL) Register.
-This register determines the effect of using a S32C1I instruction
-with various combinations of:
-
-     1. With and without an Coherent Cache Controller which
-        can do Atomic Transactions to the memory internally.
-
-     2. With and without An Intelligent Memory Controller which
-        can do Atomic Transactions itself.
-
-The Core comes up with a default value of for the three types of cache ops::
-
-      0x28: (WB: Internal, WT: Internal, BY:Exception)
-
-On the FPGA Cards we typically simulate an Intelligent Memory controller
-which can implement  RCW transactions. For FPGA cards with an External
-Memory controller we let it to the atomic operations internally while
-doing a Cached (WB) transaction and use the Memory RCW for un-cached
-operations.
-
-For systems without an coherent cache controller, non-MX, we always
-use the memory controllers RCW, thought non-MX controlers likely
-support the Internal Operation.
-
-CUSTOMER-WARNING:
-   Virtually all customers buy their memory controllers from vendors that
-   don't support atomic RCW memory transactions and will likely want to
-   configure this register to not use RCW.
-
-Developers might find using RCW in Bypass mode convenient when testing
-with the cache being bypassed; for example studying cache alias problems.
-
-See Section 4.3.12.4 of ISA; Bits::
-
-                             WB     WT      BY
-                           5   4 | 3   2 | 1   0
-
-=========    ==================      ==================      ===============
-  2 Bit
-  Field
-  Values     WB - Write Back         WT - Write Thru         BY - Bypass
-=========    ==================      ==================      ===============
-    0        Exception               Exception               Exception
-    1        RCW Transaction         RCW Transaction         RCW Transaction
-    2        Internal Operation      Internal Operation      Reserved
-    3        Reserved                Reserved                Reserved
-=========    ==================      ==================      ===============
diff --git a/Documentation/xtensa/booting.rst b/Documentation/xtensa/booting.rst
deleted file mode 100644 (file)
index e1b8370..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-=====================================
-Passing boot parameters to the kernel
-=====================================
-
-Boot parameters are represented as a TLV list in the memory. Please see
-arch/xtensa/include/asm/bootparam.h for definition of the bp_tag structure and
-tag value constants. First entry in the list must have type BP_TAG_FIRST, last
-entry must have type BP_TAG_LAST. The address of the first list entry is
-passed to the kernel in the register a2. The address type depends on MMU type:
-
-- For configurations without MMU, with region protection or with MPU the
-  address must be the physical address.
-- For configurations with region translarion MMU or with MMUv3 and CONFIG_MMU=n
-  the address must be a valid address in the current mapping. The kernel will
-  not change the mapping on its own.
-- For configurations with MMUv2 the address must be a virtual address in the
-  default virtual mapping (0xd0000000..0xffffffff).
-- For configurations with MMUv3 and CONFIG_MMU=y the address may be either a
-  virtual or physical address. In either case it must be within the default
-  virtual mapping. It is considered physical if it is within the range of
-  physical addresses covered by the default KSEG mapping (XCHAL_KSEG_PADDR..
-  XCHAL_KSEG_PADDR + XCHAL_KSEG_SIZE), otherwise it is considered virtual.
diff --git a/Documentation/xtensa/features.rst b/Documentation/xtensa/features.rst
deleted file mode 100644 (file)
index 6b92c7b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-.. kernel-feat:: $srctree/Documentation/features xtensa
diff --git a/Documentation/xtensa/index.rst b/Documentation/xtensa/index.rst
deleted file mode 100644 (file)
index 6995244..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-===================
-Xtensa Architecture
-===================
-
-.. toctree::
-   :maxdepth: 1
-
-   atomctl
-   booting
-   mmu
-
-   features
diff --git a/Documentation/xtensa/mmu.rst b/Documentation/xtensa/mmu.rst
deleted file mode 100644 (file)
index 450573a..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-=============================
-MMUv3 initialization sequence
-=============================
-
-The code in the initialize_mmu macro sets up MMUv3 memory mapping
-identically to MMUv2 fixed memory mapping. Depending on
-CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX symbol this code is
-located in addresses it was linked for (symbol undefined), or not
-(symbol defined), so it needs to be position-independent.
-
-The code has the following assumptions:
-
-  - This code fragment is run only on an MMU v3.
-  - TLBs are in their reset state.
-  - ITLBCFG and DTLBCFG are zero (reset state).
-  - RASID is 0x04030201 (reset state).
-  - PS.RING is zero (reset state).
-  - LITBASE is zero (reset state, PC-relative literals); required to be PIC.
-
-TLB setup proceeds along the following steps.
-
-  Legend:
-
-    - VA = virtual address (two upper nibbles of it);
-    - PA = physical address (two upper nibbles of it);
-    - pc = physical range that contains this code;
-
-After step 2, we jump to virtual address in the range 0x40000000..0x5fffffff
-or 0x00000000..0x1fffffff, depending on whether the kernel was loaded below
-0x40000000 or above. That address corresponds to next instruction to execute
-in this code. After step 4, we jump to intended (linked) address of this code.
-The scheme below assumes that the kernel is loaded below 0x40000000.
-
- ====== =====  =====  =====  =====   ====== =====  =====
- -      Step0  Step1  Step2  Step3          Step4  Step5
-
-   VA      PA     PA     PA     PA     VA      PA     PA
- ====== =====  =====  =====  =====   ====== =====  =====
- E0..FF -> E0  -> E0  -> E0          F0..FF -> F0  -> F0
- C0..DF -> C0  -> C0  -> C0          E0..EF -> F0  -> F0
- A0..BF -> A0  -> A0  -> A0          D8..DF -> 00  -> 00
- 80..9F -> 80  -> 80  -> 80          D0..D7 -> 00  -> 00
- 60..7F -> 60  -> 60  -> 60
- 40..5F -> 40         -> pc  -> pc   40..5F -> pc
- 20..3F -> 20  -> 20  -> 20
- 00..1F -> 00  -> 00  -> 00
- ====== =====  =====  =====  =====   ====== =====  =====
-
-The default location of IO peripherals is above 0xf0000000. This may be changed
-using a "ranges" property in a device tree simple-bus node. See the Devicetree
-Specification, section 4.5 for details on the syntax and semantics of
-simple-bus nodes. The following limitations apply:
-
-1. Only top level simple-bus nodes are considered
-
-2. Only one (first) simple-bus node is considered
-
-3. Empty "ranges" properties are not supported
-
-4. Only the first triplet in the "ranges" property is considered
-
-5. The parent-bus-address value is rounded down to the nearest 256MB boundary
-
-6. The IO area covers the entire 256MB segment of parent-bus-address; the
-   "ranges" triplet length field is ignored
-
-
-MMUv3 address space layouts.
-============================
-
-Default MMUv2-compatible layout::
-
-                        Symbol                   VADDR       Size
-  +------------------+
-  | Userspace        |                           0x00000000  TASK_SIZE
-  +------------------+                           0x40000000
-  +------------------+
-  | Page table       |  XCHAL_PAGE_TABLE_VADDR   0x80000000  XCHAL_PAGE_TABLE_SIZE
-  +------------------+
-  | KASAN shadow map |  KASAN_SHADOW_START       0x80400000  KASAN_SHADOW_SIZE
-  +------------------+                           0x8e400000
-  +------------------+
-  | VMALLOC area     |  VMALLOC_START            0xc0000000  128MB - 64KB
-  +------------------+  VMALLOC_END
-  +------------------+
-  | Cache aliasing   |  TLBTEMP_BASE_1           0xc8000000  DCACHE_WAY_SIZE
-  | remap area 1     |
-  +------------------+
-  | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
-  | remap area 2     |
-  +------------------+
-  +------------------+
-  | KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
-  |                  |                                       DCACHE_N_COLORS *
-  |                  |                                       PAGE_SIZE
-  |                  |                                       (4MB * DCACHE_N_COLORS)
-  +------------------+
-  | Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
-  |                  |                                       NR_CPUS *
-  |                  |                                       DCACHE_N_COLORS *
-  |                  |                                       PAGE_SIZE
-  +------------------+  FIXADDR_TOP              0xcffff000
-  +------------------+
-  | Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xd0000000  128MB
-  +------------------+
-  | Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xd8000000  128MB
-  +------------------+
-  | Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
-  +------------------+
-  | Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
-  +------------------+
-
-
-256MB cached + 256MB uncached layout::
-
-                        Symbol                   VADDR       Size
-  +------------------+
-  | Userspace        |                           0x00000000  TASK_SIZE
-  +------------------+                           0x40000000
-  +------------------+
-  | Page table       |  XCHAL_PAGE_TABLE_VADDR   0x80000000  XCHAL_PAGE_TABLE_SIZE
-  +------------------+
-  | KASAN shadow map |  KASAN_SHADOW_START       0x80400000  KASAN_SHADOW_SIZE
-  +------------------+                           0x8e400000
-  +------------------+
-  | VMALLOC area     |  VMALLOC_START            0xa0000000  128MB - 64KB
-  +------------------+  VMALLOC_END
-  +------------------+
-  | Cache aliasing   |  TLBTEMP_BASE_1           0xa8000000  DCACHE_WAY_SIZE
-  | remap area 1     |
-  +------------------+
-  | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
-  | remap area 2     |
-  +------------------+
-  +------------------+
-  | KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
-  |                  |                                       DCACHE_N_COLORS *
-  |                  |                                       PAGE_SIZE
-  |                  |                                       (4MB * DCACHE_N_COLORS)
-  +------------------+
-  | Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
-  |                  |                                       NR_CPUS *
-  |                  |                                       DCACHE_N_COLORS *
-  |                  |                                       PAGE_SIZE
-  +------------------+  FIXADDR_TOP              0xaffff000
-  +------------------+
-  | Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xb0000000  256MB
-  +------------------+
-  | Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xc0000000  256MB
-  +------------------+
-  +------------------+
-  | Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
-  +------------------+
-  | Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
-  +------------------+
-
-
-512MB cached + 512MB uncached layout::
-
-                        Symbol                   VADDR       Size
-  +------------------+
-  | Userspace        |                           0x00000000  TASK_SIZE
-  +------------------+                           0x40000000
-  +------------------+
-  | Page table       |  XCHAL_PAGE_TABLE_VADDR   0x80000000  XCHAL_PAGE_TABLE_SIZE
-  +------------------+
-  | KASAN shadow map |  KASAN_SHADOW_START       0x80400000  KASAN_SHADOW_SIZE
-  +------------------+                           0x8e400000
-  +------------------+
-  | VMALLOC area     |  VMALLOC_START            0x90000000  128MB - 64KB
-  +------------------+  VMALLOC_END
-  +------------------+
-  | Cache aliasing   |  TLBTEMP_BASE_1           0x98000000  DCACHE_WAY_SIZE
-  | remap area 1     |
-  +------------------+
-  | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
-  | remap area 2     |
-  +------------------+
-  +------------------+
-  | KMAP area        |  PKMAP_BASE                           PTRS_PER_PTE *
-  |                  |                                       DCACHE_N_COLORS *
-  |                  |                                       PAGE_SIZE
-  |                  |                                       (4MB * DCACHE_N_COLORS)
-  +------------------+
-  | Atomic KMAP area |  FIXADDR_START                        KM_TYPE_NR *
-  |                  |                                       NR_CPUS *
-  |                  |                                       DCACHE_N_COLORS *
-  |                  |                                       PAGE_SIZE
-  +------------------+  FIXADDR_TOP              0x9ffff000
-  +------------------+
-  | Cached KSEG      |  XCHAL_KSEG_CACHED_VADDR  0xa0000000  512MB
-  +------------------+
-  | Uncached KSEG    |  XCHAL_KSEG_BYPASS_VADDR  0xc0000000  512MB
-  +------------------+
-  | Cached KIO       |  XCHAL_KIO_CACHED_VADDR   0xe0000000  256MB
-  +------------------+
-  | Uncached KIO     |  XCHAL_KIO_BYPASS_VADDR   0xf0000000  256MB
-  +------------------+
index 3583a7f8a521ccacf715c8a2e0540e11ce141c19..cec07c796296b9bb728fe9566ebb0afb757e43b3 100644 (file)
@@ -73,7 +73,7 @@ Tips for patch submitters
        and ideally, should come with a patch proposal. Please do not send
        automated reports to this list either. Such bugs will be handled
        better and faster in the usual public places. See
-       Documentation/admin-guide/security-bugs.rst for details.
+       Documentation/process/security-bugs.rst for details.
 
 8.     Happy hacking.
 
@@ -224,13 +224,13 @@ S:        Orphan / Obsolete
 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
@@ -1071,7 +1071,7 @@ M:        Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
 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
@@ -2660,6 +2660,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>
@@ -4467,14 +4468,14 @@ F:      Documentation/devicetree/bindings/net/ieee802154/ca8210.txt
 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
@@ -4482,7 +4483,7 @@ F:        Documentation/devicetree/bindings/reset/canaan,k210-rst.yaml
 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
@@ -5946,11 +5947,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>
@@ -5977,7 +5973,7 @@ F:        include/linux/dm-*.h
 F:     include/uapi/linux/dm-*.h
 
 DEVLINK
-M:     Jiri Pirko <jiri@nvidia.com>
+M:     Jiri Pirko <jiri@resnulli.us>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/devlink
@@ -6213,6 +6209,7 @@ DOCUMENTATION REPORTING ISSUES
 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
@@ -8222,6 +8219,7 @@ F:        drivers/net/ethernet/freescale/dpaa
 
 FREESCALE QORIQ DPAA FMAN DRIVER
 M:     Madalin Bucur <madalin.bucur@nxp.com>
+R:     Sean Anderson <sean.anderson@seco.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/net/fsl-fman.txt
@@ -9734,7 +9732,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
@@ -10653,7 +10651,7 @@ L:      tboot-devel@lists.sourceforge.net
 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
 
@@ -10664,7 +10662,7 @@ L:      linux-sgx@vger.kernel.org
 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
@@ -11763,7 +11761,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
 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
@@ -14599,6 +14597,7 @@ 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
@@ -14662,10 +14661,8 @@ F:     net/ipv4/nexthop.c
 
 NFC SUBSYSTEM
 M:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-L:     linux-nfc@lists.01.org (subscribers-only)
 L:     netdev@vger.kernel.org
 S:     Maintained
-B:     mailto:linux-nfc@lists.01.org
 F:     Documentation/devicetree/bindings/net/nfc/
 F:     drivers/nfc/
 F:     include/linux/platform_data/nfcmrvl.h
@@ -14676,7 +14673,6 @@ F:      net/nfc/
 NFC VIRTUAL NCI DEVICE DRIVER
 M:     Bongsu Jeon <bongsu.jeon@samsung.com>
 L:     netdev@vger.kernel.org
-L:     linux-nfc@lists.01.org (subscribers-only)
 S:     Supported
 F:     drivers/nfc/virtual_ncidev.c
 F:     tools/testing/selftests/nci/
@@ -14752,7 +14748,7 @@ F:      include/uapi/linux/nitro_enclaves.h
 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
@@ -14878,12 +14874,12 @@ M:    Sagi Grimberg <sagi@grimberg.me>
 L:     linux-nvme@lists.infradead.org
 S:     Supported
 W:     http://git.infradead.org/nvme.git
-T:     git://git.infradead.org/nvme.git
+T:     git git://git.infradead.org/nvme.git
 F:     Documentation/nvme/
-F:     drivers/nvme/host/
 F:     drivers/nvme/common/
-F:     include/linux/nvme.h
+F:     drivers/nvme/host/
 F:     include/linux/nvme-*.h
+F:     include/linux/nvme.h
 F:     include/uapi/linux/nvme_ioctl.h
 
 NVM EXPRESS FABRICS AUTHENTICATION
@@ -14918,7 +14914,7 @@ M:      Chaitanya Kulkarni <kch@nvidia.com>
 L:     linux-nvme@lists.infradead.org
 S:     Supported
 W:     http://git.infradead.org/nvme.git
-T:     git://git.infradead.org/nvme.git
+T:     git git://git.infradead.org/nvme.git
 F:     drivers/nvme/target/
 
 NVMEM FRAMEWORK
@@ -15048,7 +15044,6 @@ F:      Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
 F:     sound/soc/codecs/tfa989x.c
 
 NXP-NCI NFC DRIVER
-L:     linux-nfc@lists.01.org (subscribers-only)
 S:     Orphan
 F:     Documentation/devicetree/bindings/net/nfc/nxp,nci.yaml
 F:     drivers/nfc/nxp-nci
@@ -15085,7 +15080,7 @@ F:      Documentation/hwmon/nzxt-smart2.rst
 F:     drivers/hwmon/nzxt-smart2.c
 
 OBJAGG
-M:     Jiri Pirko <jiri@nvidia.com>
+M:     Jiri Pirko <jiri@resnulli.us>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     include/linux/objagg.h
@@ -15648,7 +15643,7 @@ S:      Maintained
 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-*
@@ -15844,7 +15839,7 @@ W:      https://parisc.wiki.kernel.org
 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
@@ -15859,7 +15854,7 @@ F:      drivers/video/logo/logo_parisc*
 F:     include/linux/hp_sdc.h
 
 PARMAN
-M:     Jiri Pirko <jiri@nvidia.com>
+M:     Jiri Pirko <jiri@resnulli.us>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     include/linux/parman.h
@@ -17175,6 +17170,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>
@@ -17635,7 +17636,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/
@@ -17644,11 +17645,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/
@@ -17996,7 +17999,7 @@ F:      Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml
 F:     Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
 F:     arch/riscv/boot/dts/microchip/
 F:     drivers/char/hw_random/mpfs-rng.c
-F:     drivers/clk/microchip/clk-mpfs.c
+F:     drivers/clk/microchip/clk-mpfs*.c
 F:     drivers/i2c/busses/i2c-microchip-corei2c.c
 F:     drivers/mailbox/mailbox-mpfs.c
 F:     drivers/pci/controller/pcie-microchip-host.c
@@ -18297,8 +18300,9 @@ F:      drivers/s390/block/dasd*
 F:     include/linux/dasd_mod.h
 
 S390 IOMMU (PCI)
+M:     Niklas Schnelle <schnelle@linux.ibm.com>
 M:     Matthew Rosato <mjrosato@linux.ibm.com>
-M:     Gerald Schaefer <gerald.schaefer@linux.ibm.com>
+R:     Gerald Schaefer <gerald.schaefer@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 S:     Supported
 F:     drivers/iommu/s390-iommu.c
@@ -18493,7 +18497,6 @@ F:      include/media/drv-intf/s3c_camif.h
 
 SAMSUNG S3FWRN5 NFC DRIVER
 M:     Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-L:     linux-nfc@lists.01.org (subscribers-only)
 S:     Maintained
 F:     Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
 F:     drivers/nfc/s3fwrn5
@@ -18808,7 +18811,7 @@ F:      include/uapi/linux/sed*
 SECURITY CONTACT
 M:     Security Officers <security@kernel.org>
 S:     Supported
-F:     Documentation/admin-guide/security-bugs.rst
+F:     Documentation/process/security-bugs.rst
 
 SECURITY SUBSYSTEM
 M:     Paul Moore <paul@paul-moore.com>
@@ -18830,8 +18833,8 @@ S:      Supported
 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
@@ -19156,9 +19159,7 @@ W:      http://www.brownhat.org/sis900.html
 F:     drivers/net/ethernet/sis/sis900.*
 
 SIS FRAMEBUFFER DRIVER
-M:     Thomas Winischhofer <thomas@winischhofer.net>
-S:     Maintained
-W:     http://www.winischhofer.net/linuxsisvga.shtml
+S:     Orphan
 F:     Documentation/fb/sisfb.rst
 F:     drivers/video/fbdev/sis/
 F:     include/video/sisfb.h
@@ -20123,7 +20124,7 @@ M:      John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
 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/
 
@@ -20183,7 +20184,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/
@@ -20653,7 +20654,6 @@ F:      sound/soc/codecs/tscs*.h
 TENSILICA XTENSA PORT (xtensa)
 M:     Chris Zankel <chris@zankel.net>
 M:     Max Filippov <jcmvbkbc@gmail.com>
-L:     linux-xtensa@linux-xtensa.org
 S:     Maintained
 T:     git https://github.com/jcmvbkbc/linux-xtensa.git
 F:     arch/xtensa/
@@ -20989,7 +20989,6 @@ F:      drivers/iio/magnetometer/tmag5273.c
 TI TRF7970A NFC DRIVER
 M:     Mark Greer <mgreer@animalcreek.com>
 L:     linux-wireless@vger.kernel.org
-L:     linux-nfc@lists.01.org (subscribers-only)
 S:     Supported
 F:     Documentation/devicetree/bindings/net/nfc/ti,trf7970a.yaml
 F:     drivers/nfc/trf7970a.c
@@ -21244,6 +21243,14 @@ S:     Maintained
 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)
@@ -21651,6 +21658,7 @@ USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
 M:     Shuah Khan <shuah@kernel.org>
 M:     Shuah Khan <skhan@linuxfoundation.org>
+R:     Hongren Zheng <i@zenithal.me>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/usbip_protocol.rst
@@ -22176,7 +22184,9 @@ L:      virtualization@lists.linux-foundation.org
 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
 
@@ -22650,7 +22660,7 @@ L:      linux-kernel@vger.kernel.org
 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
@@ -22660,13 +22670,24 @@ S:    Maintained
 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
@@ -23045,7 +23066,6 @@ F:      drivers/gpio/gpio-xra1403.c
 
 XTENSA XTFPGA PLATFORM SUPPORT
 M:     Max Filippov <jcmvbkbc@gmail.com>
-L:     linux-xtensa@linux-xtensa.org
 S:     Maintained
 F:     drivers/spi/spi-xtensa-xtfpga.c
 F:     sound/soc/xtensa/xtfpga-i2s.c
@@ -23128,7 +23148,7 @@ S:      Maintained
 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
index c933ceb4f21db15d9789f8e9fd12a931174c121f..f5543eef4f8227a40d6a0b5a2646ff8f38658d89 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION =
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
@@ -274,8 +274,7 @@ no-dot-config-targets := $(clean-targets) \
                         cscope gtags TAGS tags help% %docs check% coccicheck \
                         $(version_h) headers headers_% archheaders archscripts \
                         %asm-generic kernelversion %src-pkg dt_binding_check \
-                        outputmakefile rustavailable rustfmt rustfmtcheck \
-                        scripts_package
+                        outputmakefile rustavailable rustfmt rustfmtcheck
 # Installation targets should not require compiler. Unfortunately, vdso_install
 # is an exception where build artifacts may be updated. This must be fixed.
 no-compiler-targets := $(no-dot-config-targets) install dtbs_install \
@@ -1605,7 +1604,7 @@ MRPROPER_FILES += include/config include/generated          \
                  certs/signing_key.pem \
                  certs/x509.genkey \
                  vmlinux-gdb.py \
-                 *.spec \
+                 *.spec rpmbuild \
                  rust/libmacros.so
 
 # clean - Delete most, but leave enough to build external modules
@@ -1656,10 +1655,6 @@ distclean: mrproper
 %pkg: include/config/kernel.release FORCE
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@
 
-PHONY += scripts_package
-scripts_package: scripts_basic
-       $(Q)$(MAKE) $(build)=scripts scripts/list-gitignored
-
 # Brief documentation of the typical targets used
 # ---------------------------------------------------------------------------
 
@@ -1886,6 +1881,8 @@ endif
 
 else # KBUILD_EXTMOD
 
+filechk_kernel.release = echo $(KERNELRELEASE)
+
 ###
 # External module support.
 # When building external modules the kernel used as basis is considered
index e24a9820e12fa0bea7e8e9db4e1b773264681a98..f52afb74e6d9c27b7de8ecf8e5233577c2cafeb4 100644 (file)
@@ -497,8 +497,6 @@ source "arch/arm/mach-omap2/Kconfig"
 
 source "arch/arm/mach-orion5x/Kconfig"
 
-source "arch/arm/mach-oxnas/Kconfig"
-
 source "arch/arm/mach-pxa/Kconfig"
 
 source "arch/arm/mach-qcom/Kconfig"
@@ -986,7 +984,7 @@ config SMP
          uniprocessor machines. On a uniprocessor machine, the kernel
          will run faster if you say N here.
 
-         See also <file:Documentation/x86/i386/IO-APIC.rst>,
+         See also <file:Documentation/arch/x86/i386/IO-APIC.rst>,
          <file:Documentation/admin-guide/lockup-watchdogs.rst> and the SMP-HOWTO available at
          <http://tldp.org/HOWTO/SMP-HOWTO.html>.
 
index 485a439e22ca8340ac740b31875672cdc0351bc1..547e5856eaa0d3af398fe73301b9befa8aca7a3b 100644 (file)
@@ -203,7 +203,6 @@ machine-$(CONFIG_ARCH_MSTARV7)              += mstar
 machine-$(CONFIG_ARCH_NOMADIK)         += nomadik
 machine-$(CONFIG_ARCH_NPCM)            += npcm
 machine-$(CONFIG_ARCH_NSPIRE)          += nspire
-machine-$(CONFIG_ARCH_OXNAS)           += oxnas
 machine-$(CONFIG_ARCH_OMAP1)           += omap1
 machine-$(CONFIG_ARCH_OMAP2PLUS)       += omap2
 machine-$(CONFIG_ARCH_ORION5X)         += orion5x
index 2ef651a78fa2a979cdf3712c01f8481b69789093..726ecabcef0932dcc04f76d79ee806bb8f1d8ff1 100644 (file)
@@ -107,7 +107,7 @@ ccflags-remove-$(CONFIG_FUNCTION_TRACER) += -pg
 asflags-y := -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
-KBSS_SZ = $(shell echo $$(($$($(NM) $(obj)/../../../../vmlinux | \
+KBSS_SZ = $(shell echo $$(($$($(NM) vmlinux | \
                sed -n -e 's/^\([^ ]*\) [ABD] __bss_start$$/-0x\1/p' \
                       -e 's/^\([^ ]*\) [ABD] __bss_stop$$/+0x\1/p') )) )
 LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
index 94944cc219317fd43ab32971e0936f9dbb501de7..dd03e3860f97f901524570a89552adee135accce 100644 (file)
 
 &usbotg1 {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        srp-disable;
        hnp-disable;
index ace3eb8a97b87c4002be0db5e21cb294d9aeccb1..4e1bf080eaca012ae0d1f9e6e74696eaea41da28 100644 (file)
 
 &usbotg1 {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        srp-disable;
        hnp-disable;
index da1399057634a040321139407b0e3afecbddd149..815119c12bd48286df5bf2f0d936508d994c08a1 100644 (file)
 
 &usbotg1 {
        pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
        disable-over-current;
        srp-disable;
        hnp-disable;
index bf64ba84b358b59239d491fe2fd49fae0ffe7c03..fde8a19aac0f7c7411414ccc56091f3e1978e3ca 100644 (file)
                self-powered;
                type = "micro";
 
-               ports {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       port@0 {
-                               reg = <0>;
-                               usb_dr_connector: endpoint {
-                                       remote-endpoint = <&usb1_drd_sw>;
-                               };
+               port {
+                       usb_dr_connector: endpoint {
+                               remote-endpoint = <&usb1_drd_sw>;
                        };
                };
        };
index dc954e4f63e07fe95367ea947884e1da4a0f0b88..92cb45dacda616dafda44c32b2c1a78d85e09cc6 100644 (file)
                reg = <0x62>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_epdpmic>;
-               #address-cells = <1>;
-               #size-cells = <0>;
                #thermal-sensor-cells = <0>;
                epd-pwr-good-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
 
index de2fb1c01b6e348ea188f1d34b51baf045cd8774..b82381229adf6ebdb1533af643e781a6717e6791 100644 (file)
        };
 
        reserved-memory {
+               sbl_region: sbl@2f00000 {
+                       reg = <0x02f00000 0x100000>;
+                       no-map;
+               };
+
+               external_image_region: external-image@3100000 {
+                       reg = <0x03100000 0x200000>;
+                       no-map;
+               };
+
                adsp_region: adsp@3300000 {
                        reg = <0x03300000 0x1400000>;
                        no-map;
index 2fa7fdc60d278be1a690631c7d24f434f9c86789..cb9cdaddffd429187a6734b1fe075649544af238 100644 (file)
                status = "disabled";
        };
 
-       spdif: sound@ff88b0000 {
+       spdif: sound@ff8b0000 {
                compatible = "rockchip,rk3288-spdif", "rockchip,rk3066-spdif";
                reg = <0x0 0xff8b0000 0x0 0x10000>;
                #sound-dai-cells = <0>;
index da30a4d4f35cd0751da37d6dcae7592618df0543..309b7478346844987bf08f45fbb1b1190d50a2b0 100644 (file)
@@ -494,7 +494,7 @@ static int locomo_probe(struct platform_device *dev)
        return __locomo_probe(&dev->dev, mem, irq);
 }
 
-static int locomo_remove(struct platform_device *dev)
+static void locomo_remove(struct platform_device *dev)
 {
        struct locomo *lchip = platform_get_drvdata(dev);
 
@@ -502,8 +502,6 @@ static int locomo_remove(struct platform_device *dev)
                __locomo_remove(lchip);
                platform_set_drvdata(dev, NULL);
        }
-
-       return 0;
 }
 
 /*
@@ -514,7 +512,7 @@ static int locomo_remove(struct platform_device *dev)
  */
 static struct platform_driver locomo_device_driver = {
        .probe          = locomo_probe,
-       .remove         = locomo_remove,
+       .remove_new     = locomo_remove,
 #ifdef CONFIG_PM
        .suspend        = locomo_suspend,
        .resume         = locomo_resume,
index f5e6990b8856b6fe805491fcb4aeb32c2d1ca121..aad6ba236f0fa0cfe9dbaa8892c85df317addcc9 100644 (file)
@@ -1123,7 +1123,7 @@ static int sa1111_probe(struct platform_device *pdev)
        return __sa1111_probe(&pdev->dev, mem, irq);
 }
 
-static int sa1111_remove(struct platform_device *pdev)
+static void sa1111_remove(struct platform_device *pdev)
 {
        struct sa1111 *sachip = platform_get_drvdata(pdev);
 
@@ -1135,8 +1135,6 @@ static int sa1111_remove(struct platform_device *pdev)
                __sa1111_remove(sachip);
                platform_set_drvdata(pdev, NULL);
        }
-
-       return 0;
 }
 
 static struct dev_pm_ops sa1111_pm_ops = {
@@ -1155,7 +1153,7 @@ static struct dev_pm_ops sa1111_pm_ops = {
  */
 static struct platform_driver sa1111_device_driver = {
        .probe          = sa1111_probe,
-       .remove         = sa1111_remove,
+       .remove_new     = sa1111_remove,
        .driver         = {
                .name   = "sa1111",
                .pm     = &sa1111_pm_ops,
index e74c5bfdc6d311414370b5afe4f381b9d2f99755..9018c72401665488dbe63943532ac8cf985242c7 100644 (file)
@@ -236,7 +236,7 @@ err_ioremap:
        return ret;
 }
 
-static int scoop_remove(struct platform_device *pdev)
+static void scoop_remove(struct platform_device *pdev)
 {
        struct scoop_dev *sdev = platform_get_drvdata(pdev);
 
@@ -246,13 +246,11 @@ static int scoop_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
        iounmap(sdev->base);
        kfree(sdev);
-
-       return 0;
 }
 
 static struct platform_driver scoop_driver = {
        .probe          = scoop_probe,
-       .remove         = scoop_remove,
+       .remove_new     = scoop_remove,
        .suspend        = scoop_suspend,
        .resume         = scoop_resume,
        .driver         = {
index 711a79e9be007683bbffdcb50bd0d872e6a23132..c9a602aee7155014c008b254a4e79343c5a8fd1b 100644 (file)
@@ -160,7 +160,7 @@ CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_DMA=y
-CONFIG_IMX_SDMA=y
+CONFIG_IMX_SDMA=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_FSL_MX25_ADC=y
index 6dc6fed12af83065464c851554c58bd763da3428..62f2b897216015c2f51f32f576beb83e9a64913e 100644 (file)
@@ -76,7 +76,7 @@ CONFIG_RFKILL=y
 CONFIG_RFKILL_INPUT=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
-CONFIG_PCI_IMX6=y
+CONFIG_PCI_IMX6_HOST=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
@@ -128,6 +128,7 @@ CONFIG_CS89x0_PLATFORM=y
 # CONFIG_NET_VENDOR_MICREL is not set
 # CONFIG_NET_VENDOR_MICROCHIP is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_QCA7000_SPI=m
 # CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
@@ -213,8 +214,12 @@ CONFIG_GPIO_SIOX=m
 CONFIG_GPIO_MAX732X=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCF857X=y
+CONFIG_GPIO_BD71815=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_74X164=y
+CONFIG_W1=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_SLAVE_THERM=m
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_POWER_RESET_SYSCON_POWEROFF=y
@@ -223,6 +228,7 @@ CONFIG_RN5T618_POWER=m
 CONFIG_SENSORS_MC13783_ADC=y
 CONFIG_SENSORS_GPIO_FAN=y
 CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_PWM_FAN=y
 CONFIG_SENSORS_SY7636A=y
 CONFIG_THERMAL_STATISTICS=y
 CONFIG_THERMAL_WRITABLE_TRIPS=y
@@ -242,8 +248,10 @@ CONFIG_MFD_MC13XXX_I2C=y
 CONFIG_MFD_SY7636A=y
 CONFIG_MFD_RN5T618=y
 CONFIG_MFD_STMPE=y
+CONFIG_MFD_ROHM_BD71828=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_ANATOP=y
+CONFIG_REGULATOR_BD71815=y
 CONFIG_REGULATOR_DA9052=y
 CONFIG_REGULATOR_DA9062=y
 CONFIG_REGULATOR_DA9063=y
@@ -271,6 +279,7 @@ CONFIG_VIDEO_OV5645=m
 CONFIG_VIDEO_ADV7180=m
 CONFIG_IMX_IPUV3_CORE=y
 CONFIG_DRM=y
+CONFIG_DRM_I2C_NXP_TDA998X=y
 CONFIG_DRM_MSM=y
 CONFIG_DRM_PANEL_LVDS=y
 CONFIG_DRM_PANEL_SIMPLE=y
@@ -380,6 +389,7 @@ CONFIG_RTC_DRV_ISL1208=y
 CONFIG_RTC_DRV_PCF8523=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_BD70528=y
 CONFIG_RTC_DRV_RC5T619=y
 CONFIG_RTC_DRV_RV3029C2=y
 CONFIG_RTC_DRV_DA9063=y
@@ -396,6 +406,7 @@ CONFIG_STAGING=y
 CONFIG_STAGING_MEDIA=y
 CONFIG_VIDEO_IMX_MEDIA=y
 CONFIG_COMMON_CLK_PWM=y
+CONFIG_COMMON_CLK_BD718XX=y
 CONFIG_CLK_IMX8MM=y
 CONFIG_CLK_IMX8MN=y
 CONFIG_CLK_IMX8MP=y
@@ -403,6 +414,7 @@ CONFIG_CLK_IMX8MQ=y
 CONFIG_SOC_IMX8M=y
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_IIO=y
+CONFIG_IIO_ST_ACCEL_3AXIS=m
 CONFIG_MMA8452=y
 CONFIG_IMX7D_ADC=y
 CONFIG_RN5T618_ADC=y
index 084cc612ea23a1c7aabbf9af56b0117d21b38234..871fffe92187bf34cc3ec06f3bba07f77e39a787 100644 (file)
@@ -251,6 +251,7 @@ CONFIG_B53_SPI_DRIVER=m
 CONFIG_B53_MDIO_DRIVER=m
 CONFIG_B53_MMAP_DRIVER=m
 CONFIG_NET_DSA_BCM_SF2=m
+CONFIG_NET_DSA_RZN1_A5PSW=m
 CONFIG_SUN4I_EMAC=y
 CONFIG_SPI_AX88796C=m
 CONFIG_BCMGENET=m
@@ -474,6 +475,7 @@ CONFIG_PINCTRL_MSM8916=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_PINCTRL_QCOM_SSBI_PMIC=y
 CONFIG_PINCTRL_RZA2=y
+CONFIG_PINCTRL_RZN1=y
 CONFIG_GPIO_ASPEED_SGPIO=y
 CONFIG_GPIO_DAVINCI=y
 CONFIG_GPIO_DWAPB=y
@@ -563,6 +565,7 @@ CONFIG_MESON_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
 CONFIG_RENESAS_WDT=m
 CONFIG_RENESAS_RZAWDT=m
+CONFIG_RENESAS_RZN1WDT=m
 CONFIG_STPMIC1_WATCHDOG=y
 CONFIG_PM8916_WATCHDOG=m
 CONFIG_BCM47XX_WDT=y
@@ -873,6 +876,7 @@ CONFIG_USB_ISP1301=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=m
+CONFIG_USB_RENESAS_USBF=m
 CONFIG_USB_ASPEED_VHUB=m
 CONFIG_USB_CONFIGFS=m
 CONFIG_USB_CONFIGFS_SERIAL=y
@@ -989,6 +993,7 @@ CONFIG_RTC_DRV_SH=m
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_AT91RM9200=m
 CONFIG_RTC_DRV_AT91SAM9=m
+CONFIG_RTC_DRV_RZN1=m
 CONFIG_RTC_DRV_VT8500=y
 CONFIG_RTC_DRV_SUNXI=y
 CONFIG_RTC_DRV_MV=y
@@ -1020,6 +1025,7 @@ CONFIG_UNIPHIER_MDMAC=y
 CONFIG_XILINX_DMA=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_DW_DMAC=y
+CONFIG_RZN1_DMAMUX=m
 CONFIG_RCAR_DMAC=y
 CONFIG_RENESAS_USB_DMAC=m
 CONFIG_VIRTIO_PCI=y
@@ -1212,6 +1218,8 @@ CONFIG_FSI_MASTER_ASPEED=m
 CONFIG_FSI_SCOM=m
 CONFIG_FSI_SBEFIFO=m
 CONFIG_FSI_OCC=m
+CONFIG_TEE=y
+CONFIG_OPTEE=y
 CONFIG_INTERCONNECT_QCOM=y
 CONFIG_INTERCONNECT_QCOM_MSM8916=y
 CONFIG_COUNTER=m
diff --git a/arch/arm/configs/oxnas_v6_defconfig b/arch/arm/configs/oxnas_v6_defconfig
deleted file mode 100644 (file)
index 70a67b3..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-CONFIG_SYSVIPC=y
-CONFIG_NO_HZ_IDLE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_CGROUPS=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_ARCH_MULTI_V6=y
-CONFIG_ARCH_OXNAS=y
-CONFIG_MACH_OX820=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=16
-CONFIG_ARCH_FORCE_MAX_ORDER=12
-CONFIG_SECCOMP=y
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_KEXEC=y
-CONFIG_EFI=y
-CONFIG_CPU_IDLE=y
-CONFIG_ARM_CPUIDLE=y
-CONFIG_VFP=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_CMDLINE_PARTITION=y
-CONFIG_CMA=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_MIP6=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAW_NAND=y
-CONFIG_MTD_NAND_OXNAS=y
-CONFIG_MTD_UBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_NETDEVICES=y
-CONFIG_STMMAC_ETH=y
-CONFIG_REALTEK_PHY=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_GPIO_GENERIC_PLATFORM=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_CLASS_FLASH=m
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_ONESHOT=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_CPU=y
-CONFIG_LEDS_TRIGGER_GPIO=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_ARM_TIMER_SP804=y
-CONFIG_EXT4_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-CONFIG_UBIFS_FS=y
-CONFIG_PSTORE=y
-CONFIG_PSTORE_CONSOLE=y
-CONFIG_PSTORE_PMSG=y
-CONFIG_PSTORE_RAM=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_UTF8=y
-CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=64
-CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
index 751d939fcb761b31d4a434d8e07ed269aa43a575..0b21c0a4758286efe9f65bbd54ed51f7e8b40ab9 100644 (file)
@@ -76,6 +76,7 @@ CONFIG_SERIAL_8250=y
 # CONFIG_SERIAL_8250_16550A_VARIANTS is not set
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_PCI1XXXX is not set
 CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_8250_EM=y
 # CONFIG_SERIAL_8250_PERICOM is not set
@@ -168,6 +169,7 @@ CONFIG_USB_R8A66597_HCD=y
 CONFIG_USB_RENESAS_USBHS=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=y
+CONFIG_USB_RENESAS_USBF=y
 CONFIG_USB_ETH=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
index 3bdc217667a6fabf9c2e7fb91d7d7cbb2ef7b678..0f55815eecb37bdd12d832103c9d6414b4fca312 100644 (file)
@@ -38,6 +38,10 @@ CONFIG_CFG80211_DEBUGFS=y
 CONFIG_MAC80211=y
 CONFIG_MAC80211_LEDS=y
 CONFIG_CAIF=y
+CONFIG_NFC=m
+CONFIG_NFC_HCI=m
+CONFIG_NFC_SHDLC=m
+CONFIG_NFC_PN544_I2C=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_GNSS=y
@@ -180,10 +184,8 @@ CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
-CONFIG_CRYPTO_DEV_UX500=y
-CONFIG_CRYPTO_DEV_UX500_CRYP=y
-CONFIG_CRYPTO_DEV_UX500_HASH=y
-CONFIG_CRYPTO_DEV_UX500_DEBUG=y
+CONFIG_CRYPTO_DEV_STM32_HASH=y
+CONFIG_CRYPTO_DEV_STM32_CRYP=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
index ac3fd7523698206f4547a308f263c62c45fe1990..96ad442089bd62b1bd1259b9e11c3f0260299113 100644 (file)
@@ -1,5 +1,7 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_FULL=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -42,6 +44,7 @@ CONFIG_NET_9P_VIRTIO=y
 CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
@@ -137,5 +140,4 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_USER=y
index 06b48ce23e1ca245fb87d68d6a26213d6bff6dd5..505a306e0271a9c44b7f78db3f653372e4133523 100644 (file)
@@ -244,19 +244,6 @@ THUMB(     fpreg   .req    r7      )
        .endm
 #endif
 
-       .macro  local_bh_disable, ti, tmp
-       ldr     \tmp, [\ti, #TI_PREEMPT]
-       add     \tmp, \tmp, #SOFTIRQ_DISABLE_OFFSET
-       str     \tmp, [\ti, #TI_PREEMPT]
-       .endm
-
-       .macro  local_bh_enable_ti, ti, tmp
-       get_thread_info \ti
-       ldr     \tmp, [\ti, #TI_PREEMPT]
-       sub     \tmp, \tmp, #SOFTIRQ_DISABLE_OFFSET
-       str     \tmp, [\ti, #TI_PREEMPT]
-       .endm
-
 #define USERL(l, x...)                         \
 9999:  x;                                      \
        .pushsection __ex_table,"a";            \
index 14eecaaf295fabacb68ac687912eb8f8c1da7a46..e4c2677cc1e9e45cac842f71d88267cb3cce32ac 100644 (file)
@@ -116,7 +116,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
                        tocopy = n;
 
                ua_flags = uaccess_save_and_enable();
-               memcpy((void *)to, from, tocopy);
+               __memcpy((void *)to, from, tocopy);
                uaccess_restore(ua_flags);
                to += tocopy;
                from += tocopy;
@@ -178,7 +178,7 @@ __clear_user_memset(void __user *addr, unsigned long n)
                        tocopy = n;
 
                ua_flags = uaccess_save_and_enable();
-               memset((void *)addr, 0, tocopy);
+               __memset((void *)addr, 0, tocopy);
                uaccess_restore(ua_flags);
                addr += tocopy;
                n -= tocopy;
index 185335843bbd58df9ab1b01088ab621d37190f32..f236e12d7a59c4d7fe529fbad7aaa131b9e1ba70 100644 (file)
@@ -31,34 +31,23 @@ static const struct of_device_id bcm_kona_smc_ids[] __initconst = {
 int __init bcm_kona_smc_init(void)
 {
        struct device_node *node;
-       const __be32 *prop_val;
-       u64 prop_size = 0;
-       unsigned long buffer_size;
-       u32 buffer_phys;
+       struct resource res;
+       int ret;
 
        /* Read buffer addr and size from the device tree node */
        node = of_find_matching_node(NULL, bcm_kona_smc_ids);
        if (!node)
                return -ENODEV;
 
-       prop_val = of_get_address(node, 0, &prop_size, NULL);
+       ret = of_address_to_resource(node, 0, &res);
        of_node_put(node);
-       if (!prop_val)
+       if (ret)
                return -EINVAL;
 
-       /* We assume space for four 32-bit arguments */
-       if (prop_size < 4 * sizeof(u32) || prop_size > (u64)ULONG_MAX)
-               return -EINVAL;
-       buffer_size = (unsigned long)prop_size;
-
-       buffer_phys = be32_to_cpup(prop_val);
-       if (!buffer_phys)
-               return -EINVAL;
-
-       bcm_smc_buffer = ioremap(buffer_phys, buffer_size);
+       bcm_smc_buffer = ioremap(res.start, resource_size(&res));
        if (!bcm_smc_buffer)
                return -ENOMEM;
-       bcm_smc_buffer_phys = buffer_phys;
+       bcm_smc_buffer_phys = res.start;
 
        pr_info("Kona Secure API initialized\n");
 
index 51a247ca4da8c86244247431ee4f16e6a7da4418..966a0995e0475636cfbd1f706251a3ee2f30cbd2 100644 (file)
@@ -50,11 +50,13 @@ void __init exynos_sysram_init(void)
        struct device_node *node;
 
        for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
+               struct resource res;
                if (!of_device_is_available(node))
                        continue;
-               sysram_base_addr = of_iomap(node, 0);
-               sysram_base_phys = of_translate_address(node,
-                                          of_get_address(node, 0, NULL, NULL));
+
+               of_address_to_resource(node, 0, &res);
+               sysram_base_addr = ioremap(res.start, resource_size(&res));
+               sysram_base_phys = res.start;
                of_node_put(node);
                break;
        }
index 3bf14ca78b62b830b4321af0d3e5543ef7823a56..6d5d7696aaf71c3684196eb8505db8b6bc0c8e61 100644 (file)
@@ -667,7 +667,7 @@ void __init exynos_pm_init(void)
                return;
        }
 
-       if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
+       if (WARN_ON(!of_property_read_bool(np, "interrupt-controller"))) {
                pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
                of_node_put(np);
                return;
index ebc4339b8be48797e6923536909bf7810a02de76..5909088d54822d728e3e2f37c4156d930702dc12 100644 (file)
@@ -275,7 +275,7 @@ void __init imx_gpc_check_dt(void)
        if (WARN_ON(!np))
                return;
 
-       if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
+       if (WARN_ON(!of_property_read_bool(np, "interrupt-controller"))) {
                pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
 
                /* map GPC, so that at least CPUidle and WARs keep working */
index c9d7c29d95e1e1eddf08196f7e42c34b7de496f4..7f62009257526f6173da6b5c89834ccc6b62641a 100644 (file)
@@ -79,7 +79,7 @@ static void __init imx6q_enet_phy_init(void)
 static void __init imx6q_1588_init(void)
 {
        struct device_node *np;
-       struct clk *ptp_clk;
+       struct clk *ptp_clk, *fec_enet_ref;
        struct clk *enet_ref;
        struct regmap *gpr;
        u32 clksel;
@@ -90,6 +90,14 @@ static void __init imx6q_1588_init(void)
                return;
        }
 
+       /*
+        * If enet_clk_ref configured, we assume DT did it properly and .
+        * clk-imx6q.c will do needed configuration.
+        */
+       fec_enet_ref = of_clk_get_by_name(np, "enet_clk_ref");
+       if (!IS_ERR(fec_enet_ref))
+               goto put_node;
+
        ptp_clk = of_clk_get(np, 2);
        if (IS_ERR(ptp_clk)) {
                pr_warn("%s: failed to get ptp clock\n", __func__);
index dbf8d19cef1163cb7a84b03f7bef3039d939bf43..7a0299de1db65238ad2a956495a196e53c7251c5 100644 (file)
@@ -4,8 +4,6 @@
  */
 #include <linux/irqchip.h>
 #include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-#include <linux/micrel_phy.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
 #include <linux/regmap.h>
 #include "cpuidle.h"
 #include "hardware.h"
 
-static void __init imx6ul_enet_clk_init(void)
-{
-       struct regmap *gpr;
-
-       gpr = syscon_regmap_lookup_by_compatible("fsl,imx6ul-iomuxc-gpr");
-       if (!IS_ERR(gpr))
-               regmap_update_bits(gpr, IOMUXC_GPR1, IMX6UL_GPR1_ENET_CLK_DIR,
-                                  IMX6UL_GPR1_ENET_CLK_OUTPUT);
-       else
-               pr_err("failed to find fsl,imx6ul-iomux-gpr regmap\n");
-}
-
-static inline void imx6ul_enet_init(void)
-{
-       imx6ul_enet_clk_init();
-}
-
 static void __init imx6ul_init_machine(void)
 {
        imx_print_silicon_rev(cpu_is_imx6ull() ? "i.MX6ULL" : "i.MX6UL",
                imx_get_soc_revision());
 
        of_platform_default_populate(NULL, NULL, NULL);
-       imx6ul_enet_init();
        imx_anatop_init();
        imx6ul_pm_init();
 }
index b9efe9da06e0bb55c85ca478cbfc04bc4fedade7..2157493b78a9bd3cbb98508b29d504ca5d196281 100644 (file)
@@ -456,7 +456,7 @@ static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc,
        return pmu_mmdc->id;
 }
 
-static int imx_mmdc_remove(struct platform_device *pdev)
+static void imx_mmdc_remove(struct platform_device *pdev)
 {
        struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev);
 
@@ -466,7 +466,6 @@ static int imx_mmdc_remove(struct platform_device *pdev)
        iounmap(pmu_mmdc->mmdc_base);
        clk_disable_unprepare(pmu_mmdc->mmdc_ipg_clk);
        kfree(pmu_mmdc);
-       return 0;
 }
 
 static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base,
@@ -592,7 +591,7 @@ static struct platform_driver imx_mmdc_driver = {
                .of_match_table = imx_mmdc_dt_ids,
        },
        .probe          = imx_mmdc_probe,
-       .remove         = imx_mmdc_remove,
+       .remove_new     = imx_mmdc_remove,
 };
 
 static int __init imx_mmdc_init(void)
index 85b0d9ddb7d822338e6d789ae0f64e864ffe5969..8c1d4402fd693eeb9353f0f16ca97febaba2d807 100644 (file)
@@ -76,10 +76,4 @@ config CPU_MMP2
        help
          Select code specific to MMP2. MMP2 is ARMv7 compatible.
 
-config USB_EHCI_MV_U2O
-        bool "EHCI support for PXA USB OTG controller"
-       depends on USB_EHCI_MV
-       help
-         Enables support for OTG controller which can be switched to host mode.
-
 endif
index 5dbea7b485af6be83a192971169390eaa1043e15..fa9709f30b4663eed490e2943e973baea0ddf6ee 100644 (file)
@@ -20,11 +20,4 @@ config MACH_INFINITY
        help
          Support for MStar/Sigmastar infinity IP camera SoCs.
 
-config MACH_MERCURY
-       bool "MStar/Sigmastar mercury SoC support"
-       default ARCH_MSTARV7
-       help
-         Support for MStar/Sigmastar mercury dash camera SoCs.
-         Note that older Mercury2 SoCs are ARM9 based and not supported.
-
 endif
index 9aa765d4cdc8a486bde42443384d05efd6d9fb9c..62e982f74bc254f35d71410f489a7327342a32d5 100644 (file)
@@ -14,6 +14,9 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/ethtool.h>
 #include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include "mv78xx0.h"
 #include "mpp.h"
 
 
+#define TSWXL_AUTO_SWITCH      15
+#define TSWXL_USB_POWER1       30
+#define TSWXL_USB_POWER2       31
+
+
 /* This arch has 2 Giga Ethernet */
 
 static struct mv643xx_eth_platform_data db78x00_ge00_data = {
@@ -39,7 +47,7 @@ static struct mv_sata_platform_data db78x00_sata_data = {
 };
 
 static struct i2c_board_info __initdata db78x00_i2c_rtc = {
-       I2C_BOARD_INFO("ds1338", 0x68),
+       I2C_BOARD_INFO("rs5c372a", 0x32),
 };
 
 
@@ -57,9 +65,9 @@ static unsigned int wxl_mpp_config[] __initdata = {
        MPP10_GE1_RXD2,
        MPP11_GE1_RXD3,
        MPP12_GPIO,
-       MPP13_SYSRST_OUTn,
-       MPP14_SATA1_ACTn,
-       MPP15_SATA0_ACTn,
+       MPP13_GPIO,
+       MPP14_GPIO,
+       MPP15_GPIO,
        MPP16_GPIO,
        MPP17_GPIO,
        MPP18_GPIO,
@@ -73,7 +81,7 @@ static unsigned int wxl_mpp_config[] __initdata = {
        MPP26_UA2_CTSn,
        MPP27_UA2_RTSn,
        MPP28_GPIO,
-       MPP29_SYSRST_OUTn,
+       MPP29_GPIO,
        MPP30_GPIO,
        MPP31_GPIO,
        MPP32_GPIO,
@@ -84,19 +92,41 @@ static unsigned int wxl_mpp_config[] __initdata = {
        MPP37_GPIO,
        MPP38_GPIO,
        MPP39_GPIO,
-       MPP40_UNUSED,
-       MPP41_UNUSED,
-       MPP42_UNUSED,
-       MPP43_UNUSED,
-       MPP44_UNUSED,
-       MPP45_UNUSED,
-       MPP46_UNUSED,
-       MPP47_UNUSED,
-       MPP48_SATA1_ACTn,
-       MPP49_SATA0_ACTn,
+       MPP40_GPIO,
+       MPP41_GPIO,
+       MPP42_GPIO,
+       MPP43_GPIO,
+       MPP44_GPIO,
+       MPP45_GPIO,
+       MPP46_GPIO,
+       MPP47_GPIO,
+       MPP48_GPIO,
+       MPP49_GPIO,
        0
 };
 
+static struct gpio_keys_button tswxl_buttons[] = {
+       {
+               .code      = KEY_OPTION,
+               .gpio      = TSWXL_AUTO_SWITCH,
+               .desc      = "Power-auto Switch",
+               .active_low     = 1,
+       }
+};
+
+static struct gpio_keys_platform_data tswxl_button_data = {
+       .buttons        = tswxl_buttons,
+       .nbuttons       = ARRAY_SIZE(tswxl_buttons),
+};
+
+static struct platform_device tswxl_button_device = {
+       .name      = "gpio-keys",
+       .id          = -1,
+       .num_resources  = 0,
+       .dev        = {
+               .platform_data  = &tswxl_button_data,
+       },
+};
 
 static void __init wxl_init(void)
 {
@@ -111,7 +141,6 @@ static void __init wxl_init(void)
         */
        mv78xx0_ehci0_init();
        mv78xx0_ehci1_init();
-       mv78xx0_ehci2_init();
        mv78xx0_ge00_init(&db78x00_ge00_data);
        mv78xx0_ge01_init(&db78x00_ge01_data);
        mv78xx0_sata_init(&db78x00_sata_data);
@@ -119,22 +148,23 @@ static void __init wxl_init(void)
        mv78xx0_uart1_init();
        mv78xx0_uart2_init();
        mv78xx0_uart3_init();
+       mv78xx0_xor_init();
+       mv78xx0_crypto_init();
        mv78xx0_i2c_init();
        i2c_register_board_info(0, &db78x00_i2c_rtc, 1);
+
+       //enable both usb ports
+       gpio_direction_output(TSWXL_USB_POWER1, 1);
+       gpio_direction_output(TSWXL_USB_POWER2, 1);
+
+       //enable rear switch
+       platform_device_register(&tswxl_button_device);
 }
 
 static int __init wxl_pci_init(void)
 {
-       if (machine_is_terastation_wxl()) {
-               /*
-                * Assign the x16 PCIe slot on the board to CPU core
-                * #0, and let CPU core #1 have the four x1 slots.
-                */
-               if (mv78xx0_core_index() == 0)
-                       mv78xx0_pcie_init(0, 1);
-               else
-                       mv78xx0_pcie_init(1, 0);
-       }
+       if (machine_is_terastation_wxl() && mv78xx0_core_index() == 0)
+                mv78xx0_pcie_init(1, 1);
 
        return 0;
 }
index 461a68945c26ebddc64a50b9dc903b2d9f62c606..679753fcc0ef1a2aa9504ad34875ead171e46424 100644 (file)
@@ -342,6 +342,29 @@ void __ref mv78xx0_timer_init(void)
                        IRQ_MV78XX0_TIMER_1, get_tclk());
 }
 
+/****************************************************************************
+* XOR engine
+****************************************************************************/
+void __init mv78xx0_xor_init(void)
+{
+       orion_xor0_init(XOR_PHYS_BASE,
+               XOR_PHYS_BASE + 0x200,
+               IRQ_MV78XX0_XOR_0, IRQ_MV78XX0_XOR_1);
+}
+
+/****************************************************************************
+ * Cryptographic Engines and Security Accelerator (CESA)
+****************************************************************************/
+void __init mv78xx0_crypto_init(void)
+{
+       mvebu_mbus_add_window_by_id(MV78XX0_MBUS_SRAM_TARGET,
+                               MV78XX0_MBUS_SRAM_ATTR,
+                               MV78XX0_SRAM_PHYS_BASE,
+                       MV78XX0_SRAM_SIZE);
+       orion_crypto_init(CRYPTO_PHYS_BASE, MV78XX0_SRAM_PHYS_BASE,
+               SZ_8K, IRQ_MV78XX0_CRYPTO);
+}
+
 
 /*****************************************************************************
  * General
index d8c6c2400e27837287db0cc00f11ab38f9d850cb..9f1dfd595003af7f2a5312b5c9e68dce969a2b9d 100644 (file)
@@ -43,6 +43,8 @@ void mv78xx0_uart0_init(void);
 void mv78xx0_uart1_init(void);
 void mv78xx0_uart2_init(void);
 void mv78xx0_uart3_init(void);
+void mv78xx0_xor_init(void);
+void mv78xx0_crypto_init(void);
 void mv78xx0_i2c_init(void);
 void mv78xx0_restart(enum reboot_mode, const char *);
 
index 3f19bef7d7acecd418fddc76ba93ead56de157a2..88efb1e441427c9b88eb99e866b60001787af6f9 100644 (file)
 #define MV78XX0_REGS_VIRT_BASE         IOMEM(0xfec00000)
 #define MV78XX0_REGS_SIZE              SZ_1M
 
+#define MV78XX0_SRAM_PHYS_BASE          (0xf2200000)
+#define MV78XX0_SRAM_SIZE               SZ_8K
+
 #define MV78XX0_PCIE_MEM_PHYS_BASE     0xc0000000
 #define MV78XX0_PCIE_MEM_SIZE          0x30000000
 
+#define MV78XX0_MBUS_SRAM_TARGET       0x09
+#define MV78XX0_MBUS_SRAM_ATTR         0x00
+
 /*
  * Core-specific peripheral registers.
  */
 #define USB1_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x51000)
 #define USB2_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x52000)
 
+#define XOR_PHYS_BASE          (MV78XX0_REGS_PHYS_BASE + 0x60900)
+
 #define GE00_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x70000)
 #define GE01_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0x74000)
 
 #define PCIE12_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x88000)
 #define PCIE13_VIRT_BASE       (MV78XX0_REGS_VIRT_BASE + 0x8c000)
 
+#define CRYPTO_PHYS_BASE       (MV78XX0_REGS_PHYS_BASE + 0x90000)
+
 #define SATA_PHYS_BASE         (MV78XX0_REGS_PHYS_BASE + 0xa0000)
 
 /*
index 6190f538a124f574867c11f64de6f519aed09915..fa68b63941b153a2a8e0cdf2edc8528f7d21ee37 100644 (file)
@@ -42,7 +42,7 @@ void __init mv78xx0_pcie_id(u32 *dev, u32 *rev)
 
 u32 pcie_port_size[8] = {
        0,
-       0x30000000,
+       0x20000000,
        0x10000000,
        0x10000000,
        0x08000000,
index 0129b7c514d755735eeadf678cbebdf1f658ed7a..51e47053c81667d7d89dce10f518e02c241f2146 100644 (file)
@@ -174,7 +174,7 @@ static void __init update_fec_mac_prop(enum mac_oui oui)
 
                from = np;
 
-               if (of_get_property(np, "local-mac-address", NULL))
+               if (of_property_present(np, "local-mac-address"))
                        continue;
 
                newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
index 8df9a4de0e7953c623d627fef2c5ce81710d0f50..cbf703f0d850f65abd62b1ed5bf18d465ab80291 100644 (file)
@@ -118,7 +118,7 @@ config MACH_OMAP_OSK
        depends on ARCH_OMAP16XX
        help
          TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
-          if you have such a board.
+         if you have such a board.
 
 config MACH_OMAP_PALMTE
        bool "Palm Tungsten E"
index 0f67ac4c6fd25c3808f1e6fd0dc0c63207cab439..9108c871d129a82401de41ce7344f06499a18389 100644 (file)
@@ -822,8 +822,6 @@ static int __init modem_nreset_init(void)
  */
 static int __init ams_delta_modem_init(void)
 {
-       int err;
-
        if (!machine_is_ams_delta())
                return -ENODEV;
 
@@ -832,9 +830,7 @@ static int __init ams_delta_modem_init(void)
        /* Initialize the modem_nreset regulator consumer before use */
        modem_priv.regulator = ERR_PTR(-ENODEV);
 
-       err = platform_device_register(&ams_delta_modem_device);
-
-       return err;
+       return platform_device_register(&ams_delta_modem_device);
 }
 arch_initcall_sync(ams_delta_modem_init);
 
index f7e62de427f3bad12f5d0041f5296cab17208d76..9ee472f8ead12f9834e685a1e31b1f553d9469ec 100644 (file)
@@ -833,7 +833,7 @@ exit_dma_irq_fail:
        return ret;
 }
 
-static int omap_system_dma_remove(struct platform_device *pdev)
+static void omap_system_dma_remove(struct platform_device *pdev)
 {
        int dma_irq, irq_rel = 0;
 
@@ -841,13 +841,11 @@ static int omap_system_dma_remove(struct platform_device *pdev)
                dma_irq = platform_get_irq(pdev, irq_rel);
                free_irq(dma_irq, (void *)(irq_rel + 1));
        }
-
-       return 0;
 }
 
 static struct platform_driver omap_system_dma_driver = {
        .probe          = omap_system_dma_probe,
-       .remove         = omap_system_dma_remove,
+       .remove_new     = omap_system_dma_remove,
        .driver         = {
                .name   = "omap_dma_system"
        },
index 3b53dda9ec79d8ecc72d2f097f9836730f3ad448..821727eefd5ad4c5322849152212e1914171af9d 100644 (file)
@@ -255,17 +255,6 @@ config MACH_NOKIA_N8X0
        select MACH_NOKIA_N810
        select MACH_NOKIA_N810_WIMAX
 
-config OMAP3_SDRC_AC_TIMING
-       bool "Enable SDRC AC timing register changes"
-       depends on ARCH_OMAP3
-       help
-         If you know that none of your system initiators will attempt to
-         access SDRAM during CORE DVFS, select Y here.  This should boost
-         SDRAM performance at lower CORE OPPs.  There are relatively few
-         users who will wish to say yes at this point - almost everyone will
-         wish to say no.  Selecting yes without understanding what is
-         going on could result in system crashes;
-
 endmenu
 
 endif
index d61fa06117b4291b26d368effa340015fa638cf6..c824d4e3db632c9ff1827ae6fff31d4ac96d94ba 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 2011-2012 Texas Instruments Incorporated - https://www.ti.com/
  * Vaibhav Hiremath <hvaibhav@ti.com>
  *
- * Reference taken from from OMAP4 cminst44xx.c
+ * Reference taken from OMAP4 cminst44xx.c
  */
 
 #include <linux/kernel.h>
index 5a2a9b8e61ed2c970f418d7a8a9476d342686c9a..aac4c4ee2528170a3eb216edc4c5ca1f14788bd2 100644 (file)
@@ -706,9 +706,7 @@ static const struct of_device_id ti_clkctrl_match_table[] __initconst = {
 
 static int __init _setup_clkctrl_provider(struct device_node *np)
 {
-       const __be32 *addrp;
        struct clkctrl_provider *provider;
-       u64 size;
        int i;
 
        provider = memblock_alloc(sizeof(*provider), SMP_CACHE_BYTES);
@@ -717,8 +715,7 @@ static int __init _setup_clkctrl_provider(struct device_node *np)
 
        provider->node = np;
 
-       provider->num_addrs =
-               of_property_count_elems_of_size(np, "reg", sizeof(u32)) / 2;
+       provider->num_addrs = of_address_count(np);
 
        provider->addr =
                memblock_alloc(sizeof(void *) * provider->num_addrs,
@@ -733,11 +730,11 @@ static int __init _setup_clkctrl_provider(struct device_node *np)
                return -ENOMEM;
 
        for (i = 0; i < provider->num_addrs; i++) {
-               addrp = of_get_address(np, i, &size, NULL);
-               provider->addr[i] = (u32)of_translate_address(np, addrp);
-               provider->size[i] = size;
-               pr_debug("%s: %pOF: %x...%x\n", __func__, np, provider->addr[i],
-                        provider->addr[i] + provider->size[i]);
+               struct resource res;
+               of_address_to_resource(np, i, &res);
+               provider->addr[i] = res.start;
+               provider->size[i] = resource_size(&res);
+               pr_debug("%s: %pOF: %pR\n", __func__, np, &res);
        }
 
        list_add(&provider->link, &clkctrl_providers);
@@ -2322,11 +2319,11 @@ static int __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data,
 static void __init parse_module_flags(struct omap_hwmod *oh,
                                      struct device_node *np)
 {
-       if (of_find_property(np, "ti,no-reset-on-init", NULL))
+       if (of_property_read_bool(np, "ti,no-reset-on-init"))
                oh->flags |= HWMOD_INIT_NO_RESET;
-       if (of_find_property(np, "ti,no-idle-on-init", NULL))
+       if (of_property_read_bool(np, "ti,no-idle-on-init"))
                oh->flags |= HWMOD_INIT_NO_IDLE;
-       if (of_find_property(np, "ti,no-idle", NULL))
+       if (of_property_read_bool(np, "ti,no-idle"))
                oh->flags |= HWMOD_NO_IDLE;
 }
 
@@ -3457,7 +3454,7 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
        }
 
        if (list_empty(&oh->slave_ports)) {
-               oi = kcalloc(1, sizeof(*oi), GFP_KERNEL);
+               oi = kzalloc(sizeof(*oi), GFP_KERNEL);
                if (!oi)
                        goto out_free_class;
 
index 711bcc6c8dddc253458d19903430b07486d99563..c907478be196ede8d6367706ca8a8d310bfa6292 100644 (file)
@@ -104,8 +104,6 @@ static int amx3_common_init(int (*idle)(u32 wfi_flags))
 
 static int am33xx_suspend_init(int (*idle)(u32 wfi_flags))
 {
-       int ret;
-
        gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm");
 
        if (!gfx_l4ls_clkdm) {
@@ -113,9 +111,7 @@ static int am33xx_suspend_init(int (*idle)(u32 wfi_flags))
                return -ENODEV;
        }
 
-       ret = amx3_common_init(idle);
-
-       return ret;
+       return amx3_common_init(idle);
 }
 
 static int am43xx_suspend_init(int (*idle)(u32 wfi_flags))
diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
deleted file mode 100644 (file)
index a9ded70..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig ARCH_OXNAS
-       bool "Oxford Semiconductor OXNAS Family SoCs"
-       depends on (ARCH_MULTI_V5 && CPU_LITTLE_ENDIAN) || ARCH_MULTI_V6
-       select ARCH_HAS_RESET_CONTROLLER
-       select COMMON_CLK_OXNAS
-       select GPIOLIB
-       select MFD_SYSCON
-       select OXNAS_RPS_TIMER
-       select PINCTRL_OXNAS
-       select RESET_CONTROLLER
-       select RESET_OXNAS
-       select VERSATILE_FPGA_IRQ
-       select PINCTRL
-       help
-         Support for OxNas SoC family developed by Oxford Semiconductor.
-
-if ARCH_OXNAS
-
-config MACH_OX810SE
-       bool "Support OX810SE Based Products"
-       depends on ARCH_MULTI_V5
-       select CPU_ARM926T
-       help
-         Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
-
-config MACH_OX820
-       bool "Support OX820 Based Products"
-       depends on ARCH_MULTI_V6
-       select ARM_GIC
-       select DMA_CACHE_RWFO if SMP
-       select HAVE_SMP
-       select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if SMP
-       help
-         Include Support for the Oxford Semiconductor OX820 SoC Based Products.
-
-endif
diff --git a/arch/arm/mach-oxnas/Makefile b/arch/arm/mach-oxnas/Makefile
deleted file mode 100644 (file)
index 0e78ecf..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
diff --git a/arch/arm/mach-oxnas/headsmp.S b/arch/arm/mach-oxnas/headsmp.S
deleted file mode 100644 (file)
index 9c0f147..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
- * Copyright (c) 2003 ARM Limited
- * All Rights Reserved
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-       __INIT
-
-/*
- * OX820 specific entry point for secondary CPUs.
- */
-ENTRY(ox820_secondary_startup)
-       mov r4, #0
-       /* invalidate both caches and branch target cache */
-       mcr p15, 0, r4, c7, c7, 0
-       /*
-        * we've been released from the holding pen: secondary_stack
-        * should now contain the SVC stack for this core
-        */
-       b       secondary_startup
diff --git a/arch/arm/mach-oxnas/platsmp.c b/arch/arm/mach-oxnas/platsmp.c
deleted file mode 100644 (file)
index f0a50b9..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
- * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
- * Copyright (C) 2002 ARM Ltd.
- * All Rights Reserved
- */
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <asm/cacheflush.h>
-#include <asm/cp15.h>
-#include <asm/smp_plat.h>
-#include <asm/smp_scu.h>
-
-extern void ox820_secondary_startup(void);
-
-static void __iomem *cpu_ctrl;
-static void __iomem *gic_cpu_ctrl;
-
-#define HOLDINGPEN_CPU_OFFSET          0xc8
-#define HOLDINGPEN_LOCATION_OFFSET     0xc4
-
-#define GIC_NCPU_OFFSET(cpu)           (0x100 + (cpu)*0x100)
-#define GIC_CPU_CTRL                   0x00
-#define GIC_CPU_CTRL_ENABLE            1
-
-static int __init ox820_boot_secondary(unsigned int cpu,
-               struct task_struct *idle)
-{
-       /*
-        * Write the address of secondary startup into the
-        * system-wide flags register. The BootMonitor waits
-        * until it receives a soft interrupt, and then the
-        * secondary CPU branches to this address.
-        */
-       writel(virt_to_phys(ox820_secondary_startup),
-                       cpu_ctrl + HOLDINGPEN_LOCATION_OFFSET);
-
-       writel(cpu, cpu_ctrl + HOLDINGPEN_CPU_OFFSET);
-
-       /*
-        * Enable GIC cpu interface in CPU Interface Control Register
-        */
-       writel(GIC_CPU_CTRL_ENABLE,
-               gic_cpu_ctrl + GIC_NCPU_OFFSET(cpu) + GIC_CPU_CTRL);
-
-       /*
-        * Send the secondary CPU a soft interrupt, thereby causing
-        * the boot monitor to read the system wide flags register,
-        * and branch to the address found there.
-        */
-       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
-
-       return 0;
-}
-
-static void __init ox820_smp_prepare_cpus(unsigned int max_cpus)
-{
-       struct device_node *np;
-       void __iomem *scu_base;
-
-       np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-scu");
-       scu_base = of_iomap(np, 0);
-       of_node_put(np);
-       if (!scu_base)
-               return;
-
-       /* Remap CPU Interrupt Interface Registers */
-       np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-gic");
-       gic_cpu_ctrl = of_iomap(np, 1);
-       of_node_put(np);
-       if (!gic_cpu_ctrl)
-               goto unmap_scu;
-
-       np = of_find_compatible_node(NULL, NULL, "oxsemi,ox820-sys-ctrl");
-       cpu_ctrl = of_iomap(np, 0);
-       of_node_put(np);
-       if (!cpu_ctrl)
-               goto unmap_scu;
-
-       scu_enable(scu_base);
-       flush_cache_all();
-
-unmap_scu:
-       iounmap(scu_base);
-}
-
-static const struct smp_operations ox820_smp_ops __initconst = {
-       .smp_prepare_cpus       = ox820_smp_prepare_cpus,
-       .smp_boot_secondary     = ox820_boot_secondary,
-};
-
-CPU_METHOD_OF_DECLARE(ox820_smp, "oxsemi,ox820-smp", &ox820_smp_ops);
index 96f33ef1d9ea283e7e316d80777e60eb674dba0a..a9ef71008147293c5db931d1117e58cf555d0794 100644 (file)
@@ -257,8 +257,7 @@ void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
        }
        pxa_irq_base = io_p2v(res.start);
 
-       if (of_find_property(node, "marvell,intc-priority", NULL))
-               cpu_has_ipr = 1;
+       cpu_has_ipr = of_property_read_bool(node, "marvell,intc-priority");
 
        ret = irq_alloc_descs(-1, 0, pxa_internal_irq_nr, 0);
        if (ret < 0) {
index 929cc51ed7c2271fcf0834ca1a52a5a3cb87135e..d29bdcd5270e0f50ccffc0a47f85e8edac0ec0dd 100644 (file)
@@ -890,7 +890,7 @@ static int sharpsl_pm_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int sharpsl_pm_remove(struct platform_device *pdev)
+static void sharpsl_pm_remove(struct platform_device *pdev)
 {
        suspend_set_ops(NULL);
 
@@ -917,13 +917,11 @@ static int sharpsl_pm_remove(struct platform_device *pdev)
 
        del_timer_sync(&sharpsl_pm.chrg_full_timer);
        del_timer_sync(&sharpsl_pm.ac_timer);
-
-       return 0;
 }
 
 static struct platform_driver sharpsl_pm_driver = {
        .probe          = sharpsl_pm_probe,
-       .remove         = sharpsl_pm_remove,
+       .remove_new     = sharpsl_pm_remove,
        .suspend        = sharpsl_pm_suspend,
        .resume         = sharpsl_pm_resume,
        .driver         = {
index 1dbe98948ce30c3da627c66d4ee803662446eab7..67f72ca984b2f5ffc9c79ad5fb8bb8d33a08eec2 100644 (file)
@@ -175,18 +175,17 @@ static int jornada_ssp_probe(struct platform_device *dev)
        return 0;
 };
 
-static int jornada_ssp_remove(struct platform_device *dev)
+static void jornada_ssp_remove(struct platform_device *dev)
 {
        /* Note that this doesn't actually remove the driver, since theres nothing to remove
         * It just makes sure everything is turned off */
        GPSR = GPIO_GPIO25;
        ssp_exit();
-       return 0;
 };
 
 struct platform_driver jornadassp_driver = {
        .probe  = jornada_ssp_probe,
-       .remove = jornada_ssp_remove,
+       .remove_new = jornada_ssp_remove,
        .driver = {
                .name   = "jornada_ssp",
        },
index 6876bc1e33b44ec178499f85e4a3971d47b9b534..0ef0ebbf31ac1f2a656809580158d191ad952d1c 100644 (file)
@@ -376,7 +376,7 @@ static int neponset_probe(struct platform_device *dev)
        return ret;
 }
 
-static int neponset_remove(struct platform_device *dev)
+static void neponset_remove(struct platform_device *dev)
 {
        struct neponset_drvdata *d = platform_get_drvdata(dev);
        int irq = platform_get_irq(dev, 0);
@@ -395,8 +395,6 @@ static int neponset_remove(struct platform_device *dev)
        nep = NULL;
        iounmap(d->base);
        kfree(d);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -425,7 +423,7 @@ static const struct dev_pm_ops neponset_pm_ops = {
 
 static struct platform_driver neponset_device_driver = {
        .probe          = neponset_probe,
-       .remove         = neponset_remove,
+       .remove_new     = neponset_remove,
        .driver         = {
                .name   = "neponset",
                .pm     = PM_OPS,
index e771ce70e132ff535962f2af51727105f72b5fc0..ec6f421c0f4d1ec6f80a0e6056091d397c41e396 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
+#include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/smp.h>
 #include <linux/suspend.h>
@@ -210,7 +211,6 @@ static void apmu_parse_dt(void (*fn)(struct resource *res, int cpu, int bit))
        struct device_node *np_apmu, *np_cpu;
        struct resource res;
        int bit, index;
-       u32 id;
 
        for_each_matching_node(np_apmu, apmu_ids) {
                /* only enable the cluster that includes the boot CPU */
@@ -218,33 +218,29 @@ static void apmu_parse_dt(void (*fn)(struct resource *res, int cpu, int bit))
 
                for (bit = 0; bit < CONFIG_NR_CPUS; bit++) {
                        np_cpu = of_parse_phandle(np_apmu, "cpus", bit);
-                       if (np_cpu) {
-                               if (!of_property_read_u32(np_cpu, "reg", &id)) {
-                                       if (id == cpu_logical_map(0)) {
-                                               is_allowed = true;
-                                               of_node_put(np_cpu);
-                                               break;
-                                       }
-
-                               }
+                       if (!np_cpu)
+                               break;
+                       if (of_cpu_node_to_id(np_cpu) == 0) {
+                               is_allowed = true;
                                of_node_put(np_cpu);
+                               break;
                        }
+                       of_node_put(np_cpu);
                }
                if (!is_allowed)
                        continue;
 
                for (bit = 0; bit < CONFIG_NR_CPUS; bit++) {
                        np_cpu = of_parse_phandle(np_apmu, "cpus", bit);
-                       if (np_cpu) {
-                               if (!of_property_read_u32(np_cpu, "reg", &id)) {
-                                       index = get_logical_index(id);
-                                       if ((index >= 0) &&
-                                           !of_address_to_resource(np_apmu,
-                                                                   0, &res))
-                                               fn(&res, index, bit);
-                               }
-                               of_node_put(np_cpu);
-                       }
+                       if (!np_cpu)
+                               break;
+
+                       index = of_cpu_node_to_id(np_cpu);
+                       if ((index >= 0) &&
+                           !of_address_to_resource(np_apmu, 0, &res))
+                               fn(&res, index, bit);
+
+                       of_node_put(np_cpu);
                }
        }
 }
index 1add7ee49b63e462cfa27659920bbbdf37cd3c0f..7108ad628f8d38a2c0ceedbdd998c6fc7d092663 100644 (file)
@@ -81,12 +81,6 @@ config ARCH_SPEAR6XX
        help
          Supports for ARM's SPEAR6XX family
 
-config MACH_SPEAR600
-       def_bool y
-       depends on ARCH_SPEAR6XX
-       help
-         Supports ST SPEAr600 boards configured via the device-tree
-
 config ARCH_SPEAR_AUTO
        bool
        depends on !ARCH_SPEAR13XX && !ARCH_SPEAR6XX
index a7ec06ce3785bf0aca77679a8625a37b09574fd7..515ca33b854c1a747c9701d1933e26425f32c12a 100644 (file)
@@ -1,8 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_ARM_JUMP_SLOT|R_ARM_GLOB_DAT|R_ARM_ABS32
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 hostprogs := vdsomunge
index 9a89264cdcc0b46ec8fc9895219f09dc52830378..7483ef8bccda394c0d21847e98b37597d8ec574a 100644 (file)
 @  IRQs enabled.
 @
 ENTRY(do_vfp)
-       local_bh_disable r10, r4
-       ldr     r4, .LCvfp
-       ldr     r11, [r10, #TI_CPU]     @ CPU number
-       add     r10, r10, #TI_VFPSTATE  @ r10 = workspace
-       ldr     pc, [r4]                @ call VFP entry point
+       mov     r1, r10
+       mov     r3, r9
+       b       vfp_entry
 ENDPROC(do_vfp)
-
-ENTRY(vfp_null_entry)
-       local_bh_enable_ti r10, r4
-       ret     lr
-ENDPROC(vfp_null_entry)
-
-       .align  2
-.LCvfp:
-       .word   vfp_vector
index 26c4f61ecfa39638ac9c1442b68409601ef515ad..4d8478264d82b3d2790b69b323118f8009c53787 100644 (file)
@@ -6,9 +6,9 @@
  *  Written by Deep Blue Solutions Limited.
  *
  * This code is called from the kernel's undefined instruction trap.
- * r9 holds the return address for successful handling.
+ * r1 holds the thread_info pointer
+ * r3 holds the return address for successful handling.
  * lr holds the return address for unrecognised instructions.
- * r10 points at the start of the private FP workspace in the thread structure
  * sp points to a struct pt_regs (as defined in include/asm/proc/ptrace.h)
  */
 #include <linux/init.h>
 @ VFP hardware support entry point.
 @
 @  r0  = instruction opcode (32-bit ARM or two 16-bit Thumb)
+@  r1  = thread_info pointer
 @  r2  = PC value to resume execution after successful emulation
-@  r9  = normal "successful" return address
-@  r10 = vfp_state union
-@  r11 = CPU number
+@  r3  = normal "successful" return address
 @  lr  = unrecognised instruction return address
 @  IRQs enabled.
 ENTRY(vfp_support_entry)
+       ldr     r11, [r1, #TI_CPU]      @ CPU number
+       add     r10, r1, #TI_VFPSTATE   @ r10 = workspace
+
        DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
 
        .fpu    vfpv2
@@ -85,9 +87,9 @@ ENTRY(vfp_support_entry)
        bne     look_for_VFP_exceptions @ VFP is already enabled
 
        DBGSTR1 "enable %x", r10
-       ldr     r3, vfp_current_hw_state_address
+       ldr     r9, vfp_current_hw_state_address
        orr     r1, r1, #FPEXC_EN       @ user FPEXC has the enable bit set
-       ldr     r4, [r3, r11, lsl #2]   @ vfp_current_hw_state pointer
+       ldr     r4, [r9, r11, lsl #2]   @ vfp_current_hw_state pointer
        bic     r5, r1, #FPEXC_EX       @ make sure exceptions are disabled
        cmp     r4, r10                 @ this thread owns the hw context?
 #ifndef CONFIG_SMP
@@ -146,7 +148,7 @@ vfp_reload_hw:
 #endif
 
        DBGSTR1 "load state %p", r10
-       str     r10, [r3, r11, lsl #2]  @ update the vfp_current_hw_state pointer
+       str     r10, [r9, r11, lsl #2]  @ update the vfp_current_hw_state pointer
                                        @ Load the saved state back into the VFP
        VFPFLDMIA r10, r5               @ reload the working registers while
                                        @ FPEXC is in a safe state
@@ -175,9 +177,12 @@ vfp_hw_state_valid:
                                        @ else it's one 32-bit instruction, so
                                        @ always subtract 4 from the following
                                        @ instruction address.
-       local_bh_enable_ti r10, r4
-       ret     r9                      @ we think we have handled things
 
+       mov     lr, r3                  @ we think we have handled things
+local_bh_enable_and_ret:
+       adr     r0, .
+       mov     r1, #SOFTIRQ_DISABLE_OFFSET
+       b       __local_bh_enable_ip    @ tail call
 
 look_for_VFP_exceptions:
        @ Check for synchronous or asynchronous exception
@@ -200,13 +205,12 @@ skip:
        @ not recognised by VFP
 
        DBGSTR  "not VFP"
-       local_bh_enable_ti r10, r4
-       ret     lr
+       b       local_bh_enable_and_ret
 
 process_exception:
        DBGSTR  "bounce"
        mov     r2, sp                  @ nothing stacked - regdump is at TOS
-       mov     lr, r9                  @ setup for a return to the user code.
+       mov     lr, r3                  @ setup for a return to the user code.
 
        @ Now call the C code to package up the bounce to the support code
        @   r0 holds the trigger instruction
index 01bc48d7384781427cc7172e5140152bdcabe4ba..349dcb944a937a72907d60eb0020c963b040afdd 100644 (file)
 /*
  * Our undef handlers (in entry.S)
  */
-asmlinkage void vfp_support_entry(void);
-asmlinkage void vfp_null_entry(void);
+asmlinkage void vfp_support_entry(u32, void *, u32, u32);
 
-asmlinkage void (*vfp_vector)(void) = vfp_null_entry;
+static bool have_vfp __ro_after_init;
 
 /*
  * Dual-use variable.
@@ -645,6 +644,25 @@ static int vfp_starting_cpu(unsigned int unused)
        return 0;
 }
 
+/*
+ * Entered with:
+ *
+ *  r0  = instruction opcode (32-bit ARM or two 16-bit Thumb)
+ *  r1  = thread_info pointer
+ *  r2  = PC value to resume execution after successful emulation
+ *  r3  = normal "successful" return address
+ *  lr  = unrecognised instruction return address
+ */
+asmlinkage void vfp_entry(u32 trigger, struct thread_info *ti, u32 resume_pc,
+                         u32 resume_return_address)
+{
+       if (unlikely(!have_vfp))
+               return;
+
+       local_bh_disable();
+       vfp_support_entry(trigger, ti, resume_pc, resume_return_address);
+}
+
 #ifdef CONFIG_KERNEL_MODE_NEON
 
 static int vfp_kmode_exception(struct pt_regs *regs, unsigned int instr)
@@ -798,7 +816,6 @@ static int __init vfp_init(void)
        vfpsid = fmrx(FPSID);
        barrier();
        unregister_undef_hook(&vfp_detect_hook);
-       vfp_vector = vfp_null_entry;
 
        pr_info("VFP support v0.3: ");
        if (VFP_arch) {
@@ -883,7 +900,7 @@ static int __init vfp_init(void)
                                  "arm/vfp:starting", vfp_starting_cpu,
                                  vfp_dying_cpu);
 
-       vfp_vector = vfp_support_entry;
+       have_vfp = true;
 
        thread_register_notifier(&vfp_notifier_block);
        vfp_pm_init();
index 1023e896d46b89698c69c84fcf0779f407c390da..02789215d2510b5f253126693c312a001e73709b 100644 (file)
@@ -1150,6 +1150,16 @@ config NVIDIA_CARMEL_CNP_ERRATUM
 
          If unsure, say Y.
 
+config ROCKCHIP_ERRATUM_3588001
+       bool "Rockchip 3588001: GIC600 can not support shareability attributes"
+       default y
+       help
+         The Rockchip RK3588 GIC600 SoC integration does not support ACE/ACE-lite.
+         This means, that its sharability feature may not be used, even though it
+         is supported by the IP itself.
+
+         If unsure, say Y.
+
 config SOCIONEXT_SYNQUACER_PREITS
        bool "Socionext Synquacer: Workaround for GICv3 pre-ITS"
        default y
index 123a56f7f81836d13fbbd027dc5a6a3788f822be..feb27a0ccfb4d80cffe7eb64ac99e4929fdf739b 100644 (file)
 
                        dmc: bus@38000 {
                                compatible = "simple-bus";
-                               reg = <0x0 0x38000 0x0 0x400>;
                                #address-cells = <2>;
                                #size-cells = <2>;
-                               ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>;
+                               ranges = <0x0 0x0 0x0 0x38000 0x0 0x2000>;
 
                                canvas: video-lut@48 {
                                        compatible = "amlogic,canvas";
                                        reg = <0x0 0x48 0x0 0x14>;
                                };
+
+                               pmu: pmu@80 {
+                                       reg = <0x0 0x80 0x0 0x40>,
+                                             <0x0 0xc00 0x0 0x40>;
+                                       interrupts = <GIC_SPI 52 IRQ_TYPE_EDGE_RISING>;
+                               };
                        };
 
                        usb2_phy1: phy@3a000 {
                        };
                };
 
-               pmu: pmu@ff638000 {
-                       reg = <0x0 0xff638000 0x0 0x100>,
-                             <0x0 0xff638c00 0x0 0x100>;
-                       interrupts = <GIC_SPI 52 IRQ_TYPE_EDGE_RISING>;
-               };
-
                aobus: bus@ff800000 {
                        compatible = "simple-bus";
                        reg = <0x0 0xff800000 0x0 0x100000>;
index af9194eca5564df46b71cd51549a5e2898d75bf8..73eb6061c73eeaa475ef80812c2371476da36210 100644 (file)
 };
 
 &enetc_port2 {
-       nvmem-cells = <&base_mac_address 2>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
 &enetc_port3 {
-       nvmem-cells = <&base_mac_address 3>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -84,8 +80,6 @@
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy0>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 4>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -94,8 +88,6 @@
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy1>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 5>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy2>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 6>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
        managed = "in-band-status";
        phy-handle = <&qsgmii_phy3>;
        phy-mode = "qsgmii";
-       nvmem-cells = <&base_mac_address 7>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
index 1f34c75534594ce25b440ee6d5dae1be0b3168ec..7cd29ab970d9237ee4675c87ee6f39b279aae2ba 100644 (file)
@@ -55,7 +55,5 @@
 &enetc_port1 {
        phy-handle = <&phy0>;
        phy-mode = "rgmii-id";
-       nvmem-cells = <&base_mac_address 0>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
index aac41192caa12801d853f96d71adee7a2599e808..113b1df74bf87cdebf0607ef3020c3e2b35ed6b2 100644 (file)
 };
 
 &enetc_port2 {
-       nvmem-cells = <&base_mac_address 2>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
 &enetc_port3 {
-       nvmem-cells = <&base_mac_address 3>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -56,8 +52,6 @@
        managed = "in-band-status";
        phy-handle = <&phy0>;
        phy-mode = "sgmii";
-       nvmem-cells = <&base_mac_address 0>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
@@ -66,8 +60,6 @@
        managed = "in-band-status";
        phy-handle = <&phy1>;
        phy-mode = "sgmii";
-       nvmem-cells = <&base_mac_address 1>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
index a4421db3784e325602ac89c9c72d28b34418d6ce..9b5e92fb753e22effdb5b14f04cf3371291df162 100644 (file)
@@ -43,7 +43,5 @@
 &enetc_port1 {
        phy-handle = <&phy1>;
        phy-mode = "rgmii-id";
-       nvmem-cells = <&base_mac_address 1>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
index 8b65af4a7147b6520907e282171bde5611acdffb..4ab17b984b03bc77e2243cbbfffb4d19ef3f8a4f 100644 (file)
@@ -92,8 +92,6 @@
        phy-handle = <&phy0>;
        phy-mode = "sgmii";
        managed = "in-band-status";
-       nvmem-cells = <&base_mac_address 0>;
-       nvmem-cell-names = "mac-address";
        status = "okay";
 };
 
                                label = "bootloader environment";
                        };
                };
-
-               otp-1 {
-                       compatible = "user-otp";
-
-                       nvmem-layout {
-                               compatible = "kontron,sl28-vpd";
-
-                               serial_number: serial-number {
-                               };
-
-                               base_mac_address: base-mac-address {
-                                       #nvmem-cell-cells = <1>;
-                               };
-                       };
-               };
        };
 };
 
index 62b7f7a3e1bc9a2944059f8d519527d4ce0bb623..ea8c93757521b3e6b93280e6f00326fe885e97f9 100644 (file)
@@ -165,7 +165,7 @@ lsio_subsys: bus@5d000000 {
                interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clk IMX_SC_R_FSPI_0 IMX_SC_PM_CLK_PER>,
                         <&clk IMX_SC_R_FSPI_0 IMX_SC_PM_CLK_PER>;
-               clock-names = "fspi", "fspi_en";
+               clock-names = "fspi_en", "fspi";
                power-domains = <&pd IMX_SC_R_FSPI_0>;
                status = "disabled";
        };
index 57099ac0d77361757d44af6b243c2236a3860bcf..f542476187b300f9e49107c547fb4bce67067bcd 100644 (file)
        phy-handle = <&ethphy0>;
        nvmem-cells = <&fec_mac1>;
        nvmem-cell-names = "mac-address";
-       snps,reset-gpios = <&pca6416_1 2 GPIO_ACTIVE_LOW>;
-       snps,reset-delays-us = <10 20 200000>;
        status = "okay";
 
        mdio {
                        eee-broken-1000t;
                        qca,disable-smarteee;
                        qca,disable-hibernation-mode;
+                       reset-gpios = <&pca6416_1 2 GPIO_ACTIVE_LOW>;
+                       reset-assert-us = <20>;
+                       reset-deassert-us = <200000>;
                        vddio-supply = <&vddio0>;
 
                        vddio0: vddio-regulator {
index d1a6390976a9caeaadc97d15a828608dc53ab39d..3f9dfd4d38848fc314cb7081b97c6968f3429dcf 100644 (file)
                rohm,reset-snvs-powered;
 
                #clock-cells = <0>;
-               clocks = <&osc_32k 0>;
+               clocks = <&osc_32k>;
                clock-output-names = "clk-32k-out";
 
                regulators {
index 6357078185eddb44d64d4ce0cbb4b89231a55111..0e8f0d7161ad0f4989c91149bbb29f20d000a45e 100644 (file)
                compatible = "wlf,wm8960";
                reg = <0x1a>;
                clocks = <&clk IMX8MM_CLK_SAI1_ROOT>;
-               clock-names = "mclk1";
+               clock-names = "mclk";
                wlf,shared-lrclk;
                #sound-dai-cells = <0>;
        };
index 88321b5b0693e52003c5ee48698861c970c88725..6f0811587142d2725db959d100e7229c6ca82f02 100644 (file)
@@ -99,7 +99,7 @@
                compatible = "regulator-fixed";
                enable-active-high;
                gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>; /* PMIC_EN_ETH */
-               off-on-delay = <500000>;
+               off-on-delay-us = <500000>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_reg_eth>;
                regulator-always-on;
                enable-active-high;
                /* Verdin SD_1_PWR_EN (SODIMM 76) */
                gpio = <&gpio3 5 GPIO_ACTIVE_HIGH>;
-               off-on-delay = <100000>;
+               off-on-delay-us = <100000>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_usdhc2_pwr_en>;
                regulator-max-microvolt = <3300000>;
index 6f1101b7e2fd4e166b740d12e3ba04041d094df5..c94ab45ee96c38dbcc13a4c2bca334985892d9fa 100644 (file)
                                sai2: sai@30020000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30020000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI2_IPG>,
                                                <&clk IMX8MN_CLK_DUMMY>,
                                sai3: sai@30030000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30030000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI3_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
                                sai5: sai@30050000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30050000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI5_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
                                sai6: sai@30060000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x30060000  0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI6_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
                                sai7: sai@300b0000 {
                                        compatible = "fsl,imx8mn-sai", "fsl,imx8mq-sai";
                                        reg = <0x300b0000 0x10000>;
+                                       #sound-dai-cells = <0>;
                                        interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clk IMX8MN_CLK_SAI7_IPG>,
                                                 <&clk IMX8MN_CLK_DUMMY>,
index 096a6f2300f9fd5e57ed17a07d45d86d42a77fbb..bdfdd4c782f1d51ffe12ad92f4e1b13a8369d813 100644 (file)
@@ -10,7 +10,7 @@
                compatible = "regulator-fixed";
                enable-active-high;
                gpio = <&gpio_expander_21 4 GPIO_ACTIVE_HIGH>; /* ETH_PWR_EN */
-               off-on-delay = <500000>;
+               off-on-delay-us = <500000>;
                regulator-max-microvolt = <3300000>;
                regulator-min-microvolt = <3300000>;
                regulator-name = "+V3.3_ETH";
index 00faaf9a02b2d9a361e2a18fbbbfbacbcc5bf679..e9e4fcb562f10c6c5c0041959c1e2ce37ef62a8d 100644 (file)
@@ -87,7 +87,7 @@
                compatible = "regulator-fixed";
                enable-active-high;
                gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>; /* PMIC_EN_ETH */
-               off-on-delay = <500000>;
+               off-on-delay-us = <500000>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_reg_eth>;
                regulator-always-on;
                enable-active-high;
                /* Verdin SD_1_PWR_EN (SODIMM 76) */
                gpio = <&gpio4 22 GPIO_ACTIVE_HIGH>;
-               off-on-delay = <100000>;
+               off-on-delay-us = <100000>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_usdhc2_pwr_en>;
                regulator-max-microvolt = <3300000>;
index 7879bbedd01b370e24d59b3284bb1f978a06c55e..f81391993354f484aa60380a4b23545b3cfb724e 100644 (file)
 
                        lcdif2: display-controller@32e90000 {
                                compatible = "fsl,imx8mp-lcdif";
-                               reg = <0x32e90000 0x238>;
+                               reg = <0x32e90000 0x10000>;
                                interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT>,
-                                        <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
-                                        <&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
+                                        <&clk IMX8MP_CLK_MEDIA_APB_ROOT>,
+                                        <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>;
                                clock-names = "pix", "axi", "disp_axi";
                                assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
                                                  <&clk IMX8MP_VIDEO_PLL1>;
index 282374d011f6d5de4368348e4ad63950a55e6a9f..e8d49660ac85b00add7f0181b9b8b777bd48fb7f 100644 (file)
                        lpi2c1: i2c@44340000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x44340000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C1_GATE>,
                                         <&clk IMX93_CLK_BUS_AON>;
                        lpi2c2: i2c@44350000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x44350000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C2_GATE>,
                                         <&clk IMX93_CLK_BUS_AON>;
                        lpi2c3: i2c@42530000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x42530000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C3_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c4: i2c@42540000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x42540000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C4_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c5: i2c@426b0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426b0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C5_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c6: i2c@426c0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426c0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C6_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c7: i2c@426d0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426d0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C7_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        lpi2c8: i2c@426e0000 {
                                compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
                                reg = <0x426e0000 0x10000>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX93_CLK_LPI2C8_GATE>,
                                         <&clk IMX93_CLK_BUS_WAKEUP>;
                        eqos: ethernet@428a0000 {
                                compatible = "nxp,imx93-dwmac-eqos", "snps,dwmac-5.10a";
                                reg = <0x428a0000 0x10000>;
-                               interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>,
-                                            <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
-                               interrupt-names = "eth_wake_irq", "macirq";
+                               interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "macirq", "eth_wake_irq";
                                clocks = <&clk IMX93_CLK_ENET_QOS_GATE>,
                                         <&clk IMX93_CLK_ENET_QOS_GATE>,
                                         <&clk IMX93_CLK_ENET_TIMER2>,
                                                         <&clk IMX93_CLK_SYS_PLL_PFD0_DIV2>;
                                assigned-clock-rates = <100000000>, <250000000>;
                                intf_mode = <&wakeupmix_gpr 0x28>;
-                               clk_csr = <0>;
+                               snps,clk-csr = <0>;
                                status = "disabled";
                        };
 
index 2ddade14fe4b66f5131ce7a608793cb6bb00e9f7..154fc8c0eb6d4d67667dd6a3f992f372754eb108 100644 (file)
@@ -22,7 +22,7 @@
 
                #address-cells = <2>;
                #size-cells = <2>;
-               ranges = <0x0 0x0 0x0 0x0 0x0 0x40000000>;
+               ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
 
                apbmisc: misc@100000 {
                        compatible = "nvidia,tegra194-misc";
index 01504ede6334dc95d79a786e1217e409c353b1fc..5d354f8923b404b0bd8071111fd60f6a274ab9db 100644 (file)
@@ -20,7 +20,7 @@
 
                #address-cells = <2>;
                #size-cells = <2>;
-               ranges = <0x0 0x0 0x0 0x0 0x0 0x40000000>;
+               ranges = <0x0 0x0 0x0 0x0 0x100 0x0>;
 
                misc@100000 {
                        compatible = "nvidia,tegra234-misc";
index e651f633341f51f59982447a3b76723dc829a2c9..5b1c175c47f103806ab7511937db670cdddcc753 100644 (file)
@@ -464,7 +464,7 @@ ap_i2c_tpm: &i2c14 {
 
 &mdss_dp_out {
        data-lanes = <0 1>;
-       link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000 8100000000>;
+       link-frequencies = /bits/ 64 <1620000000 2700000000 5400000000>;
 };
 
 &mdss_mdp {
index 61b31688b469b26958e0ade3d2f7c87ffcf2c039..ce318e05f0a60a306e897bd478f9d22a6c0db000 100644 (file)
@@ -24,6 +24,8 @@
 
 &internal_display {
        compatible = "elida,kd35t133";
+       iovcc-supply = <&vcc_lcd>;
+       vdd-supply = <&vcc_lcd>;
 };
 
 &pwm0 {
index 04eba432fb0eb2d8217788004f1aadf3979140e0..80fc53c807a42c09faeca9b436e5ffe39865764a 100644 (file)
        internal_display: panel@0 {
                reg = <0>;
                backlight = <&backlight>;
-               iovcc-supply = <&vcc_lcd>;
                reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>;
                rotation = <270>;
-               vdd-supply = <&vcc_lcd>;
 
                port {
                        mipi_in_panel: endpoint {
index 139c898e590e2f3136db561ad4ee798110c42255..d94ac81eb4e67801d373564669eaf26e0ae11aad 100644 (file)
@@ -83,6 +83,8 @@
 
 &internal_display {
        compatible = "elida,kd35t133";
+       iovcc-supply = <&vcc_lcd>;
+       vdd-supply = <&vcc_lcd>;
 };
 
 &rk817 {
index 4702183b673c145c4bcb2a7b00a727f378deafb8..aa6f5b12206bad5198228625ab9395c3f695e98b 100644 (file)
@@ -59,6 +59,8 @@
 
 &internal_display {
        compatible = "elida,kd35t133";
+       iovcc-supply = <&vcc_lcd>;
+       vdd-supply = <&vcc_lcd>;
 };
 
 &rk817_charger {
index 083452c6771197f1f9114ea49a7a14d0e5aeb59b..e47d1398aecac7bbb151cd9d542b57ff7c163b7f 100644 (file)
@@ -61,7 +61,6 @@
                pinctrl-names = "default";
                pinctrl-0 = <&bl_en>;
                pwms = <&pwm0 0 1000000 PWM_POLARITY_INVERTED>;
-               pwm-delay-us = <10000>;
        };
 
        emmc_pwrseq: emmc-pwrseq {
index ee6095baba4d3a0679f1ce01106ae81c05920760..5c1929d41cc0b700998f7aa048cc815306b0f97c 100644 (file)
                power-supply = <&pp3300_disp>;
                pinctrl-names = "default";
                pinctrl-0 = <&bl_en>;
-               pwm-delay-us = <10000>;
        };
 
        gpio_keys: gpio-keys {
index a47d9f758611e2dfc11894b0edc7ff0fc39445ce..c5e7de60c12140c0dae9789cc338ef5f1b9fac3c 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&bl_en>;
                pwms = <&pwm1 0 1000000 0>;
-               pwm-delay-us = <10000>;
        };
 
        dmic: dmic {
index 3e32159527e5fbce5aa2c70cfb23058da5715207..054c6a4d1a45f71c7951752cbe8e86bd4e24d6ab 100644 (file)
                pinctrl-0 = <&panel_en_pin>;
                power-supply = <&vcc3v3_panel>;
 
-               ports {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       port@0 {
-                               reg = <0>;
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               panel_in_edp: endpoint@0 {
-                                       reg = <0>;
-                                       remote-endpoint = <&edp_out_panel>;
-                               };
+               port {
+                       panel_in_edp: endpoint {
+                               remote-endpoint = <&edp_out_panel>;
                        };
                };
        };
        disable-wp;
        pinctrl-names = "default";
        pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
-       sd-uhs-sdr104;
+       sd-uhs-sdr50;
        vmmc-supply = <&vcc3v0_sd>;
        vqmmc-supply = <&vcc_sdio>;
        status = "okay";
index 78157521e94493c32b74c27b7694a734027ec37e..bca2b50e0a93473d6fe63fbcb682d5cb2ad8d126 100644 (file)
                avdd-supply = <&avdd>;
                backlight = <&backlight>;
                dvdd-supply = <&vcc3v3_s0>;
-               ports {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
 
-                       port@0 {
-                               reg = <0>;
-
-                               mipi_in_panel: endpoint {
-                                       remote-endpoint = <&mipi_out_panel>;
-                               };
+               port {
+                       mipi_in_panel: endpoint {
+                               remote-endpoint = <&mipi_out_panel>;
                        };
                };
        };
index 74f667fbdf5bf970e2318f20734301fb48284ea3..928948e7c7bbb4a4013d9c6e5eda65bfb702a76c 100644 (file)
                      <0x0 0xfff10000 0 0x10000>, /* GICH */
                      <0x0 0xfff20000 0 0x10000>; /* GICV */
                interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
-               its: interrupt-controller@fee20000 {
+               its: msi-controller@fee20000 {
                        compatible = "arm,gic-v3-its";
                        msi-controller;
                        #msi-cells = <1>;
index 17450aa283b97dc7efe4636c252abf5590b2bc78..2a2821f4c580b0afe219394e0de64072e924482f 100644 (file)
 };
 
 &cru {
-       assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
-       assigned-clock-rates = <1200000000>, <200000000>, <241500000>;
+       assigned-clocks = <&pmucru CLK_RTC_32K>, <&cru PLL_GPLL>,
+                         <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
+       assigned-clock-rates = <32768>, <1200000000>,
+                              <200000000>, <241500000>;
 };
 
 &dsi_dphy0 {
index b4b2df821cba90412ad7a60e5752b2590ddb23b4..c763c7f3b1b38b71fc1702c1e6a157d58e6af2e8 100644 (file)
 };
 
 &cru {
-       assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
-       assigned-clock-rates = <1200000000>, <200000000>, <500000000>;
+       assigned-clocks = <&pmucru CLK_RTC_32K>, <&cru PLL_GPLL>,
+                         <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
+       assigned-clock-rates = <32768>, <1200000000>,
+                              <200000000>, <500000000>;
 };
 
 &dsi_dphy0 {
index ce7165d7f1a14da78273fdfff2b68a4eea5948cc..102e448bc026a78a3783dd9530c4f12a0aad0e09 100644 (file)
        non-removable;
        pinctrl-names = "default";
        pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>;
-       sd-uhs-sdr104;
+       sd-uhs-sdr50;
        vmmc-supply = <&vcc3v3_sys>;
        vqmmc-supply = <&vcc_1v8>;
        status = "okay";
index 9d524dcb7b2537fd2694159c86b88fc6cbeb16e8..657c019d27fa9a54012ccbfac0a458656ba1a92d 100644 (file)
                        cache-size = <131072>;
                        cache-line-size = <64>;
                        cache-sets = <512>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <131072>;
                        cache-line-size = <64>;
                        cache-sets = <512>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <131072>;
                        cache-line-size = <64>;
                        cache-sets = <512>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <131072>;
                        cache-line-size = <64>;
                        cache-sets = <512>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <524288>;
                        cache-line-size = <64>;
                        cache-sets = <1024>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <524288>;
                        cache-line-size = <64>;
                        cache-sets = <1024>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <524288>;
                        cache-line-size = <64>;
                        cache-sets = <1024>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <524288>;
                        cache-line-size = <64>;
                        cache-sets = <1024>;
+                       cache-level = <2>;
                        next-level-cache = <&l3_cache>;
                };
 
                        cache-size = <3145728>;
                        cache-line-size = <64>;
                        cache-sets = <4096>;
+                       cache-level = <3>;
                };
        };
 
index 7790ee42c68a88d7620c02f9dda25e5bc70d0a08..a24609e14d50ee77244dd2e23fc3b45884c434c5 100644 (file)
@@ -273,6 +273,8 @@ CONFIG_VIRTIO_BLK=y
 CONFIG_BLK_DEV_NVME=m
 CONFIG_QCOM_COINCELL=m
 CONFIG_QCOM_FASTRPC=m
+CONFIG_BATTERY_QCOM_BATTMGR=m
+CONFIG_UCSI_PMIC_GLINK=m
 CONFIG_SRAM=y
 CONFIG_PCI_ENDPOINT_TEST=m
 CONFIG_EEPROM_AT24=m
@@ -367,11 +369,13 @@ CONFIG_AT803X_PHY=y
 CONFIG_REALTEK_PHY=y
 CONFIG_ROCKCHIP_PHY=y
 CONFIG_DP83867_PHY=y
+CONFIG_DP83TD510_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_CAN_FLEXCAN=m
 CONFIG_CAN_RCAR=m
 CONFIG_CAN_RCAR_CANFD=m
 CONFIG_CAN_MCP251XFD=m
+CONFIG_MDIO_GPIO=y
 CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
 CONFIG_MDIO_BUS_MUX_MMIOREG=y
 CONFIG_USB_PEGASUS=m
@@ -418,6 +422,7 @@ CONFIG_TOUCHSCREEN_EDT_FT5X06=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_PM8941_PWRKEY=y
 CONFIG_INPUT_PM8XXX_VIBRATOR=m
+CONFIG_INPUT_TPS65219_PWRBUTTON=m
 CONFIG_INPUT_PWM_BEEPER=m
 CONFIG_INPUT_PWM_VIBRA=m
 CONFIG_INPUT_HISI_POWERKEY=y
@@ -463,6 +468,8 @@ CONFIG_VIRTIO_CONSOLE=y
 CONFIG_IPMI_HANDLER=m
 CONFIG_IPMI_DEVICE_INTERFACE=m
 CONFIG_IPMI_SI=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
 CONFIG_TCG_TPM=y
 CONFIG_TCG_TIS=m
 CONFIG_TCG_TIS_SPI=m
@@ -513,6 +520,7 @@ CONFIG_SPI_MESON_SPICC=m
 CONFIG_SPI_MESON_SPIFC=m
 CONFIG_SPI_MT65XX=y
 CONFIG_SPI_MTK_NOR=m
+CONFIG_SPI_OMAP24XX=m
 CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_ROCKCHIP=y
@@ -545,7 +553,9 @@ CONFIG_PINCTRL_IMX8ULP=y
 CONFIG_PINCTRL_IMX93=y
 CONFIG_PINCTRL_MSM=y
 CONFIG_PINCTRL_IPQ8074=y
+CONFIG_PINCTRL_IPQ5332=y
 CONFIG_PINCTRL_IPQ6018=y
+CONFIG_PINCTRL_IPQ9574=y
 CONFIG_PINCTRL_MSM8916=y
 CONFIG_PINCTRL_MSM8953=y
 CONFIG_PINCTRL_MSM8976=y
@@ -556,19 +566,29 @@ CONFIG_PINCTRL_QCM2290=y
 CONFIG_PINCTRL_QCS404=y
 CONFIG_PINCTRL_QDF2XXX=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_PINCTRL_QDU1000=y
 CONFIG_PINCTRL_SA8775P=y
 CONFIG_PINCTRL_SC7180=y
 CONFIG_PINCTRL_SC7280=y
+CONFIG_PINCTRL_SC7280_LPASS_LPI=m
 CONFIG_PINCTRL_SC8180X=y
 CONFIG_PINCTRL_SC8280XP=y
+CONFIG_PINCTRL_SDM660=y
+CONFIG_PINCTRL_SDM670=y
 CONFIG_PINCTRL_SDM845=y
 CONFIG_PINCTRL_SM6115=y
+CONFIG_PINCTRL_SM6125=y
+CONFIG_PINCTRL_SM6350=y
+CONFIG_PINCTRL_SM6375=y
 CONFIG_PINCTRL_SM8150=y
 CONFIG_PINCTRL_SM8250=y
 CONFIG_PINCTRL_SM8250_LPASS_LPI=m
 CONFIG_PINCTRL_SM8350=y
 CONFIG_PINCTRL_SM8450=y
+CONFIG_PINCTRL_SM8450_LPASS_LPI=m
+CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m
 CONFIG_PINCTRL_SM8550=y
+CONFIG_PINCTRL_SM8550_LPASS_LPI=m
 CONFIG_PINCTRL_LPASS_LPI=m
 CONFIG_GPIO_ALTERA=m
 CONFIG_GPIO_DAVINCI=y
@@ -594,6 +614,7 @@ CONFIG_POWER_RESET_QCOM_PON=m
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_SYSCON_REBOOT_MODE=y
+CONFIG_NVMEM_REBOOT_MODE=m
 CONFIG_BATTERY_SBS=m
 CONFIG_BATTERY_BQ27XXX=y
 CONFIG_BATTERY_MAX17042=m
@@ -670,6 +691,8 @@ CONFIG_MFD_SPMI_PMIC=y
 CONFIG_MFD_RK808=y
 CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_SL28CPLD=y
+CONFIG_MFD_TPS65219=y
+CONFIG_MFD_TI_AM335X_TSCADC=m
 CONFIG_MFD_ROHM_BD718XX=y
 CONFIG_MFD_WCD934X=m
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -699,6 +722,7 @@ CONFIG_REGULATOR_QCOM_SPMI=y
 CONFIG_REGULATOR_RK808=y
 CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_TPS65132=m
+CONFIG_REGULATOR_TPS65219=y
 CONFIG_REGULATOR_VCTRL=m
 CONFIG_RC_CORE=m
 CONFIG_RC_DECODERS=y
@@ -871,7 +895,9 @@ CONFIG_SND_SOC_TEGRA210_AMX=m
 CONFIG_SND_SOC_TEGRA210_ADX=m
 CONFIG_SND_SOC_TEGRA210_MIXER=m
 CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m
+CONFIG_SND_SOC_DAVINCI_MCASP=m
 CONFIG_SND_SOC_AK4613=m
+CONFIG_SND_SOC_DA7213=m
 CONFIG_SND_SOC_ES7134=m
 CONFIG_SND_SOC_ES7241=m
 CONFIG_SND_SOC_GTM601=m
@@ -885,6 +911,7 @@ CONFIG_SND_SOC_SIMPLE_MUX=m
 CONFIG_SND_SOC_TAS2552=m
 CONFIG_SND_SOC_TAS571X=m
 CONFIG_SND_SOC_TLV320AIC32X4_I2C=m
+CONFIG_SND_SOC_TLV320AIC3X_I2C=m
 CONFIG_SND_SOC_WCD9335=m
 CONFIG_SND_SOC_WCD934X=m
 CONFIG_SND_SOC_WM8524=m
@@ -908,6 +935,7 @@ CONFIG_USB=y
 CONFIG_USB_OTG=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_PCI_RENESAS=m
+CONFIG_USB_XHCI_RZV2M=y
 CONFIG_USB_XHCI_TEGRA=y
 CONFIG_USB_BRCMSTB=m
 CONFIG_USB_EHCI_HCD=y
@@ -943,6 +971,7 @@ CONFIG_USB_ONBOARD_HUB=m
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=m
+CONFIG_USB_RZV2M_USB3DRD=y
 CONFIG_USB_RENESAS_USB3=m
 CONFIG_USB_TEGRA_XUDC=m
 CONFIG_USB_CONFIGFS=m
@@ -1026,6 +1055,7 @@ CONFIG_RTC_DRV_RK808=m
 CONFIG_RTC_DRV_PCF85063=m
 CONFIG_RTC_DRV_PCF85363=m
 CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_BQ32K=m
 CONFIG_RTC_DRV_RX8581=m
 CONFIG_RTC_DRV_RV3028=m
 CONFIG_RTC_DRV_RV8803=m
@@ -1045,6 +1075,7 @@ CONFIG_RTC_DRV_SNVS=m
 CONFIG_RTC_DRV_IMX_SC=m
 CONFIG_RTC_DRV_MT6397=m
 CONFIG_RTC_DRV_XGENE=y
+CONFIG_RTC_DRV_TI_K3=m
 CONFIG_DMADEVICES=y
 CONFIG_DMA_BCM2835=y
 CONFIG_DMA_SUN6I=m
@@ -1122,11 +1153,15 @@ CONFIG_QCOM_CLK_APCS_MSM8916=y
 CONFIG_QCOM_CLK_APCC_MSM8996=y
 CONFIG_QCOM_CLK_SMD_RPM=y
 CONFIG_QCOM_CLK_RPMH=y
+CONFIG_IPQ_GCC_5332=y
 CONFIG_IPQ_GCC_6018=y
 CONFIG_IPQ_GCC_8074=y
+CONFIG_IPQ_GCC_9574=y
 CONFIG_MSM_GCC_8916=y
 CONFIG_MSM_GCC_8994=y
-CONFIG_MSM_MMCC_8996=y
+CONFIG_MSM_MMCC_8994=m
+CONFIG_MSM_MMCC_8996=m
+CONFIG_MSM_MMCC_8998=m
 CONFIG_MSM_GCC_8998=y
 CONFIG_QCS_GCC_404=y
 CONFIG_SA_GCC_8775P=y
@@ -1217,7 +1252,6 @@ CONFIG_QCOM_APR=m
 CONFIG_QCOM_ICC_BWMON=m
 CONFIG_ARCH_R8A77995=y
 CONFIG_ARCH_R8A77990=y
-CONFIG_ARCH_R8A77950=y
 CONFIG_ARCH_R8A77951=y
 CONFIG_ARCH_R8A77965=y
 CONFIG_ARCH_R8A77960=y
@@ -1252,6 +1286,7 @@ CONFIG_EXTCON_USBC_CROS_EC=y
 CONFIG_RENESAS_RPCIF=m
 CONFIG_IIO=y
 CONFIG_EXYNOS_ADC=y
+CONFIG_IMX93_ADC=m
 CONFIG_MAX9611=m
 CONFIG_MEDIATEK_MT6577_AUXADC=m
 CONFIG_QCOM_SPMI_VADC=m
@@ -1259,6 +1294,7 @@ CONFIG_QCOM_SPMI_ADC5=m
 CONFIG_ROCKCHIP_SARADC=m
 CONFIG_RZG2L_ADC=m
 CONFIG_TI_ADS1015=m
+CONFIG_TI_AM335X_ADC=m
 CONFIG_IIO_CROS_EC_SENSORS_CORE=m
 CONFIG_IIO_CROS_EC_SENSORS=m
 CONFIG_IIO_ST_LSM6DSX=m
@@ -1292,6 +1328,7 @@ CONFIG_RESET_QCOM_PDC=m
 CONFIG_RESET_RZG2L_USBPHY_CTRL=y
 CONFIG_RESET_TI_SCI=y
 CONFIG_PHY_XGENE=y
+CONFIG_PHY_CAN_TRANSCEIVER=m
 CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_CADENCE_TORRENT=m
 CONFIG_PHY_CADENCE_SIERRA=m
@@ -1303,9 +1340,11 @@ CONFIG_PHY_HISI_INNO_USB2=y
 CONFIG_PHY_MVEBU_CP110_COMPHY=y
 CONFIG_PHY_MTK_TPHY=y
 CONFIG_PHY_QCOM_EDP=m
+CONFIG_PHY_QCOM_EUSB2_REPEATER=m
 CONFIG_PHY_QCOM_PCIE2=m
 CONFIG_PHY_QCOM_QMP=m
 CONFIG_PHY_QCOM_QUSB2=m
+CONFIG_PHY_QCOM_SNPS_EUSB2=m
 CONFIG_PHY_QCOM_USB_HS=m
 CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
 CONFIG_PHY_QCOM_USB_HS_28NM=m
@@ -1329,6 +1368,7 @@ CONFIG_PHY_J721E_WIZ=m
 CONFIG_ARM_CCI_PMU=m
 CONFIG_ARM_CCN=m
 CONFIG_ARM_CMN=m
+CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU=m
 CONFIG_ARM_SMMU_V3_PMU=m
 CONFIG_ARM_DSU_PMU=m
 CONFIG_FSL_IMX8_DDR_PMU=m
@@ -1415,6 +1455,7 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_ECHAINIV=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_ANSI_CPRNG=y
@@ -1440,6 +1481,7 @@ CONFIG_CRYPTO_DEV_HISI_SEC2=m
 CONFIG_CRYPTO_DEV_HISI_ZIP=m
 CONFIG_CRYPTO_DEV_HISI_HPRE=m
 CONFIG_CRYPTO_DEV_HISI_TRNG=m
+CONFIG_CRYPTO_DEV_SA2UL=m
 CONFIG_DMA_RESTRICTED_POOL=y
 CONFIG_CMA_SIZE_MBYTES=32
 CONFIG_PRINTK_TIME=y
index 6ef0a739717ffabb6adb8ee8a942db78fb4cb38d..6865d54e68f8880eb86705b1ce8fc1c446200d24 100644 (file)
@@ -1,3 +1,7 @@
+#
+# Base options for platforms
+#
+
 # CONFIG_ARCH_ACTIONS is not set
 # CONFIG_ARCH_SUNXI is not set
 # CONFIG_ARCH_ALPINE is not set
 # CONFIG_ARCH_VISCONTI is not set
 # CONFIG_ARCH_XGENE is not set
 # CONFIG_ARCH_ZYNQMP is not set
+
+#
+# Subsystems which can't be used in mach-virt
+#
+# CONFIG_CHROME_PLATFORMS is not set
+# CONFIG_EXTCON is not set
+# CONFIG_IIO is not set
+# CONFIG_MTD is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_PWM is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_SLIMBUS is not set
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUNDWIRE is not set
+# CONFIG_SPI is not set
+# CONFIG_SURFACE_PLATFORMS is not set
+# CONFIG_THERMAL is not set
index a1892a8f603236984721b7c2f74e810f1d5bbe21..3dd691c85ca0d81d0c4e6897dcdc91a81cd82581 100644 (file)
@@ -193,6 +193,9 @@ struct kvm_arch {
        /* Interrupt controller */
        struct vgic_dist        vgic;
 
+       /* Timers */
+       struct arch_timer_vm_data timer_data;
+
        /* Mandated version of PSCI */
        u32 psci_version;
 
@@ -573,9 +576,22 @@ struct kvm_vcpu_arch {
        ({                                                      \
                __build_check_flag(v, flagset, f, m);           \
                                                                \
-               v->arch.flagset & (m);                          \
+               READ_ONCE(v->arch.flagset) & (m);               \
        })
 
+/*
+ * Note that the set/clear accessors must be preempt-safe in order to
+ * avoid nesting them with load/put which also manipulate flags...
+ */
+#ifdef __KVM_NVHE_HYPERVISOR__
+/* the nVHE hypervisor is always non-preemptible */
+#define __vcpu_flags_preempt_disable()
+#define __vcpu_flags_preempt_enable()
+#else
+#define __vcpu_flags_preempt_disable() preempt_disable()
+#define __vcpu_flags_preempt_enable()  preempt_enable()
+#endif
+
 #define __vcpu_set_flag(v, flagset, f, m)                      \
        do {                                                    \
                typeof(v->arch.flagset) *fset;                  \
@@ -583,9 +599,11 @@ struct kvm_vcpu_arch {
                __build_check_flag(v, flagset, f, m);           \
                                                                \
                fset = &v->arch.flagset;                        \
+               __vcpu_flags_preempt_disable();                 \
                if (HWEIGHT(m) > 1)                             \
                        *fset &= ~(m);                          \
                *fset |= (f);                                   \
+               __vcpu_flags_preempt_enable();                  \
        } while (0)
 
 #define __vcpu_clear_flag(v, flagset, f, m)                    \
@@ -595,7 +613,9 @@ struct kvm_vcpu_arch {
                __build_check_flag(v, flagset, f, m);           \
                                                                \
                fset = &v->arch.flagset;                        \
+               __vcpu_flags_preempt_disable();                 \
                *fset &= ~(m);                                  \
+               __vcpu_flags_preempt_enable();                  \
        } while (0)
 
 #define vcpu_get_flag(v, ...)  __vcpu_get_flag((v), __VA_ARGS__)
index 5edec2f49ec98c9b040d7698db52a62be0315b48..deff21bfa6800cfc2ceefd36c6e06f01880a1f4f 100644 (file)
@@ -314,36 +314,32 @@ int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs)
        int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs);
        unsigned int type;
        u32 instr = 0;
-       u16 tinstr = 0;
        int isize = 4;
        int thumb2_32b = 0;
-       int fault;
 
        instrptr = instruction_pointer(regs);
 
        if (compat_thumb_mode(regs)) {
                __le16 __user *ptr = (__le16 __user *)(instrptr & ~1);
+               u16 tinstr, tinst2;
 
-               fault = alignment_get_thumb(regs, ptr, &tinstr);
-               if (!fault) {
-                       if (IS_T32(tinstr)) {
-                               /* Thumb-2 32-bit */
-                               u16 tinst2;
-                               fault = alignment_get_thumb(regs, ptr + 1, &tinst2);
-                               instr = ((u32)tinstr << 16) | tinst2;
-                               thumb2_32b = 1;
-                       } else {
-                               isize = 2;
-                               instr = thumb2arm(tinstr);
-                       }
+               if (alignment_get_thumb(regs, ptr, &tinstr))
+                       return 1;
+
+               if (IS_T32(tinstr)) { /* Thumb-2 32-bit */
+                       if (alignment_get_thumb(regs, ptr + 1, &tinst2))
+                               return 1;
+                       instr = ((u32)tinstr << 16) | tinst2;
+                       thumb2_32b = 1;
+               } else {
+                       isize = 2;
+                       instr = thumb2arm(tinstr);
                }
        } else {
-               fault = alignment_get_arm(regs, (__le32 __user *)instrptr, &instr);
+               if (alignment_get_arm(regs, (__le32 __user *)instrptr, &instr))
+                       return 1;
        }
 
-       if (fault)
-               return 1;
-
        switch (CODING_BITS(instr)) {
        case 0x00000000:        /* 3.13.4 load/store instruction extensions */
                if (LDSTHD_I_BIT(instr))
index 28d8a5dca5f129784b158589a3c4c1d231ffd6e9..d731b4655df8eb271c185f732c4ec5a725fb4905 100644 (file)
@@ -66,7 +66,7 @@
        .long   .Lefi_header_end - .L_head              // SizeOfHeaders
        .long   0                                       // CheckSum
        .short  IMAGE_SUBSYSTEM_EFI_APPLICATION         // Subsystem
-       .short  0                                       // DllCharacteristics
+       .short  IMAGE_DLL_CHARACTERISTICS_NX_COMPAT     // DllCharacteristics
        .quad   0                                       // SizeOfStackReserve
        .quad   0                                       // SizeOfStackCommit
        .quad   0                                       // SizeOfHeapReserve
index beaf9586338f5c10569764a9728209289a06756c..fe7a53c6781f15b6546aa9d8a17823c0ccea819b 100644 (file)
@@ -6,9 +6,7 @@
 # Heavily based on the vDSO Makefiles for other archs.
 #
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_AARCH64_JUMP_SLOT|R_AARCH64_GLOB_DAT|R_AARCH64_ABS64
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 obj-vdso := vgettimeofday.o note.o sigreturn.o
index f59bd1a4ead6b46d31f0a7a6e3d5bf08212b1891..d014162c5c7134688b441734899b0ef028cf87ef 100644 (file)
@@ -3,9 +3,6 @@
 # Makefile for vdso32
 #
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_ARM_JUMP_SLOT|R_ARM_GLOB_DAT|R_ARM_ABS32
 include $(srctree)/lib/vdso/Makefile
 
 # Same as cc-*option, but using CC_COMPAT instead of CC
index ca6eadeb7d1a1142c4212dd51495099fae8db2cf..f531da6b362e902a06e9aa76968d9f0ad52e1a23 100644 (file)
@@ -29,7 +29,6 @@ menuconfig KVM
        select KVM_MMIO
        select KVM_GENERIC_DIRTYLOG_READ_PROTECT
        select KVM_XFER_TO_GUEST_WORK
-       select SRCU
        select KVM_VFIO
        select HAVE_KVM_EVENTFD
        select HAVE_KVM_IRQFD
index 00610477ec7bd8da4a7ccbd5a764851145989490..e1af4301b913d87024cc55f1d2aa4cbeb4d3f20c 100644 (file)
@@ -84,14 +84,10 @@ u64 timer_get_cval(struct arch_timer_context *ctxt)
 
 static u64 timer_get_offset(struct arch_timer_context *ctxt)
 {
-       struct kvm_vcpu *vcpu = ctxt->vcpu;
+       if (ctxt->offset.vm_offset)
+               return *ctxt->offset.vm_offset;
 
-       switch(arch_timer_ctx_index(ctxt)) {
-       case TIMER_VTIMER:
-               return __vcpu_sys_reg(vcpu, CNTVOFF_EL2);
-       default:
-               return 0;
-       }
+       return 0;
 }
 
 static void timer_set_ctl(struct arch_timer_context *ctxt, u32 ctl)
@@ -128,15 +124,12 @@ static void timer_set_cval(struct arch_timer_context *ctxt, u64 cval)
 
 static void timer_set_offset(struct arch_timer_context *ctxt, u64 offset)
 {
-       struct kvm_vcpu *vcpu = ctxt->vcpu;
-
-       switch(arch_timer_ctx_index(ctxt)) {
-       case TIMER_VTIMER:
-               __vcpu_sys_reg(vcpu, CNTVOFF_EL2) = offset;
-               break;
-       default:
+       if (!ctxt->offset.vm_offset) {
                WARN(offset, "timer %ld\n", arch_timer_ctx_index(ctxt));
+               return;
        }
+
+       WRITE_ONCE(*ctxt->offset.vm_offset, offset);
 }
 
 u64 kvm_phys_timer_read(void)
@@ -765,25 +758,6 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
        return 0;
 }
 
-/* Make the updates of cntvoff for all vtimer contexts atomic */
-static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
-{
-       unsigned long i;
-       struct kvm *kvm = vcpu->kvm;
-       struct kvm_vcpu *tmp;
-
-       mutex_lock(&kvm->lock);
-       kvm_for_each_vcpu(i, tmp, kvm)
-               timer_set_offset(vcpu_vtimer(tmp), cntvoff);
-
-       /*
-        * When called from the vcpu create path, the CPU being created is not
-        * included in the loop above, so we just set it here as well.
-        */
-       timer_set_offset(vcpu_vtimer(vcpu), cntvoff);
-       mutex_unlock(&kvm->lock);
-}
-
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_cpu *timer = vcpu_timer(vcpu);
@@ -791,10 +765,11 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
        struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
 
        vtimer->vcpu = vcpu;
+       vtimer->offset.vm_offset = &vcpu->kvm->arch.timer_data.voffset;
        ptimer->vcpu = vcpu;
 
        /* Synchronize cntvoff across all vtimers of a VM. */
-       update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
+       timer_set_offset(vtimer, kvm_phys_timer_read());
        timer_set_offset(ptimer, 0);
 
        hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_HARD);
@@ -840,7 +815,7 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
                break;
        case KVM_REG_ARM_TIMER_CNT:
                timer = vcpu_vtimer(vcpu);
-               update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
+               timer_set_offset(timer, kvm_phys_timer_read() - value);
                break;
        case KVM_REG_ARM_TIMER_CVAL:
                timer = vcpu_vtimer(vcpu);
index 3bd732eaf08725509f7f0991cb359d1c1c7672cc..4b2e16e696a807cb6328892082ff71bcad90d1ca 100644 (file)
@@ -220,6 +220,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_VCPU_ATTRIBUTES:
        case KVM_CAP_PTP_KVM:
        case KVM_CAP_ARM_SYSTEM_SUSPEND:
+       case KVM_CAP_IRQFD_RESAMPLE:
                r = 1;
                break;
        case KVM_CAP_SET_GUEST_DEBUG2:
@@ -1889,9 +1890,33 @@ static int __init do_pkvm_init(u32 hyp_va_bits)
        return ret;
 }
 
+static u64 get_hyp_id_aa64pfr0_el1(void)
+{
+       /*
+        * Track whether the system isn't affected by spectre/meltdown in the
+        * hypervisor's view of id_aa64pfr0_el1, used for protected VMs.
+        * Although this is per-CPU, we make it global for simplicity, e.g., not
+        * to have to worry about vcpu migration.
+        *
+        * Unlike for non-protected VMs, userspace cannot override this for
+        * protected VMs.
+        */
+       u64 val = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+
+       val &= ~(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2) |
+                ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3));
+
+       val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2),
+                         arm64_get_spectre_v2_state() == SPECTRE_UNAFFECTED);
+       val |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3),
+                         arm64_get_meltdown_state() == SPECTRE_UNAFFECTED);
+
+       return val;
+}
+
 static void kvm_hyp_init_symbols(void)
 {
-       kvm_nvhe_sym(id_aa64pfr0_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+       kvm_nvhe_sym(id_aa64pfr0_el1_sys_val) = get_hyp_id_aa64pfr0_el1();
        kvm_nvhe_sym(id_aa64pfr1_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
        kvm_nvhe_sym(id_aa64isar0_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64ISAR0_EL1);
        kvm_nvhe_sym(id_aa64isar1_el1_sys_val) = read_sanitised_ftr_reg(SYS_ID_AA64ISAR1_EL1);
index 07edfc7524c942eb2e199578b306bf92b869acbe..37440e1dda9306f7abde4cd24cc32c0d229b81ce 100644 (file)
  * Allow for protected VMs:
  * - Floating-point and Advanced SIMD
  * - Data Independent Timing
+ * - Spectre/Meltdown Mitigation
  */
 #define PVM_ID_AA64PFR0_ALLOW (\
        ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_FP) | \
        ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_AdvSIMD) | \
-       ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_DIT) \
+       ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_DIT) | \
+       ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2) | \
+       ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3) \
        )
 
 /*
index 08d2b004f4b73cd61bd80f5b10b6749fd1052459..edd969a1f36b54bfe14b8e9a02a4bc35939f0118 100644 (file)
@@ -85,19 +85,12 @@ static u64 get_restricted_features_unsigned(u64 sys_reg_val,
 
 static u64 get_pvm_id_aa64pfr0(const struct kvm_vcpu *vcpu)
 {
-       const struct kvm *kvm = (const struct kvm *)kern_hyp_va(vcpu->kvm);
        u64 set_mask = 0;
        u64 allow_mask = PVM_ID_AA64PFR0_ALLOW;
 
        set_mask |= get_restricted_features_unsigned(id_aa64pfr0_el1_sys_val,
                PVM_ID_AA64PFR0_RESTRICT_UNSIGNED);
 
-       /* Spectre and Meltdown mitigation in KVM */
-       set_mask |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV2),
-                              (u64)kvm->arch.pfr0_csv2);
-       set_mask |= FIELD_PREP(ARM64_FEATURE_MASK(ID_AA64PFR0_EL1_CSV3),
-                              (u64)kvm->arch.pfr0_csv3);
-
        return (id_aa64pfr0_el1_sys_val & allow_mask) | set_mask;
 }
 
index 64c086c02c603167ddffa612f59b43daa2d9830f..c4b4678bc4a4580c6d9fd924cb66656d3c87cd98 100644 (file)
@@ -44,7 +44,7 @@ static void kvm_ptp_get_time(struct kvm_vcpu *vcpu, u64 *val)
        feature = smccc_get_arg1(vcpu);
        switch (feature) {
        case KVM_PTP_VIRT_COUNTER:
-               cycles = systime_snapshot.cycles - vcpu_read_sys_reg(vcpu, CNTVOFF_EL2);
+               cycles = systime_snapshot.cycles - vcpu->kvm->arch.timer_data.voffset;
                break;
        case KVM_PTP_PHYS_COUNTER:
                cycles = systime_snapshot.cycles;
@@ -397,6 +397,8 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
        u64 val;
        int wa_level;
 
+       if (KVM_REG_SIZE(reg->id) != sizeof(val))
+               return -ENOENT;
        if (copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id)))
                return -EFAULT;
 
index 7113587222ffe8e1befff0c4d4d7c29e4fde29c5..3b9d4d24c361ae4f903e12c19df146dcb90c9db8 100644 (file)
@@ -666,14 +666,33 @@ static int get_user_mapping_size(struct kvm *kvm, u64 addr)
                                   CONFIG_PGTABLE_LEVELS),
                .mm_ops         = &kvm_user_mm_ops,
        };
+       unsigned long flags;
        kvm_pte_t pte = 0;      /* Keep GCC quiet... */
        u32 level = ~0;
        int ret;
 
+       /*
+        * Disable IRQs so that we hazard against a concurrent
+        * teardown of the userspace page tables (which relies on
+        * IPI-ing threads).
+        */
+       local_irq_save(flags);
        ret = kvm_pgtable_get_leaf(&pgt, addr, &pte, &level);
-       VM_BUG_ON(ret);
-       VM_BUG_ON(level >= KVM_PGTABLE_MAX_LEVELS);
-       VM_BUG_ON(!(pte & PTE_VALID));
+       local_irq_restore(flags);
+
+       if (ret)
+               return ret;
+
+       /*
+        * Not seeing an error, but not updating level? Something went
+        * deeply wrong...
+        */
+       if (WARN_ON(level >= KVM_PGTABLE_MAX_LEVELS))
+               return -EFAULT;
+
+       /* Oops, the userspace PTs are gone... Replay the fault */
+       if (!kvm_pte_valid(pte))
+               return -EAGAIN;
 
        return BIT(ARM64_HW_PGTABLE_LEVEL_SHIFT(level));
 }
@@ -1079,7 +1098,7 @@ static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
  *
  * Returns the size of the mapping.
  */
-static unsigned long
+static long
 transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot,
                            unsigned long hva, kvm_pfn_t *pfnp,
                            phys_addr_t *ipap)
@@ -1091,8 +1110,15 @@ transparent_hugepage_adjust(struct kvm *kvm, struct kvm_memory_slot *memslot,
         * sure that the HVA and IPA are sufficiently aligned and that the
         * block map is contained within the memslot.
         */
-       if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE) &&
-           get_user_mapping_size(kvm, hva) >= PMD_SIZE) {
+       if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) {
+               int sz = get_user_mapping_size(kvm, hva);
+
+               if (sz < 0)
+                       return sz;
+
+               if (sz < PMD_SIZE)
+                       return PAGE_SIZE;
+
                /*
                 * The address we faulted on is backed by a transparent huge
                 * page.  However, because we map the compound huge page and
@@ -1192,7 +1218,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 {
        int ret = 0;
        bool write_fault, writable, force_pte = false;
-       bool exec_fault;
+       bool exec_fault, mte_allowed;
        bool device = false;
        unsigned long mmu_seq;
        struct kvm *kvm = vcpu->kvm;
@@ -1203,7 +1229,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
        kvm_pfn_t pfn;
        bool logging_active = memslot_is_logging(memslot);
        unsigned long fault_level = kvm_vcpu_trap_get_fault_level(vcpu);
-       unsigned long vma_pagesize, fault_granule;
+       long vma_pagesize, fault_granule;
        enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R;
        struct kvm_pgtable *pgt;
 
@@ -1217,6 +1243,20 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                return -EFAULT;
        }
 
+       /*
+        * Permission faults just need to update the existing leaf entry,
+        * and so normally don't require allocations from the memcache. The
+        * only exception to this is when dirty logging is enabled at runtime
+        * and a write fault needs to collapse a block entry into a table.
+        */
+       if (fault_status != ESR_ELx_FSC_PERM ||
+           (logging_active && write_fault)) {
+               ret = kvm_mmu_topup_memory_cache(memcache,
+                                                kvm_mmu_cache_min_pages(kvm));
+               if (ret)
+                       return ret;
+       }
+
        /*
         * Let's check if we will get back a huge page backed by hugetlbfs, or
         * get block mapping for device MMIO region.
@@ -1269,37 +1309,21 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                fault_ipa &= ~(vma_pagesize - 1);
 
        gfn = fault_ipa >> PAGE_SHIFT;
-       mmap_read_unlock(current->mm);
+       mte_allowed = kvm_vma_mte_allowed(vma);
 
-       /*
-        * Permission faults just need to update the existing leaf entry,
-        * and so normally don't require allocations from the memcache. The
-        * only exception to this is when dirty logging is enabled at runtime
-        * and a write fault needs to collapse a block entry into a table.
-        */
-       if (fault_status != ESR_ELx_FSC_PERM ||
-           (logging_active && write_fault)) {
-               ret = kvm_mmu_topup_memory_cache(memcache,
-                                                kvm_mmu_cache_min_pages(kvm));
-               if (ret)
-                       return ret;
-       }
+       /* Don't use the VMA after the unlock -- it may have vanished */
+       vma = NULL;
 
-       mmu_seq = vcpu->kvm->mmu_invalidate_seq;
        /*
-        * Ensure the read of mmu_invalidate_seq happens before we call
-        * gfn_to_pfn_prot (which calls get_user_pages), so that we don't risk
-        * the page we just got a reference to gets unmapped before we have a
-        * chance to grab the mmu_lock, which ensure that if the page gets
-        * unmapped afterwards, the call to kvm_unmap_gfn will take it away
-        * from us again properly. This smp_rmb() interacts with the smp_wmb()
-        * in kvm_mmu_notifier_invalidate_<page|range_end>.
+        * Read mmu_invalidate_seq so that KVM can detect if the results of
+        * vma_lookup() or __gfn_to_pfn_memslot() become stale prior to
+        * acquiring kvm->mmu_lock.
         *
-        * Besides, __gfn_to_pfn_memslot() instead of gfn_to_pfn_prot() is
-        * used to avoid unnecessary overhead introduced to locate the memory
-        * slot because it's always fixed even @gfn is adjusted for huge pages.
+        * Rely on mmap_read_unlock() for an implicit smp_rmb(), which pairs
+        * with the smp_wmb() in kvm_mmu_invalidate_end().
         */
-       smp_rmb();
+       mmu_seq = vcpu->kvm->mmu_invalidate_seq;
+       mmap_read_unlock(current->mm);
 
        pfn = __gfn_to_pfn_memslot(memslot, gfn, false, false, NULL,
                                   write_fault, &writable, NULL);
@@ -1350,11 +1374,16 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                        vma_pagesize = transparent_hugepage_adjust(kvm, memslot,
                                                                   hva, &pfn,
                                                                   &fault_ipa);
+
+               if (vma_pagesize < 0) {
+                       ret = vma_pagesize;
+                       goto out_unlock;
+               }
        }
 
        if (fault_status != ESR_ELx_FSC_PERM && !device && kvm_has_mte(kvm)) {
                /* Check the VMM hasn't introduced a new disallowed VMA */
-               if (kvm_vma_mte_allowed(vma)) {
+               if (mte_allowed) {
                        sanitise_mte_tags(kvm, pfn, vma_pagesize);
                } else {
                        ret = -EFAULT;
index 24908400e190616f317b9e6725b4605c12d1c8a4..5eca0cdd961df8410161e35a154b17a1583b7f9e 100644 (file)
@@ -538,7 +538,8 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
        if (!kvm_pmu_is_3p5(vcpu))
                val &= ~ARMV8_PMU_PMCR_LP;
 
-       __vcpu_sys_reg(vcpu, PMCR_EL0) = val;
+       /* The reset bits don't indicate any state, and shouldn't be saved. */
+       __vcpu_sys_reg(vcpu, PMCR_EL0) = val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P);
 
        if (val & ARMV8_PMU_PMCR_E) {
                kvm_pmu_enable_counter_mask(vcpu,
@@ -557,6 +558,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
                for_each_set_bit(i, &mask, 32)
                        kvm_pmu_set_pmc_value(kvm_vcpu_idx_to_pmc(vcpu, i), 0, true);
        }
+       kvm_vcpu_pmu_restore_guest(vcpu);
 }
 
 static bool kvm_pmu_counter_is_enabled(struct kvm_pmc *pmc)
index 53749d3a0996d73646290c4ceeb96cc21511446d..34688918c81134b8df65f5612f46321d674b670f 100644 (file)
@@ -794,7 +794,6 @@ static bool access_pmcr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
                if (!kvm_supports_32bit_el0())
                        val |= ARMV8_PMU_PMCR_LC;
                kvm_pmu_handle_pmcr(vcpu, val);
-               kvm_vcpu_pmu_restore_guest(vcpu);
        } else {
                /* PMCR.P & PMCR.C are RAZ */
                val = __vcpu_sys_reg(vcpu, PMCR_EL0)
@@ -856,6 +855,22 @@ static bool pmu_counter_idx_valid(struct kvm_vcpu *vcpu, u64 idx)
        return true;
 }
 
+static int get_pmu_evcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
+                         u64 *val)
+{
+       u64 idx;
+
+       if (r->CRn == 9 && r->CRm == 13 && r->Op2 == 0)
+               /* PMCCNTR_EL0 */
+               idx = ARMV8_PMU_CYCLE_IDX;
+       else
+               /* PMEVCNTRn_EL0 */
+               idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
+
+       *val = kvm_pmu_get_counter_value(vcpu, idx);
+       return 0;
+}
+
 static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
                              struct sys_reg_params *p,
                              const struct sys_reg_desc *r)
@@ -1072,7 +1087,7 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 /* Macro to expand the PMEVCNTRn_EL0 register */
 #define PMU_PMEVCNTR_EL0(n)                                            \
        { PMU_SYS_REG(SYS_PMEVCNTRn_EL0(n)),                            \
-         .reset = reset_pmevcntr,                                      \
+         .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,          \
          .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
@@ -1982,7 +1997,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { PMU_SYS_REG(SYS_PMCEID1_EL0),
          .access = access_pmceid, .reset = NULL },
        { PMU_SYS_REG(SYS_PMCCNTR_EL0),
-         .access = access_pmu_evcntr, .reset = reset_unknown, .reg = PMCCNTR_EL0 },
+         .access = access_pmu_evcntr, .reset = reset_unknown,
+         .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
        { PMU_SYS_REG(SYS_PMXEVTYPER_EL0),
          .access = access_pmu_evtyper, .reset = NULL },
        { PMU_SYS_REG(SYS_PMXEVCNTR_EL0),
index a6acb94ea3d63370bec139fa5ff757206e1b1d6e..c2edadb8ec6a30de7788a6b67fdce762711b9475 100644 (file)
 /* DMB */
 #define A64_DMB_ISH aarch64_insn_gen_dmb(AARCH64_INSN_MB_ISH)
 
+/* ADR */
+#define A64_ADR(Rd, offset) \
+       aarch64_insn_gen_adr(0, offset, Rd, AARCH64_INSN_ADR_TYPE_ADR)
+
 #endif /* _BPF_JIT_H */
index 62f805f427b79fd1ce10abdee53f8b1283dc0c1e..b26da8efa616ec133b23b0d4cacd54192ea7c6af 100644 (file)
@@ -1900,7 +1900,8 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
                restore_args(ctx, args_off, nargs);
                /* call original func */
                emit(A64_LDR64I(A64_R(10), A64_SP, retaddr_off), ctx);
-               emit(A64_BLR(A64_R(10)), ctx);
+               emit(A64_ADR(A64_LR, AARCH64_INSN_SIZE * 2), ctx);
+               emit(A64_RET(A64_R(10)), ctx);
                /* store return value */
                emit(A64_STR64I(A64_R(0), A64_SP, retval_off), ctx);
                /* reserve a nop for bpf_tramp_image_put */
index ea75d72dea86966232dd4b04ec4fa4ea419ef784..e487a46d1c37b47f1c9e46b4b341bff60a0f0152 100644 (file)
@@ -72,8 +72,6 @@ struct task_struct;
 /* Prepare to copy thread state - unlazy all lazy status */
 #define prepare_to_copy(tsk)    do { } while (0)
 
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 unsigned long __get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)          (task_pt_regs(tsk)->pc)
index 0b6909f10667936b86834883035584fe9d13e8dc..299e4e41ebc50565d786f4338fa37507488b038c 100644 (file)
@@ -1,8 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_CKCORE_ADDR32|R_CKCORE_JUMP_SLOT
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 # Symbols present in the vdso
index 21dfa4aa35bb1e8559c9d6b3051f9d520b87c6ec..033f5aead88a4d5e9aab8578290dc1c9dd5cc518 100644 (file)
@@ -853,7 +853,7 @@ valid_phys_addr_range (phys_addr_t phys_addr, unsigned long size)
         * /dev/mem reads and writes use copy_to_user(), which implicitly
         * uses a granule-sized kernel identity mapping.  It's really
         * only safe to do this for regions in kern_memmap.  For more
-        * details, see Documentation/ia64/aliasing.rst.
+        * details, see Documentation/arch/ia64/aliasing.rst.
         */
        attr = kern_mem_attribute(phys_addr, size);
        if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
index 2094f324901982e2a225f9a248f75db5fe4230aa..cc4733e9990a74b2a89e47d2bec7a02e67256f7c 100644 (file)
@@ -28,7 +28,7 @@
 #include <asm/native/inst.h>
 
 /*
- * See Documentation/ia64/fsys.rst for details on fsyscalls.
+ * See Documentation/arch/ia64/fsys.rst for details on fsyscalls.
  *
  * On entry to an fsyscall handler:
  *   r10       = 0 (i.e., defaults to "successful syscall return")
index 55fd3eb753ff94fe8491e095a42ca6a1c3a2b5ba..92b81bc91397f79776971c44ab70c06afb2b15c5 100644 (file)
@@ -43,7 +43,7 @@ ioremap (unsigned long phys_addr, unsigned long size)
        /*
         * For things in kern_memmap, we must use the same attribute
         * as the rest of the kernel.  For more details, see
-        * Documentation/ia64/aliasing.rst.
+        * Documentation/arch/ia64/aliasing.rst.
         */
        attr = kern_mem_attribute(phys_addr, size);
        if (attr & EFI_MEMORY_WB)
index 211757e34198a35267160298d6e0b923f5e8d5a0..0a0328e61bef3f10a0787bb3ab0584879ebc4a8c 100644 (file)
@@ -448,7 +448,7 @@ pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
                return -ENOSYS;
 
        /*
-        * Avoid attribute aliasing.  See Documentation/ia64/aliasing.rst
+        * Avoid attribute aliasing.  See Documentation/arch/ia64/aliasing.rst
         * for more details.
         */
        if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
index 7fd51257e0ed41b0460e584683805c2ed0f3714f..3ddde336e6a56f8c014fa0d0413379116e0f96f2 100644 (file)
@@ -447,6 +447,22 @@ config ARCH_IOREMAP
          protection support. However, you can enable LoongArch DMW-based
          ioremap() for better performance.
 
+config ARCH_WRITECOMBINE
+       bool "Enable WriteCombine (WUC) for ioremap()"
+       help
+         LoongArch maintains cache coherency in hardware, but when paired
+         with LS7A chipsets the WUC attribute (Weak-ordered UnCached, which
+         is similar to WriteCombine) is out of the scope of cache coherency
+         machanism for PCIe devices (this is a PCIe protocol violation, which
+         may be fixed in newer chipsets).
+
+         This means WUC can only used for write-only memory regions now, so
+         this option is disabled by default, making WUC silently fallback to
+         SUC for ioremap(). You can enable this option if the kernel is ensured
+         to run on hardware without this bug.
+
+         You can override this setting via writecombine=on/off boot parameter.
+
 config ARCH_STRICT_ALIGN
        bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
        default y
index 4198753aa1d0f1782a1cb17f2a4280881aa3d0c2..976a810352c601ddb7bd286a2bf732a1b46b5ae0 100644 (file)
@@ -41,8 +41,11 @@ extern void loongarch_suspend_enter(void);
 
 static inline unsigned long acpi_get_wakeup_address(void)
 {
+#ifdef CONFIG_SUSPEND
        extern void loongarch_wakeup_start(void);
        return (unsigned long)loongarch_wakeup_start;
+#endif
+       return 0UL;
 }
 
 #endif /* _ASM_LOONGARCH_ACPI_H */
index 8fb699b4d40afb0ac7ccdeaf30a41e9783e30d26..5c9c03bdf91569154b9a449019e29b46049d5bef 100644 (file)
@@ -71,9 +71,9 @@ extern unsigned long vm_map_base;
 #define _ATYPE32_      int
 #define _ATYPE64_      __s64
 #ifdef CONFIG_64BIT
-#define _CONST64_(x)   x ## L
+#define _CONST64_(x)   x ## UL
 #else
-#define _CONST64_(x)   x ## LL
+#define _CONST64_(x)   x ## ULL
 #endif
 #endif
 
index 0051b526ac6d31307643dc317b6310a72ba53217..c60796869b2b80377d9d6afca9c8705f8d2433e1 100644 (file)
@@ -13,7 +13,6 @@ const char *get_system_type(void);
 extern void init_environ(void);
 extern void memblock_init(void);
 extern void platform_init(void);
-extern void plat_swiotlb_setup(void);
 extern int __init init_numa_memory(void);
 
 struct loongson_board_info {
index b07974218393d1dd6f47fa45f429363134f4d605..f6177f133477670edc2b5f955d379101e8147032 100644 (file)
@@ -42,6 +42,7 @@
 #define cpu_has_fpu            cpu_opt(LOONGARCH_CPU_FPU)
 #define cpu_has_lsx            cpu_opt(LOONGARCH_CPU_LSX)
 #define cpu_has_lasx           cpu_opt(LOONGARCH_CPU_LASX)
+#define cpu_has_crc32          cpu_opt(LOONGARCH_CPU_CRC32)
 #define cpu_has_complex                cpu_opt(LOONGARCH_CPU_COMPLEX)
 #define cpu_has_crypto         cpu_opt(LOONGARCH_CPU_CRYPTO)
 #define cpu_has_lvz            cpu_opt(LOONGARCH_CPU_LVZ)
index c3da91759472841c0f15e71b5f03603077ae6d0d..88773d849e332f08047460efecf97fb429976505 100644 (file)
@@ -78,25 +78,26 @@ enum cpu_type_enum {
 #define CPU_FEATURE_FPU                        3       /* CPU has FPU */
 #define CPU_FEATURE_LSX                        4       /* CPU has LSX (128-bit SIMD) */
 #define CPU_FEATURE_LASX               5       /* CPU has LASX (256-bit SIMD) */
-#define CPU_FEATURE_COMPLEX            6       /* CPU has Complex instructions */
-#define CPU_FEATURE_CRYPTO             7       /* CPU has Crypto instructions */
-#define CPU_FEATURE_LVZ                        8       /* CPU has Virtualization extension */
-#define CPU_FEATURE_LBT_X86            9       /* CPU has X86 Binary Translation */
-#define CPU_FEATURE_LBT_ARM            10      /* CPU has ARM Binary Translation */
-#define CPU_FEATURE_LBT_MIPS           11      /* CPU has MIPS Binary Translation */
-#define CPU_FEATURE_TLB                        12      /* CPU has TLB */
-#define CPU_FEATURE_CSR                        13      /* CPU has CSR */
-#define CPU_FEATURE_WATCH              14      /* CPU has watchpoint registers */
-#define CPU_FEATURE_VINT               15      /* CPU has vectored interrupts */
-#define CPU_FEATURE_CSRIPI             16      /* CPU has CSR-IPI */
-#define CPU_FEATURE_EXTIOI             17      /* CPU has EXT-IOI */
-#define CPU_FEATURE_PREFETCH           18      /* CPU has prefetch instructions */
-#define CPU_FEATURE_PMP                        19      /* CPU has perfermance counter */
-#define CPU_FEATURE_SCALEFREQ          20      /* CPU supports cpufreq scaling */
-#define CPU_FEATURE_FLATMODE           21      /* CPU has flat mode */
-#define CPU_FEATURE_EIODECODE          22      /* CPU has EXTIOI interrupt pin decode mode */
-#define CPU_FEATURE_GUESTID            23      /* CPU has GuestID feature */
-#define CPU_FEATURE_HYPERVISOR         24      /* CPU has hypervisor (running in VM) */
+#define CPU_FEATURE_CRC32              6       /* CPU has CRC32 instructions */
+#define CPU_FEATURE_COMPLEX            7       /* CPU has Complex instructions */
+#define CPU_FEATURE_CRYPTO             8       /* CPU has Crypto instructions */
+#define CPU_FEATURE_LVZ                        9       /* CPU has Virtualization extension */
+#define CPU_FEATURE_LBT_X86            10      /* CPU has X86 Binary Translation */
+#define CPU_FEATURE_LBT_ARM            11      /* CPU has ARM Binary Translation */
+#define CPU_FEATURE_LBT_MIPS           12      /* CPU has MIPS Binary Translation */
+#define CPU_FEATURE_TLB                        13      /* CPU has TLB */
+#define CPU_FEATURE_CSR                        14      /* CPU has CSR */
+#define CPU_FEATURE_WATCH              15      /* CPU has watchpoint registers */
+#define CPU_FEATURE_VINT               16      /* CPU has vectored interrupts */
+#define CPU_FEATURE_CSRIPI             17      /* CPU has CSR-IPI */
+#define CPU_FEATURE_EXTIOI             18      /* CPU has EXT-IOI */
+#define CPU_FEATURE_PREFETCH           19      /* CPU has prefetch instructions */
+#define CPU_FEATURE_PMP                        20      /* CPU has perfermance counter */
+#define CPU_FEATURE_SCALEFREQ          21      /* CPU supports cpufreq scaling */
+#define CPU_FEATURE_FLATMODE           22      /* CPU has flat mode */
+#define CPU_FEATURE_EIODECODE          23      /* CPU has EXTIOI interrupt pin decode mode */
+#define CPU_FEATURE_GUESTID            24      /* CPU has GuestID feature */
+#define CPU_FEATURE_HYPERVISOR         25      /* CPU has hypervisor (running in VM) */
 
 #define LOONGARCH_CPU_CPUCFG           BIT_ULL(CPU_FEATURE_CPUCFG)
 #define LOONGARCH_CPU_LAM              BIT_ULL(CPU_FEATURE_LAM)
@@ -104,6 +105,7 @@ enum cpu_type_enum {
 #define LOONGARCH_CPU_FPU              BIT_ULL(CPU_FEATURE_FPU)
 #define LOONGARCH_CPU_LSX              BIT_ULL(CPU_FEATURE_LSX)
 #define LOONGARCH_CPU_LASX             BIT_ULL(CPU_FEATURE_LASX)
+#define LOONGARCH_CPU_CRC32            BIT_ULL(CPU_FEATURE_CRC32)
 #define LOONGARCH_CPU_COMPLEX          BIT_ULL(CPU_FEATURE_COMPLEX)
 #define LOONGARCH_CPU_CRYPTO           BIT_ULL(CPU_FEATURE_CRYPTO)
 #define LOONGARCH_CPU_LVZ              BIT_ULL(CPU_FEATURE_LVZ)
index 402a7d9e3a53eafed41c4170de5627f673d142f4..545e2708fbf7042f6a61f29c1423be1f11de7a7e 100644 (file)
@@ -54,8 +54,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
  * @offset:    bus address of the memory
  * @size:      size of the resource to map
  */
+extern pgprot_t pgprot_wc;
+
 #define ioremap_wc(offset, size)       \
-       ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))
+       ioremap_prot((offset), (size), pgprot_val(pgprot_wc))
 
 #define ioremap_cache(offset, size)    \
        ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
index 65b7dcdea16d0f4f59bfed5cbee2444767327a6c..83da5d29e2d17b5c4e90d70d3a18575f6707eb60 100644 (file)
@@ -117,7 +117,7 @@ static inline u32 read_cpucfg(u32 reg)
 #define  CPUCFG1_EP                    BIT(22)
 #define  CPUCFG1_RPLV                  BIT(23)
 #define  CPUCFG1_HUGEPG                        BIT(24)
-#define  CPUCFG1_IOCSRBRD              BIT(25)
+#define  CPUCFG1_CRC32                 BIT(25)
 #define  CPUCFG1_MSGINT                        BIT(26)
 
 #define LOONGARCH_CPUCFG2              0x2
@@ -423,9 +423,9 @@ static __always_inline void iocsr_write64(u64 val, u32 reg)
 #define  CSR_ASID_ASID_WIDTH           10
 #define  CSR_ASID_ASID                 (_ULCAST_(0x3ff) << CSR_ASID_ASID_SHIFT)
 
-#define LOONGARCH_CSR_PGDL             0x19    /* Page table base address when VA[47] = 0 */
+#define LOONGARCH_CSR_PGDL             0x19    /* Page table base address when VA[VALEN-1] = 0 */
 
-#define LOONGARCH_CSR_PGDH             0x1a    /* Page table base address when VA[47] = 1 */
+#define LOONGARCH_CSR_PGDH             0x1a    /* Page table base address when VA[VALEN-1] = 1 */
 
 #define LOONGARCH_CSR_PGD              0x1b    /* Page table base */
 
index 438f09d4ccf41d6032f07b7ebcb3799ff7bf4c22..88554f92e0103de153ece66aa2e8b7d1857db1c8 100644 (file)
@@ -2,8 +2,8 @@
 /* Copyright (C) 2020-2022 Loongson Technology Corporation Limited */
 SECTIONS {
        . = ALIGN(4);
-       .got : { BYTE(0) }
-       .plt : { BYTE(0) }
-       .plt.idx : { BYTE(0) }
-       .ftrace_trampoline : { BYTE(0) }
+       .got : { BYTE(0) }
+       .plt : { BYTE(0) }
+       .plt.idx : { BYTE(0) }
+       .ftrace_trampoline : { BYTE(0) }
 }
index cc48ed262021244bcbcc7e0f98b63d8dc7e4b9de..82d811b5c6e972fe06771948b4f8b5d0a2c2791b 100644 (file)
@@ -47,11 +47,12 @@ struct user_fp_state {
 };
 
 struct user_watch_state {
-       uint16_t dbg_info;
+       uint64_t dbg_info;
        struct {
                uint64_t    addr;
                uint64_t    mask;
                uint32_t    ctrl;
+               uint32_t    pad;
        } dbg_regs[8];
 };
 
index 3a3fce2d784611e1118e6a6d5dab1b509501dd9c..5adf0f736c6d74b132b9c24d6a154b12db77d309 100644 (file)
@@ -60,7 +60,7 @@ static inline void set_elf_platform(int cpu, const char *plat)
 
 /* MAP BASE */
 unsigned long vm_map_base;
-EXPORT_SYMBOL_GPL(vm_map_base);
+EXPORT_SYMBOL(vm_map_base);
 
 static void cpu_probe_addrbits(struct cpuinfo_loongarch *c)
 {
@@ -94,13 +94,18 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c)
        c->options = LOONGARCH_CPU_CPUCFG | LOONGARCH_CPU_CSR |
                     LOONGARCH_CPU_TLB | LOONGARCH_CPU_VINT | LOONGARCH_CPU_WATCH;
 
-       elf_hwcap = HWCAP_LOONGARCH_CPUCFG | HWCAP_LOONGARCH_CRC32;
+       elf_hwcap = HWCAP_LOONGARCH_CPUCFG;
 
        config = read_cpucfg(LOONGARCH_CPUCFG1);
        if (config & CPUCFG1_UAL) {
                c->options |= LOONGARCH_CPU_UAL;
                elf_hwcap |= HWCAP_LOONGARCH_UAL;
        }
+       if (config & CPUCFG1_CRC32) {
+               c->options |= LOONGARCH_CPU_CRC32;
+               elf_hwcap |= HWCAP_LOONGARCH_CRC32;
+       }
+
 
        config = read_cpucfg(LOONGARCH_CPUCFG2);
        if (config & CPUCFG2_LAM) {
index 5c67cc4fd56d5f68301d3738ea312632bf2a3746..0d82907b5404c31d0965df34a4220157e99d5e8e 100644 (file)
@@ -76,6 +76,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        if (cpu_has_fpu)        seq_printf(m, " fpu");
        if (cpu_has_lsx)        seq_printf(m, " lsx");
        if (cpu_has_lasx)       seq_printf(m, " lasx");
+       if (cpu_has_crc32)      seq_printf(m, " crc32");
        if (cpu_has_complex)    seq_printf(m, " complex");
        if (cpu_has_crypto)     seq_printf(m, " crypto");
        if (cpu_has_lvz)        seq_printf(m, " lvz");
index 06bceae7d1040c6cfb38fe07acea7f1f765eb1a0..5fcffb45236764ee75fce64c2508003b5773bffc 100644 (file)
@@ -391,10 +391,10 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
        return 0;
 }
 
-static int ptrace_hbp_get_resource_info(unsigned int note_type, u16 *info)
+static int ptrace_hbp_get_resource_info(unsigned int note_type, u64 *info)
 {
        u8 num;
-       u16 reg = 0;
+       u64 reg = 0;
 
        switch (note_type) {
        case NT_LOONGARCH_HW_BREAK:
@@ -524,15 +524,16 @@ static int ptrace_hbp_set_addr(unsigned int note_type,
        return modify_user_hw_breakpoint(bp, &attr);
 }
 
-#define PTRACE_HBP_CTRL_SZ     sizeof(u32)
 #define PTRACE_HBP_ADDR_SZ     sizeof(u64)
 #define PTRACE_HBP_MASK_SZ     sizeof(u64)
+#define PTRACE_HBP_CTRL_SZ     sizeof(u32)
+#define PTRACE_HBP_PAD_SZ      sizeof(u32)
 
 static int hw_break_get(struct task_struct *target,
                        const struct user_regset *regset,
                        struct membuf to)
 {
-       u16 info;
+       u64 info;
        u32 ctrl;
        u64 addr, mask;
        int ret, idx = 0;
@@ -545,7 +546,7 @@ static int hw_break_get(struct task_struct *target,
 
        membuf_write(&to, &info, sizeof(info));
 
-       /* (address, ctrl) registers */
+       /* (address, mask, ctrl) registers */
        while (to.left) {
                ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
                if (ret)
@@ -562,6 +563,7 @@ static int hw_break_get(struct task_struct *target,
                membuf_store(&to, addr);
                membuf_store(&to, mask);
                membuf_store(&to, ctrl);
+               membuf_zero(&to, sizeof(u32));
                idx++;
        }
 
@@ -582,7 +584,7 @@ static int hw_break_set(struct task_struct *target,
        offset = offsetof(struct user_watch_state, dbg_regs);
        user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
 
-       /* (address, ctrl) registers */
+       /* (address, mask, ctrl) registers */
        limit = regset->n * regset->size;
        while (count && offset < limit) {
                if (count < PTRACE_HBP_ADDR_SZ)
@@ -602,7 +604,7 @@ static int hw_break_set(struct task_struct *target,
                        break;
 
                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &mask,
-                                        offset, offset + PTRACE_HBP_ADDR_SZ);
+                                        offset, offset + PTRACE_HBP_MASK_SZ);
                if (ret)
                        return ret;
 
@@ -611,8 +613,8 @@ static int hw_break_set(struct task_struct *target,
                        return ret;
                offset += PTRACE_HBP_MASK_SZ;
 
-               ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &mask,
-                                        offset, offset + PTRACE_HBP_MASK_SZ);
+               ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
+                                        offset, offset + PTRACE_HBP_CTRL_SZ);
                if (ret)
                        return ret;
 
@@ -620,6 +622,11 @@ static int hw_break_set(struct task_struct *target,
                if (ret)
                        return ret;
                offset += PTRACE_HBP_CTRL_SZ;
+
+               user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                         offset, offset + PTRACE_HBP_PAD_SZ);
+               offset += PTRACE_HBP_PAD_SZ;
+
                idx++;
        }
 
index bae84ccf6d3671c29e1849ec1542693d1ef5a06f..4444b13418f0e0621d56d339ba4302c4d0ec2f29 100644 (file)
@@ -160,6 +160,27 @@ static void __init smbios_parse(void)
        dmi_walk(find_tokens, NULL);
 }
 
+#ifdef CONFIG_ARCH_WRITECOMBINE
+pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
+#else
+pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
+#endif
+
+EXPORT_SYMBOL(pgprot_wc);
+
+static int __init setup_writecombine(char *p)
+{
+       if (!strcmp(p, "on"))
+               pgprot_wc = PAGE_KERNEL_WUC;
+       else if (!strcmp(p, "off"))
+               pgprot_wc = PAGE_KERNEL_SUC;
+       else
+               pr_warn("Unknown writecombine setting \"%s\".\n", p);
+
+       return 0;
+}
+early_param("writecombine", setup_writecombine);
+
 static int usermem __initdata;
 
 static int __init early_parse_mem(char *p)
@@ -368,8 +389,8 @@ static void __init arch_mem_init(char **cmdline_p)
        /*
         * In order to reduce the possibility of kernel panic when failed to
         * get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
-        * low memory as small as possible before plat_swiotlb_setup(), so
-        * make sparse_init() using top-down allocation.
+        * low memory as small as possible before swiotlb_init(), so make
+        * sparse_init() using top-down allocation.
         */
        memblock_set_bottom_up(false);
        sparse_init();
index 3a690f96f00c1a67edccefd66c8f46f006dd4f4e..2463d2fea21f5f4bc9dd762fd5b1ed3c77c0fc40 100644 (file)
@@ -30,7 +30,7 @@ void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
 
        regs->regs[1] = 0;
        for (unwind_start(&state, task, regs);
-             !unwind_done(&state); unwind_next_frame(&state)) {
+            !unwind_done(&state) && !unwind_error(&state); unwind_next_frame(&state)) {
                addr = unwind_get_return_address(&state);
                if (!addr || !consume_entry(cookie, addr))
                        break;
index a463d6961344c0899aacd72a8951b9cc5d18ea83..ba324ba76fa15605d9ada6c26101ce78aa108df1 100644 (file)
@@ -28,5 +28,6 @@ bool default_next_frame(struct unwind_state *state)
 
        } while (!get_stack_info(state->sp, state->task, info));
 
+       state->error = true;
        return false;
 }
index 9095fde8e55d5c57177c83ab0548ab888c348f16..55afc27320e12a1c52fd98445ef32f383f1d2bf1 100644 (file)
@@ -211,7 +211,7 @@ static bool next_frame(struct unwind_state *state)
                        pc = regs->csr_era;
 
                        if (user_mode(regs) || !__kernel_text_address(pc))
-                               return false;
+                               goto out;
 
                        state->first = true;
                        state->pc = pc;
@@ -226,6 +226,8 @@ static bool next_frame(struct unwind_state *state)
 
        } while (!get_stack_info(state->sp, state->task, info));
 
+out:
+       state->error = true;
        return false;
 }
 
index e018aed345866010c0822c82bfc0c5459ef2e41e..3b7d8129570b83ac87455e8bb1c2f7c8a0ee35b1 100644 (file)
@@ -41,7 +41,7 @@
  * don't have to care about aliases on other CPUs.
  */
 unsigned long empty_zero_page, zero_page_mask;
-EXPORT_SYMBOL_GPL(empty_zero_page);
+EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(zero_page_mask);
 
 void setup_zero_pages(void)
@@ -270,7 +270,7 @@ pud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss;
 #endif
 #ifndef __PAGETABLE_PMD_FOLDED
 pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss;
-EXPORT_SYMBOL_GPL(invalid_pmd_table);
+EXPORT_SYMBOL(invalid_pmd_table);
 #endif
 pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
 EXPORT_SYMBOL(invalid_pte_table);
index 288003a9f0cae478a058102a6413e15a07585b29..d586df48ecc6432b94d034fcdc7641c9d1580794 100644 (file)
@@ -1022,6 +1022,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
                emit_atomic(insn, ctx);
                break;
 
+       /* Speculation barrier */
+       case BPF_ST | BPF_NOSPEC:
+               break;
+
        default:
                pr_err("bpf_jit: unknown opcode %02x\n", code);
                return -EINVAL;
index 90da899c06a194989ee4c0044f7cc908131090e7..e2fc3b4e31f0019164f57de05c05324cc2bb391d 100644 (file)
@@ -80,6 +80,10 @@ SYM_INNER_LABEL(loongarch_wakeup_start, SYM_L_GLOBAL)
 
        JUMP_VIRT_ADDR  t0, t1
 
+       /* Enable PG */
+       li.w            t0, 0xb0                # PLV=0, IE=0, PG=1
+       csrwr           t0, LOONGARCH_CSR_CRMD
+
        la.pcrel        t0, acpi_saved_sp
        ld.d            sp, t0, 0
        SETUP_WAKEUP
index d89e2ac75f7b85a360e50e81186a9536a43acc2d..461240ab44365f2a1d75b9f870a7a5540c2036e5 100644 (file)
@@ -1,9 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 # Objects to go into the VDSO.
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_LARCH_32|R_LARCH_64|R_LARCH_MARK_LA|R_LARCH_JUMP_SLOT
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 obj-vdso-y := elf.o vgetcpu.o vgettimeofday.o sigreturn.o
index 465e28be0ce46a6976674a3bcd49eb51421841a7..30638a6e8edcb35e72c283911321cd3e304cf40c 100644 (file)
@@ -36,11 +36,6 @@ config HIGHPROFILE
        help
          Use a fast secondary clock to produce profiling information.
 
-config NO_KERNEL_MSG
-       bool "Suppress Kernel BUG Messages"
-       help
-         Do not output any debug BUG messages within the kernel.
-
 config BDM_DISABLE
        bool "Disable BDM signals"
        depends on COLDFIRE
index e2f961208f18bec599c6712bacd7393182a6e9f6..28eebabfd34bc33bc16d9fe26432451ac1830f8a 100644 (file)
@@ -11,7 +11,7 @@ config AMIGA
        help
          This option enables support for the Amiga series of computers. If
          you plan to use this kernel on an Amiga, say Y here and browse the
-         material available in <file:Documentation/m68k>; otherwise say N.
+         material available in <file:Documentation/arch/m68k>; otherwise say N.
 
 config ATARI
        bool "Atari support"
@@ -23,7 +23,7 @@ config ATARI
          This option enables support for the 68000-based Atari series of
          computers (including the TT, Falcon and Medusa). If you plan to use
          this kernel on an Atari, say Y here and browse the material
-         available in <file:Documentation/m68k>; otherwise say N.
+         available in <file:Documentation/arch/m68k>; otherwise say N.
 
 config ATARI_KBD_CORE
        bool
index ec2d792015a4bdd0d74d67bc27b9171d7a0c11bb..b26469a65bc11ed45622096d42680b35ee310e44 100644 (file)
@@ -214,7 +214,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -495,6 +494,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -621,6 +621,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index 061a07824dc29502f081016263039163b23de691..944a49a129bedab08af9795f196b1168c2a47fed 100644 (file)
@@ -210,7 +210,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -452,6 +451,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -577,6 +577,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index 02af5f501dae7f0f357591a5a1d4abff3259254d..a32dd884fcce236ae739f5138d7994246fc8ecfa 100644 (file)
@@ -217,7 +217,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -472,6 +471,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -598,6 +598,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index 0d5832cb3e10b9ce1d92086e1fe913fa3fe2308c..23b7805309bd4407508a43e53c431c8512dc92d6 100644 (file)
@@ -207,7 +207,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -444,6 +443,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -569,6 +569,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index c246c3538839beb5fbf2312d0d7d4e75d1d5c5f9..5605ab5c3dcfc25f71ce7ef4e5335f9c173f6628 100644 (file)
@@ -209,7 +209,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -454,6 +453,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -579,6 +579,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index 98d2d0599e5a8f2c0239a9bf1c285f40ed927a1a..d0d1f9c33756d795f66905dc4442dbd71e41f053 100644 (file)
@@ -208,7 +208,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -474,6 +473,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -600,6 +600,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index b2d5ec6ba625c7b2ad6c2069d20ec00cdcff5df7..6d04314ce7eafb39a5045bfe0bc6535a36875f5b 100644 (file)
@@ -228,7 +228,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -314,7 +313,6 @@ CONFIG_AF_KCM=m
 # CONFIG_WIRELESS is not set
 CONFIG_PSAMPLE=m
 CONFIG_NET_IFE=m
-CONFIG_PCCARD=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_TEST_ASYNC_DRIVER_PROBE=m
@@ -561,6 +559,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -687,6 +686,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index d3420c642992b2e72d9294c1e493954684175ef2..e6f5ae526d0893393e5804ef4d45495126ce16ba 100644 (file)
@@ -206,7 +206,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -443,6 +442,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -568,6 +568,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index e294b0b67695069c52ca6c80a4cc5c7289018d0c..f2d4dff4787aade7b4510078104899604b24c24e 100644 (file)
@@ -207,7 +207,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -444,6 +443,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -569,6 +569,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index 764a94b089362003d5119ad39a7819d03b7d5e70..907eedecd040262c71c6ce7d1b125c8464312b9d 100644 (file)
@@ -208,7 +208,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -461,6 +460,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -587,6 +587,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index d4eeddac6bb8de48653c679eab54288888d01f86..9e3d47008f2186756b99ee9053bd6b0fa4fcc5e9 100644 (file)
@@ -204,7 +204,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -443,6 +442,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -567,6 +567,7 @@ CONFIG_TEST_LOCKUP=m
 CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index ca359b8806830d5674b1c140189a626d98a206d4..f6540078cb4beb48a0a9236c1f85cf050111ccc8 100644 (file)
@@ -204,7 +204,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_NETMAP=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -442,6 +441,7 @@ CONFIG_NFS_V4=m
 CONFIG_NFS_SWAP=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
+CONFIG_RPCSEC_GSS_KRB5=m
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS2 is not set
 # CONFIG_CIFS_DEBUG is not set
@@ -567,6 +567,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_KUNIT=m
 CONFIG_KUNIT_ALL_TESTS=m
+CONFIG_TEST_DHRY=m
 CONFIG_TEST_MIN_HEAP=m
 CONFIG_TEST_DIV64=m
 CONFIG_REED_SOLOMON_TEST=m
index 206f849831203ca1bfd40045732b630903b4950d..739875540e8971f549e385b9361cdc5bfe4b63c2 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kexec.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
 
 #include <asm/cacheflush.h>
 #include <asm/page.h>
index 33788668cbdbfc3ab12862e5f3b8874b15af1ea7..3779e7855bd756be930077c659d401e74df7af05 100644 (file)
@@ -5,6 +5,8 @@
 #include <asm/bmips.h>
 #include <asm/io.h>
 
+bool bmips_rac_flush_disable;
+
 void arch_sync_dma_for_cpu_all(void)
 {
        void __iomem *cbr = BMIPS_GET_CBR();
@@ -15,6 +17,9 @@ void arch_sync_dma_for_cpu_all(void)
            boot_cpu_type() != CPU_BMIPS4380)
                return;
 
+       if (unlikely(bmips_rac_flush_disable))
+               return;
+
        /* Flush stale data out of the readahead cache */
        cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
        __raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG);
index e95b3f78e7cd414899b1445cfb315abebc6d4d74..549a6392a3d2d3c6c6f890cb9a59b7ebb03d4922 100644 (file)
@@ -35,6 +35,8 @@
 #define REG_BCM6328_OTP                ((void __iomem *)CKSEG1ADDR(0x1000062c))
 #define BCM6328_TP1_DISABLED   BIT(9)
 
+extern bool bmips_rac_flush_disable;
+
 static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000;
 
 struct bmips_quirk {
@@ -104,6 +106,12 @@ static void bcm6358_quirks(void)
         * disable SMP for now
         */
        bmips_smp_enabled = 0;
+
+       /*
+        * RAC flush causes kernel panics on BCM6358 when booting from TP1
+        * because the bootloader is not initializing it properly.
+        */
+       bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31));
 }
 
 static void bcm6368_quirks(void)
index 52cbde60edf5b1b780b0ba30666aca3df4196b96..9ff55cb80a6457bba4c5a103c66372523380aff6 100644 (file)
@@ -15,6 +15,8 @@
 #define EMITS_PT_NOTE
 #endif
 
+#define RUNTIME_DISCARD_EXIT
+
 #include <asm-generic/vmlinux.lds.h>
 
 #undef mips
index 29e51649203bb5aa8f377f4b4d4b33da6bd62bd9..a8cdba75f98dde949c9cd86ef073027cc49bfad3 100644 (file)
@@ -26,7 +26,6 @@ config KVM
        select HAVE_KVM_VCPU_ASYNC_IOCTL
        select KVM_MMIO
        select MMU_NOTIFIER
-       select SRCU
        select INTERVAL_TREE
        select KVM_GENERIC_HARDWARE_ENABLING
        help
index 18af9474ed0eaebeae2e110c58017217e9b97a74..eb56581f6d734fa8fbfab419a954ba12b685eff0 100644 (file)
@@ -4,9 +4,7 @@
 # Sanitizer runtimes are unavailable and cannot be linked here.
  KCSAN_SANITIZE                        := n
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_MIPS_JUMP_SLOT|R_MIPS_GLOB_DAT
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 obj-vdso-y := elf.o vgettimeofday.o sigreturn.o
index bcc0e9915ebdab3d30a316525f5b1956c21daa1c..5abac9893b32b54e22d5b99ef9461a8b4723146d 100644 (file)
@@ -96,9 +96,6 @@ static inline struct thread_info *current_thread_info(void)
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK         0x0000FFFE
 
-/* work to do on any return to u-space */
-# define _TIF_ALLWORK_MASK     0x0000FFFF
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_NIOS2_THREAD_INFO_H */
index 2bbc0fcce04a36004ed31c4a5ce4f7ec92d2b84f..5e26c7f2c25ab29a528b3c70ddfe7926bc5a636f 100644 (file)
@@ -148,6 +148,11 @@ static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma,
         */
 }
 
+static inline bool __pte_protnone(unsigned long pte)
+{
+       return (pte & (pgprot_val(PAGE_NONE) | _PAGE_RWX)) == pgprot_val(PAGE_NONE);
+}
+
 static inline bool __pte_flags_need_flush(unsigned long oldval,
                                          unsigned long newval)
 {
@@ -164,8 +169,8 @@ static inline bool __pte_flags_need_flush(unsigned long oldval,
        /*
         * We do not expect kernel mappings or non-PTEs or not-present PTEs.
         */
-       VM_WARN_ON_ONCE(oldval & _PAGE_PRIVILEGED);
-       VM_WARN_ON_ONCE(newval & _PAGE_PRIVILEGED);
+       VM_WARN_ON_ONCE(!__pte_protnone(oldval) && oldval & _PAGE_PRIVILEGED);
+       VM_WARN_ON_ONCE(!__pte_protnone(newval) && newval & _PAGE_PRIVILEGED);
        VM_WARN_ON_ONCE(!(oldval & _PAGE_PTE));
        VM_WARN_ON_ONCE(!(newval & _PAGE_PTE));
        VM_WARN_ON_ONCE(!(oldval & _PAGE_PRESENT));
index 92a968202ba7ccf9c6d8b2da54fea778186e9cf5..365d2720097cb0724ced2c978de21e3f919f5b69 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef __ASM_KASAN_H
 #define __ASM_KASAN_H
 
-#ifdef CONFIG_KASAN
+#if defined(CONFIG_KASAN) && !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX)
 #define _GLOBAL_KASAN(fn)      _GLOBAL(__##fn)
 #define _GLOBAL_TOC_KASAN(fn)  _GLOBAL_TOC(__##fn)
 #define EXPORT_SYMBOL_KASAN(fn)        EXPORT_SYMBOL(__##fn)
index 2aa0e31e68844336a0fd37ac81bd2b97204b454f..60ba22770f51c867d50c3bbba32e192292c0b916 100644 (file)
@@ -30,11 +30,17 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
 extern void * memchr(const void *,int,__kernel_size_t);
 void memcpy_flushcache(void *dest, const void *src, size_t size);
 
+#ifdef CONFIG_KASAN
+/* __mem variants are used by KASAN to implement instrumented meminstrinsics. */
+#ifdef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX
+#define __memset memset
+#define __memcpy memcpy
+#define __memmove memmove
+#else /* CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */
 void *__memset(void *s, int c, __kernel_size_t count);
 void *__memcpy(void *to, const void *from, __kernel_size_t n);
 void *__memmove(void *to, const void *from, __kernel_size_t n);
-
-#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
+#ifndef __SANITIZE_ADDRESS__
 /*
  * For files that are not instrumented (e.g. mm/slub.c) we
  * should use not instrumented version of mem* functions.
@@ -46,8 +52,9 @@ void *__memmove(void *to, const void *from, __kernel_size_t n);
 #ifndef __NO_FORTIFY
 #define __NO_FORTIFY /* FORTIFY_SOURCE uses __builtin_memcpy, etc. */
 #endif
-
-#endif
+#endif /* !__SANITIZE_ADDRESS__ */
+#endif /* CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */
+#endif /* CONFIG_KASAN */
 
 #ifdef CONFIG_PPC64
 #ifndef CONFIG_KASAN
index 5a319863f2890f4a6aca7ee9b25948fe659f3eea..69623b9045d55678ef43310c4090a1caf14fe840 100644 (file)
 # If you really need to reference something from prom_init.o add
 # it to the list below:
 
-grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
-if [ $? -eq 0 ]
+has_renamed_memintrinsics()
+{
+       grep -q "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} && \
+               ! grep -q "^CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX=y" ${KCONFIG_CONFIG}
+}
+
+if has_renamed_memintrinsics
 then
        MEM_FUNCS="__memcpy __memset"
 else
index 2087a785f05f1f188c828e1121de5f1fb3faac4d..5fff0d04b23f7a7161de470e504378807a887568 100644 (file)
@@ -290,6 +290,9 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 static int ppr_get(struct task_struct *target, const struct user_regset *regset,
                   struct membuf to)
 {
+       if (!target->thread.regs)
+               return -EINVAL;
+
        return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64));
 }
 
@@ -297,6 +300,9 @@ static int ppr_set(struct task_struct *target, const struct user_regset *regset,
                   unsigned int pos, unsigned int count, const void *kbuf,
                   const void __user *ubuf)
 {
+       if (!target->thread.regs)
+               return -EINVAL;
+
        return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                  &target->thread.regs->ppr, 0, sizeof(u64));
 }
index 66f723f53be2bb01462a17c19a8b13480c35becb..4c3f34485f08f8ba0f933fdb5d42f0c494512252 100644 (file)
@@ -2,7 +2,7 @@
 
 # List of files in the vdso, has to be asm only for now
 
-ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN|R_PPC_REL24
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 obj-vdso32 = sigtramp32-32.o gettimeofday-32.o datapage-32.o cacheflush-32.o note-32.o getcpu-32.o
index a9f57dad6d916436f1eb754d9559ff59855193d6..902611954200df90c43e2b2516ce242006dba09c 100644 (file)
@@ -22,7 +22,6 @@ config KVM
        select PREEMPT_NOTIFIERS
        select HAVE_KVM_EVENTFD
        select HAVE_KVM_VCPU_ASYNC_IOCTL
-       select SRCU
        select KVM_VFIO
        select IRQ_BYPASS_MANAGER
        select HAVE_KVM_IRQ_BYPASS
index 4c5405fc55387028e33e26f83fac20c99a2e5316..d23e25e8432d351dcd33e534f0d1b1765b7317aa 100644 (file)
@@ -576,6 +576,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                break;
 #endif
 
+#ifdef CONFIG_HAVE_KVM_IRQFD
+       case KVM_CAP_IRQFD_RESAMPLE:
+               r = !xive_enabled();
+               break;
+#endif
+
        case KVM_CAP_PPC_ALLOC_HTAB:
                r = hv_enabled;
                break;
index 2bef19cc1b98c659b38109ba47ea2811d0976b66..af46aa88422bf950cd1868dd4715c6adf2f6c5bb 100644 (file)
@@ -271,11 +271,16 @@ static bool access_error(bool is_write, bool is_exec, struct vm_area_struct *vma
        }
 
        /*
-        * Check for a read fault.  This could be caused by a read on an
-        * inaccessible page (i.e. PROT_NONE), or a Radix MMU execute-only page.
+        * VM_READ, VM_WRITE and VM_EXEC all imply read permissions, as
+        * defined in protection_map[].  Read faults can only be caused by
+        * a PROT_NONE mapping, or with a PROT_EXEC-only mapping on Radix.
         */
-       if (unlikely(!(vma->vm_flags & VM_READ)))
+       if (unlikely(!vma_is_accessible(vma)))
                return true;
+
+       if (unlikely(radix_enabled() && ((vma->vm_flags & VM_ACCESS_FLAGS) == VM_EXEC)))
+               return true;
+
        /*
         * We should ideally do the vma pkey access check here. But in the
         * fault path, handle_mm_fault() also does the same check. To avoid
index b44ce71917d75a9668d42e0fe6fe328e653a2790..16cfe56be05bb28723a065daf1dbf2de91d29aac 100644 (file)
@@ -366,6 +366,7 @@ void update_numa_distance(struct device_node *node)
        WARN(numa_distance_table[nid][nid] == -1,
             "NUMA distance details for node %d not provided\n", nid);
 }
+EXPORT_SYMBOL_GPL(update_numa_distance);
 
 /*
  * ibm,numa-lookup-index-table= {N, domainid1, domainid2, ..... domainidN}
index b481c5c8bae11c8e556b932ac505f8597ecb79ac..21b22bf16ce66b8e374f731d2f377104eb0071fc 100644 (file)
@@ -7,6 +7,7 @@ config PPC_PSERIES
        select OF_DYNAMIC
        select FORCE_PCI
        select PCI_MSI
+       select GENERIC_ALLOCATOR
        select PPC_XICS
        select PPC_XIVE_SPAPR
        select PPC_ICP_NATIVE
index 2f8385523a1320047925af07a7219618a48c60d5..1a53e048ceb768f175237361018d6177092b4220 100644 (file)
@@ -1428,6 +1428,13 @@ static int papr_scm_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       /*
+        * open firmware platform device create won't update the NUMA 
+        * distance table. For PAPR SCM devices we use numa_map_to_online_node()
+        * to find the nearest online NUMA node and that requires correct
+        * distance table information.
+        */
+       update_numa_distance(dn);
 
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
index 5591123128107c461e8143cc42b97d33d1c58e1c..513180467562b60e78956813027b90894b05ffe6 100644 (file)
@@ -856,6 +856,13 @@ int pseries_vas_dlpar_cpu(void)
 {
        int new_nr_creds, rc;
 
+       /*
+        * NX-GZIP is not enabled. Nothing to do for DLPAR event
+        */
+       if (!copypaste_feat)
+               return 0;
+
+
        rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES,
                                      vascaps[VAS_GZIP_DEF_FEAT_TYPE].feat,
                                      (u64)virt_to_phys(&hv_cop_caps));
@@ -1012,6 +1019,7 @@ static int __init pseries_vas_init(void)
         * Linux supports user space COPY/PASTE only with Radix
         */
        if (!radix_enabled()) {
+               copypaste_feat = false;
                pr_err("API is supported only with radix page tables\n");
                return -ENOTSUPP;
        }
index c5e42cc376048dbc9d960a6275b40c983acb7618..139055bcfcae567ebdd8b6de15e7aa460b13bda9 100644 (file)
@@ -63,6 +63,8 @@ config RISCV
        select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
        select GENERIC_IDLE_POLL_SETUP
        select GENERIC_IOREMAP if MMU
+       select GENERIC_IRQ_IPI if SMP
+       select GENERIC_IRQ_IPI_MUX if SMP
        select GENERIC_IRQ_MULTI_HANDLER
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_SHOW_LEVEL
@@ -126,6 +128,7 @@ config RISCV
        select OF_IRQ
        select PCI_DOMAINS_GENERIC if PCI
        select PCI_MSI if PCI
+       select RISCV_ALTERNATIVE if !XIP_KERNEL
        select RISCV_INTC
        select RISCV_TIMER if RISCV_SBI
        select SIFIVE_PLIC
@@ -401,9 +404,8 @@ config RISCV_ISA_C
 config RISCV_ISA_SVPBMT
        bool "SVPBMT extension support"
        depends on 64BIT && MMU
-       depends on !XIP_KERNEL
+       depends on RISCV_ALTERNATIVE
        default y
-       select RISCV_ALTERNATIVE
        help
           Adds support to dynamically detect the presence of the SVPBMT
           ISA-extension (Supervisor-mode: page-based memory types) and
@@ -428,8 +430,8 @@ config TOOLCHAIN_HAS_ZBB
 config RISCV_ISA_ZBB
        bool "Zbb extension support for bit manipulation instructions"
        depends on TOOLCHAIN_HAS_ZBB
-       depends on !XIP_KERNEL && MMU
-       select RISCV_ALTERNATIVE
+       depends on MMU
+       depends on RISCV_ALTERNATIVE
        default y
        help
           Adds support to dynamically detect the presence of the ZBB
@@ -443,9 +445,9 @@ config RISCV_ISA_ZBB
 
 config RISCV_ISA_ZICBOM
        bool "Zicbom extension support for non-coherent DMA operation"
-       depends on !XIP_KERNEL && MMU
+       depends on MMU
+       depends on RISCV_ALTERNATIVE
        default y
-       select RISCV_ALTERNATIVE
        select RISCV_DMA_NONCOHERENT
        help
           Adds support to dynamically detect the presence of the ZICBOM
@@ -464,6 +466,28 @@ config TOOLCHAIN_HAS_ZIHINTPAUSE
        depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zihintpause)
        depends on LLD_VERSION >= 150000 || LD_VERSION >= 23600
 
+config TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
+       def_bool y
+       # https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aed44286efa8ae8717a77d94b51ac3614e2ca6dc
+       depends on AS_IS_GNU && AS_VERSION >= 23800
+       help
+         Newer binutils versions default to ISA spec version 20191213 which
+         moves some instructions from the I extension to the Zicsr and Zifencei
+         extensions.
+
+config TOOLCHAIN_NEEDS_OLD_ISA_SPEC
+       def_bool y
+       depends on TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
+       # https://github.com/llvm/llvm-project/commit/22e199e6afb1263c943c0c0d4498694e15bf8a16
+       depends on CC_IS_CLANG && CLANG_VERSION < 170000
+       help
+         Certain versions of clang do not support zicsr and zifencei via -march
+         but newer versions of binutils require it for the reasons noted in the
+         help text of CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI. This
+         option causes an older ISA spec compatible with these older versions
+         of clang to be passed to GAS, which has the same result as passing zicsr
+         and zifencei to -march.
+
 config FPU
        bool "FPU support"
        default y
index 69621ae6d647aa369cee22c5751d3a55ec93e0b6..0c8f4652cd8289b62256f8c93756b84d327f4a88 100644 (file)
@@ -2,8 +2,7 @@ menu "CPU errata selection"
 
 config ERRATA_SIFIVE
        bool "SiFive errata"
-       depends on !XIP_KERNEL
-       select RISCV_ALTERNATIVE
+       depends on RISCV_ALTERNATIVE
        help
          All SiFive errata Kconfig depend on this Kconfig. Disabling
          this Kconfig will disable all SiFive errata. Please say "Y"
@@ -35,8 +34,7 @@ config ERRATA_SIFIVE_CIP_1200
 
 config ERRATA_THEAD
        bool "T-HEAD errata"
-       depends on !XIP_KERNEL
-       select RISCV_ALTERNATIVE
+       depends on RISCV_ALTERNATIVE
        help
          All T-HEAD errata Kconfig depend on this Kconfig. Disabling
          this Kconfig will disable all T-HEAD errata. Please say "Y"
index 4de83b9b1772d14d766d6b3a14102709b9c96caa..b05e833a022d17094e67dff727cb9ae9aa4c6cfb 100644 (file)
@@ -57,10 +57,12 @@ riscv-march-$(CONFIG_ARCH_RV64I)    := rv64ima
 riscv-march-$(CONFIG_FPU)              := $(riscv-march-y)fd
 riscv-march-$(CONFIG_RISCV_ISA_C)      := $(riscv-march-y)c
 
-# Newer binutils versions default to ISA spec version 20191213 which moves some
-# instructions from the I extension to the Zicsr and Zifencei extensions.
-toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
-riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
+ifdef CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC
+KBUILD_CFLAGS += -Wa,-misa-spec=2.2
+KBUILD_AFLAGS += -Wa,-misa-spec=2.2
+else
+riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei
+endif
 
 # Check if the toolchain supports Zihintpause extension
 riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE) := $(riscv-march-y)_zihintpause
index 07e2e2649604640156aa61b6c7594b3c23e7a902..f87c5164d9cf658d6dbc58af85764ed2c6cd4cf3 100644 (file)
                                         <&sysclk K210_CLK_APB0>;
                                clock-names = "ssi_clk", "pclk";
                                resets = <&sysrst K210_RST_SPI2>;
-                               spi-max-frequency = <25000000>;
                        };
 
                        i2s0: i2s@50250000 {
index 5c3e7b97fcc6f6356b5a11bb7476609d90dd713a..0a55099bb7349d0adbc9acbabe95441b4c2991e0 100644 (file)
  */
 enum fixed_addresses {
        FIX_HOLE,
+       /*
+        * The fdt fixmap mapping must be PMD aligned and will be mapped
+        * using PMD entries in fixmap_pmd in 64-bit and a PGD entry in 32-bit.
+        */
+       FIX_FDT_END,
+       FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,
+
+       /* Below fixmaps will be mapped using fixmap_pte */
        FIX_PTE,
        FIX_PMD,
        FIX_PUD,
index e3021b2590de0a04e5ebd9ed936b464e09ce9b47..6263a0de1c6a19e68f3ec4008ecf2a1d90e2e786 100644 (file)
@@ -57,18 +57,31 @@ struct riscv_isa_ext_data {
        unsigned int isa_ext_id;
 };
 
+unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
+
+#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
+
+bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
+#define riscv_isa_extension_available(isa_bitmap, ext) \
+       __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
+
 static __always_inline bool
 riscv_has_extension_likely(const unsigned long ext)
 {
        compiletime_assert(ext < RISCV_ISA_EXT_MAX,
                           "ext must be < RISCV_ISA_EXT_MAX");
 
-       asm_volatile_goto(
-       ALTERNATIVE("j  %l[l_no]", "nop", 0, %[ext], 1)
-       :
-       : [ext] "i" (ext)
-       :
-       : l_no);
+       if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
+               asm_volatile_goto(
+               ALTERNATIVE("j  %l[l_no]", "nop", 0, %[ext], 1)
+               :
+               : [ext] "i" (ext)
+               :
+               : l_no);
+       } else {
+               if (!__riscv_isa_extension_available(NULL, ext))
+                       goto l_no;
+       }
 
        return true;
 l_no:
@@ -81,26 +94,23 @@ riscv_has_extension_unlikely(const unsigned long ext)
        compiletime_assert(ext < RISCV_ISA_EXT_MAX,
                           "ext must be < RISCV_ISA_EXT_MAX");
 
-       asm_volatile_goto(
-       ALTERNATIVE("nop", "j   %l[l_yes]", 0, %[ext], 1)
-       :
-       : [ext] "i" (ext)
-       :
-       : l_yes);
+       if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
+               asm_volatile_goto(
+               ALTERNATIVE("nop", "j   %l[l_yes]", 0, %[ext], 1)
+               :
+               : [ext] "i" (ext)
+               :
+               : l_yes);
+       } else {
+               if (__riscv_isa_extension_available(NULL, ext))
+                       goto l_yes;
+       }
 
        return false;
 l_yes:
        return true;
 }
 
-unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
-
-#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
-
-bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
-#define riscv_isa_extension_available(isa_bitmap, ext) \
-       __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
-
 #endif
 
 #endif /* _ASM_RISCV_HWCAP_H */
index e4c435509983e544f73150ef4f6e7bd5a7267c85..43b9ebfbd94364f229f139ef0a0ed5c63c89dfc4 100644 (file)
 
 #include <asm-generic/irq.h>
 
+void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
+
+struct fwnode_handle *riscv_get_intc_hwnode(void);
+
 extern void __init init_IRQ(void);
 
 #endif /* _ASM_RISCV_IRQ_H */
index 5ff1f19fd45c29b4fc7d2c8b44ac4984caf1e75c..0099dc1161683ddd1e3c45460309e331b7e6b0a7 100644 (file)
@@ -19,8 +19,6 @@ typedef struct {
 #ifdef CONFIG_SMP
        /* A local icache flush is needed before user execution can resume. */
        cpumask_t icache_stale_mask;
-       /* A local tlb flush is needed before user execution can resume. */
-       cpumask_t tlb_stale_mask;
 #endif
 } mm_context_t;
 
index ab05f892d317a82d808d3d8e058f441a44bc45a2..f641837ccf31d62d104d6798a63b3b1e3e8d4383 100644 (file)
 
 #define FIXADDR_TOP      PCI_IO_START
 #ifdef CONFIG_64BIT
-#define FIXADDR_SIZE     PMD_SIZE
+#define MAX_FDT_SIZE    PMD_SIZE
+#define FIX_FDT_SIZE    (MAX_FDT_SIZE + SZ_2M)
+#define FIXADDR_SIZE     (PMD_SIZE + FIX_FDT_SIZE)
 #else
-#define FIXADDR_SIZE     PGDIR_SIZE
+#define MAX_FDT_SIZE    PGDIR_SIZE
+#define FIX_FDT_SIZE    MAX_FDT_SIZE
+#define FIXADDR_SIZE     (PGDIR_SIZE + FIX_FDT_SIZE)
 #endif
 #define FIXADDR_START    (FIXADDR_TOP - FIXADDR_SIZE)
 
index 945b7be249c10066d6fd6d8c8173e0d1b62642f1..acab4410ef2a923be4871265e1f3ebfeb5b3c372 100644 (file)
@@ -271,8 +271,7 @@ long sbi_get_marchid(void);
 long sbi_get_mimpid(void);
 void sbi_set_timer(uint64_t stime_value);
 void sbi_shutdown(void);
-void sbi_clear_ipi(void);
-int sbi_send_ipi(const struct cpumask *cpu_mask);
+void sbi_send_ipi(unsigned int cpu);
 int sbi_remote_fence_i(const struct cpumask *cpu_mask);
 int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
                           unsigned long start,
@@ -335,4 +334,10 @@ unsigned long riscv_cached_mvendorid(unsigned int cpu_id);
 unsigned long riscv_cached_marchid(unsigned int cpu_id);
 unsigned long riscv_cached_mimpid(unsigned int cpu_id);
 
+#if IS_ENABLED(CONFIG_SMP) && IS_ENABLED(CONFIG_RISCV_SBI)
+void sbi_ipi_init(void);
+#else
+static inline void sbi_ipi_init(void) { }
+#endif
+
 #endif /* _ASM_RISCV_SBI_H */
index 3831b638ecabcd16d0b3aea2d05af085efad17d2..c4b77017ec5869fd507d7e366b44e22ef376abe8 100644 (file)
 struct seq_file;
 extern unsigned long boot_cpu_hartid;
 
-struct riscv_ipi_ops {
-       void (*ipi_inject)(const struct cpumask *target);
-       void (*ipi_clear)(void);
-};
-
 #ifdef CONFIG_SMP
+
+#include <linux/jump_label.h>
+
 /*
  * Mapping between linux logical cpu index and hartid.
  */
@@ -33,9 +31,6 @@ void show_ipi_stats(struct seq_file *p, int prec);
 /* SMP initialization hook for setup_arch */
 void __init setup_smp(void);
 
-/* Called from C code, this handles an IPI. */
-void handle_IPI(struct pt_regs *regs);
-
 /* Hook for the generic smp_call_function_many() routine. */
 void arch_send_call_function_ipi_mask(struct cpumask *mask);
 
@@ -44,11 +39,22 @@ void arch_send_call_function_single_ipi(int cpu);
 
 int riscv_hartid_to_cpuid(unsigned long hartid);
 
-/* Set custom IPI operations */
-void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops);
+/* Enable IPI for CPU hotplug */
+void riscv_ipi_enable(void);
+
+/* Disable IPI for CPU hotplug */
+void riscv_ipi_disable(void);
 
-/* Clear IPI for current CPU */
-void riscv_clear_ipi(void);
+/* Check if IPI interrupt numbers are available */
+bool riscv_ipi_have_virq_range(void);
+
+/* Set the IPI interrupt numbers for arch (called by irqchip drivers) */
+void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence);
+
+/* Check if we can use IPIs for remote FENCEs */
+DECLARE_STATIC_KEY_FALSE(riscv_ipi_for_rfence);
+#define riscv_use_ipi_for_rfence() \
+       static_branch_unlikely(&riscv_ipi_for_rfence)
 
 /* Check other CPUs stop or not */
 bool smp_crash_stop_failed(void);
@@ -85,14 +91,29 @@ static inline unsigned long cpuid_to_hartid_map(int cpu)
        return boot_cpu_hartid;
 }
 
-static inline void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
+static inline void riscv_ipi_enable(void)
+{
+}
+
+static inline void riscv_ipi_disable(void)
 {
 }
 
-static inline void riscv_clear_ipi(void)
+static inline bool riscv_ipi_have_virq_range(void)
+{
+       return false;
+}
+
+static inline void riscv_ipi_set_virq_range(int virq, int nr,
+                                           bool use_for_rfence)
 {
 }
 
+static inline bool riscv_use_ipi_for_rfence(void)
+{
+       return false;
+}
+
 #endif /* CONFIG_SMP */
 
 #if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP)
index 907b9efd39a87dd3853c1f8f21f4baa2fdd1125c..a09196f8de688ea90123bb74fc21e080cde19f22 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/errata_list.h>
 
 #ifdef CONFIG_MMU
+extern unsigned long asid_mask;
+
 static inline void local_flush_tlb_all(void)
 {
        __asm__ __volatile__ ("sfence.vma" : : : "memory");
@@ -22,24 +24,6 @@ static inline void local_flush_tlb_page(unsigned long addr)
 {
        ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory"));
 }
-
-static inline void local_flush_tlb_all_asid(unsigned long asid)
-{
-       __asm__ __volatile__ ("sfence.vma x0, %0"
-                       :
-                       : "r" (asid)
-                       : "memory");
-}
-
-static inline void local_flush_tlb_page_asid(unsigned long addr,
-               unsigned long asid)
-{
-       __asm__ __volatile__ ("sfence.vma %0, %1"
-                       :
-                       : "r" (addr), "r" (asid)
-                       : "memory");
-}
-
 #else /* CONFIG_MMU */
 #define local_flush_tlb_all()                  do { } while (0)
 #define local_flush_tlb_page(addr)             do { } while (0)
index 4cf303a779ab906c313c9bc91f695bf2911c5687..67f542be1bea3158720f6985499311d4e6e0b793 100644 (file)
@@ -74,6 +74,7 @@ obj-$(CONFIG_PERF_EVENTS)     += perf_callchain.o
 obj-$(CONFIG_HAVE_PERF_REGS)   += perf_regs.o
 obj-$(CONFIG_RISCV_SBI)                += sbi.o
 ifeq ($(CONFIG_RISCV_SBI), y)
+obj-$(CONFIG_SMP)              += sbi-ipi.o
 obj-$(CONFIG_SMP) += cpu_ops_sbi.o
 endif
 obj-$(CONFIG_HOTPLUG_CPU)      += cpu-hotplug.o
index f7a832e3a1d1d44f0568a5f7336eb587092d85a0..39235cf5065221870aa9e7a6bd6b84bcaf3f6cee 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/irq.h>
 #include <asm/cpu_ops.h>
 #include <asm/numa.h>
-#include <asm/sbi.h>
+#include <asm/smp.h>
 
 bool cpu_has_hotplug(unsigned int cpu)
 {
@@ -43,6 +43,7 @@ int __cpu_disable(void)
        remove_cpu_topology(cpu);
        numa_remove_cpu(cpu);
        set_cpu_online(cpu, false);
+       riscv_ipi_disable();
        irq_migrate_all_off_this_cpu();
 
        return ret;
index 7207fa08d78f86a26b0181c97c0c3761f4d49043..eb9a68a539e66292fa655e9a7ce1348e561a2ab8 100644 (file)
@@ -7,8 +7,26 @@
 
 #include <linux/interrupt.h>
 #include <linux/irqchip.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
 #include <linux/seq_file.h>
-#include <asm/smp.h>
+#include <asm/sbi.h>
+
+static struct fwnode_handle *(*__get_intc_node)(void);
+
+void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void))
+{
+       __get_intc_node = fn;
+}
+
+struct fwnode_handle *riscv_get_intc_hwnode(void)
+{
+       if (__get_intc_node)
+               return __get_intc_node();
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(riscv_get_intc_hwnode);
 
 int arch_show_interrupts(struct seq_file *p, int prec)
 {
@@ -21,4 +39,5 @@ void __init init_IRQ(void)
        irqchip_init();
        if (!handle_arch_irq)
                panic("No interrupt controller found.");
+       sbi_ipi_init();
 }
diff --git a/arch/riscv/kernel/sbi-ipi.c b/arch/riscv/kernel/sbi-ipi.c
new file mode 100644 (file)
index 0000000..a455969
--- /dev/null
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Multiplex several IPIs over a single HW IPI.
+ *
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ */
+
+#define pr_fmt(fmt) "riscv: " fmt
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <asm/sbi.h>
+
+static int sbi_ipi_virq;
+
+static void sbi_ipi_handle(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(chip, desc);
+
+       csr_clear(CSR_IP, IE_SIE);
+       ipi_mux_process();
+
+       chained_irq_exit(chip, desc);
+}
+
+static int sbi_ipi_starting_cpu(unsigned int cpu)
+{
+       enable_percpu_irq(sbi_ipi_virq, irq_get_trigger_type(sbi_ipi_virq));
+       return 0;
+}
+
+void __init sbi_ipi_init(void)
+{
+       int virq;
+       struct irq_domain *domain;
+
+       if (riscv_ipi_have_virq_range())
+               return;
+
+       domain = irq_find_matching_fwnode(riscv_get_intc_hwnode(),
+                                         DOMAIN_BUS_ANY);
+       if (!domain) {
+               pr_err("unable to find INTC IRQ domain\n");
+               return;
+       }
+
+       sbi_ipi_virq = irq_create_mapping(domain, RV_IRQ_SOFT);
+       if (!sbi_ipi_virq) {
+               pr_err("unable to create INTC IRQ mapping\n");
+               return;
+       }
+
+       virq = ipi_mux_create(BITS_PER_BYTE, sbi_send_ipi);
+       if (virq <= 0) {
+               pr_err("unable to create muxed IPIs\n");
+               irq_dispose_mapping(sbi_ipi_virq);
+               return;
+       }
+
+       irq_set_chained_handler(sbi_ipi_virq, sbi_ipi_handle);
+
+       /*
+        * Don't disable IPI when CPU goes offline because
+        * the masking/unmasking of virtual IPIs is done
+        * via generic IPI-Mux
+        */
+       cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+                         "irqchip/sbi-ipi:starting",
+                         sbi_ipi_starting_cpu, NULL);
+
+       riscv_ipi_set_virq_range(virq, BITS_PER_BYTE, false);
+       pr_info("providing IPIs using SBI IPI extension\n");
+}
index 5c87db8fdff2d1eabe0eb6e72740bc5ae78fb3b0..92b9b759ab3d56c8f19524b4f15353de9f54e4d0 100644 (file)
@@ -17,7 +17,7 @@ unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
 EXPORT_SYMBOL(sbi_spec_version);
 
 static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
-static int (*__sbi_send_ipi)(const struct cpumask *cpu_mask) __ro_after_init;
+static void (*__sbi_send_ipi)(unsigned int cpu) __ro_after_init;
 static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
                           unsigned long start, unsigned long size,
                           unsigned long arg4, unsigned long arg5) __ro_after_init;
@@ -130,17 +130,6 @@ void sbi_shutdown(void)
 }
 EXPORT_SYMBOL(sbi_shutdown);
 
-/**
- * sbi_clear_ipi() - Clear any pending IPIs for the calling hart.
- *
- * Return: None
- */
-void sbi_clear_ipi(void)
-{
-       sbi_ecall(SBI_EXT_0_1_CLEAR_IPI, 0, 0, 0, 0, 0, 0, 0);
-}
-EXPORT_SYMBOL(sbi_clear_ipi);
-
 /**
  * __sbi_set_timer_v01() - Program the timer for next timer event.
  * @stime_value: The value after which next timer event should fire.
@@ -157,17 +146,12 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
 #endif
 }
 
-static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
+static void __sbi_send_ipi_v01(unsigned int cpu)
 {
-       unsigned long hart_mask;
-
-       if (!cpu_mask || cpumask_empty(cpu_mask))
-               cpu_mask = cpu_online_mask;
-       hart_mask = __sbi_v01_cpumask_to_hartmask(cpu_mask);
-
+       unsigned long hart_mask =
+               __sbi_v01_cpumask_to_hartmask(cpumask_of(cpu));
        sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)(&hart_mask),
                  0, 0, 0, 0, 0);
-       return 0;
 }
 
 static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
@@ -216,12 +200,10 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
                sbi_major_version(), sbi_minor_version());
 }
 
-static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
+static void __sbi_send_ipi_v01(unsigned int cpu)
 {
        pr_warn("IPI extension is not available in SBI v%lu.%lu\n",
                sbi_major_version(), sbi_minor_version());
-
-       return 0;
 }
 
 static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
@@ -248,55 +230,18 @@ static void __sbi_set_timer_v02(uint64_t stime_value)
 #endif
 }
 
-static int __sbi_send_ipi_v02(const struct cpumask *cpu_mask)
+static void __sbi_send_ipi_v02(unsigned int cpu)
 {
-       unsigned long hartid, cpuid, hmask = 0, hbase = 0, htop = 0;
-       struct sbiret ret = {0};
        int result;
+       struct sbiret ret = {0};
 
-       if (!cpu_mask || cpumask_empty(cpu_mask))
-               cpu_mask = cpu_online_mask;
-
-       for_each_cpu(cpuid, cpu_mask) {
-               hartid = cpuid_to_hartid_map(cpuid);
-               if (hmask) {
-                       if (hartid + BITS_PER_LONG <= htop ||
-                           hbase + BITS_PER_LONG <= hartid) {
-                               ret = sbi_ecall(SBI_EXT_IPI,
-                                               SBI_EXT_IPI_SEND_IPI, hmask,
-                                               hbase, 0, 0, 0, 0);
-                               if (ret.error)
-                                       goto ecall_failed;
-                               hmask = 0;
-                       } else if (hartid < hbase) {
-                               /* shift the mask to fit lower hartid */
-                               hmask <<= hbase - hartid;
-                               hbase = hartid;
-                       }
-               }
-               if (!hmask) {
-                       hbase = hartid;
-                       htop = hartid;
-               } else if (hartid > htop) {
-                       htop = hartid;
-               }
-               hmask |= BIT(hartid - hbase);
-       }
-
-       if (hmask) {
-               ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
-                               hmask, hbase, 0, 0, 0, 0);
-               if (ret.error)
-                       goto ecall_failed;
+       ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
+                       1UL, cpuid_to_hartid_map(cpu), 0, 0, 0, 0);
+       if (ret.error) {
+               result = sbi_err_map_linux_errno(ret.error);
+               pr_err("%s: hbase = [%lu] failed (error [%d])\n",
+                       __func__, cpuid_to_hartid_map(cpu), result);
        }
-
-       return 0;
-
-ecall_failed:
-       result = sbi_err_map_linux_errno(ret.error);
-       pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n",
-              __func__, hbase, hmask, result);
-       return result;
 }
 
 static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask,
@@ -410,13 +355,11 @@ void sbi_set_timer(uint64_t stime_value)
 
 /**
  * sbi_send_ipi() - Send an IPI to any hart.
- * @cpu_mask: A cpu mask containing all the target harts.
- *
- * Return: 0 on success, appropriate linux error code otherwise.
+ * @cpu: Logical id of the target CPU.
  */
-int sbi_send_ipi(const struct cpumask *cpu_mask)
+void sbi_send_ipi(unsigned int cpu)
 {
-       return __sbi_send_ipi(cpu_mask);
+       __sbi_send_ipi(cpu);
 }
 EXPORT_SYMBOL(sbi_send_ipi);
 
@@ -641,15 +584,6 @@ long sbi_get_mimpid(void)
 }
 EXPORT_SYMBOL_GPL(sbi_get_mimpid);
 
-static void sbi_send_cpumask_ipi(const struct cpumask *target)
-{
-       sbi_send_ipi(target);
-}
-
-static const struct riscv_ipi_ops sbi_ipi_ops = {
-       .ipi_inject = sbi_send_cpumask_ipi
-};
-
 void __init sbi_init(void)
 {
        int ret;
@@ -696,6 +630,4 @@ void __init sbi_init(void)
                __sbi_send_ipi  = __sbi_send_ipi_v01;
                __sbi_rfence    = __sbi_rfence_v01;
        }
-
-       riscv_set_ipi_ops(&sbi_ipi_ops);
 }
index 376d2827e7365af086c0c2b7d40f9ec2507d999b..a059b73f4ddb263744e47774d0549efe24e5933c 100644 (file)
@@ -278,12 +278,8 @@ void __init setup_arch(char **cmdline_p)
 #if IS_ENABLED(CONFIG_BUILTIN_DTB)
        unflatten_and_copy_device_tree();
 #else
-       if (early_init_dt_verify(__va(XIP_FIXUP(dtb_early_pa))))
-               unflatten_device_tree();
-       else
-               pr_err("No DTB found in kernel mappings\n");
+       unflatten_device_tree();
 #endif
-       early_init_fdt_scan_reserved_mem();
        misc_mem_init();
 
        init_resources();
index bfb2afa4135f89690b90da20d281252a539d8cda..dee66c9290ccee95e20f93517e47d16a133b02bb 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/signal32.h>
 #include <asm/switch_to.h>
 #include <asm/csr.h>
+#include <asm/cacheflush.h>
 
 extern u32 __user_rt_sigreturn[2];
 
@@ -181,6 +182,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 {
        struct rt_sigframe __user *frame;
        long err = 0;
+       unsigned long __maybe_unused addr;
 
        frame = get_sigframe(ksig, regs, sizeof(*frame));
        if (!access_ok(frame, sizeof(*frame)))
@@ -209,7 +211,12 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
                         sizeof(frame->sigreturn_code)))
                return -EFAULT;
-       regs->ra = (unsigned long)&frame->sigreturn_code;
+
+       addr = (unsigned long)&frame->sigreturn_code;
+       /* Make sure the two instructions are pushed to icache. */
+       flush_icache_range(addr, addr + sizeof(frame->sigreturn_code));
+
+       regs->ra = addr;
 #endif /* CONFIG_MMU */
 
        /*
index 8c3b59f1f9b802947a39099cf94fb12702e64229..5f985a197effb9eff1814e7fa9e6c69868053c2b 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/smp.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 #include <linux/irq_work.h>
 
-#include <asm/sbi.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu_ops.h>
@@ -44,11 +45,10 @@ void __init smp_setup_processor_id(void)
        cpuid_to_hartid_map(0) = boot_cpu_hartid;
 }
 
-/* A collection of single bit ipi messages.  */
-static struct {
-       unsigned long stats[IPI_MAX] ____cacheline_aligned;
-       unsigned long bits ____cacheline_aligned;
-} ipi_data[NR_CPUS] __cacheline_aligned;
+static DEFINE_PER_CPU_READ_MOSTLY(int, ipi_dummy_dev);
+static int ipi_virq_base __ro_after_init;
+static int nr_ipi __ro_after_init = IPI_MAX;
+static struct irq_desc *ipi_desc[IPI_MAX] __read_mostly;
 
 int riscv_hartid_to_cpuid(unsigned long hartid)
 {
@@ -100,48 +100,14 @@ static inline void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
 }
 #endif
 
-static const struct riscv_ipi_ops *ipi_ops __ro_after_init;
-
-void riscv_set_ipi_ops(const struct riscv_ipi_ops *ops)
-{
-       ipi_ops = ops;
-}
-EXPORT_SYMBOL_GPL(riscv_set_ipi_ops);
-
-void riscv_clear_ipi(void)
-{
-       if (ipi_ops && ipi_ops->ipi_clear)
-               ipi_ops->ipi_clear();
-
-       csr_clear(CSR_IP, IE_SIE);
-}
-EXPORT_SYMBOL_GPL(riscv_clear_ipi);
-
 static void send_ipi_mask(const struct cpumask *mask, enum ipi_message_type op)
 {
-       int cpu;
-
-       smp_mb__before_atomic();
-       for_each_cpu(cpu, mask)
-               set_bit(op, &ipi_data[cpu].bits);
-       smp_mb__after_atomic();
-
-       if (ipi_ops && ipi_ops->ipi_inject)
-               ipi_ops->ipi_inject(mask);
-       else
-               pr_warn("SMP: IPI inject method not available\n");
+       __ipi_send_mask(ipi_desc[op], mask);
 }
 
 static void send_ipi_single(int cpu, enum ipi_message_type op)
 {
-       smp_mb__before_atomic();
-       set_bit(op, &ipi_data[cpu].bits);
-       smp_mb__after_atomic();
-
-       if (ipi_ops && ipi_ops->ipi_inject)
-               ipi_ops->ipi_inject(cpumask_of(cpu));
-       else
-               pr_warn("SMP: IPI inject method not available\n");
+       __ipi_send_mask(ipi_desc[op], cpumask_of(cpu));
 }
 
 #ifdef CONFIG_IRQ_WORK
@@ -151,59 +117,98 @@ void arch_irq_work_raise(void)
 }
 #endif
 
-void handle_IPI(struct pt_regs *regs)
+static irqreturn_t handle_IPI(int irq, void *data)
 {
-       unsigned int cpu = smp_processor_id();
-       unsigned long *pending_ipis = &ipi_data[cpu].bits;
-       unsigned long *stats = ipi_data[cpu].stats;
+       int ipi = irq - ipi_virq_base;
+
+       switch (ipi) {
+       case IPI_RESCHEDULE:
+               scheduler_ipi();
+               break;
+       case IPI_CALL_FUNC:
+               generic_smp_call_function_interrupt();
+               break;
+       case IPI_CPU_STOP:
+               ipi_stop();
+               break;
+       case IPI_CPU_CRASH_STOP:
+               ipi_cpu_crash_stop(smp_processor_id(), get_irq_regs());
+               break;
+       case IPI_IRQ_WORK:
+               irq_work_run();
+               break;
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+       case IPI_TIMER:
+               tick_receive_broadcast();
+               break;
+#endif
+       default:
+               pr_warn("CPU%d: unhandled IPI%d\n", smp_processor_id(), ipi);
+               break;
+       }
 
-       riscv_clear_ipi();
+       return IRQ_HANDLED;
+}
 
-       while (true) {
-               unsigned long ops;
+void riscv_ipi_enable(void)
+{
+       int i;
 
-               /* Order bit clearing and data access. */
-               mb();
+       if (WARN_ON_ONCE(!ipi_virq_base))
+               return;
 
-               ops = xchg(pending_ipis, 0);
-               if (ops == 0)
-                       return;
+       for (i = 0; i < nr_ipi; i++)
+               enable_percpu_irq(ipi_virq_base + i, 0);
+}
 
-               if (ops & (1 << IPI_RESCHEDULE)) {
-                       stats[IPI_RESCHEDULE]++;
-                       scheduler_ipi();
-               }
+void riscv_ipi_disable(void)
+{
+       int i;
 
-               if (ops & (1 << IPI_CALL_FUNC)) {
-                       stats[IPI_CALL_FUNC]++;
-                       generic_smp_call_function_interrupt();
-               }
+       if (WARN_ON_ONCE(!ipi_virq_base))
+               return;
 
-               if (ops & (1 << IPI_CPU_STOP)) {
-                       stats[IPI_CPU_STOP]++;
-                       ipi_stop();
-               }
+       for (i = 0; i < nr_ipi; i++)
+               disable_percpu_irq(ipi_virq_base + i);
+}
 
-               if (ops & (1 << IPI_CPU_CRASH_STOP)) {
-                       ipi_cpu_crash_stop(cpu, get_irq_regs());
-               }
+bool riscv_ipi_have_virq_range(void)
+{
+       return (ipi_virq_base) ? true : false;
+}
 
-               if (ops & (1 << IPI_IRQ_WORK)) {
-                       stats[IPI_IRQ_WORK]++;
-                       irq_work_run();
-               }
+DEFINE_STATIC_KEY_FALSE(riscv_ipi_for_rfence);
+EXPORT_SYMBOL_GPL(riscv_ipi_for_rfence);
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-               if (ops & (1 << IPI_TIMER)) {
-                       stats[IPI_TIMER]++;
-                       tick_receive_broadcast();
-               }
-#endif
-               BUG_ON((ops >> IPI_MAX) != 0);
+void riscv_ipi_set_virq_range(int virq, int nr, bool use_for_rfence)
+{
+       int i, err;
+
+       if (WARN_ON(ipi_virq_base))
+               return;
+
+       WARN_ON(nr < IPI_MAX);
+       nr_ipi = min(nr, IPI_MAX);
+       ipi_virq_base = virq;
 
-               /* Order data access and bit testing. */
-               mb();
+       /* Request IPIs */
+       for (i = 0; i < nr_ipi; i++) {
+               err = request_percpu_irq(ipi_virq_base + i, handle_IPI,
+                                        "IPI", &ipi_dummy_dev);
+               WARN_ON(err);
+
+               ipi_desc[i] = irq_to_desc(ipi_virq_base + i);
+               irq_set_status_flags(ipi_virq_base + i, IRQ_HIDDEN);
        }
+
+       /* Enabled IPIs for boot CPU immediately */
+       riscv_ipi_enable();
+
+       /* Update RFENCE static key */
+       if (use_for_rfence)
+               static_branch_enable(&riscv_ipi_for_rfence);
+       else
+               static_branch_disable(&riscv_ipi_for_rfence);
 }
 
 static const char * const ipi_names[] = {
@@ -223,7 +228,7 @@ void show_ipi_stats(struct seq_file *p, int prec)
                seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
                           prec >= 4 ? " " : "");
                for_each_online_cpu(cpu)
-                       seq_printf(p, "%10lu ", ipi_data[cpu].stats[i]);
+                       seq_printf(p, "%10u ", irq_desc_kstat_cpu(ipi_desc[i], cpu));
                seq_printf(p, " %s\n", ipi_names[i]);
        }
 }
index ddb2afba6d25558c26748f8f63dd1dc1702b5e89..00b53913d4c607ab504ee1f79fa81c03661dff9e 100644 (file)
@@ -30,7 +30,6 @@
 #include <asm/numa.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
-#include <asm/sbi.h>
 #include <asm/smp.h>
 
 #include "head.h"
@@ -158,12 +157,12 @@ asmlinkage __visible void smp_callin(void)
        struct mm_struct *mm = &init_mm;
        unsigned int curr_cpuid = smp_processor_id();
 
-       riscv_clear_ipi();
-
        /* All kernel threads share the same mm context.  */
        mmgrab(mm);
        current->active_mm = mm;
 
+       riscv_ipi_enable();
+
        store_cpu_topology(curr_cpuid);
        notify_cpu_starting(curr_cpuid);
        numa_add_cpu(curr_cpuid);
index 06e6b27f3bcc938ba336f32e51de459fd6c15ad2..a04b3bc35ca20647342ee0a762f0e7971068e7c5 100644 (file)
@@ -1,9 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 # Copied from arch/tile/kernel/vdso/Makefile
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_RISCV_32|R_RISCV_64|R_RISCV_JUMP_SLOT
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 # Symbols present in the vdso
 vdso-syms  = rt_sigreturn
index d5a658a047a7f738fc91df06709ee0e867ac2347..5682d8c017b3e419d982115777d17c7c1184d717 100644 (file)
@@ -28,7 +28,6 @@ config KVM
        select KVM_XFER_TO_GUEST_WORK
        select HAVE_KVM_VCPU_ASYNC_IOCTL
        select HAVE_KVM_EVENTFD
-       select SRCU
        help
          Support hosting virtualized guest machines.
 
index ad34519c8a13dff001587abd739c018ac4038b6d..3ac2ff6a65dacbeb1e5c030602bef10962ecbb21 100644 (file)
@@ -147,10 +147,8 @@ static void kvm_riscv_vcpu_timer_blocking(struct kvm_vcpu *vcpu)
                return;
 
        delta_ns = kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t);
-       if (delta_ns) {
-               hrtimer_start(&t->hrt, ktime_set(0, delta_ns), HRTIMER_MODE_REL);
-               t->next_set = true;
-       }
+       hrtimer_start(&t->hrt, ktime_set(0, delta_ns), HRTIMER_MODE_REL);
+       t->next_set = true;
 }
 
 static void kvm_riscv_vcpu_timer_unblocking(struct kvm_vcpu *vcpu)
index fcd6145fbeadce85a3de645e384b73c52146432a..20cec5e7cdbfde4a9f7ecd3cf3ff2c5c6fd9629f 100644 (file)
@@ -19,7 +19,7 @@ void flush_icache_all(void)
 {
        local_flush_icache_all();
 
-       if (IS_ENABLED(CONFIG_RISCV_SBI))
+       if (IS_ENABLED(CONFIG_RISCV_SBI) && !riscv_use_ipi_for_rfence())
                sbi_remote_fence_i(NULL);
        else
                on_each_cpu(ipi_remote_fence_i, NULL, 1);
@@ -67,7 +67,8 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
                 * with flush_icache_deferred().
                 */
                smp_mb();
-       } else if (IS_ENABLED(CONFIG_RISCV_SBI)) {
+       } else if (IS_ENABLED(CONFIG_RISCV_SBI) &&
+                  !riscv_use_ipi_for_rfence()) {
                sbi_remote_fence_i(&others);
        } else {
                on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1);
index 80ce9caba8d225979426f01f9a636d11890f9de6..12e22e7330e7bd2f0feee680b143c407473f0a81 100644 (file)
@@ -22,7 +22,7 @@ DEFINE_STATIC_KEY_FALSE(use_asid_allocator);
 
 static unsigned long asid_bits;
 static unsigned long num_asids;
-static unsigned long asid_mask;
+unsigned long asid_mask;
 
 static atomic_long_t current_version;
 
@@ -196,16 +196,6 @@ switch_mm_fast:
 
        if (need_flush_tlb)
                local_flush_tlb_all();
-#ifdef CONFIG_SMP
-       else {
-               cpumask_t *mask = &mm->context.tlb_stale_mask;
-
-               if (cpumask_test_cpu(cpu, mask)) {
-                       cpumask_clear_cpu(cpu, mask);
-                       local_flush_tlb_all_asid(cntx & asid_mask);
-               }
-       }
-#endif
 }
 
 static void set_mm_noasid(struct mm_struct *mm)
@@ -215,12 +205,24 @@ static void set_mm_noasid(struct mm_struct *mm)
        local_flush_tlb_all();
 }
 
-static inline void set_mm(struct mm_struct *mm, unsigned int cpu)
+static inline void set_mm(struct mm_struct *prev,
+                         struct mm_struct *next, unsigned int cpu)
 {
-       if (static_branch_unlikely(&use_asid_allocator))
-               set_mm_asid(mm, cpu);
-       else
-               set_mm_noasid(mm);
+       /*
+        * The mm_cpumask indicates which harts' TLBs contain the virtual
+        * address mapping of the mm. Compared to noasid, using asid
+        * can't guarantee that stale TLB entries are invalidated because
+        * the asid mechanism wouldn't flush TLB for every switch_mm for
+        * performance. So when using asid, keep all CPUs footmarks in
+        * cpumask() until mm reset.
+        */
+       cpumask_set_cpu(cpu, mm_cpumask(next));
+       if (static_branch_unlikely(&use_asid_allocator)) {
+               set_mm_asid(next, cpu);
+       } else {
+               cpumask_clear_cpu(cpu, mm_cpumask(prev));
+               set_mm_noasid(next);
+       }
 }
 
 static int __init asids_init(void)
@@ -274,7 +276,8 @@ static int __init asids_init(void)
 }
 early_initcall(asids_init);
 #else
-static inline void set_mm(struct mm_struct *mm, unsigned int cpu)
+static inline void set_mm(struct mm_struct *prev,
+                         struct mm_struct *next, unsigned int cpu)
 {
        /* Nothing to do here when there is no MMU */
 }
@@ -327,10 +330,7 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
         */
        cpu = smp_processor_id();
 
-       cpumask_clear_cpu(cpu, mm_cpumask(prev));
-       cpumask_set_cpu(cpu, mm_cpumask(next));
-
-       set_mm(next, cpu);
+       set_mm(prev, next, cpu);
 
        flush_icache_deferred(next, cpu);
 }
index 460f785f6e09cd8fb1441f2fff49288f5256181e..d5f3e501dffb3a6dd2596682b26a011389ac2cb1 100644 (file)
@@ -143,6 +143,8 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
                no_context(regs, addr);
                return;
        }
+       if (pud_leaf(*pud_k))
+               goto flush_tlb;
 
        /*
         * Since the vmalloc area is global, it is unnecessary
@@ -153,6 +155,8 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
                no_context(regs, addr);
                return;
        }
+       if (pmd_leaf(*pmd_k))
+               goto flush_tlb;
 
        /*
         * Make sure the actual PTE exists as well to
@@ -172,6 +176,7 @@ static inline void vmalloc_fault(struct pt_regs *regs, int code, unsigned long a
         * ordering constraint, not a cache flush; it is
         * necessary even after writing invalid entries.
         */
+flush_tlb:
        local_flush_tlb_page(addr);
 }
 
index 478d6763a01a1ebde626635a2f7703f4415649a7..0f14f4a8d179a64f9b75541cefe3409d0cb22a12 100644 (file)
@@ -57,7 +57,6 @@ unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
 EXPORT_SYMBOL(empty_zero_page);
 
 extern char _start[];
-#define DTB_EARLY_BASE_VA      PGDIR_SIZE
 void *_dtb_early_va __initdata;
 uintptr_t _dtb_early_pa __initdata;
 
@@ -236,31 +235,22 @@ static void __init setup_bootmem(void)
        set_max_mapnr(max_low_pfn - ARCH_PFN_OFFSET);
 
        reserve_initrd_mem();
+
+       /*
+        * No allocation should be done before reserving the memory as defined
+        * in the device tree, otherwise the allocation could end up in a
+        * reserved region.
+        */
+       early_init_fdt_scan_reserved_mem();
+
        /*
         * If DTB is built in, no need to reserve its memblock.
         * Otherwise, do reserve it but avoid using
         * early_init_fdt_reserve_self() since __pa() does
         * not work for DTB pointers that are fixmap addresses
         */
-       if (!IS_ENABLED(CONFIG_BUILTIN_DTB)) {
-               /*
-                * In case the DTB is not located in a memory region we won't
-                * be able to locate it later on via the linear mapping and
-                * get a segfault when accessing it via __va(dtb_early_pa).
-                * To avoid this situation copy DTB to a memory region.
-                * Note that memblock_phys_alloc will also reserve DTB region.
-                */
-               if (!memblock_is_memory(dtb_early_pa)) {
-                       size_t fdt_size = fdt_totalsize(dtb_early_va);
-                       phys_addr_t new_dtb_early_pa = memblock_phys_alloc(fdt_size, PAGE_SIZE);
-                       void *new_dtb_early_va = early_memremap(new_dtb_early_pa, fdt_size);
-
-                       memcpy(new_dtb_early_va, dtb_early_va, fdt_size);
-                       early_memunmap(new_dtb_early_va, fdt_size);
-                       _dtb_early_pa = new_dtb_early_pa;
-               } else
-                       memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
-       }
+       if (!IS_ENABLED(CONFIG_BUILTIN_DTB))
+               memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
 
        dma_contiguous_reserve(dma32_phys_limit);
        if (IS_ENABLED(CONFIG_64BIT))
@@ -279,9 +269,6 @@ pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
 
 pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
-static p4d_t __maybe_unused early_dtb_p4d[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
-static pud_t __maybe_unused early_dtb_pud[PTRS_PER_PUD] __initdata __aligned(PAGE_SIZE);
-static pmd_t __maybe_unused early_dtb_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
 
 #ifdef CONFIG_XIP_KERNEL
 #define pt_ops                 (*(struct pt_alloc_ops *)XIP_FIXUP(&pt_ops))
@@ -626,9 +613,6 @@ static void __init create_p4d_mapping(p4d_t *p4dp,
 #define trampoline_pgd_next    (pgtable_l5_enabled ?                   \
                (uintptr_t)trampoline_p4d : (pgtable_l4_enabled ?       \
                (uintptr_t)trampoline_pud : (uintptr_t)trampoline_pmd))
-#define early_dtb_pgd_next     (pgtable_l5_enabled ?                   \
-               (uintptr_t)early_dtb_p4d : (pgtable_l4_enabled ?        \
-               (uintptr_t)early_dtb_pud : (uintptr_t)early_dtb_pmd))
 #else
 #define pgd_next_t             pte_t
 #define alloc_pgd_next(__va)   pt_ops.alloc_pte(__va)
@@ -636,7 +620,6 @@ static void __init create_p4d_mapping(p4d_t *p4dp,
 #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot)     \
        create_pte_mapping(__nextp, __va, __pa, __sz, __prot)
 #define fixmap_pgd_next                ((uintptr_t)fixmap_pte)
-#define early_dtb_pgd_next     ((uintptr_t)early_dtb_pmd)
 #define create_p4d_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
 #define create_pud_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
 #define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
@@ -860,32 +843,28 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
  * this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR
  * entry.
  */
-static void __init create_fdt_early_page_table(pgd_t *pgdir, uintptr_t dtb_pa)
+static void __init create_fdt_early_page_table(pgd_t *pgdir,
+                                              uintptr_t fix_fdt_va,
+                                              uintptr_t dtb_pa)
 {
-#ifndef CONFIG_BUILTIN_DTB
        uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1);
 
-       create_pgd_mapping(early_pg_dir, DTB_EARLY_BASE_VA,
-                          IS_ENABLED(CONFIG_64BIT) ? early_dtb_pgd_next : pa,
-                          PGDIR_SIZE,
-                          IS_ENABLED(CONFIG_64BIT) ? PAGE_TABLE : PAGE_KERNEL);
-
-       if (pgtable_l5_enabled)
-               create_p4d_mapping(early_dtb_p4d, DTB_EARLY_BASE_VA,
-                                  (uintptr_t)early_dtb_pud, P4D_SIZE, PAGE_TABLE);
-
-       if (pgtable_l4_enabled)
-               create_pud_mapping(early_dtb_pud, DTB_EARLY_BASE_VA,
-                                  (uintptr_t)early_dtb_pmd, PUD_SIZE, PAGE_TABLE);
+#ifndef CONFIG_BUILTIN_DTB
+       /* Make sure the fdt fixmap address is always aligned on PMD size */
+       BUILD_BUG_ON(FIX_FDT % (PMD_SIZE / PAGE_SIZE));
 
-       if (IS_ENABLED(CONFIG_64BIT)) {
-               create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA,
+       /* In 32-bit only, the fdt lies in its own PGD */
+       if (!IS_ENABLED(CONFIG_64BIT)) {
+               create_pgd_mapping(early_pg_dir, fix_fdt_va,
+                                  pa, MAX_FDT_SIZE, PAGE_KERNEL);
+       } else {
+               create_pmd_mapping(fixmap_pmd, fix_fdt_va,
                                   pa, PMD_SIZE, PAGE_KERNEL);
-               create_pmd_mapping(early_dtb_pmd, DTB_EARLY_BASE_VA + PMD_SIZE,
+               create_pmd_mapping(fixmap_pmd, fix_fdt_va + PMD_SIZE,
                                   pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
        }
 
-       dtb_early_va = (void *)DTB_EARLY_BASE_VA + (dtb_pa & (PMD_SIZE - 1));
+       dtb_early_va = (void *)fix_fdt_va + (dtb_pa & (PMD_SIZE - 1));
 #else
        /*
         * For 64-bit kernel, __va can't be used since it would return a linear
@@ -1055,7 +1034,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
        create_kernel_page_table(early_pg_dir, true);
 
        /* Setup early mapping for FDT early scan */
-       create_fdt_early_page_table(early_pg_dir, dtb_pa);
+       create_fdt_early_page_table(early_pg_dir,
+                                   __fix_to_virt(FIX_FDT), dtb_pa);
 
        /*
         * Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap
@@ -1097,6 +1077,16 @@ static void __init setup_vm_final(void)
        u64 i;
 
        /* Setup swapper PGD for fixmap */
+#if !defined(CONFIG_64BIT)
+       /*
+        * In 32-bit, the device tree lies in a pgd entry, so it must be copied
+        * directly in swapper_pg_dir in addition to the pgd entry that points
+        * to fixmap_pte.
+        */
+       unsigned long idx = pgd_index(__fix_to_virt(FIX_FDT));
+
+       set_pgd(&swapper_pg_dir[idx], early_pg_dir[idx]);
+#endif
        create_pgd_mapping(swapper_pg_dir, FIXADDR_START,
                           __pa_symbol(fixmap_pgd_next),
                           PGDIR_SIZE, PAGE_TABLE);
index ce7dfc81bb3fe386748557f44310aa4b1a86f3a9..77be59aadc735ea9979473fd2d4dd8ffa04394e2 100644 (file)
@@ -5,17 +5,80 @@
 #include <linux/sched.h>
 #include <asm/sbi.h>
 #include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
+
+static inline void local_flush_tlb_all_asid(unsigned long asid)
+{
+       __asm__ __volatile__ ("sfence.vma x0, %0"
+                       :
+                       : "r" (asid)
+                       : "memory");
+}
+
+static inline void local_flush_tlb_page_asid(unsigned long addr,
+               unsigned long asid)
+{
+       __asm__ __volatile__ ("sfence.vma %0, %1"
+                       :
+                       : "r" (addr), "r" (asid)
+                       : "memory");
+}
+
+static inline void local_flush_tlb_range(unsigned long start,
+               unsigned long size, unsigned long stride)
+{
+       if (size <= stride)
+               local_flush_tlb_page(start);
+       else
+               local_flush_tlb_all();
+}
+
+static inline void local_flush_tlb_range_asid(unsigned long start,
+               unsigned long size, unsigned long stride, unsigned long asid)
+{
+       if (size <= stride)
+               local_flush_tlb_page_asid(start, asid);
+       else
+               local_flush_tlb_all_asid(asid);
+}
+
+static void __ipi_flush_tlb_all(void *info)
+{
+       local_flush_tlb_all();
+}
 
 void flush_tlb_all(void)
 {
-       sbi_remote_sfence_vma(NULL, 0, -1);
+       if (riscv_use_ipi_for_rfence())
+               on_each_cpu(__ipi_flush_tlb_all, NULL, 1);
+       else
+               sbi_remote_sfence_vma(NULL, 0, -1);
+}
+
+struct flush_tlb_range_data {
+       unsigned long asid;
+       unsigned long start;
+       unsigned long size;
+       unsigned long stride;
+};
+
+static void __ipi_flush_tlb_range_asid(void *info)
+{
+       struct flush_tlb_range_data *d = info;
+
+       local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
+}
+
+static void __ipi_flush_tlb_range(void *info)
+{
+       struct flush_tlb_range_data *d = info;
+
+       local_flush_tlb_range(d->start, d->size, d->stride);
 }
 
-static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
-                                 unsigned long size, unsigned long stride)
+static void __flush_tlb_range(struct mm_struct *mm, unsigned long start,
+                             unsigned long size, unsigned long stride)
 {
-       struct cpumask *pmask = &mm->context.tlb_stale_mask;
+       struct flush_tlb_range_data ftd;
        struct cpumask *cmask = mm_cpumask(mm);
        unsigned int cpuid;
        bool broadcast;
@@ -27,31 +90,37 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
        /* check if the tlbflush needs to be sent to other CPUs */
        broadcast = cpumask_any_but(cmask, cpuid) < nr_cpu_ids;
        if (static_branch_unlikely(&use_asid_allocator)) {
-               unsigned long asid = atomic_long_read(&mm->context.id);
-
-               /*
-                * TLB will be immediately flushed on harts concurrently
-                * executing this MM context. TLB flush on other harts
-                * is deferred until this MM context migrates there.
-                */
-               cpumask_setall(pmask);
-               cpumask_clear_cpu(cpuid, pmask);
-               cpumask_andnot(pmask, pmask, cmask);
+               unsigned long asid = atomic_long_read(&mm->context.id) & asid_mask;
 
                if (broadcast) {
-                       sbi_remote_sfence_vma_asid(cmask, start, size, asid);
-               } else if (size <= stride) {
-                       local_flush_tlb_page_asid(start, asid);
+                       if (riscv_use_ipi_for_rfence()) {
+                               ftd.asid = asid;
+                               ftd.start = start;
+                               ftd.size = size;
+                               ftd.stride = stride;
+                               on_each_cpu_mask(cmask,
+                                                __ipi_flush_tlb_range_asid,
+                                                &ftd, 1);
+                       } else
+                               sbi_remote_sfence_vma_asid(cmask,
+                                                          start, size, asid);
                } else {
-                       local_flush_tlb_all_asid(asid);
+                       local_flush_tlb_range_asid(start, size, stride, asid);
                }
        } else {
                if (broadcast) {
-                       sbi_remote_sfence_vma(cmask, start, size);
-               } else if (size <= stride) {
-                       local_flush_tlb_page(start);
+                       if (riscv_use_ipi_for_rfence()) {
+                               ftd.asid = 0;
+                               ftd.start = start;
+                               ftd.size = size;
+                               ftd.stride = stride;
+                               on_each_cpu_mask(cmask,
+                                                __ipi_flush_tlb_range,
+                                                &ftd, 1);
+                       } else
+                               sbi_remote_sfence_vma(cmask, start, size);
                } else {
-                       local_flush_tlb_all();
+                       local_flush_tlb_range(start, size, stride);
                }
        }
 
@@ -60,23 +129,23 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
-       __sbi_tlb_flush_range(mm, 0, -1, PAGE_SIZE);
+       __flush_tlb_range(mm, 0, -1, PAGE_SIZE);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
 {
-       __sbi_tlb_flush_range(vma->vm_mm, addr, PAGE_SIZE, PAGE_SIZE);
+       __flush_tlb_range(vma->vm_mm, addr, PAGE_SIZE, PAGE_SIZE);
 }
 
 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                     unsigned long end)
 {
-       __sbi_tlb_flush_range(vma->vm_mm, start, end - start, PAGE_SIZE);
+       __flush_tlb_range(vma->vm_mm, start, end - start, PAGE_SIZE);
 }
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 void flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
                        unsigned long end)
 {
-       __sbi_tlb_flush_range(vma->vm_mm, start, end - start, PMD_SIZE);
+       __flush_tlb_range(vma->vm_mm, start, end - start, PMD_SIZE);
 }
 #endif
index d16bf715a586bb5595e5017da7c99870b096d36e..5730797a6b402c39c96cd0360486b3548631b389 100644 (file)
@@ -84,12 +84,7 @@ CFLAGS_string.o                      += $(PURGATORY_CFLAGS)
 CFLAGS_REMOVE_ctype.o          += $(PURGATORY_CFLAGS_REMOVE)
 CFLAGS_ctype.o                 += $(PURGATORY_CFLAGS)
 
-AFLAGS_REMOVE_entry.o          += -Wa,-gdwarf-2
-AFLAGS_REMOVE_memcpy.o         += -Wa,-gdwarf-2
-AFLAGS_REMOVE_memset.o         += -Wa,-gdwarf-2
-AFLAGS_REMOVE_strcmp.o         += -Wa,-gdwarf-2
-AFLAGS_REMOVE_strlen.o         += -Wa,-gdwarf-2
-AFLAGS_REMOVE_strncmp.o                += -Wa,-gdwarf-2
+asflags-remove-y               += $(foreach x, -g -gdwarf-4 -gdwarf-5, $(x) -Wa,$(x))
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
index b3235ab0ace83993dc62cab43e46c9aa326bed46..ed646c583e4fe694e1678d9e54356d370c67d7f8 100644 (file)
@@ -162,7 +162,7 @@ vdso_prepare: prepare0
 
 ifdef CONFIG_EXPOLINE_EXTERN
 modules_prepare: expoline_prepare
-expoline_prepare:
+expoline_prepare: scripts
        $(Q)$(MAKE) $(build)=arch/s390/lib/expoline arch/s390/lib/expoline/expoline.o
 endif
 endif
index 9b14045065b6e1e4bfbfcfa6c714a1d5d1e08a6e..74b5cd264862247fc040cabfe24c6a289d3d08a3 100644 (file)
@@ -57,11 +57,19 @@ repeat:
        if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_data.start && initrd_data.size &&
            intersects(initrd_data.start, initrd_data.size, safe_addr, size))
                safe_addr = initrd_data.start + initrd_data.size;
+       if (intersects(safe_addr, size, (unsigned long)comps, comps->len)) {
+               safe_addr = (unsigned long)comps + comps->len;
+               goto repeat;
+       }
        for_each_rb_entry(comp, comps)
                if (intersects(safe_addr, size, comp->addr, comp->len)) {
                        safe_addr = comp->addr + comp->len;
                        goto repeat;
                }
+       if (intersects(safe_addr, size, (unsigned long)certs, certs->len)) {
+               safe_addr = (unsigned long)certs + certs->len;
+               goto repeat;
+       }
        for_each_rb_entry(cert, certs)
                if (intersects(safe_addr, size, cert->addr, cert->len)) {
                        safe_addr = cert->addr + cert->len;
index 3c68fe49042c2630bf37230b672c5edf26d5338d..4ccf66d29fc24b9cad9425fc0fcb9a01bfe4b3c0 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_NUMA_BALANCING=y
 CONFIG_MEMCG=y
 CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -90,7 +89,6 @@ CONFIG_MINIX_SUBPARTITION=y
 CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_IOSCHED_BFQ=y
-CONFIG_BFQ_GROUP_IOSCHED=y
 CONFIG_BINFMT_MISC=m
 CONFIG_ZSWAP=y
 CONFIG_ZSMALLOC_STAT=y
@@ -298,7 +296,6 @@ CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -340,7 +337,6 @@ CONFIG_BRIDGE_MRP=y
 CONFIG_VLAN_8021Q=m
 CONFIG_VLAN_8021Q_GVRP=y
 CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_HFSC=m
 CONFIG_NET_SCH_PRIO=m
@@ -351,7 +347,6 @@ CONFIG_NET_SCH_SFQ=m
 CONFIG_NET_SCH_TEQL=m
 CONFIG_NET_SCH_TBF=m
 CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
 CONFIG_NET_SCH_NETEM=m
 CONFIG_NET_SCH_DRR=m
 CONFIG_NET_SCH_MQPRIO=m
@@ -363,14 +358,11 @@ CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_SCH_PLUG=m
 CONFIG_NET_SCH_ETS=m
 CONFIG_NET_CLS_BASIC=m
-CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_FW=m
 CONFIG_NET_CLS_U32=m
 CONFIG_CLS_U32_PERF=y
 CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_FLOW=m
 CONFIG_NET_CLS_CGROUP=y
 CONFIG_NET_CLS_BPF=m
@@ -584,7 +576,7 @@ CONFIG_DIAG288_WATCHDOG=m
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-# CONFIG_HID is not set
+# CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_ACCESS=m
@@ -828,6 +820,7 @@ CONFIG_PANIC_ON_OOPS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_WQ_WATCHDOG=y
 CONFIG_TEST_LOCKUP=m
+CONFIG_DEBUG_PREEMPT=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
@@ -843,6 +836,7 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=300
 # CONFIG_RCU_TRACE is not set
 CONFIG_LATENCYTOP=y
 CONFIG_BOOTTIME_TRACING=y
+CONFIG_FPROBE=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_STACK_TRACER=y
 CONFIG_IRQSOFF_TRACER=y
@@ -857,6 +851,7 @@ CONFIG_SAMPLES=y
 CONFIG_SAMPLE_TRACE_PRINTK=m
 CONFIG_SAMPLE_FTRACE_DIRECT=m
 CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m
+CONFIG_SAMPLE_FTRACE_OPS=m
 CONFIG_DEBUG_ENTRY=y
 CONFIG_CIO_INJECT=y
 CONFIG_KUNIT=m
index 9ab91632f74cca3c35eefdcd80d4d94adf74704a..693297a2e89733d888c30e78e9d95f981c6db015 100644 (file)
@@ -21,7 +21,6 @@ CONFIG_NUMA_BALANCING=y
 CONFIG_MEMCG=y
 CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
-CONFIG_RT_GROUP_SCHED=y
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_RDMA=y
 CONFIG_CGROUP_FREEZER=y
@@ -85,7 +84,6 @@ CONFIG_MINIX_SUBPARTITION=y
 CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_IOSCHED_BFQ=y
-CONFIG_BFQ_GROUP_IOSCHED=y
 CONFIG_BINFMT_MISC=m
 CONFIG_ZSWAP=y
 CONFIG_ZSMALLOC_STAT=y
@@ -289,7 +287,6 @@ CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_TTL=m
 CONFIG_IP_NF_RAW=m
@@ -330,7 +327,6 @@ CONFIG_BRIDGE_MRP=y
 CONFIG_VLAN_8021Q=m
 CONFIG_VLAN_8021Q_GVRP=y
 CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
 CONFIG_NET_SCH_HFSC=m
 CONFIG_NET_SCH_PRIO=m
@@ -341,7 +337,6 @@ CONFIG_NET_SCH_SFQ=m
 CONFIG_NET_SCH_TEQL=m
 CONFIG_NET_SCH_TBF=m
 CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
 CONFIG_NET_SCH_NETEM=m
 CONFIG_NET_SCH_DRR=m
 CONFIG_NET_SCH_MQPRIO=m
@@ -353,14 +348,11 @@ CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_SCH_PLUG=m
 CONFIG_NET_SCH_ETS=m
 CONFIG_NET_CLS_BASIC=m
-CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_FW=m
 CONFIG_NET_CLS_U32=m
 CONFIG_CLS_U32_PERF=y
 CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_FLOW=m
 CONFIG_NET_CLS_CGROUP=y
 CONFIG_NET_CLS_BPF=m
@@ -573,7 +565,7 @@ CONFIG_DIAG288_WATCHDOG=m
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
-# CONFIG_HID is not set
+# CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_ACCESS=m
@@ -795,6 +787,7 @@ CONFIG_RCU_REF_SCALE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
 CONFIG_BOOTTIME_TRACING=y
+CONFIG_FPROBE=y
 CONFIG_FUNCTION_PROFILER=y
 CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
@@ -805,6 +798,7 @@ CONFIG_SAMPLES=y
 CONFIG_SAMPLE_TRACE_PRINTK=m
 CONFIG_SAMPLE_FTRACE_DIRECT=m
 CONFIG_SAMPLE_FTRACE_DIRECT_MULTI=m
+CONFIG_SAMPLE_FTRACE_OPS=m
 CONFIG_KUNIT=m
 CONFIG_KUNIT_DEBUGFS=y
 CONFIG_LKDTM=m
index a9c0c81d1de992c8cfdadb7985e293856318681e..33a232bb68af95b460eb098136fbdd23e3045751 100644 (file)
@@ -58,7 +58,7 @@ CONFIG_ZFCP=y
 # CONFIG_VMCP is not set
 # CONFIG_MONWRITER is not set
 # CONFIG_S390_VMUR is not set
-# CONFIG_HID is not set
+# CONFIG_HID_SUPPORT is not set
 # CONFIG_VIRTIO_MENU is not set
 # CONFIG_VHOST_MENU is not set
 # CONFIG_IOMMU_SUPPORT is not set
index cf9659e13f03d9245165561e3cb45ced0aef1c7e..ea244a73efad9d6b83fd7e1fff118e65b0309471 100644 (file)
@@ -474,9 +474,7 @@ long arch_ptrace(struct task_struct *child, long request,
                }
                return 0;
        case PTRACE_GET_LAST_BREAK:
-               put_user(child->thread.last_break,
-                        (unsigned long __user *) data);
-               return 0;
+               return put_user(child->thread.last_break, (unsigned long __user *)data);
        case PTRACE_ENABLE_TE:
                if (!MACHINE_HAS_TE)
                        return -EIO;
@@ -824,9 +822,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                }
                return 0;
        case PTRACE_GET_LAST_BREAK:
-               put_user(child->thread.last_break,
-                        (unsigned int __user *) data);
-               return 0;
+               return put_user(child->thread.last_break, (unsigned int __user *)data);
        }
        return compat_ptrace_request(child, request, addr, data);
 }
index 245bddfe9bc0e6bfd8c1997bdef8f55924128f33..bafd3147eb4efbdc96308a78e9d54cdfe25b82a6 100644 (file)
@@ -2,9 +2,8 @@
 # List of files in the vdso
 
 KCOV_INSTRUMENT := n
-ARCH_REL_TYPE_ABS := R_390_COPY|R_390_GLOB_DAT|R_390_JMP_SLOT|R_390_RELATIVE
-ARCH_REL_TYPE_ABS += R_390_GOT|R_390_PLT
 
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 obj-vdso32 = vdso_user_wrapper-32.o note-32.o
 
index 34f9542636e92e30325a74e4e2c89cd89e1b4fb5..a766d286e15ff6482c29dc2735894088f2aa52c5 100644 (file)
@@ -2,9 +2,8 @@
 # List of files in the vdso
 
 KCOV_INSTRUMENT := n
-ARCH_REL_TYPE_ABS := R_390_COPY|R_390_GLOB_DAT|R_390_JMP_SLOT|R_390_RELATIVE
-ARCH_REL_TYPE_ABS += R_390_GOT|R_390_PLT
 
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 obj-vdso64 = vdso_user_wrapper.o note.o
 obj-cvdso64 = vdso64_generic.o getcpu.o
index 33f4ff909476cd25dee05fc9ea78bfb7fdf6ed4e..45fdf2a9b2e326140033a78bb19f95ccddfac255 100644 (file)
@@ -31,7 +31,6 @@ config KVM
        select HAVE_KVM_IRQ_ROUTING
        select HAVE_KVM_INVALID_WAKEUPS
        select HAVE_KVM_NO_POLL
-       select SRCU
        select KVM_VFIO
        select INTERVAL_TREE
        select MMU_NOTIFIER
index 0ee02dae14b2bdc1294d4685825f25f042715fac..2cda8d9d7c6ef1f4d3762dcd2d6735ccb8e18100 100644 (file)
@@ -271,10 +271,18 @@ static int handle_prog(struct kvm_vcpu *vcpu)
  * handle_external_interrupt - used for external interruption interceptions
  * @vcpu: virtual cpu
  *
- * This interception only occurs if the CPUSTAT_EXT_INT bit was set, or if
- * the new PSW does not have external interrupts disabled. In the first case,
- * we've got to deliver the interrupt manually, and in the second case, we
- * drop to userspace to handle the situation there.
+ * This interception occurs if:
+ * - the CPUSTAT_EXT_INT bit was already set when the external interrupt
+ *   occurred. In this case, the interrupt needs to be injected manually to
+ *   preserve interrupt priority.
+ * - the external new PSW has external interrupts enabled, which will cause an
+ *   interruption loop. We drop to userspace in this case.
+ *
+ * The latter case can be detected by inspecting the external mask bit in the
+ * external new psw.
+ *
+ * Under PV, only the latter case can occur, since interrupt priorities are
+ * handled in the ultravisor.
  */
 static int handle_external_interrupt(struct kvm_vcpu *vcpu)
 {
@@ -285,10 +293,18 @@ static int handle_external_interrupt(struct kvm_vcpu *vcpu)
 
        vcpu->stat.exit_external_interrupt++;
 
-       rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
-       if (rc)
-               return rc;
-       /* We can not handle clock comparator or timer interrupt with bad PSW */
+       if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+               newpsw = vcpu->arch.sie_block->gpsw;
+       } else {
+               rc = read_guest_lc(vcpu, __LC_EXT_NEW_PSW, &newpsw, sizeof(psw_t));
+               if (rc)
+                       return rc;
+       }
+
+       /*
+        * Clock comparator or timer interrupt with external interrupt enabled
+        * will cause interrupt loop. Drop to userspace.
+        */
        if ((eic == EXT_IRQ_CLK_COMP || eic == EXT_IRQ_CPU_TIMER) &&
            (newpsw.mask & PSW_MASK_EXT))
                return -EOPNOTSUPP;
index 39b36562c043f6ba8ad0d29248744fceaaedab63..1eeb9ae57879c8d67c465fffc438e18ed3f05c58 100644 (file)
@@ -573,6 +573,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_S390_VCPU_RESETS:
        case KVM_CAP_SET_GUEST_DEBUG:
        case KVM_CAP_S390_DIAG318:
+       case KVM_CAP_IRQFD_RESAMPLE:
                r = 1;
                break;
        case KVM_CAP_SET_GUEST_DEBUG2:
index 720036fb1924266cb720badf76a72df1ffbead8e..d44214072779e7abbbe0862a3af28b2c01954cbb 100644 (file)
@@ -172,7 +172,7 @@ unsigned long __clear_user(void __user *to, unsigned long size)
                "4: slgr  %0,%0\n"
                "5:\n"
                EX_TABLE(0b,2b) EX_TABLE(6b,2b) EX_TABLE(3b,5b) EX_TABLE(7b,5b)
-               : "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2)
+               : "+&a" (size), "+&a" (to), "+a" (tmp1), "=&a" (tmp2)
                : "a" (empty_zero_page), [spec] "d" (spec.val)
                : "cc", "memory", "0");
        return size;
index d0846ba818eeaee7e574ff925f64c5365b472be0..6b1876e4ad3f52ca39e7022a0166dda03c61351e 100644 (file)
@@ -539,7 +539,7 @@ static void bpf_jit_plt(void *plt, void *ret, void *target)
 {
        memcpy(plt, bpf_plt, BPF_PLT_SIZE);
        *(void **)((char *)plt + (bpf_plt_ret - bpf_plt)) = ret;
-       *(void **)((char *)plt + (bpf_plt_target - bpf_plt)) = target;
+       *(void **)((char *)plt + (bpf_plt_target - bpf_plt)) = target ?: ret;
 }
 
 /*
@@ -2010,7 +2010,9 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
        } __packed insn;
        char expected_plt[BPF_PLT_SIZE];
        char current_plt[BPF_PLT_SIZE];
+       char new_plt[BPF_PLT_SIZE];
        char *plt;
+       char *ret;
        int err;
 
        /* Verify the branch to be patched. */
@@ -2032,12 +2034,15 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
                err = copy_from_kernel_nofault(current_plt, plt, BPF_PLT_SIZE);
                if (err < 0)
                        return err;
-               bpf_jit_plt(expected_plt, (char *)ip + 6, old_addr);
+               ret = (char *)ip + 6;
+               bpf_jit_plt(expected_plt, ret, old_addr);
                if (memcmp(current_plt, expected_plt, BPF_PLT_SIZE))
                        return -EINVAL;
                /* Adjust the call address. */
+               bpf_jit_plt(new_plt, ret, new_addr);
                s390_kernel_write(plt + (bpf_plt_target - bpf_plt),
-                                 &new_addr, sizeof(void *));
+                                 new_plt + (bpf_plt_target - bpf_plt),
+                                 sizeof(void *));
        }
 
        /* Adjust the mask of the branch. */
index ef38b1514c77aedb56b66f004b5c2a4fcfc23e4f..e16afacc8fd1b97c6eca33d456354c481a307704 100644 (file)
@@ -544,8 +544,7 @@ static struct resource *__alloc_res(struct zpci_dev *zdev, unsigned long start,
        return r;
 }
 
-int zpci_setup_bus_resources(struct zpci_dev *zdev,
-                            struct list_head *resources)
+int zpci_setup_bus_resources(struct zpci_dev *zdev)
 {
        unsigned long addr, size, flags;
        struct resource *res;
@@ -581,7 +580,6 @@ int zpci_setup_bus_resources(struct zpci_dev *zdev,
                        return -ENOMEM;
                }
                zdev->bars[i].res = res;
-               pci_add_resource(resources, res);
        }
        zdev->has_resources = 1;
 
@@ -590,17 +588,23 @@ int zpci_setup_bus_resources(struct zpci_dev *zdev,
 
 static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
 {
+       struct resource *res;
        int i;
 
+       pci_lock_rescan_remove();
        for (i = 0; i < PCI_STD_NUM_BARS; i++) {
-               if (!zdev->bars[i].size || !zdev->bars[i].res)
+               res = zdev->bars[i].res;
+               if (!res)
                        continue;
 
+               release_resource(res);
+               pci_bus_remove_resource(zdev->zbus->bus, res);
                zpci_free_iomap(zdev, zdev->bars[i].map_idx);
-               release_resource(zdev->bars[i].res);
-               kfree(zdev->bars[i].res);
+               zdev->bars[i].res = NULL;
+               kfree(res);
        }
        zdev->has_resources = 0;
+       pci_unlock_rescan_remove();
 }
 
 int pcibios_device_add(struct pci_dev *pdev)
index 6a8da1b742ae5aa76d08d6abb34e94735bc1f08e..a99926af2b69a352cdd7480ed1f2888f1728a7f9 100644 (file)
@@ -41,9 +41,7 @@ static int zpci_nb_devices;
  */
 static int zpci_bus_prepare_device(struct zpci_dev *zdev)
 {
-       struct resource_entry *window, *n;
-       struct resource *res;
-       int rc;
+       int rc, i;
 
        if (!zdev_enabled(zdev)) {
                rc = zpci_enable_device(zdev);
@@ -57,10 +55,10 @@ static int zpci_bus_prepare_device(struct zpci_dev *zdev)
        }
 
        if (!zdev->has_resources) {
-               zpci_setup_bus_resources(zdev, &zdev->zbus->resources);
-               resource_list_for_each_entry_safe(window, n, &zdev->zbus->resources) {
-                       res = window->res;
-                       pci_bus_add_resource(zdev->zbus->bus, res, 0);
+               zpci_setup_bus_resources(zdev);
+               for (i = 0; i < PCI_STD_NUM_BARS; i++) {
+                       if (zdev->bars[i].res)
+                               pci_bus_add_resource(zdev->zbus->bus, zdev->bars[i].res, 0);
                }
        }
 
index e96c9860e0644b4d1dd144d5c0fccbdf484a60cb..af9f0ac79a1b1b8a249e7a22703f3dec45dcdad8 100644 (file)
@@ -30,8 +30,7 @@ static inline void zpci_zdev_get(struct zpci_dev *zdev)
 
 int zpci_alloc_domain(int domain);
 void zpci_free_domain(int domain);
-int zpci_setup_bus_resources(struct zpci_dev *zdev,
-                            struct list_head *resources);
+int zpci_setup_bus_resources(struct zpci_dev *zdev);
 
 static inline struct zpci_dev *zdev_from_bus(struct pci_bus *bus,
                                             unsigned int devfn)
index fff419f3d7574c16e5f965559ad98d449d5180f1..336c54369636d7290a46cfc5478f94f4a26806c0 100644 (file)
@@ -85,7 +85,7 @@ config CPU_HAS_SR_RB
          that are lacking this bit must have another method in place for
          accomplishing what is taken care of by the banked registers.
 
-         See <file:Documentation/sh/register-banks.rst> for further
+         See <file:Documentation/arch/sh/register-banks.rst> for further
          information on SR.RB and register banking in the kernel in general.
 
 config CPU_HAS_PTEAEX
index a825bf031f4957396c8201ff375abeafaceceab2..57a14206ad8f52de38ed2d0bbbac1ed7a86160ac 100644 (file)
@@ -283,7 +283,6 @@ config X86
        select RTC_LIB
        select RTC_MC146818_LIB
        select SPARSE_IRQ
-       select SRCU
        select SYSCTL_EXCEPTION_TRACE
        select THREAD_INFO_IN_TASK
        select TRACE_IRQFLAGS_SUPPORT
@@ -434,7 +433,7 @@ config SMP
          Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
          Management" code will be disabled if you say Y here.
 
-         See also <file:Documentation/x86/i386/IO-APIC.rst>,
+         See also <file:Documentation/arch/x86/i386/IO-APIC.rst>,
          <file:Documentation/admin-guide/lockup-watchdogs.rst> and the SMP-HOWTO available at
          <http://www.tldp.org/docs.html#howto>.
 
@@ -1324,7 +1323,7 @@ config MICROCODE
          the Linux kernel.
 
          The preferred method to load microcode from a detached initrd is described
-         in Documentation/x86/microcode.rst. For that you need to enable
+         in Documentation/arch/x86/microcode.rst. For that you need to enable
          CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
          initrd for microcode blobs.
 
@@ -1510,7 +1509,7 @@ config X86_5LEVEL
          A kernel with the option enabled can be booted on machines that
          support 4- or 5-level paging.
 
-         See Documentation/x86/x86_64/5level-paging.rst for more
+         See Documentation/arch/x86/x86_64/5level-paging.rst for more
          information.
 
          Say N if unsure.
@@ -1774,7 +1773,7 @@ config MTRR
          You can safely say Y even if your machine doesn't have MTRRs, you'll
          just add about 9 KB to your kernel.
 
-         See <file:Documentation/x86/mtrr.rst> for more information.
+         See <file:Documentation/arch/x86/mtrr.rst> for more information.
 
 config MTRR_SANITIZER
        def_bool y
@@ -1938,7 +1937,6 @@ config X86_SGX
        depends on X86_64 && CPU_SUP_INTEL && X86_X2APIC
        depends on CRYPTO=y
        depends on CRYPTO_SHA256=y
-       select SRCU
        select MMU_NOTIFIER
        select NUMA_KEEP_MEMINFO if NUMA
        select XARRAY_MULTI
@@ -2551,7 +2549,7 @@ config PAGE_TABLE_ISOLATION
          ensuring that the majority of kernel addresses are not mapped
          into userspace.
 
-         See Documentation/x86/pti.rst for more details.
+         See Documentation/arch/x86/pti.rst for more details.
 
 config RETPOLINE
        bool "Avoid speculative indirect branches in kernel"
index bdfe08f1a9304f8c7c8df77de4665fc07a63c21c..c5d614d28a759954fb6f61965c0ff5f1526ed648 100644 (file)
@@ -97,7 +97,7 @@ config IOMMU_DEBUG
          code. When you use it make sure you have a big enough
          IOMMU/AGP aperture.  Most of the options enabled by this can
          be set more finegrained using the iommu= command line
-         options. See Documentation/x86/x86_64/boot-options.rst for more
+         options. See Documentation/arch/x86/x86_64/boot-options.rst for more
          details.
 
 config IOMMU_LEAK
index b70559b821df80a1737d913c04a434d1b6511f79..2106a2bd152bfaf1edcc7d58ebfcf5548e76d14e 100644 (file)
@@ -3,9 +3,14 @@ core-y += arch/x86/crypto/
 
 #
 # Disable SSE and other FP/SIMD instructions to match normal x86
+# This is required to work around issues in older LLVM versions, but breaks
+# GCC versions < 11. See:
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99652
 #
+ifeq ($(CONFIG_CC_IS_CLANG),y)
 KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx
 KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2
+endif
 
 ifeq ($(CONFIG_X86_32),y)
 START := 0x8048000
index 9338c68e7413d6e6ca4c7d2e8eb7ec214e422343..b04ca8e2b213c6e647ad855140682545442321c7 100644 (file)
@@ -321,7 +321,7 @@ start_sys_seg:      .word   SYSSEG          # obsolete and meaningless, but just
 
 type_of_loader:        .byte   0               # 0 means ancient bootloader, newer
                                        # bootloaders know to change this.
-                                       # See Documentation/x86/boot.rst for
+                                       # See Documentation/arch/x86/boot.rst for
                                        # assigned ids
 
 # flags, unused bits must be zero (RFU) bit within loadflags
index 49b44f881484680376a7393dc0f101e4565a4009..73f83233d25df8481b322456039b49b0f108699f 100644 (file)
@@ -13,7 +13,7 @@
 #include <asm/coco.h>
 #include <asm/processor.h>
 
-static enum cc_vendor vendor __ro_after_init;
+enum cc_vendor cc_vendor __ro_after_init;
 static u64 cc_mask __ro_after_init;
 
 static bool intel_cc_platform_has(enum cc_attr attr)
@@ -29,6 +29,22 @@ static bool intel_cc_platform_has(enum cc_attr attr)
        }
 }
 
+/*
+ * Handle the SEV-SNP vTOM case where sme_me_mask is zero, and
+ * the other levels of SME/SEV functionality, including C-bit
+ * based SEV-SNP, are not enabled.
+ */
+static __maybe_unused bool amd_cc_platform_vtom(enum cc_attr attr)
+{
+       switch (attr) {
+       case CC_ATTR_GUEST_MEM_ENCRYPT:
+       case CC_ATTR_MEM_ENCRYPT:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /*
  * SME and SEV are very similar but they are not the same, so there are
  * times that the kernel will need to distinguish between SME and SEV. The
@@ -41,9 +57,14 @@ static bool intel_cc_platform_has(enum cc_attr attr)
  * up under SME the trampoline area cannot be encrypted, whereas under SEV
  * the trampoline area must be encrypted.
  */
+
 static bool amd_cc_platform_has(enum cc_attr attr)
 {
 #ifdef CONFIG_AMD_MEM_ENCRYPT
+
+       if (sev_status & MSR_AMD64_SNP_VTOM)
+               return amd_cc_platform_vtom(attr);
+
        switch (attr) {
        case CC_ATTR_MEM_ENCRYPT:
                return sme_me_mask;
@@ -76,20 +97,13 @@ static bool amd_cc_platform_has(enum cc_attr attr)
 #endif
 }
 
-static bool hyperv_cc_platform_has(enum cc_attr attr)
-{
-       return attr == CC_ATTR_GUEST_MEM_ENCRYPT;
-}
-
 bool cc_platform_has(enum cc_attr attr)
 {
-       switch (vendor) {
+       switch (cc_vendor) {
        case CC_VENDOR_AMD:
                return amd_cc_platform_has(attr);
        case CC_VENDOR_INTEL:
                return intel_cc_platform_has(attr);
-       case CC_VENDOR_HYPERV:
-               return hyperv_cc_platform_has(attr);
        default:
                return false;
        }
@@ -103,11 +117,14 @@ u64 cc_mkenc(u64 val)
         * encryption status of the page.
         *
         * - for AMD, bit *set* means the page is encrypted
-        * - for Intel *clear* means encrypted.
+        * - for AMD with vTOM and for Intel, *clear* means encrypted
         */
-       switch (vendor) {
+       switch (cc_vendor) {
        case CC_VENDOR_AMD:
-               return val | cc_mask;
+               if (sev_status & MSR_AMD64_SNP_VTOM)
+                       return val & ~cc_mask;
+               else
+                       return val | cc_mask;
        case CC_VENDOR_INTEL:
                return val & ~cc_mask;
        default:
@@ -118,9 +135,12 @@ u64 cc_mkenc(u64 val)
 u64 cc_mkdec(u64 val)
 {
        /* See comment in cc_mkenc() */
-       switch (vendor) {
+       switch (cc_vendor) {
        case CC_VENDOR_AMD:
-               return val & ~cc_mask;
+               if (sev_status & MSR_AMD64_SNP_VTOM)
+                       return val | cc_mask;
+               else
+                       return val & ~cc_mask;
        case CC_VENDOR_INTEL:
                return val | cc_mask;
        default:
@@ -129,11 +149,6 @@ u64 cc_mkdec(u64 val)
 }
 EXPORT_SYMBOL_GPL(cc_mkdec);
 
-__init void cc_set_vendor(enum cc_vendor v)
-{
-       vendor = v;
-}
-
 __init void cc_set_mask(u64 mask)
 {
        cc_mask = mask;
index eccc3431e515a674b584f2984679aa8140bcc631..d94d361f506f5d4dc505dfa253684c69f6871779 100644 (file)
@@ -8,7 +8,7 @@
  *
  * entry.S contains the system-call and fault low-level handling routines.
  *
- * Some of this is documented in Documentation/x86/entry_64.rst
+ * Some of this is documented in Documentation/arch/x86/entry_64.rst
  *
  * A note on terminology:
  * - iret frame:       Architecture defined interrupt frame from SS to RIP
index 1506a22a4fb6f8c629bdefa1f57db44a68e5f14b..6a1821bd7d5e9b63209356ee30ec81b45797cb33 100644 (file)
@@ -3,10 +3,7 @@
 # Building vDSO images for x86.
 #
 
-# Absolute relocation type $(ARCH_REL_TYPE_ABS) needs to be defined before
-# the inclusion of generic Makefile.
-ARCH_REL_TYPE_ABS := R_X86_64_JUMP_SLOT|R_X86_64_GLOB_DAT|R_X86_64_RELATIVE|
-ARCH_REL_TYPE_ABS += R_386_GLOB_DAT|R_386_JMP_SLOT|R_386_RELATIVE
+# Include the generic Makefile to check the built vdso.
 include $(srctree)/lib/vdso/Makefile
 
 # Sanitizer runtimes are unavailable and cannot be linked here.
index 8c45b198b62f555d1565c0d68b38304afe767f7c..bccea57dee81ecd12caac3ecc7a2cbe654d9fe90 100644 (file)
@@ -923,6 +923,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
 
                /* Event overflow */
                handled++;
+               status &= ~mask;
                perf_sample_data_init(&data, 0, hwc->last_period);
 
                if (!x86_perf_event_set_period(event))
@@ -933,8 +934,6 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs)
 
                if (perf_event_overflow(event, &data, regs))
                        x86_pmu_stop(event, 0);
-
-               status &= ~mask;
        }
 
        /*
index 41ef036ebb7bae50e4818fe4cbf125c8aa6a1f2a..edbc67ec1f3ecf91a0d484bd490a2cf0055f1da6 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/syscore_ops.h>
 #include <clocksource/hyperv_timer.h>
 #include <linux/highmem.h>
-#include <linux/swiotlb.h>
 
 int hyperv_init_cpuhp;
 u64 hv_current_partition_id = ~0ull;
@@ -504,16 +503,6 @@ void __init hyperv_init(void)
        /* Query the VMs extended capability once, so that it can be cached. */
        hv_query_ext_cap(0);
 
-#ifdef CONFIG_SWIOTLB
-       /*
-        * Swiotlb bounce buffer needs to be mapped in extra address
-        * space. Map function doesn't work in the early place and so
-        * call swiotlb_update_mem_attributes() here.
-        */
-       if (hv_is_isolation_supported())
-               swiotlb_update_mem_attributes();
-#endif
-
        return;
 
 clean_guest_os_id:
index 1dbcbd9da74d445e609e2c0bcc689bf922813740..f6a020cb1a249b2c3ef9241b14ba8d348baf07bf 100644 (file)
@@ -13,6 +13,8 @@
 #include <asm/svm.h>
 #include <asm/sev.h>
 #include <asm/io.h>
+#include <asm/coco.h>
+#include <asm/mem_encrypt.h>
 #include <asm/mshyperv.h>
 #include <asm/hypervisor.h>
 
@@ -233,41 +235,6 @@ void hv_ghcb_msr_read(u64 msr, u64 *value)
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
-#endif
-
-enum hv_isolation_type hv_get_isolation_type(void)
-{
-       if (!(ms_hyperv.priv_high & HV_ISOLATION))
-               return HV_ISOLATION_TYPE_NONE;
-       return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
-}
-EXPORT_SYMBOL_GPL(hv_get_isolation_type);
-
-/*
- * hv_is_isolation_supported - Check system runs in the Hyper-V
- * isolation VM.
- */
-bool hv_is_isolation_supported(void)
-{
-       if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
-               return false;
-
-       if (!hypervisor_is_type(X86_HYPER_MS_HYPERV))
-               return false;
-
-       return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
-}
-
-DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
-
-/*
- * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based
- * isolation VM.
- */
-bool hv_isolation_type_snp(void)
-{
-       return static_branch_unlikely(&isolation_type_snp);
-}
 
 /*
  * hv_mark_gpa_visibility - Set pages visible to host via hvcall.
@@ -320,27 +287,25 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[],
 }
 
 /*
- * hv_set_mem_host_visibility - Set specified memory visible to host.
+ * hv_vtom_set_host_visibility - Set specified memory visible to host.
  *
  * In Isolation VM, all guest memory is encrypted from host and guest
  * needs to set memory visible to host via hvcall before sharing memory
  * with host. This function works as wrap of hv_mark_gpa_visibility()
  * with memory base and size.
  */
-int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visible)
+static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc)
 {
-       enum hv_mem_host_visibility visibility = visible ?
-                       VMBUS_PAGE_VISIBLE_READ_WRITE : VMBUS_PAGE_NOT_VISIBLE;
+       enum hv_mem_host_visibility visibility = enc ?
+                       VMBUS_PAGE_NOT_VISIBLE : VMBUS_PAGE_VISIBLE_READ_WRITE;
        u64 *pfn_array;
        int ret = 0;
+       bool result = true;
        int i, pfn;
 
-       if (!hv_is_isolation_supported() || !hv_hypercall_pg)
-               return 0;
-
        pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL);
        if (!pfn_array)
-               return -ENOMEM;
+               return false;
 
        for (i = 0, pfn = 0; i < pagecount; i++) {
                pfn_array[pfn] = virt_to_hvpfn((void *)kbuffer + i * HV_HYP_PAGE_SIZE);
@@ -349,17 +314,68 @@ int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visibl
                if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) {
                        ret = hv_mark_gpa_visibility(pfn, pfn_array,
                                                     visibility);
-                       if (ret)
+                       if (ret) {
+                               result = false;
                                goto err_free_pfn_array;
+                       }
                        pfn = 0;
                }
        }
 
  err_free_pfn_array:
        kfree(pfn_array);
-       return ret;
+       return result;
+}
+
+static bool hv_vtom_tlb_flush_required(bool private)
+{
+       return true;
 }
 
+static bool hv_vtom_cache_flush_required(void)
+{
+       return false;
+}
+
+static bool hv_is_private_mmio(u64 addr)
+{
+       /*
+        * Hyper-V always provides a single IO-APIC in a guest VM.
+        * When a paravisor is used, it is emulated by the paravisor
+        * in the guest context and must be mapped private.
+        */
+       if (addr >= HV_IOAPIC_BASE_ADDRESS &&
+           addr < (HV_IOAPIC_BASE_ADDRESS + PAGE_SIZE))
+               return true;
+
+       /* Same with a vTPM */
+       if (addr >= VTPM_BASE_ADDRESS &&
+           addr < (VTPM_BASE_ADDRESS + PAGE_SIZE))
+               return true;
+
+       return false;
+}
+
+void __init hv_vtom_init(void)
+{
+       /*
+        * By design, a VM using vTOM doesn't see the SEV setting,
+        * so SEV initialization is bypassed and sev_status isn't set.
+        * Set it here to indicate a vTOM VM.
+        */
+       sev_status = MSR_AMD64_SNP_VTOM;
+       cc_set_vendor(CC_VENDOR_AMD);
+       cc_set_mask(ms_hyperv.shared_gpa_boundary);
+       physical_mask &= ms_hyperv.shared_gpa_boundary - 1;
+
+       x86_platform.hyper.is_private_mmio = hv_is_private_mmio;
+       x86_platform.guest.enc_cache_flush_required = hv_vtom_cache_flush_required;
+       x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required;
+       x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility;
+}
+
+#endif /* CONFIG_AMD_MEM_ENCRYPT */
+
 /*
  * hv_map_memory - map memory to extra space in the AMD SEV-SNP Isolation VM.
  */
@@ -377,7 +393,7 @@ void *hv_map_memory(void *addr, unsigned long size)
                pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) +
                        (ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT);
 
-       vaddr = vmap_pfn(pfns, size / PAGE_SIZE, PAGE_KERNEL_IO);
+       vaddr = vmap_pfn(pfns, size / PAGE_SIZE, pgprot_decrypted(PAGE_KERNEL));
        kfree(pfns);
 
        return vaddr;
@@ -387,3 +403,37 @@ void hv_unmap_memory(void *addr)
 {
        vunmap(addr);
 }
+
+enum hv_isolation_type hv_get_isolation_type(void)
+{
+       if (!(ms_hyperv.priv_high & HV_ISOLATION))
+               return HV_ISOLATION_TYPE_NONE;
+       return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b);
+}
+EXPORT_SYMBOL_GPL(hv_get_isolation_type);
+
+/*
+ * hv_is_isolation_supported - Check system runs in the Hyper-V
+ * isolation VM.
+ */
+bool hv_is_isolation_supported(void)
+{
+       if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
+               return false;
+
+       if (!hypervisor_is_type(X86_HYPER_MS_HYPERV))
+               return false;
+
+       return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE;
+}
+
+DEFINE_STATIC_KEY_FALSE(isolation_type_snp);
+
+/*
+ * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based
+ * isolation VM.
+ */
+bool hv_isolation_type_snp(void)
+{
+       return static_branch_unlikely(&isolation_type_snp);
+}
index e2975a32d443fa888a76847c3a8a27597a16a7a8..d7da28fada87a35445c2c9740dda83c589a23de0 100644 (file)
@@ -8,7 +8,7 @@
 
 #define ALT_FLAGS_SHIFT                16
 
-#define ALT_FLAG_NOT           BIT(0)
+#define ALT_FLAG_NOT           (1 << 0)
 #define ALT_NOT(feature)       ((ALT_FLAG_NOT << ALT_FLAGS_SHIFT) | (feature))
 
 #ifndef __ASSEMBLY__
index 53e9b0620d969339a6f1aa890256fc7cc93b2968..d90ae472fb76fdec71fc1f1df9acc134d0f17649 100644 (file)
@@ -38,7 +38,7 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         * IMPORTANT NOTE TO BOOTLOADER AUTHORS: do not simply clear
         * this field.  The purpose of this field is to guarantee
         * compliance with the x86 boot spec located in
-        * Documentation/x86/boot.rst .  That spec says that the
+        * Documentation/arch/x86/boot.rst .  That spec says that the
         * *whole* structure should be cleared, after which only the
         * portion defined by struct setup_header (boot_params->hdr)
         * should be copied in.
index 3d98c3a60d34f97fc6403a7248b9c06c03b63f8d..eb08796002f3c59c352172da5a44d4ef386988ea 100644 (file)
@@ -7,17 +7,33 @@
 enum cc_vendor {
        CC_VENDOR_NONE,
        CC_VENDOR_AMD,
-       CC_VENDOR_HYPERV,
        CC_VENDOR_INTEL,
 };
 
-void cc_set_vendor(enum cc_vendor v);
-void cc_set_mask(u64 mask);
-
 #ifdef CONFIG_ARCH_HAS_CC_PLATFORM
+extern enum cc_vendor cc_vendor;
+
+static inline enum cc_vendor cc_get_vendor(void)
+{
+       return cc_vendor;
+}
+
+static inline void cc_set_vendor(enum cc_vendor vendor)
+{
+       cc_vendor = vendor;
+}
+
+void cc_set_mask(u64 mask);
 u64 cc_mkenc(u64 val);
 u64 cc_mkdec(u64 val);
 #else
+static inline enum cc_vendor cc_get_vendor(void)
+{
+       return CC_VENDOR_NONE;
+}
+
+static inline void cc_set_vendor(enum cc_vendor vendor) { }
+
 static inline u64 cc_mkenc(u64 val)
 {
        return val;
index cbaf174d8efd9e73ff8b187cfe338fa6cc1b5b41..b3af2d45bbbb58424e2d34b3887d836470d80d21 100644 (file)
 
 #define INTEL_FAM6_LUNARLAKE_M         0xBD
 
+#define INTEL_FAM6_ARROWLAKE           0xC6
+
 /* "Small Core" Processors (Atom/E-Core) */
 
 #define INTEL_FAM6_ATOM_BONNELL                0x1C /* Diamondville, Pineview */
index 72ca90552b6a400b00ac54564b56fc146bba6abc..b7126701574c1b10f1e24f11f9952bc7b9217bc9 100644 (file)
@@ -56,6 +56,7 @@ void __init sev_es_init_vc_handling(void);
 #else  /* !CONFIG_AMD_MEM_ENCRYPT */
 
 #define sme_me_mask    0ULL
+#define sev_status     0ULL
 
 static inline void __init sme_early_encrypt(resource_size_t paddr,
                                            unsigned long size) { }
index e01aa74a6de7872f17ec2ccc82be895d6df910de..c3ad8a526378f9de192d4beedd3eb11ad8213c27 100644 (file)
 
 extern atomic64_t last_mm_ctx_id;
 
-#ifndef CONFIG_PARAVIRT_XXL
-static inline void paravirt_activate_mm(struct mm_struct *prev,
-                                       struct mm_struct *next)
-{
-}
-#endif /* !CONFIG_PARAVIRT_XXL */
-
 #ifdef CONFIG_PERF_EVENTS
 DECLARE_STATIC_KEY_FALSE(rdpmc_never_available_key);
 DECLARE_STATIC_KEY_FALSE(rdpmc_always_available_key);
@@ -135,7 +128,7 @@ extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
 
 #define activate_mm(prev, next)                        \
 do {                                           \
-       paravirt_activate_mm((prev), (next));   \
+       paravirt_enter_mmap(next);              \
        switch_mm((prev), (next), NULL);        \
 } while (0);
 
@@ -168,7 +161,7 @@ static inline void arch_dup_pkeys(struct mm_struct *oldmm,
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
        arch_dup_pkeys(oldmm, mm);
-       paravirt_arch_dup_mmap(oldmm, mm);
+       paravirt_enter_mmap(mm);
        return ldt_dup_context(oldmm, mm);
 }
 
index 4c4c0ec3b62e81dc2908bb2b115f98bf94bb7c00..e3cef98a014201ce8e23df5586818561c9707724 100644 (file)
 #include <asm/paravirt.h>
 #include <asm/mshyperv.h>
 
+/*
+ * Hyper-V always provides a single IO-APIC at this MMIO address.
+ * Ideally, the value should be looked up in ACPI tables, but it
+ * is needed for mapping the IO-APIC early in boot on Confidential
+ * VMs, before ACPI functions can be used.
+ */
+#define HV_IOAPIC_BASE_ADDRESS 0xfec00000
+
 union hv_ghcb;
 
 DECLARE_STATIC_KEY_FALSE(isolation_type_snp);
@@ -206,18 +214,19 @@ struct irq_domain *hv_create_pci_msi_domain(void);
 int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
                struct hv_interrupt_entry *entry);
 int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
-int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible);
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 void hv_ghcb_msr_write(u64 msr, u64 value);
 void hv_ghcb_msr_read(u64 msr, u64 *value);
 bool hv_ghcb_negotiate_protocol(void);
 void hv_ghcb_terminate(unsigned int set, unsigned int reason);
+void hv_vtom_init(void);
 #else
 static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
 static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
 static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
 static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
+static inline void hv_vtom_init(void) {}
 #endif
 
 extern bool hv_isolation_type_snp(void);
@@ -259,11 +268,6 @@ static inline void hv_set_register(unsigned int reg, u64 value) { }
 static inline u64 hv_get_register(unsigned int reg) { return 0; }
 static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }
 static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
-static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages,
-                                            bool visible)
-{
-       return -1;
-}
 #endif /* CONFIG_HYPERV */
 
 
index e9e2c3ba59239ad4b240a641d07a991957f5ef37..06ef25411d622b9137a5c74e6930d5492ccec6b8 100644 (file)
@@ -49,7 +49,7 @@
 
 #define __START_KERNEL_map     _AC(0xffffffff80000000, UL)
 
-/* See Documentation/x86/x86_64/mm.rst for a description of the memory map. */
+/* See Documentation/arch/x86/x86_64/mm.rst for a description of the memory map. */
 
 #define __PHYSICAL_MASK_SHIFT  52
 
index cf40e813b3d7d71df60c98d1c1056bb2d7672135..b49778664d2be31be98094cbd8db4ce7bcce581b 100644 (file)
@@ -334,16 +334,9 @@ static inline void tss_update_io_bitmap(void)
 }
 #endif
 
-static inline void paravirt_activate_mm(struct mm_struct *prev,
-                                       struct mm_struct *next)
+static inline void paravirt_enter_mmap(struct mm_struct *next)
 {
-       PVOP_VCALL2(mmu.activate_mm, prev, next);
-}
-
-static inline void paravirt_arch_dup_mmap(struct mm_struct *oldmm,
-                                         struct mm_struct *mm)
-{
-       PVOP_VCALL2(mmu.dup_mmap, oldmm, mm);
+       PVOP_VCALL1(mmu.enter_mmap, next);
 }
 
 static inline int paravirt_pgd_alloc(struct mm_struct *mm)
@@ -789,8 +782,7 @@ extern void default_banner(void);
 
 #ifndef __ASSEMBLY__
 #ifndef CONFIG_PARAVIRT_XXL
-static inline void paravirt_arch_dup_mmap(struct mm_struct *oldmm,
-                                         struct mm_struct *mm)
+static inline void paravirt_enter_mmap(struct mm_struct *mm)
 {
 }
 #endif
index 8c1da419260f96040e5e63a64c576126c35eee4b..4acbcddddc29f21fc9f21117b653c842430d943c 100644 (file)
@@ -164,11 +164,8 @@ struct pv_mmu_ops {
        unsigned long (*read_cr3)(void);
        void (*write_cr3)(unsigned long);
 
-       /* Hooks for intercepting the creation/use of an mm_struct. */
-       void (*activate_mm)(struct mm_struct *prev,
-                           struct mm_struct *next);
-       void (*dup_mmap)(struct mm_struct *oldmm,
-                        struct mm_struct *mm);
+       /* Hook for intercepting the creation/use of an mm_struct. */
+       void (*enter_mmap)(struct mm_struct *mm);
 
        /* Hooks for allocating and freeing a pagetable top-level */
        int  (*pgd_alloc)(struct mm_struct *mm);
@@ -562,8 +559,14 @@ void paravirt_flush_lazy_mmu(void);
 
 void _paravirt_nop(void);
 void paravirt_BUG(void);
-u64 _paravirt_ident_64(u64);
 unsigned long paravirt_ret0(void);
+#ifdef CONFIG_PARAVIRT_XXL
+u64 _paravirt_ident_64(u64);
+unsigned long pv_native_save_fl(void);
+void pv_native_irq_disable(void);
+void pv_native_irq_enable(void);
+unsigned long pv_native_read_cr2(void);
+#endif
 
 #define paravirt_nop   ((void *)_paravirt_nop)
 
index 38bf837e3554449f21b2384d2b233483573e1565..38b54b992f32e3027c5fa066f9684900fdd348d5 100644 (file)
@@ -104,7 +104,7 @@ extern unsigned int ptrs_per_p4d;
 #define PGDIR_MASK     (~(PGDIR_SIZE - 1))
 
 /*
- * See Documentation/x86/x86_64/mm.rst for a description of the memory map.
+ * See Documentation/arch/x86/x86_64/mm.rst for a description of the memory map.
  *
  * Be very careful vs. KASLR when changing anything here. The KASLR address
  * range must not overlap with anything except the KASAN shadow area, which
index 8d73004e4cac7c93fe362af81de5dcb6fe2c12b8..a1e4fa58b357464a631f4028879ce28baf9a177b 100644 (file)
@@ -647,7 +647,11 @@ static inline void spin_lock_prefetch(const void *x)
 #define KSTK_ESP(task)         (task_pt_regs(task)->sp)
 
 #else
-#define INIT_THREAD { }
+extern unsigned long __end_init_task[];
+
+#define INIT_THREAD {                                                      \
+       .sp     = (unsigned long)&__end_init_task - sizeof(struct pt_regs), \
+}
 
 extern unsigned long KSTK_ESP(struct task_struct *task);
 
index a336feef0af14318bf3776e417c4fbcd8277b976..f6a1737c77be2dc128147978e7f9f85945aed7a6 100644 (file)
@@ -59,7 +59,6 @@ extern struct real_mode_header *real_mode_header;
 extern unsigned char real_mode_blob_end[];
 
 extern unsigned long initial_code;
-extern unsigned long initial_gs;
 extern unsigned long initial_stack;
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 extern unsigned long initial_vc_handler;
index b8357d6ecd47ef6766a0fe9fe5161f6447228c16..0759af9b1acfcf4544ecc9d20b461ee35a8e8228 100644 (file)
@@ -128,9 +128,6 @@ struct snp_psc_desc {
        struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY];
 } __packed;
 
-/* Guest message request error code */
-#define SNP_GUEST_REQ_INVALID_LEN      BIT_ULL(32)
-
 #define GHCB_MSR_TERM_REQ              0x100
 #define GHCB_MSR_TERM_REASON_SET_POS   12
 #define GHCB_MSR_TERM_REASON_SET_MASK  0xf
index ebc271bb6d8ed1d74e07194604b25244646ffc0a..13dc2a9d23c1eb258ce4e2b78e74859902dd9f4b 100644 (file)
@@ -9,6 +9,8 @@
 #define __ASM_ENCRYPTED_STATE_H
 
 #include <linux/types.h>
+#include <linux/sev-guest.h>
+
 #include <asm/insn.h>
 #include <asm/sev-common.h>
 #include <asm/bootparam.h>
@@ -185,6 +187,9 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
 
        return rc;
 }
+
+struct snp_guest_request_ioctl;
+
 void setup_ghcb(void);
 void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
                                         unsigned int npages);
@@ -196,7 +201,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned int npages);
 void snp_set_wakeup_secondary_cpu(void);
 bool snp_init(struct boot_params *bp);
 void __init __noreturn snp_abort(void);
-int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err);
+int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
 #else
 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
 static inline void sev_es_ist_exit(void) { }
@@ -216,8 +221,7 @@ static inline void snp_set_memory_private(unsigned long vaddr, unsigned int npag
 static inline void snp_set_wakeup_secondary_cpu(void) { }
 static inline bool snp_init(struct boot_params *bp) { return false; }
 static inline void snp_abort(void) { }
-static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input,
-                                         unsigned long *fw_err)
+static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
 {
        return -ENOTTY;
 }
index b4dbb20dab1a11d509b4f702f4bde6a6269b4d18..bf2c51df9e0b39f6f171696e6bda246d911cb5ce 100644 (file)
@@ -199,5 +199,8 @@ extern void nmi_selftest(void);
 #define nmi_selftest() do { } while (0)
 #endif
 
-#endif /* __ASSEMBLY__ */
+extern unsigned int smpboot_control;
+
+#endif /* !__ASSEMBLY__ */
+
 #endif /* _ASM_X86_SMP_H */
index cb1ee53ad3b18900a6945b11bb4e267d5d77cd6e..770dcf75eaa97e0c3c8cc191d88bd9e8a9fc1d34 100644 (file)
@@ -261,20 +261,22 @@ enum avic_ipi_failure_cause {
        AVIC_IPI_FAILURE_INVALID_BACKING_PAGE,
 };
 
-#define AVIC_PHYSICAL_MAX_INDEX_MASK   GENMASK_ULL(9, 0)
+#define AVIC_PHYSICAL_MAX_INDEX_MASK   GENMASK_ULL(8, 0)
 
 /*
- * For AVIC, the max index allowed for physical APIC ID
- * table is 0xff (255).
+ * For AVIC, the max index allowed for physical APIC ID table is 0xfe (254), as
+ * 0xff is a broadcast to all CPUs, i.e. can't be targeted individually.
  */
 #define AVIC_MAX_PHYSICAL_ID           0XFEULL
 
 /*
- * For x2AVIC, the max index allowed for physical APIC ID
- * table is 0x1ff (511).
+ * For x2AVIC, the max index allowed for physical APIC ID table is 0x1ff (511).
  */
 #define X2AVIC_MAX_PHYSICAL_ID         0x1FFUL
 
+static_assert((AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == AVIC_MAX_PHYSICAL_ID);
+static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_MAX_PHYSICAL_ID);
+
 #define AVIC_HPA_MASK  ~((0xFFFULL << 52) | 0xFFF)
 #define VMCB_AVIC_APIC_BAR_MASK                0xFFFFFFFFFF000ULL
 
index d13d71af5cf61045147d84ea66703ec44ee3da82..0a49a8de9f3c458ffd41fa5c4cf1a7ae3a1b47b3 100644 (file)
 
 /* Handles exceptions in both to and from, but doesn't do access_ok */
 __must_check unsigned long
-copy_user_enhanced_fast_string(void *to, const void *from, unsigned len);
-__must_check unsigned long
-copy_user_generic_string(void *to, const void *from, unsigned len);
-__must_check unsigned long
-copy_user_generic_unrolled(void *to, const void *from, unsigned len);
+rep_movs_alternative(void *to, const void *from, unsigned len);
 
 static __always_inline __must_check unsigned long
-copy_user_generic(void *to, const void *from, unsigned len)
+copy_user_generic(void *to, const void *from, unsigned long len)
 {
-       unsigned ret;
-
+       stac();
        /*
-        * If CPU has ERMS feature, use copy_user_enhanced_fast_string.
-        * Otherwise, if CPU has rep_good feature, use copy_user_generic_string.
-        * Otherwise, use copy_user_generic_unrolled.
+        * If CPU has FSRM feature, use 'rep movs'.
+        * Otherwise, use rep_movs_alternative.
         */
-       alternative_call_2(copy_user_generic_unrolled,
-                        copy_user_generic_string,
-                        X86_FEATURE_REP_GOOD,
-                        copy_user_enhanced_fast_string,
-                        X86_FEATURE_ERMS,
-                        ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from),
-                                    "=d" (len)),
-                        "1" (to), "2" (from), "3" (len)
-                        : "memory", "rcx", "r8", "r9", "r10", "r11");
-       return ret;
+       asm volatile(
+               "1:\n\t"
+               ALTERNATIVE("rep movsb",
+                           "call rep_movs_alternative", ALT_NOT(X86_FEATURE_FSRM))
+               "2:\n"
+               _ASM_EXTABLE_UA(1b, 2b)
+               :"+c" (len), "+D" (to), "+S" (from), ASM_CALL_CONSTRAINT
+               : : "memory", "rax", "r8", "r9", "r10", "r11");
+       clac();
+       return len;
 }
 
 static __always_inline __must_check unsigned long
@@ -58,9 +52,7 @@ raw_copy_to_user(void __user *dst, const void *src, unsigned long size)
        return copy_user_generic((__force void *)dst, src, size);
 }
 
-extern long __copy_user_nocache(void *dst, const void __user *src,
-                               unsigned size, int zerorest);
-
+extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size);
 extern long __copy_user_flushcache(void *dst, const void __user *src, unsigned size);
 extern void memcpy_page_flushcache(char *to, struct page *page, size_t offset,
                           size_t len);
@@ -69,8 +61,12 @@ static inline int
 __copy_from_user_inatomic_nocache(void *dst, const void __user *src,
                                  unsigned size)
 {
+       long ret;
        kasan_check_write(dst, size);
-       return __copy_user_nocache(dst, src, size, 0);
+       stac();
+       ret = __copy_user_nocache(dst, src, size);
+       clac();
+       return ret;
 }
 
 static inline int
@@ -85,11 +81,7 @@ __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size)
  */
 
 __must_check unsigned long
-clear_user_original(void __user *addr, unsigned long len);
-__must_check unsigned long
-clear_user_rep_good(void __user *addr, unsigned long len);
-__must_check unsigned long
-clear_user_erms(void __user *addr, unsigned long len);
+rep_stos_alternative(void __user *addr, unsigned long len);
 
 static __always_inline __must_check unsigned long __clear_user(void __user *addr, unsigned long size)
 {
@@ -102,16 +94,12 @@ static __always_inline __must_check unsigned long __clear_user(void __user *addr
         */
        asm volatile(
                "1:\n\t"
-               ALTERNATIVE_3("rep stosb",
-                             "call clear_user_erms",     ALT_NOT(X86_FEATURE_FSRM),
-                             "call clear_user_rep_good", ALT_NOT(X86_FEATURE_ERMS),
-                             "call clear_user_original", ALT_NOT(X86_FEATURE_REP_GOOD))
+               ALTERNATIVE("rep stosb",
+                           "call rep_stos_alternative", ALT_NOT(X86_FEATURE_FSRS))
                "2:\n"
               _ASM_EXTABLE_UA(1b, 2b)
               : "+c" (size), "+D" (addr), ASM_CALL_CONSTRAINT
-              : "a" (0)
-               /* rep_good clobbers %rdx */
-              : "rdx");
+              : "a" (0));
 
        clac();
 
index c1c8c581759d69bfe807a81bfa5eb3a799d2ebc8..acc20ae4079d312008cb80c6f50d6b0599721d6d 100644 (file)
@@ -259,11 +259,15 @@ struct x86_legacy_features {
  *                             VMMCALL under SEV-ES.  Needs to return 'false'
  *                             if the checks fail.  Called from the #VC
  *                             exception handler.
+ * @is_private_mmio:           For CoCo VMs, must map MMIO address as private.
+ *                             Used when device is emulated by a paravisor
+ *                             layer in the VM context.
  */
 struct x86_hyper_runtime {
        void (*pin_vcpu)(int cpu);
        void (*sev_es_hcall_prepare)(struct ghcb *ghcb, struct pt_regs *regs);
        bool (*sev_es_hcall_finish)(struct ghcb *ghcb, struct pt_regs *regs);
+       bool (*is_private_mmio)(u64 addr);
 };
 
 /**
index 6daa9b0c8d11474b73ebd63b703fc60ef8972ba3..a3c29b1496c8353eca2f6dd13db042018fa25e51 100644 (file)
  * Sub-leaf 2: EAX: host tsc frequency in kHz
  */
 
+#define XEN_CPUID_TSC_EMULATED               (1u << 0)
+#define XEN_CPUID_HOST_TSC_RELIABLE          (1u << 1)
+#define XEN_CPUID_RDTSCP_INSTR_AVAIL         (1u << 2)
+
+#define XEN_CPUID_TSC_MODE_DEFAULT           (0)
+#define XEN_CPUID_TSC_MODE_ALWAYS_EMULATE    (1u)
+#define XEN_CPUID_TSC_MODE_NEVER_EMULATE     (2u)
+#define XEN_CPUID_TSC_MODE_PVRDTSCP          (3u)
+
 /*
  * Leaf 5 (0x40000x04)
  * HVM-specific features
  * Sub-leaf 0: EAX: Features
  * Sub-leaf 0: EBX: vcpu id (iff EAX has XEN_HVM_CPUID_VCPU_ID_PRESENT flag)
+ * Sub-leaf 0: ECX: domain id (iff EAX has XEN_HVM_CPUID_DOMID_PRESENT flag)
  */
 #define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */
 #define XEN_HVM_CPUID_X2APIC_VIRT      (1u << 1) /* Virtualized x2APIC accesses */
 #define XEN_HVM_CPUID_VCPU_ID_PRESENT  (1u << 3) /* vcpu id is present in EBX */
 #define XEN_HVM_CPUID_DOMID_PRESENT    (1u << 4) /* domid is present in ECX */
 /*
- * Bits 55:49 from the IO-APIC RTE and bits 11:5 from the MSI address can be
- * used to store high bits for the Destination ID. This expands the Destination
- * ID field from 8 to 15 bits, allowing to target APIC IDs up 32768.
+ * With interrupt format set to 0 (non-remappable) bits 55:49 from the
+ * IO-APIC RTE and bits 11:5 from the MSI address can be used to store
+ * high bits for the Destination ID. This expands the Destination ID
+ * field from 8 to 15 bits, allowing to target APIC IDs up 32768.
  */
 #define XEN_HVM_CPUID_EXT_DEST_ID      (1u << 5)
-/* Per-vCPU event channel upcalls */
+/*
+ * Per-vCPU event channel upcalls work correctly with physical IRQs
+ * bound to event channels.
+ */
 #define XEN_HVM_CPUID_UPCALL_VECTOR    (1u << 6)
 
 /*
index 1c38174b5f0197355a96135b03858d6bebe3e84a..21b542a6866cf74b303f099ce42f6341186e5a27 100644 (file)
@@ -146,7 +146,11 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
 
                pr_debug("Local APIC address 0x%08x\n", madt->address);
        }
-       if (madt->header.revision >= 5)
+
+       /* ACPI 6.3 and newer support the online capable bit. */
+       if (acpi_gbl_FADT.header.revision > 6 ||
+           (acpi_gbl_FADT.header.revision == 6 &&
+            acpi_gbl_FADT.minor_revision >= 3))
                acpi_support_online_capable = true;
 
        default_acpi_madt_oem_check(madt->header.oem_id,
@@ -193,7 +197,8 @@ static bool __init acpi_is_processor_usable(u32 lapic_flags)
        if (lapic_flags & ACPI_MADT_ENABLED)
                return true;
 
-       if (acpi_support_online_capable && (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
+       if (!acpi_support_online_capable ||
+           (lapic_flags & ACPI_MADT_ONLINE_CAPABLE))
                return true;
 
        return false;
@@ -1853,13 +1858,18 @@ early_param("acpi_sci", setup_acpi_sci);
 
 int __acpi_acquire_global_lock(unsigned int *lock)
 {
-       unsigned int old, new;
+       unsigned int old, new, val;
 
        old = READ_ONCE(*lock);
        do {
-               new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
+               val = (old >> 1) & 0x1;
+               new = (old & ~0x3) + 2 + val;
        } while (!try_cmpxchg(lock, &old, new));
-       return ((new & 0x3) < 3) ? -1 : 0;
+
+       if (val)
+               return 0;
+
+       return -1;
 }
 
 int __acpi_release_global_lock(unsigned int *lock)
index 3b7f4cdbf2e0a12b9bfcb2e485327d01f20cbf87..1328c221af30e8dba1ef7c89a679de3c64132a08 100644 (file)
@@ -111,13 +111,26 @@ int x86_acpi_suspend_lowlevel(void)
        saved_magic = 0x12345678;
 #else /* CONFIG_64BIT */
 #ifdef CONFIG_SMP
-       initial_stack = (unsigned long)temp_stack + sizeof(temp_stack);
-       early_gdt_descr.address =
-                       (unsigned long)get_cpu_gdt_rw(smp_processor_id());
-       initial_gs = per_cpu_offset(smp_processor_id());
+       /*
+        * As each CPU starts up, it will find its own stack pointer
+        * from its current_task->thread.sp. Typically that will be
+        * the idle thread for a newly-started AP, or even the boot
+        * CPU which will find it set to &init_task in the static
+        * per-cpu data.
+        *
+        * Make the resuming CPU use the temporary stack at startup
+        * by setting current->thread.sp to point to that. The true
+        * %rsp will be restored with the rest of the CPU context,
+        * by do_suspend_lowlevel(). And unwinders don't care about
+        * the abuse of ->thread.sp because it's a dead variable
+        * while the thread is running on the CPU anyway; the true
+        * value is in the actual %rsp register.
+        */
+       current->thread.sp = (unsigned long)temp_stack + sizeof(temp_stack);
+       smpboot_control = smp_processor_id();
 #endif
        initial_code = (unsigned long)wakeup_long64;
-       saved_magic = 0x123456789abcdef0L;
+       saved_magic = 0x123456789abcdef0L;
 #endif /* CONFIG_64BIT */
 
        /*
index 20d9a604da7c4b624f701182f0ead13244d1323f..77055711005187c10c9b973f0df4ca27ac5b772d 100644 (file)
@@ -422,10 +422,9 @@ static unsigned int reserve_eilvt_offset(int offset, unsigned int new)
                if (vector && !eilvt_entry_is_changeable(vector, new))
                        /* may not change if vectors are different */
                        return rsvd;
-               rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
-       } while (rsvd != new);
+       } while (!atomic_try_cmpxchg(&eilvt_offsets[offset], &rsvd, new));
 
-       rsvd &= ~APIC_EILVT_MASKED;
+       rsvd = new & ~APIC_EILVT_MASKED;
        if (rsvd && rsvd != vector)
                pr_info("LVT offset %d assigned for vector 0x%02x\n",
                        offset, rsvd);
index 1f83b052bb74e0894abd128d4c71dcd4e5e80f96..4241dc243aa88d019b28cb3cd114a24e3c93679e 100644 (file)
@@ -66,6 +66,7 @@
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
 #include <asm/pgtable.h>
+#include <asm/x86_init.h>
 
 #define        for_each_ioapic(idx)            \
        for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
@@ -2477,17 +2478,21 @@ static int io_apic_get_redir_entries(int ioapic)
 
 unsigned int arch_dynirq_lower_bound(unsigned int from)
 {
+       unsigned int ret;
+
        /*
         * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
         * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
         */
-       if (!ioapic_initialized)
-               return gsi_top;
+       ret = ioapic_dynirq_base ? : gsi_top;
+
        /*
-        * For DT enabled machines ioapic_dynirq_base is irrelevant and not
-        * updated. So simply return @from if ioapic_dynirq_base == 0.
+        * For DT enabled machines ioapic_dynirq_base is irrelevant and
+        * always 0. gsi_top can be 0 if there is no IO/APIC registered.
+        * 0 is an invalid interrupt number for dynamic allocations. Return
+        * @from instead.
         */
-       return ioapic_dynirq_base ? : from;
+       return ret ? : from;
 }
 
 #ifdef CONFIG_X86_32
@@ -2680,10 +2685,15 @@ static void io_apic_set_fixmap(enum fixed_addresses idx, phys_addr_t phys)
        pgprot_t flags = FIXMAP_PAGE_NOCACHE;
 
        /*
-        * Ensure fixmaps for IOAPIC MMIO respect memory encryption pgprot
+        * Ensure fixmaps for IO-APIC MMIO respect memory encryption pgprot
         * bits, just like normal ioremap():
         */
-       flags = pgprot_decrypted(flags);
+       if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+               if (x86_platform.hyper.is_private_mmio(phys))
+                       flags = pgprot_encrypted(flags);
+               else
+                       flags = pgprot_decrypted(flags);
+       }
 
        __set_fixmap(idx, phys, flags);
 }
index e696e22d0531976f7cba72ed17443592eac72c13..b2b2b7f3e03f69c716ff3555325390566b559692 100644 (file)
@@ -9,11 +9,7 @@
 
 #include "local.h"
 
-struct cluster_mask {
-       unsigned int    clusterid;
-       int             node;
-       struct cpumask  mask;
-};
+#define apic_cluster(apicid) ((apicid) >> 4)
 
 /*
  * __x2apic_send_IPI_mask() possibly needs to read
@@ -23,8 +19,7 @@ struct cluster_mask {
 static u32 *x86_cpu_to_logical_apicid __read_mostly;
 
 static DEFINE_PER_CPU(cpumask_var_t, ipi_mask);
-static DEFINE_PER_CPU_READ_MOSTLY(struct cluster_mask *, cluster_masks);
-static struct cluster_mask *cluster_hotplug_mask;
+static DEFINE_PER_CPU_READ_MOSTLY(struct cpumask *, cluster_masks);
 
 static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
@@ -60,10 +55,10 @@ __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
 
        /* Collapse cpus in a cluster so a single IPI per cluster is sent */
        for_each_cpu(cpu, tmpmsk) {
-               struct cluster_mask *cmsk = per_cpu(cluster_masks, cpu);
+               struct cpumask *cmsk = per_cpu(cluster_masks, cpu);
 
                dest = 0;
-               for_each_cpu_and(clustercpu, tmpmsk, &cmsk->mask)
+               for_each_cpu_and(clustercpu, tmpmsk, cmsk)
                        dest |= x86_cpu_to_logical_apicid[clustercpu];
 
                if (!dest)
@@ -71,7 +66,7 @@ __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
 
                __x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL);
                /* Remove cluster CPUs from tmpmask */
-               cpumask_andnot(tmpmsk, tmpmsk, &cmsk->mask);
+               cpumask_andnot(tmpmsk, tmpmsk, cmsk);
        }
 
        local_irq_restore(flags);
@@ -105,55 +100,98 @@ static u32 x2apic_calc_apicid(unsigned int cpu)
 
 static void init_x2apic_ldr(void)
 {
-       struct cluster_mask *cmsk = this_cpu_read(cluster_masks);
-       u32 cluster, apicid = apic_read(APIC_LDR);
-       unsigned int cpu;
+       struct cpumask *cmsk = this_cpu_read(cluster_masks);
 
-       x86_cpu_to_logical_apicid[smp_processor_id()] = apicid;
+       BUG_ON(!cmsk);
 
-       if (cmsk)
-               goto update;
-
-       cluster = apicid >> 16;
-       for_each_online_cpu(cpu) {
-               cmsk = per_cpu(cluster_masks, cpu);
-               /* Matching cluster found. Link and update it. */
-               if (cmsk && cmsk->clusterid == cluster)
-                       goto update;
+       cpumask_set_cpu(smp_processor_id(), cmsk);
+}
+
+/*
+ * As an optimisation during boot, set the cluster_mask for all present
+ * CPUs at once, to prevent each of them having to iterate over the others
+ * to find the existing cluster_mask.
+ */
+static void prefill_clustermask(struct cpumask *cmsk, unsigned int cpu, u32 cluster)
+{
+       int cpu_i;
+
+       for_each_present_cpu(cpu_i) {
+               struct cpumask **cpu_cmsk = &per_cpu(cluster_masks, cpu_i);
+               u32 apicid = apic->cpu_present_to_apicid(cpu_i);
+
+               if (apicid == BAD_APICID || cpu_i == cpu || apic_cluster(apicid) != cluster)
+                       continue;
+
+               if (WARN_ON_ONCE(*cpu_cmsk == cmsk))
+                       continue;
+
+               BUG_ON(*cpu_cmsk);
+               *cpu_cmsk = cmsk;
        }
-       cmsk = cluster_hotplug_mask;
-       cmsk->clusterid = cluster;
-       cluster_hotplug_mask = NULL;
-update:
-       this_cpu_write(cluster_masks, cmsk);
-       cpumask_set_cpu(smp_processor_id(), &cmsk->mask);
 }
 
-static int alloc_clustermask(unsigned int cpu, int node)
+static int alloc_clustermask(unsigned int cpu, u32 cluster, int node)
 {
+       struct cpumask *cmsk = NULL;
+       unsigned int cpu_i;
+
+       /*
+        * At boot time, the CPU present mask is stable. The cluster mask is
+        * allocated for the first CPU in the cluster and propagated to all
+        * present siblings in the cluster. If the cluster mask is already set
+        * on entry to this function for a given CPU, there is nothing to do.
+        */
        if (per_cpu(cluster_masks, cpu))
                return 0;
+
+       if (system_state < SYSTEM_RUNNING)
+               goto alloc;
+
        /*
-        * If a hotplug spare mask exists, check whether it's on the right
-        * node. If not, free it and allocate a new one.
+        * On post boot hotplug for a CPU which was not present at boot time,
+        * iterate over all possible CPUs (even those which are not present
+        * any more) to find any existing cluster mask.
         */
-       if (cluster_hotplug_mask) {
-               if (cluster_hotplug_mask->node == node)
-                       return 0;
-               kfree(cluster_hotplug_mask);
+       for_each_possible_cpu(cpu_i) {
+               u32 apicid = apic->cpu_present_to_apicid(cpu_i);
+
+               if (apicid != BAD_APICID && apic_cluster(apicid) == cluster) {
+                       cmsk = per_cpu(cluster_masks, cpu_i);
+                       /*
+                        * If the cluster is already initialized, just store
+                        * the mask and return. There's no need to propagate.
+                        */
+                       if (cmsk) {
+                               per_cpu(cluster_masks, cpu) = cmsk;
+                               return 0;
+                       }
+               }
        }
-
-       cluster_hotplug_mask = kzalloc_node(sizeof(*cluster_hotplug_mask),
-                                           GFP_KERNEL, node);
-       if (!cluster_hotplug_mask)
+       /*
+        * No CPU in the cluster has ever been initialized, so fall through to
+        * the boot time code which will also populate the cluster mask for any
+        * other CPU in the cluster which is (now) present.
+        */
+alloc:
+       cmsk = kzalloc_node(sizeof(*cmsk), GFP_KERNEL, node);
+       if (!cmsk)
                return -ENOMEM;
-       cluster_hotplug_mask->node = node;
+       per_cpu(cluster_masks, cpu) = cmsk;
+       prefill_clustermask(cmsk, cpu, cluster);
+
        return 0;
 }
 
 static int x2apic_prepare_cpu(unsigned int cpu)
 {
-       if (alloc_clustermask(cpu, cpu_to_node(cpu)) < 0)
+       u32 phys_apicid = apic->cpu_present_to_apicid(cpu);
+       u32 cluster = apic_cluster(phys_apicid);
+       u32 logical_apicid = (cluster << 16) | (1 << (phys_apicid & 0xf));
+
+       x86_cpu_to_logical_apicid[cpu] = logical_apicid;
+
+       if (alloc_clustermask(cpu, cluster, cpu_to_node(cpu)) < 0)
                return -ENOMEM;
        if (!zalloc_cpumask_var(&per_cpu(ipi_mask, cpu), GFP_KERNEL))
                return -ENOMEM;
@@ -162,10 +200,10 @@ static int x2apic_prepare_cpu(unsigned int cpu)
 
 static int x2apic_dead_cpu(unsigned int dead_cpu)
 {
-       struct cluster_mask *cmsk = per_cpu(cluster_masks, dead_cpu);
+       struct cpumask *cmsk = per_cpu(cluster_masks, dead_cpu);
 
        if (cmsk)
-               cpumask_clear_cpu(dead_cpu, &cmsk->mask);
+               cpumask_clear_cpu(dead_cpu, cmsk);
        free_cpumask_var(per_cpu(ipi_mask, dead_cpu));
        return 0;
 }
index 283dcd2f62c8f7a10896346795a82ccd8411d233..dc3576303f1ade63aa729ae1e5b4cb80cac50ccf 100644 (file)
@@ -115,6 +115,7 @@ static void __used common(void)
        OFFSET(TSS_sp1, tss_struct, x86_tss.sp1);
        OFFSET(TSS_sp2, tss_struct, x86_tss.sp2);
        OFFSET(X86_top_of_stack, pcpu_hot, top_of_stack);
+       OFFSET(X86_current_task, pcpu_hot, current_task);
 #ifdef CONFIG_CALL_DEPTH_TRACKING
        OFFSET(X86_call_depth, pcpu_hot, call_depth);
 #endif
index 95cdd08c4cbb91ffa88fb14960ca532132c363ff..571abf808ea3129131765ef78acbaeb21500e2a6 100644 (file)
@@ -929,6 +929,10 @@ static void init_amd(struct cpuinfo_x86 *c)
        if (c->x86 >= 0x10)
                set_cpu_cap(c, X86_FEATURE_REP_GOOD);
 
+       /* AMD FSRM also implies FSRS */
+       if (cpu_has(c, X86_FEATURE_FSRM))
+               set_cpu_cap(c, X86_FEATURE_FSRS);
+
        /* get apicid instead of initial apic id from cpuid */
        c->apicid = hard_smp_processor_id();
 
@@ -1005,6 +1009,17 @@ static void init_amd(struct cpuinfo_x86 *c)
                msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
 
        check_null_seg_clears_base(c);
+
+       /*
+        * Make sure EFER[AIBRSE - Automatic IBRS Enable] is set. The APs are brought up
+        * using the trampoline code and as part of it, MSR_EFER gets prepared there in
+        * order to be replicated onto them. Regardless, set it here again, if not set,
+        * to protect against any future refactoring/code reorganization which might
+        * miss setting this important bit.
+        */
+       if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+           cpu_has(c, X86_FEATURE_AUTOIBRS))
+               WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
 }
 
 #ifdef CONFIG_X86_32
index f9d060e71c3eecfc77c7acda99f8e4a4e4b2d27f..182af64387d061294d4883b3b7b752c60aa616fc 100644 (file)
@@ -784,8 +784,7 @@ static int __init nospectre_v1_cmdline(char *str)
 }
 early_param("nospectre_v1", nospectre_v1_cmdline);
 
-static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
-       SPECTRE_V2_NONE;
+enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = SPECTRE_V2_NONE;
 
 #undef pr_fmt
 #define pr_fmt(fmt)     "RETBleed: " fmt
@@ -1133,13 +1132,6 @@ spectre_v2_parse_user_cmdline(void)
        return SPECTRE_V2_USER_CMD_AUTO;
 }
 
-static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
-{
-       return mode == SPECTRE_V2_EIBRS ||
-              mode == SPECTRE_V2_EIBRS_RETPOLINE ||
-              mode == SPECTRE_V2_EIBRS_LFENCE;
-}
-
 static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
 {
        return spectre_v2_in_eibrs_mode(mode) || mode == SPECTRE_V2_IBRS;
index 8cd4126d825391514c1a4bbb9fa09cac8c53a53c..80710a68ef7daedcc565faead87445a0554f1839 100644 (file)
@@ -121,6 +121,7 @@ static const struct x86_cpu_id ppin_cpuids[] = {
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, &ppin_info[X86_VENDOR_INTEL]),
        X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &ppin_info[X86_VENDOR_INTEL]),
        X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &ppin_info[X86_VENDOR_INTEL]),
+       X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &ppin_info[X86_VENDOR_INTEL]),
        X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &ppin_info[X86_VENDOR_INTEL]),
        X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &ppin_info[X86_VENDOR_INTEL]),
 
index 57a5349e69548fe8acb6aaaa1da09f38e19eef40..f97b0fe13da805badcb180c4e27a1add8d6ccf1b 100644 (file)
@@ -83,4 +83,12 @@ unsigned int aperfmperf_get_khz(int cpu);
 extern void x86_spec_ctrl_setup_ap(void);
 extern void update_srbds_msr(void);
 
+extern enum spectre_v2_mitigation spectre_v2_enabled;
+
+static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
+{
+       return mode == SPECTRE_V2_EIBRS ||
+              mode == SPECTRE_V2_EIBRS_RETPOLINE ||
+              mode == SPECTRE_V2_EIBRS_LFENCE;
+}
 #endif /* ARCH_X86_CPU_H */
index 291d4167fab841f371c552cabffca7a84f2d9324..1c648b09e05373139859bb2921a9ed546ce8f09b 100644 (file)
@@ -1451,31 +1451,13 @@ void handle_bus_lock(struct pt_regs *regs)
 }
 
 /*
- * Bits in the IA32_CORE_CAPABILITIES are not architectural, so they should
- * only be trusted if it is confirmed that a CPU model implements a
- * specific feature at a particular bit position.
- *
- * The possible driver data field values:
- *
- * - 0: CPU models that are known to have the per-core split-lock detection
- *     feature even though they do not enumerate IA32_CORE_CAPABILITIES.
- *
- * - 1: CPU models which may enumerate IA32_CORE_CAPABILITIES and if so use
- *      bit 5 to enumerate the per-core split-lock detection feature.
+ * CPU models that are known to have the per-core split-lock detection
+ * feature even though they do not enumerate IA32_CORE_CAPABILITIES.
  */
 static const struct x86_cpu_id split_lock_cpu_ids[] __initconst = {
-       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,           0),
-       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L,           0),
-       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,           0),
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT,        1),
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D,      1),
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L,      1),
-       X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L,         1),
-       X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE,           1),
-       X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,    1),
-       X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE,           1),
-       X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,         1),
-       X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE,          1),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X,   0),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L,   0),
+       X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,   0),
        {}
 };
 
@@ -1487,24 +1469,27 @@ static void __init split_lock_setup(struct cpuinfo_x86 *c)
        if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
                return;
 
+       /* Check for CPUs that have support but do not enumerate it: */
        m = x86_match_cpu(split_lock_cpu_ids);
-       if (!m)
-               return;
+       if (m)
+               goto supported;
 
-       switch (m->driver_data) {
-       case 0:
-               break;
-       case 1:
-               if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
-                       return;
-               rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
-               if (!(ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT))
-                       return;
-               break;
-       default:
+       if (!cpu_has(c, X86_FEATURE_CORE_CAPABILITIES))
                return;
-       }
 
+       /*
+        * Not all bits in MSR_IA32_CORE_CAPS are architectural, but
+        * MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT is.  All CPUs that set
+        * it have split lock detection.
+        */
+       rdmsrl(MSR_IA32_CORE_CAPS, ia32_core_caps);
+       if (ia32_core_caps & MSR_IA32_CORE_CAPS_SPLIT_LOCK_DETECT)
+               goto supported;
+
+       /* CPU is not in the model list and does not have the MSR bit: */
+       return;
+
+supported:
        cpu_model_supports_sld = true;
        __split_lock_setup();
 }
index 23c5072fbbb76d6625ffb8a31cc5502f00dcd301..0b971f97409642636b7a4cff8e2f15885e8df9c1 100644 (file)
@@ -235,10 +235,10 @@ static DEFINE_PER_CPU(struct threshold_bank **, threshold_banks);
  * A list of the banks enabled on each logical CPU. Controls which respective
  * descriptors to initialize later in mce_threshold_create_device().
  */
-static DEFINE_PER_CPU(unsigned int, bank_map);
+static DEFINE_PER_CPU(u64, bank_map);
 
 /* Map of banks that have more than MCA_MISC0 available. */
-static DEFINE_PER_CPU(u32, smca_misc_banks_map);
+static DEFINE_PER_CPU(u64, smca_misc_banks_map);
 
 static void amd_threshold_interrupt(void);
 static void amd_deferred_error_interrupt(void);
@@ -267,7 +267,7 @@ static void smca_set_misc_banks_map(unsigned int bank, unsigned int cpu)
                return;
 
        if (low & MASK_BLKPTR_LO)
-               per_cpu(smca_misc_banks_map, cpu) |= BIT(bank);
+               per_cpu(smca_misc_banks_map, cpu) |= BIT_ULL(bank);
 
 }
 
@@ -530,7 +530,7 @@ static u32 smca_get_block_address(unsigned int bank, unsigned int block,
        if (!block)
                return MSR_AMD64_SMCA_MCx_MISC(bank);
 
-       if (!(per_cpu(smca_misc_banks_map, cpu) & BIT(bank)))
+       if (!(per_cpu(smca_misc_banks_map, cpu) & BIT_ULL(bank)))
                return 0;
 
        return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
@@ -574,7 +574,7 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
        int new;
 
        if (!block)
-               per_cpu(bank_map, cpu) |= (1 << bank);
+               per_cpu(bank_map, cpu) |= BIT_ULL(bank);
 
        memset(&b, 0, sizeof(b));
        b.cpu                   = cpu;
@@ -878,7 +878,7 @@ static void amd_threshold_interrupt(void)
                return;
 
        for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) {
-               if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+               if (!(per_cpu(bank_map, cpu) & BIT_ULL(bank)))
                        continue;
 
                first_block = bp[bank]->blocks;
@@ -1029,7 +1029,7 @@ static const struct sysfs_ops threshold_ops = {
 
 static void threshold_block_release(struct kobject *kobj);
 
-static struct kobj_type threshold_ktype = {
+static const struct kobj_type threshold_ktype = {
        .sysfs_ops              = &threshold_ops,
        .default_groups         = default_groups,
        .release                = threshold_block_release,
@@ -1356,7 +1356,7 @@ int mce_threshold_create_device(unsigned int cpu)
                return -ENOMEM;
 
        for (bank = 0; bank < numbanks; ++bank) {
-               if (!(this_cpu_read(bank_map) & (1 << bank)))
+               if (!(this_cpu_read(bank_map) & BIT_ULL(bank)))
                        continue;
                err = threshold_create_bank(bp, cpu, bank);
                if (err) {
index 7832a69d170e723c1088098606d9f7b9796d1a94..2eec60f50057a7204ea9e36e208d2637614de06d 100644 (file)
@@ -2355,6 +2355,7 @@ static void mce_restart(void)
 {
        mce_timer_delete_all();
        on_each_cpu(mce_cpu_restart, NULL, 1);
+       mce_schedule_work();
 }
 
 /* Toggle features for corrected errors */
index 91a415553c272136c597be432dcf5aa6aa315420..d2412ce2d312f4fc7771f8f276ac079e29371cd1 100644 (file)
@@ -244,11 +244,11 @@ noinstr void pentium_machine_check(struct pt_regs *regs);
 noinstr void winchip_machine_check(struct pt_regs *regs);
 static inline void enable_p5_mce(void) { mce_p5_enabled = 1; }
 #else
-static inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
-static inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
-static inline void enable_p5_mce(void) {}
-static inline void pentium_machine_check(struct pt_regs *regs) {}
-static inline void winchip_machine_check(struct pt_regs *regs) {}
+static __always_inline void intel_p5_mcheck_init(struct cpuinfo_x86 *c) {}
+static __always_inline void winchip_mcheck_init(struct cpuinfo_x86 *c) {}
+static __always_inline void enable_p5_mce(void) {}
+static __always_inline void pentium_machine_check(struct pt_regs *regs) {}
+static __always_inline void winchip_machine_check(struct pt_regs *regs) {}
 #endif
 
 noinstr u64 mce_rdmsrl(u32 msr);
index 9eb457b1034133dc03d5560f4c82053bbdc4816c..f5fdeb1e3606ec3ce989624d513a459f3fd3d04a 100644 (file)
@@ -61,7 +61,7 @@ static u8 amd_ucode_patch[MAX_NUMNODES][PATCH_MAX_SIZE];
 
 /*
  * Microcode patch container file is prepended to the initrd in cpio
- * format. See Documentation/x86/microcode.rst
+ * format. See Documentation/arch/x86/microcode.rst
  */
 static const char
 ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin";
index f36dc2f796c5c0eca284a9d58c8139d2a108472f..315fc358e5848373b53f6a1f513b524551d9ff6e 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/nmi.h>
 #include <clocksource/hyperv_timer.h>
 #include <asm/numa.h>
-#include <asm/coco.h>
 
 /* Is Linux running as the root partition? */
 bool hv_root_partition;
@@ -358,12 +357,16 @@ static void __init ms_hyperv_init_platform(void)
         * To mirror what Windows does we should extract CPU management
         * features and use the ReservedIdentityBit to detect if Linux is the
         * root partition. But that requires negotiating CPU management
-        * interface (a process to be finalized).
+        * interface (a process to be finalized). For now, use the privilege
+        * flag as the indicator for running as root.
         *
-        * For now, use the privilege flag as the indicator for running as
-        * root.
+        * Hyper-V should never specify running as root and as a Confidential
+        * VM. But to protect against a compromised/malicious Hyper-V trying
+        * to exploit root behavior to expose Confidential VM memory, ignore
+        * the root partition setting if also a Confidential VM.
         */
-       if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_CPU_MANAGEMENT) {
+       if ((ms_hyperv.priv_high & HV_CPU_MANAGEMENT) &&
+           !(ms_hyperv.priv_high & HV_ISOLATION)) {
                hv_root_partition = true;
                pr_info("Hyper-V: running as root partition\n");
        }
@@ -397,8 +400,10 @@ static void __init ms_hyperv_init_platform(void)
        if (ms_hyperv.priv_high & HV_ISOLATION) {
                ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG);
                ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG);
-               ms_hyperv.shared_gpa_boundary =
-                       BIT_ULL(ms_hyperv.shared_gpa_boundary_bits);
+
+               if (ms_hyperv.shared_gpa_boundary_active)
+                       ms_hyperv.shared_gpa_boundary =
+                               BIT_ULL(ms_hyperv.shared_gpa_boundary_bits);
 
                pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n",
                        ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b);
@@ -409,11 +414,6 @@ static void __init ms_hyperv_init_platform(void)
                        swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary;
 #endif
                }
-               /* Isolation VMs are unenlightened SEV-based VMs, thus this check: */
-               if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) {
-                       if (hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE)
-                               cc_set_vendor(CC_VENDOR_HYPERV);
-               }
        }
 
        if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) {
@@ -482,6 +482,9 @@ static void __init ms_hyperv_init_platform(void)
        i8253_clear_counter_on_shutdown = false;
 
 #if IS_ENABLED(CONFIG_HYPERV)
+       if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) ||
+           (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP))
+               hv_vtom_init();
        /*
         * Setup the hook to get control post apic initialization.
         */
index eb07d4435391bedc4db1a2d6483bda477c093bea..b44c487727d456e445a4ad53ddaff76d84e449b1 100644 (file)
@@ -368,7 +368,6 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
 {
        struct resctrl_schema *s;
        struct rdtgroup *rdtgrp;
-       struct rdt_domain *dom;
        struct rdt_resource *r;
        char *tok, *resname;
        int ret = 0;
@@ -397,10 +396,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
                goto out;
        }
 
-       list_for_each_entry(s, &resctrl_schema_all, list) {
-               list_for_each_entry(dom, &s->res->domains, list)
-                       memset(dom->staged_config, 0, sizeof(dom->staged_config));
-       }
+       rdt_staged_configs_clear();
 
        while ((tok = strsep(&buf, "\n")) != NULL) {
                resname = strim(strsep(&tok, ":"));
@@ -445,6 +441,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
        }
 
 out:
+       rdt_staged_configs_clear();
        rdtgroup_kn_unlock(of->kn);
        cpus_read_unlock();
        return ret ?: nbytes;
index 8edecc5763d8e31313294145b7e0af8a6e477611..85ceaf9a31ac20099c86647b4958e4ca0f28fa6b 100644 (file)
@@ -555,5 +555,6 @@ void __check_limbo(struct rdt_domain *d, bool force_free);
 void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
 void __init thread_throttle_mode_init(void);
 void __init mbm_config_rftype_init(const char *config);
+void rdt_staged_configs_clear(void);
 
 #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
index 7fe51488e136ab7b6c320589ca09c5dd1d37ed0b..0e7b6afe2fa682097f6d463a0f5e4148e9940599 100644 (file)
@@ -76,7 +76,7 @@ unsigned int resctrl_rmid_realloc_limit;
 #define CF(cf) ((unsigned long)(1048576 * (cf) + 0.5))
 
 /*
- * The correction factor table is documented in Documentation/x86/resctrl.rst.
+ * The correction factor table is documented in Documentation/arch/x86/resctrl.rst.
  * If rmid > rmid threshold, MBM total and local values should be multiplied
  * by the correction factor.
  *
index 884b6e9a7e31c36281afe21b2f507f9b223781b2..6ad33f355861feab9a1f013ff82e026e9638044b 100644 (file)
@@ -78,6 +78,19 @@ void rdt_last_cmd_printf(const char *fmt, ...)
        va_end(ap);
 }
 
+void rdt_staged_configs_clear(void)
+{
+       struct rdt_resource *r;
+       struct rdt_domain *dom;
+
+       lockdep_assert_held(&rdtgroup_mutex);
+
+       for_each_alloc_capable_rdt_resource(r) {
+               list_for_each_entry(dom, &r->domains, list)
+                       memset(dom->staged_config, 0, sizeof(dom->staged_config));
+       }
+}
+
 /*
  * Trivial allocator for CLOSIDs. Since h/w only supports a small number,
  * we can keep a bitmap of free CLOSIDs in a single integer.
@@ -3107,7 +3120,9 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
 {
        struct resctrl_schema *s;
        struct rdt_resource *r;
-       int ret;
+       int ret = 0;
+
+       rdt_staged_configs_clear();
 
        list_for_each_entry(s, &resctrl_schema_all, list) {
                r = s->res;
@@ -3119,20 +3134,22 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
                } else {
                        ret = rdtgroup_init_cat(s, rdtgrp->closid);
                        if (ret < 0)
-                               return ret;
+                               goto out;
                }
 
                ret = resctrl_arch_update_domains(r, rdtgrp->closid);
                if (ret < 0) {
                        rdt_last_cmd_puts("Failed to initialize allocations\n");
-                       return ret;
+                       goto out;
                }
 
        }
 
        rdtgrp->mode = RDT_MODE_SHAREABLE;
 
-       return 0;
+out:
+       rdt_staged_configs_clear();
+       return ret;
 }
 
 static int mkdir_rdt_prepare(struct kernfs_node *parent_kn,
index e5a37b6e9aa585df3a91abfef9b6231f61940363..166692f2d501112a887106971212cc1b8e6c2856 100644 (file)
@@ -892,20 +892,19 @@ static struct miscdevice sgx_dev_provision = {
 int sgx_set_attribute(unsigned long *allowed_attributes,
                      unsigned int attribute_fd)
 {
-       struct file *file;
+       struct fd f = fdget(attribute_fd);
 
-       file = fget(attribute_fd);
-       if (!file)
+       if (!f.file)
                return -EINVAL;
 
-       if (file->f_op != &sgx_provision_fops) {
-               fput(file);
+       if (f.file->f_op != &sgx_provision_fops) {
+               fdput(f);
                return -EINVAL;
        }
 
        *allowed_attributes |= SGX_ATTR_PROVISIONKEY;
 
-       fput(file);
+       fdput(f);
        return 0;
 }
 EXPORT_SYMBOL_GPL(sgx_set_attribute);
index 0f2020653fba05544f1477ba5871c18a991e924e..d2dad21259a8d2d4cf06d4d908690625501fdab3 100644 (file)
@@ -15,7 +15,7 @@
 
 #define EREMOVE_ERROR_MESSAGE \
        "EREMOVE returned %d (0x%x) and an EPC page was leaked. SGX may become unusable. " \
-       "Refer to Documentation/x86/sgx.rst for more information."
+       "Refer to Documentation/arch/x86/sgx.rst for more information."
 
 #define SGX_MAX_EPC_SECTIONS           8
 #define SGX_EEXTEND_BLOCK_SIZE         256
index 714166cc25f2f6bff10cffd2dee9d40a2fca9db8..0bab497c94369428ceb247f8de26582b7716ce84 100644 (file)
@@ -1118,21 +1118,20 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
        zerofrom = offsetof(struct xregs_state, extended_state_area);
 
        /*
-        * The ptrace buffer is in non-compacted XSAVE format.  In
-        * non-compacted format disabled features still occupy state space,
-        * but there is no state to copy from in the compacted
-        * init_fpstate. The gap tracking will zero these states.
-        */
-       mask = fpstate->user_xfeatures;
-
-       /*
-        * Dynamic features are not present in init_fpstate. When they are
-        * in an all zeros init state, remove those from 'mask' to zero
-        * those features in the user buffer instead of retrieving them
-        * from init_fpstate.
+        * This 'mask' indicates which states to copy from fpstate.
+        * Those extended states that are not present in fpstate are
+        * either disabled or initialized:
+        *
+        * In non-compacted format, disabled features still occupy
+        * state space but there is no state to copy from in the
+        * compacted init_fpstate. The gap tracking will zero these
+        * states.
+        *
+        * The extended features have an all zeroes init state. Thus,
+        * remove them from 'mask' to zero those features in the user
+        * buffer instead of retrieving them from init_fpstate.
         */
-       if (fpu_state_size_dynamic())
-               mask &= (header.xfeatures | xinit->header.xcomp_bv);
+       mask = header.xfeatures;
 
        for_each_extended_xfeature(i, mask) {
                /*
@@ -1151,9 +1150,8 @@ void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
                        pkru.pkru = pkru_val;
                        membuf_write(&to, &pkru, sizeof(pkru));
                } else {
-                       copy_feature(header.xfeatures & BIT_ULL(i), &to,
+                       membuf_write(&to,
                                     __raw_xsave_addr(xsave, i),
-                                    __raw_xsave_addr(xinit, i),
                                     xstate_sizes[i]);
                }
                /*
index 1265ad519249c027cae82d8941d394b8dbc50795..fb4f1e01b64a28af7b85ff26fa8edac39ce67bd6 100644 (file)
@@ -136,10 +136,12 @@ SYM_TYPED_FUNC_START(ftrace_stub)
        RET
 SYM_FUNC_END(ftrace_stub)
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
 SYM_TYPED_FUNC_START(ftrace_stub_graph)
        CALL_DEPTH_ACCOUNT
        RET
 SYM_FUNC_END(ftrace_stub_graph)
+#endif
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 
index 222efd4a09bc8861b3871f4a175013c0730f8759..6a8238702eabb5ed7d84107fbef7fdabfaae13a5 100644 (file)
@@ -61,23 +61,15 @@ SYM_CODE_START_NOALIGN(startup_64)
         * tables and then reload them.
         */
 
-       /* Set up the stack for verify_cpu(), similar to initial_stack below */
-       leaq    (__end_init_task - FRAME_SIZE)(%rip), %rsp
+       /* Set up the stack for verify_cpu() */
+       leaq    (__end_init_task - PTREGS_SIZE)(%rip), %rsp
 
        leaq    _text(%rip), %rdi
 
-       /*
-        * initial_gs points to initial fixed_percpu_data struct with storage for
-        * the stack protector canary. Global pointer fixups are needed at this
-        * stage, so apply them as is done in fixup_pointer(), and initialize %gs
-        * such that the canary can be accessed at %gs:40 for subsequent C calls.
-        */
+       /* Setup GSBASE to allow stack canary access for C code */
        movl    $MSR_GS_BASE, %ecx
-       movq    initial_gs(%rip), %rax
-       movq    $_text, %rdx
-       subq    %rdx, %rax
-       addq    %rdi, %rax
-       movq    %rax, %rdx
+       leaq    INIT_PER_CPU_VAR(fixed_percpu_data)(%rip), %rdx
+       movl    %edx, %eax
        shrq    $32,  %rdx
        wrmsr
 
@@ -241,13 +233,36 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
        UNWIND_HINT_EMPTY
        ANNOTATE_NOENDBR // above
 
+#ifdef CONFIG_SMP
+       movl    smpboot_control(%rip), %ecx
+
+       /* Get the per cpu offset for the given CPU# which is in ECX */
+       movq    __per_cpu_offset(,%rcx,8), %rdx
+#else
+       xorl    %edx, %edx /* zero-extended to clear all of RDX */
+#endif /* CONFIG_SMP */
+
+       /*
+        * Setup a boot time stack - Any secondary CPU will have lost its stack
+        * by now because the cr3-switch above unmaps the real-mode stack.
+        *
+        * RDX contains the per-cpu offset
+        */
+       movq    pcpu_hot + X86_current_task(%rdx), %rax
+       movq    TASK_threadsp(%rax), %rsp
+
        /*
         * We must switch to a new descriptor in kernel space for the GDT
         * because soon the kernel won't have access anymore to the userspace
         * addresses where we're currently running on. We have to do that here
         * because in 32bit we couldn't load a 64bit linear address.
         */
-       lgdt    early_gdt_descr(%rip)
+       subq    $16, %rsp
+       movw    $(GDT_SIZE-1), (%rsp)
+       leaq    gdt_page(%rdx), %rax
+       movq    %rax, 2(%rsp)
+       lgdt    (%rsp)
+       addq    $16, %rsp
 
        /* set up data segments */
        xorl %eax,%eax
@@ -271,16 +286,13 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
         * the per cpu areas are set up.
         */
        movl    $MSR_GS_BASE,%ecx
-       movl    initial_gs(%rip),%eax
-       movl    initial_gs+4(%rip),%edx
+#ifndef CONFIG_SMP
+       leaq    INIT_PER_CPU_VAR(fixed_percpu_data)(%rip), %rdx
+#endif
+       movl    %edx, %eax
+       shrq    $32, %rdx
        wrmsr
 
-       /*
-        * Setup a boot time stack - Any secondary CPU will have lost its stack
-        * by now because the cr3-switch above unmaps the real-mode stack
-        */
-       movq initial_stack(%rip), %rsp
-
        /* Setup and Load IDT */
        pushq   %rsi
        call    early_setup_idt
@@ -372,7 +384,11 @@ SYM_CODE_END(secondary_startup_64)
 SYM_CODE_START(start_cpu0)
        ANNOTATE_NOENDBR
        UNWIND_HINT_EMPTY
-       movq    initial_stack(%rip), %rsp
+
+       /* Find the idle task stack */
+       movq    PER_CPU_VAR(pcpu_hot) + X86_current_task, %rcx
+       movq    TASK_threadsp(%rcx), %rsp
+
        jmp     .Ljump_to_C_code
 SYM_CODE_END(start_cpu0)
 #endif
@@ -416,16 +432,9 @@ SYM_CODE_END(vc_boot_ghcb)
        __REFDATA
        .balign 8
 SYM_DATA(initial_code, .quad x86_64_start_kernel)
-SYM_DATA(initial_gs,   .quad INIT_PER_CPU_VAR(fixed_percpu_data))
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 SYM_DATA(initial_vc_handler,   .quad handle_vc_boot_ghcb)
 #endif
-
-/*
- * The FRAME_SIZE gap is a convention which helps the in-kernel unwinder
- * reliably detect the end of the stack.
- */
-SYM_DATA(initial_stack, .quad init_thread_union + THREAD_SIZE - FRAME_SIZE)
        __FINITDATA
 
        __INIT
@@ -657,8 +666,7 @@ SYM_DATA_END(level1_fixmap_pgt)
        .data
        .align 16
 
-SYM_DATA(early_gdt_descr,              .word GDT_ENTRIES*8-1)
-SYM_DATA_LOCAL(early_gdt_descr_base,   .quad INIT_PER_CPU_VAR(gdt_page))
+SYM_DATA(smpboot_control,              .long 0)
 
        .align 16
 /* This must match the first entry in level2_kernel_pgt */
index 6b58610a15521da6323b856e14f7dbe8bcb3ed28..a61c12c012709799ba0b2e1f11295b0861a96122 100644 (file)
@@ -476,7 +476,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
        efi_map_offset = params_cmdline_sz;
        efi_setup_data_offset = efi_map_offset + ALIGN(efi_map_sz, 16);
 
-       /* Copy setup header onto bootparams. Documentation/x86/boot.rst */
+       /* Copy setup header onto bootparams. Documentation/arch/x86/boot.rst */
        setup_header_size = 0x0202 + kernel[0x0201] - setup_hdr_offset;
 
        /* Is there a limit on setup header size? */
index 42e1828688731d4fc7fa92500410f9b5756b4db0..ac10b46c5832bf9f57ababa615903e877bd8f02a 100644 (file)
@@ -64,11 +64,11 @@ static unsigned paravirt_patch_call(void *insn_buff, const void *target,
 }
 
 #ifdef CONFIG_PARAVIRT_XXL
-/* identity function, which can be inlined */
-u64 notrace _paravirt_ident_64(u64 x)
-{
-       return x;
-}
+DEFINE_PARAVIRT_ASM(_paravirt_ident_64, "mov %rdi, %rax", .text);
+DEFINE_PARAVIRT_ASM(pv_native_save_fl, "pushf; pop %rax", .noinstr.text);
+DEFINE_PARAVIRT_ASM(pv_native_irq_disable, "cli", .noinstr.text);
+DEFINE_PARAVIRT_ASM(pv_native_irq_enable, "sti", .noinstr.text);
+DEFINE_PARAVIRT_ASM(pv_native_read_cr2, "mov %cr2, %rax", .noinstr.text);
 #endif
 
 DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key);
@@ -197,11 +197,6 @@ void paravirt_end_context_switch(struct task_struct *next)
                arch_enter_lazy_mmu_mode();
 }
 
-static noinstr unsigned long pv_native_read_cr2(void)
-{
-       return native_read_cr2();
-}
-
 static noinstr void pv_native_write_cr2(unsigned long val)
 {
        native_write_cr2(val);
@@ -222,16 +217,6 @@ noinstr void pv_native_wbinvd(void)
        native_wbinvd();
 }
 
-static noinstr void pv_native_irq_enable(void)
-{
-       native_irq_enable();
-}
-
-static noinstr void pv_native_irq_disable(void)
-{
-       native_irq_disable();
-}
-
 static noinstr void pv_native_safe_halt(void)
 {
        native_safe_halt();
@@ -298,7 +283,7 @@ struct paravirt_patch_template pv_ops = {
        .cpu.end_context_switch         = paravirt_nop,
 
        /* Irq ops. */
-       .irq.save_fl            = __PV_IS_CALLEE_SAVE(native_save_fl),
+       .irq.save_fl            = __PV_IS_CALLEE_SAVE(pv_native_save_fl),
        .irq.irq_disable        = __PV_IS_CALLEE_SAVE(pv_native_irq_disable),
        .irq.irq_enable         = __PV_IS_CALLEE_SAVE(pv_native_irq_enable),
        .irq.safe_halt          = pv_native_safe_halt,
@@ -363,8 +348,7 @@ struct paravirt_patch_template pv_ops = {
        .mmu.make_pte           = PTE_IDENT,
        .mmu.make_pgd           = PTE_IDENT,
 
-       .mmu.dup_mmap           = paravirt_nop,
-       .mmu.activate_mm        = paravirt_nop,
+       .mmu.enter_mmap         = paravirt_nop,
 
        .mmu.lazy_mode = {
                .enter          = paravirt_nop,
index 30bbe4abb5d615a91c1a6939700cf06defe390df..de6be0a3965ee4cc5cdd1e42f1042eab71f30c7e 100644 (file)
@@ -124,7 +124,7 @@ void __init pci_iommu_alloc(void)
 }
 
 /*
- * See <Documentation/x86/x86_64/boot-options.rst> for the iommu kernel
+ * See <Documentation/arch/x86/x86_64/boot-options.rst> for the iommu kernel
  * parameter documentation.
  */
 static __init int iommu_setup(char *p)
index 679026a640efd8e2e87a03d3b5e57cf18de1a6dd..b031244d6d2df4cfb5e508c28eaf8d15d580b69a 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/efi.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/psp-sev.h>
+#include <uapi/linux/sev-guest.h>
 
 #include <asm/cpu_entry_area.h>
 #include <asm/stacktrace.h>
@@ -2175,7 +2177,7 @@ static int __init init_sev_config(char *str)
 }
 __setup("sev=", init_sev_config);
 
-int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err)
+int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
 {
        struct ghcb_state state;
        struct es_em_ctxt ctxt;
@@ -2183,11 +2185,7 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
        struct ghcb *ghcb;
        int ret;
 
-       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
-               return -ENODEV;
-
-       if (!fw_err)
-               return -EINVAL;
+       rio->exitinfo2 = SEV_RET_NO_FW_CALL;
 
        /*
         * __sev_get_ghcb() needs to run with IRQs disabled because it is using
@@ -2212,15 +2210,26 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
        if (ret)
                goto e_put;
 
-       if (ghcb->save.sw_exit_info_2) {
-               /* Number of expected pages are returned in RBX */
-               if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
-                   ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN)
-                       input->data_npages = ghcb_get_rbx(ghcb);
+       rio->exitinfo2 = ghcb->save.sw_exit_info_2;
+       switch (rio->exitinfo2) {
+       case 0:
+               break;
 
-               *fw_err = ghcb->save.sw_exit_info_2;
+       case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_BUSY):
+               ret = -EAGAIN;
+               break;
 
+       case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN):
+               /* Number of expected pages are returned in RBX */
+               if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) {
+                       input->data_npages = ghcb_get_rbx(ghcb);
+                       ret = -ENOSPC;
+                       break;
+               }
+               fallthrough;
+       default:
                ret = -EIO;
+               break;
        }
 
 e_put:
index 9013bb28255a13da21afdf291d4f5f04c0a5f923..851477f7d7282bad9a912705bd5a88bd13a65411 100644 (file)
@@ -121,17 +121,20 @@ int arch_update_cpu_topology(void)
        return retval;
 }
 
+
+static unsigned int smpboot_warm_reset_vector_count;
+
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&rtc_lock, flags);
-       CMOS_WRITE(0xa, 0xf);
+       if (!smpboot_warm_reset_vector_count++) {
+               CMOS_WRITE(0xa, 0xf);
+               *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) = start_eip >> 4;
+               *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = start_eip & 0xf;
+       }
        spin_unlock_irqrestore(&rtc_lock, flags);
-       *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
-                                                       start_eip >> 4;
-       *((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
-                                                       start_eip & 0xf;
 }
 
 static inline void smpboot_restore_warm_reset_vector(void)
@@ -143,10 +146,12 @@ static inline void smpboot_restore_warm_reset_vector(void)
         * to default values.
         */
        spin_lock_irqsave(&rtc_lock, flags);
-       CMOS_WRITE(0, 0xf);
+       if (!--smpboot_warm_reset_vector_count) {
+               CMOS_WRITE(0, 0xf);
+               *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
+       }
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       *((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
 }
 
 /*
@@ -1059,8 +1064,6 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
 #ifdef CONFIG_X86_32
        /* Stack for startup_32 can be just as for start_secondary onwards */
        per_cpu(pcpu_hot.top_of_stack, cpu) = task_top_of_stack(idle);
-#else
-       initial_gs = per_cpu_offset(cpu);
 #endif
        return 0;
 }
@@ -1086,9 +1089,14 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle,
                start_ip = real_mode_header->trampoline_start64;
 #endif
        idle->thread.sp = (unsigned long)task_pt_regs(idle);
-       early_gdt_descr.address = (unsigned long)get_cpu_gdt_rw(cpu);
        initial_code = (unsigned long)start_secondary;
-       initial_stack  = idle->thread.sp;
+
+       if (IS_ENABLED(CONFIG_X86_32)) {
+               early_gdt_descr.address = (unsigned long)get_cpu_gdt_rw(cpu);
+               initial_stack  = idle->thread.sp;
+       } else {
+               smpboot_control = cpu;
+       }
 
        /* Enable the espfix hack for this CPU */
        init_espfix_ap(cpu);
index ef80d361b4632ec64bb8aacd0f0bf6e88acb1021..ecdeb0974a87967eca830db5d0107d1d21ca8642 100644 (file)
@@ -33,8 +33,8 @@ static int __init iommu_init_noop(void) { return 0; }
 static void iommu_shutdown_noop(void) { }
 bool __init bool_x86_init_noop(void) { return false; }
 void x86_op_int_noop(int cpu) { }
-static __init int set_rtc_noop(const struct timespec64 *now) { return -EINVAL; }
-static __init void get_rtc_noop(struct timespec64 *now) { }
+static int set_rtc_noop(const struct timespec64 *now) { return -EINVAL; }
+static void get_rtc_noop(struct timespec64 *now) { }
 
 static __initconst const struct of_device_id of_cmos_match[] = {
        { .compatible = "motorola,mc146818" },
@@ -134,6 +134,7 @@ static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool
 static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; }
 static bool enc_tlb_flush_required_noop(bool enc) { return false; }
 static bool enc_cache_flush_required_noop(void) { return false; }
+static bool is_private_mmio_noop(u64 addr) {return false; }
 
 struct x86_platform_ops x86_platform __ro_after_init = {
        .calibrate_cpu                  = native_calibrate_cpu_early,
@@ -149,6 +150,7 @@ struct x86_platform_ops x86_platform __ro_after_init = {
        .realmode_reserve               = reserve_real_mode,
        .realmode_init                  = init_real_mode,
        .hyper.pin_vcpu                 = x86_op_int_noop,
+       .hyper.is_private_mmio          = is_private_mmio_noop,
 
        .guest = {
                .enc_status_change_prepare = enc_status_change_prepare_noop,
index 8e578311ca9d4d1e24302d471eab0bdb4d40535f..89ca7f4c1464337bd42646caa24d37c3df2464d3 100644 (file)
@@ -46,7 +46,6 @@ config KVM
        select KVM_XFER_TO_GUEST_WORK
        select KVM_GENERIC_DIRTYLOG_READ_PROTECT
        select KVM_VFIO
-       select SRCU
        select INTERVAL_TREE
        select HAVE_KVM_PM_NOTIFIER if PM
        select KVM_GENERIC_HARDWARE_ENABLING
index 042dee5561258f166f289276be3376d6130c4a0c..995eb50543601f70f8162ef1dfc2a79f6d21d032 100644 (file)
@@ -368,9 +368,39 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
                mask_after = e->fields.mask;
                if (mask_before != mask_after)
                        kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after);
-               if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG
-                   && ioapic->irr & (1 << index))
-                       ioapic_service(ioapic, index, false);
+               if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG &&
+                   ioapic->irr & (1 << index) && !e->fields.mask && !e->fields.remote_irr) {
+                       /*
+                        * Pending status in irr may be outdated: the IRQ line may have
+                        * already been deasserted by a device while the IRQ was masked.
+                        * This occurs, for instance, if the interrupt is handled in a
+                        * Linux guest as a oneshot interrupt (IRQF_ONESHOT). In this
+                        * case the guest acknowledges the interrupt to the device in
+                        * its threaded irq handler, i.e. after the EOI but before
+                        * unmasking, so at the time of unmasking the IRQ line is
+                        * already down but our pending irr bit is still set. In such
+                        * cases, injecting this pending interrupt to the guest is
+                        * buggy: the guest will receive an extra unwanted interrupt.
+                        *
+                        * So we need to check here if the IRQ is actually still pending.
+                        * As we are generally not able to probe the IRQ line status
+                        * directly, we do it through irqfd resampler. Namely, we clear
+                        * the pending status and notify the resampler that this interrupt
+                        * is done, without actually injecting it into the guest. If the
+                        * IRQ line is actually already deasserted, we are done. If it is
+                        * still asserted, a new interrupt will be shortly triggered
+                        * through irqfd and injected into the guest.
+                        *
+                        * If, however, it's not possible to resample (no irqfd resampler
+                        * registered for this irq), then unconditionally inject this
+                        * pending interrupt into the guest, so the guest will not miss
+                        * an interrupt, although may get an extra unwanted interrupt.
+                        */
+                       if (kvm_notify_irqfd_resampler(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index))
+                               ioapic->irr &= ~(1 << index);
+                       else
+                               ioapic_service(ioapic, index, false);
+               }
                if (e->fields.delivery_mode == APIC_DM_FIXED) {
                        struct kvm_lapic_irq irq;
 
index 287e98ef9df3d820244133f4aa73547abe613f1d..6272dabec02da8ae81aaf39fe5165d5b3c225f7b 100644 (file)
@@ -12,6 +12,11 @@ int hv_remote_flush_tlb_with_range(struct kvm *kvm,
 int hv_remote_flush_tlb(struct kvm *kvm);
 void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
 #else /* !CONFIG_HYPERV */
+static inline int hv_remote_flush_tlb(struct kvm *kvm)
+{
+       return -EOPNOTSUPP;
+}
+
 static inline void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp)
 {
 }
index ca684979e90d65e27a9fc250326e2d947e6c4a82..cfc8ab7730250598cf0f29be7bacfe5e49a82424 100644 (file)
 #include "irq.h"
 #include "svm.h"
 
-/* AVIC GATAG is encoded using VM and VCPU IDs */
-#define AVIC_VCPU_ID_BITS              8
-#define AVIC_VCPU_ID_MASK              ((1 << AVIC_VCPU_ID_BITS) - 1)
+/*
+ * Encode the arbitrary VM ID and the vCPU's default APIC ID, i.e the vCPU ID,
+ * into the GATag so that KVM can retrieve the correct vCPU from a GALog entry
+ * if an interrupt can't be delivered, e.g. because the vCPU isn't running.
+ *
+ * For the vCPU ID, use however many bits are currently allowed for the max
+ * guest physical APIC ID (limited by the size of the physical ID table), and
+ * use whatever bits remain to assign arbitrary AVIC IDs to VMs.  Note, the
+ * size of the GATag is defined by hardware (32 bits), but is an opaque value
+ * as far as hardware is concerned.
+ */
+#define AVIC_VCPU_ID_MASK              AVIC_PHYSICAL_MAX_INDEX_MASK
 
-#define AVIC_VM_ID_BITS                        24
-#define AVIC_VM_ID_NR                  (1 << AVIC_VM_ID_BITS)
-#define AVIC_VM_ID_MASK                        ((1 << AVIC_VM_ID_BITS) - 1)
+#define AVIC_VM_ID_SHIFT               HWEIGHT32(AVIC_PHYSICAL_MAX_INDEX_MASK)
+#define AVIC_VM_ID_MASK                        (GENMASK(31, AVIC_VM_ID_SHIFT) >> AVIC_VM_ID_SHIFT)
 
-#define AVIC_GATAG(x, y)               (((x & AVIC_VM_ID_MASK) << AVIC_VCPU_ID_BITS) | \
-                                               (y & AVIC_VCPU_ID_MASK))
-#define AVIC_GATAG_TO_VMID(x)          ((x >> AVIC_VCPU_ID_BITS) & AVIC_VM_ID_MASK)
+#define AVIC_GATAG_TO_VMID(x)          ((x >> AVIC_VM_ID_SHIFT) & AVIC_VM_ID_MASK)
 #define AVIC_GATAG_TO_VCPUID(x)                (x & AVIC_VCPU_ID_MASK)
 
+#define __AVIC_GATAG(vm_id, vcpu_id)   ((((vm_id) & AVIC_VM_ID_MASK) << AVIC_VM_ID_SHIFT) | \
+                                        ((vcpu_id) & AVIC_VCPU_ID_MASK))
+#define AVIC_GATAG(vm_id, vcpu_id)                                     \
+({                                                                     \
+       u32 ga_tag = __AVIC_GATAG(vm_id, vcpu_id);                      \
+                                                                       \
+       WARN_ON_ONCE(AVIC_GATAG_TO_VCPUID(ga_tag) != (vcpu_id));        \
+       WARN_ON_ONCE(AVIC_GATAG_TO_VMID(ga_tag) != (vm_id));            \
+       ga_tag;                                                         \
+})
+
+static_assert(__AVIC_GATAG(AVIC_VM_ID_MASK, AVIC_VCPU_ID_MASK) == -1u);
+
 static bool force_avic;
 module_param_unsafe(force_avic, bool, 0444);
 
index c25aeb550cd97fbbbae82e7f1b95a5d0f8bc8add..52398d49bc2f54f50f7dd0e9a461d16843b703a0 100644 (file)
@@ -1767,18 +1767,20 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
 {
        struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
        struct kvm_sev_info *src_sev, *cg_cleanup_sev;
-       struct file *source_kvm_file;
+       struct fd f = fdget(source_fd);
        struct kvm *source_kvm;
        bool charged = false;
        int ret;
 
-       source_kvm_file = fget(source_fd);
-       if (!file_is_kvm(source_kvm_file)) {
+       if (!f.file)
+               return -EBADF;
+
+       if (!file_is_kvm(f.file)) {
                ret = -EBADF;
                goto out_fput;
        }
 
-       source_kvm = source_kvm_file->private_data;
+       source_kvm = f.file->private_data;
        ret = sev_lock_two_vms(kvm, source_kvm);
        if (ret)
                goto out_fput;
@@ -1828,8 +1830,7 @@ out_dst_cgroup:
 out_unlock:
        sev_unlock_two_vms(kvm, source_kvm);
 out_fput:
-       if (source_kvm_file)
-               fput(source_kvm_file);
+       fdput(f);
        return ret;
 }
 
@@ -2046,18 +2047,20 @@ failed:
 
 int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
 {
-       struct file *source_kvm_file;
+       struct fd f = fdget(source_fd);
        struct kvm *source_kvm;
        struct kvm_sev_info *source_sev, *mirror_sev;
        int ret;
 
-       source_kvm_file = fget(source_fd);
-       if (!file_is_kvm(source_kvm_file)) {
+       if (!f.file)
+               return -EBADF;
+
+       if (!file_is_kvm(f.file)) {
                ret = -EBADF;
                goto e_source_fput;
        }
 
-       source_kvm = source_kvm_file->private_data;
+       source_kvm = f.file->private_data;
        ret = sev_lock_two_vms(kvm, source_kvm);
        if (ret)
                goto e_source_fput;
@@ -2103,8 +2106,7 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
 e_unlock:
        sev_unlock_two_vms(kvm, source_kvm);
 e_source_fput:
-       if (source_kvm_file)
-               fput(source_kvm_file);
+       fdput(f);
        return ret;
 }
 
index 252e7f37e4e2e27f2194d008c7c18e7c26c00eb1..f25bc3cbb250007b905e9c3c4d3be0daec6f918f 100644 (file)
@@ -3729,7 +3729,7 @@ static void svm_enable_nmi_window(struct kvm_vcpu *vcpu)
        svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
 }
 
-static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
+static void svm_flush_tlb_asid(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
@@ -3753,6 +3753,37 @@ static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
                svm->current_vmcb->asid_generation--;
 }
 
+static void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
+{
+       hpa_t root_tdp = vcpu->arch.mmu->root.hpa;
+
+       /*
+        * When running on Hyper-V with EnlightenedNptTlb enabled, explicitly
+        * flush the NPT mappings via hypercall as flushing the ASID only
+        * affects virtual to physical mappings, it does not invalidate guest
+        * physical to host physical mappings.
+        */
+       if (svm_hv_is_enlightened_tlb_enabled(vcpu) && VALID_PAGE(root_tdp))
+               hyperv_flush_guest_mapping(root_tdp);
+
+       svm_flush_tlb_asid(vcpu);
+}
+
+static void svm_flush_tlb_all(struct kvm_vcpu *vcpu)
+{
+       /*
+        * When running on Hyper-V with EnlightenedNptTlb enabled, remote TLB
+        * flushes should be routed to hv_remote_flush_tlb() without requesting
+        * a "regular" remote flush.  Reaching this point means either there's
+        * a KVM bug or a prior hv_remote_flush_tlb() call failed, both of
+        * which might be fatal to the guest.  Yell, but try to recover.
+        */
+       if (WARN_ON_ONCE(svm_hv_is_enlightened_tlb_enabled(vcpu)))
+               hv_remote_flush_tlb(vcpu->kvm);
+
+       svm_flush_tlb_asid(vcpu);
+}
+
 static void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -4745,10 +4776,10 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
        .set_rflags = svm_set_rflags,
        .get_if_flag = svm_get_if_flag,
 
-       .flush_tlb_all = svm_flush_tlb_current,
+       .flush_tlb_all = svm_flush_tlb_all,
        .flush_tlb_current = svm_flush_tlb_current,
        .flush_tlb_gva = svm_flush_tlb_gva,
-       .flush_tlb_guest = svm_flush_tlb_current,
+       .flush_tlb_guest = svm_flush_tlb_asid,
 
        .vcpu_pre_run = svm_vcpu_pre_run,
        .vcpu_run = svm_vcpu_run,
index cff838f15db5399b1fba358965e38fb8adcddea0..786d46d73a8e5e3c743b0b85e6c578674dd624e1 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef __ARCH_X86_KVM_SVM_ONHYPERV_H__
 #define __ARCH_X86_KVM_SVM_ONHYPERV_H__
 
+#include <asm/mshyperv.h>
+
 #if IS_ENABLED(CONFIG_HYPERV)
 
 #include "kvm_onhyperv.h"
@@ -15,6 +17,14 @@ static struct kvm_x86_ops svm_x86_ops;
 
 int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu);
 
+static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
+{
+       struct hv_vmcb_enlightenments *hve = &to_svm(vcpu)->vmcb->control.hv_enlightenments;
+
+       return ms_hyperv.nested_features & HV_X64_NESTED_ENLIGHTENED_TLB &&
+              !!hve->hv_enlightenments_control.enlightened_npt_tlb;
+}
+
 static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
 {
        struct hv_vmcb_enlightenments *hve = &vmcb->control.hv_enlightenments;
@@ -80,6 +90,11 @@ static inline void svm_hv_update_vp_id(struct vmcb *vmcb, struct kvm_vcpu *vcpu)
 }
 #else
 
+static inline bool svm_hv_is_enlightened_tlb_enabled(struct kvm_vcpu *vcpu)
+{
+       return false;
+}
+
 static inline void svm_hv_init_vmcb(struct vmcb *vmcb)
 {
 }
index 7c4f5ca405c75f881264ec10c76da9ca3886d65e..768487611db78a85dbe57f11a9584d215496b5f1 100644 (file)
@@ -2903,7 +2903,7 @@ static int nested_vmx_check_address_space_size(struct kvm_vcpu *vcpu,
 static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
                                       struct vmcs12 *vmcs12)
 {
-       bool ia32e;
+       bool ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE);
 
        if (CC(!nested_host_cr0_valid(vcpu, vmcs12->host_cr0)) ||
            CC(!nested_host_cr4_valid(vcpu, vmcs12->host_cr4)) ||
@@ -2923,12 +2923,6 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
                                           vmcs12->host_ia32_perf_global_ctrl)))
                return -EINVAL;
 
-#ifdef CONFIG_X86_64
-       ia32e = !!(vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE);
-#else
-       ia32e = false;
-#endif
-
        if (ia32e) {
                if (CC(!(vmcs12->host_cr4 & X86_CR4_PAE)))
                        return -EINVAL;
@@ -3022,7 +3016,7 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
                                        struct vmcs12 *vmcs12,
                                        enum vm_entry_failure_code *entry_failure_code)
 {
-       bool ia32e;
+       bool ia32e = !!(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE);
 
        *entry_failure_code = ENTRY_FAIL_DEFAULT;
 
@@ -3048,6 +3042,13 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
                                           vmcs12->guest_ia32_perf_global_ctrl)))
                return -EINVAL;
 
+       if (CC((vmcs12->guest_cr0 & (X86_CR0_PG | X86_CR0_PE)) == X86_CR0_PG))
+               return -EINVAL;
+
+       if (CC(ia32e && !(vmcs12->guest_cr4 & X86_CR4_PAE)) ||
+           CC(ia32e && !(vmcs12->guest_cr0 & X86_CR0_PG)))
+               return -EINVAL;
+
        /*
         * If the load IA32_EFER VM-entry control is 1, the following checks
         * are performed on the field for the IA32_EFER MSR:
@@ -3059,7 +3060,6 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu,
         */
        if (to_vmx(vcpu)->nested.nested_run_pending &&
            (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) {
-               ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
                if (CC(!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer)) ||
                    CC(ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA)) ||
                    CC(((vmcs12->guest_cr0 & X86_CR0_PG) &&
@@ -3868,7 +3868,12 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu)
                exit_qual = 0;
        }
 
-       if (ex->has_error_code) {
+       /*
+        * Unlike AMD's Paged Real Mode, which reports an error code on #PF
+        * VM-Exits even if the CPU is in Real Mode, Intel VMX never sets the
+        * "has error code" flags on VM-Exit if the CPU is in Real Mode.
+        */
+       if (ex->has_error_code && is_protmode(vcpu)) {
                /*
                 * Intel CPUs do not generate error codes with bits 31:16 set,
                 * and more importantly VMX disallows setting bits 31:16 in the
index f550540ed54ee1820f6c02074e5f8cc7683e62ba..631fd7da2bc36fc7b86c1d04500d168f5cc9b8de 100644 (file)
@@ -262,7 +262,7 @@ SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL)
         * eIBRS has its own protection against poisoned RSB, so it doesn't
         * need the RSB filling sequence.  But it does need to be enabled, and a
         * single call to retire, before the first unbalanced RET.
-         */
+        */
 
        FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT,\
                           X86_FEATURE_RSB_VMEXIT_LITE
@@ -311,7 +311,7 @@ SYM_FUNC_END(vmx_do_nmi_irqoff)
  * vmread_error_trampoline - Trampoline from inline asm to vmread_error()
  * @field:     VMCS field encoding that failed
  * @fault:     %true if the VMREAD faulted, %false if it failed
-
+ *
  * Save and restore volatile registers across a call to vmread_error().  Note,
  * all parameters are passed on the stack.
  */
index bcac3efcde412b3340664f818d16170475cc01cd..d2d6e1b6c7882779c657adc062c83ae049445bc9 100644 (file)
@@ -874,7 +874,7 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu)
         */
        if (is_guest_mode(vcpu))
                eb |= get_vmcs12(vcpu)->exception_bitmap;
-        else {
+       else {
                int mask = 0, match = 0;
 
                if (enable_ept && (eb & (1u << PF_VECTOR))) {
@@ -1282,7 +1282,7 @@ void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
                }
        }
 
-       if (vmx->nested.need_vmcs12_to_shadow_sync)
+       if (vmx->nested.need_vmcs12_to_shadow_sync)
                nested_sync_vmcs12_to_shadow(vcpu);
 
        if (vmx->guest_state_loaded)
@@ -5049,10 +5049,10 @@ static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu, bool for_injection)
        if (to_vmx(vcpu)->nested.nested_run_pending)
                return -EBUSY;
 
-       /*
-        * An IRQ must not be injected into L2 if it's supposed to VM-Exit,
-        * e.g. if the IRQ arrived asynchronously after checking nested events.
-        */
+       /*
+        * An IRQ must not be injected into L2 if it's supposed to VM-Exit,
+        * e.g. if the IRQ arrived asynchronously after checking nested events.
+        */
        if (for_injection && is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
                return -EBUSY;
 
index 7713420abab093b19d6c19e41d9ca9454c006a08..3d852ce8492066705214e84456eb2fc5bda80b42 100644 (file)
@@ -4432,6 +4432,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_VAPIC:
        case KVM_CAP_ENABLE_CAP:
        case KVM_CAP_VM_DISABLE_NX_HUGE_PAGES:
+       case KVM_CAP_IRQFD_RESAMPLE:
                r = 1;
                break;
        case KVM_CAP_EXIT_HYPERCALL:
@@ -8903,6 +8904,8 @@ restart:
        }
 
        if (ctxt->have_exception) {
+               WARN_ON_ONCE(vcpu->mmio_needed && !vcpu->mmio_is_write);
+               vcpu->mmio_needed = false;
                r = 1;
                inject_emulated_exception(vcpu);
        } else if (vcpu->arch.pio.count) {
@@ -9906,13 +9909,20 @@ int kvm_check_nested_events(struct kvm_vcpu *vcpu)
 
 static void kvm_inject_exception(struct kvm_vcpu *vcpu)
 {
+       /*
+        * Suppress the error code if the vCPU is in Real Mode, as Real Mode
+        * exceptions don't report error codes.  The presence of an error code
+        * is carried with the exception and only stripped when the exception
+        * is injected as intercepted #PF VM-Exits for AMD's Paged Real Mode do
+        * report an error code despite the CPU being in Real Mode.
+        */
+       vcpu->arch.exception.has_error_code &= is_protmode(vcpu);
+
        trace_kvm_inj_exception(vcpu->arch.exception.vector,
                                vcpu->arch.exception.has_error_code,
                                vcpu->arch.exception.error_code,
                                vcpu->arch.exception.injected);
 
-       if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
-               vcpu->arch.exception.error_code = false;
        static_call(kvm_x86_inject_exception)(vcpu);
 }
 
index 4f1a40a86534329100d0344bb9388ddede6dc54e..01932af64193c14a3da15d86b92ca2ee332929ad 100644 (file)
@@ -71,6 +71,6 @@ ifneq ($(CONFIG_GENERIC_CSUM),y)
 endif
         lib-y += clear_page_64.o copy_page_64.o
         lib-y += memmove_64.o memset_64.o
-        lib-y += copy_user_64.o
+        lib-y += copy_user_64.o copy_user_uncached_64.o
        lib-y += cmpxchg16b_emu.o
 endif
index ecbfb4dd3b019c5731d15d095dd16067fd6288bb..f74a3e704a1cf0783e10c9c01d5d2e6bc3c5876f 100644 (file)
@@ -57,134 +57,85 @@ EXPORT_SYMBOL_GPL(clear_page_erms)
  * Input:
  * rdi destination
  * rcx count
+ * rax is zero
  *
  * Output:
  * rcx: uncleared bytes or 0 if successful.
  */
-SYM_FUNC_START(clear_user_original)
-       /*
-        * Copy only the lower 32 bits of size as that is enough to handle the rest bytes,
-        * i.e., no need for a 'q' suffix and thus a REX prefix.
-        */
-       mov %ecx,%eax
-       shr $3,%rcx
-       jz .Lrest_bytes
+SYM_FUNC_START(rep_stos_alternative)
+       cmpq $64,%rcx
+       jae .Lunrolled
 
-       # do the qwords first
-       .p2align 4
-.Lqwords:
-       movq $0,(%rdi)
-       lea 8(%rdi),%rdi
-       dec %rcx
-       jnz .Lqwords
+       cmp $8,%ecx
+       jae .Lword
 
-.Lrest_bytes:
-       and $7,  %eax
-       jz .Lexit
+       testl %ecx,%ecx
+       je .Lexit
 
-       # now do the rest bytes
-.Lbytes:
-       movb $0,(%rdi)
+.Lclear_user_tail:
+0:     movb %al,(%rdi)
        inc %rdi
-       dec %eax
-       jnz .Lbytes
-
+       dec %rcx
+       jnz .Lclear_user_tail
 .Lexit:
-       /*
-        * %rax still needs to be cleared in the exception case because this function is called
-        * from inline asm and the compiler expects %rax to be zero when exiting the inline asm,
-        * in case it might reuse it somewhere.
-        */
-        xor %eax,%eax
-        RET
-
-.Lqwords_exception:
-        # convert remaining qwords back into bytes to return to caller
-        shl $3, %rcx
-        and $7, %eax
-        add %rax,%rcx
-        jmp .Lexit
-
-.Lbytes_exception:
-        mov %eax,%ecx
-        jmp .Lexit
-
-        _ASM_EXTABLE_UA(.Lqwords, .Lqwords_exception)
-        _ASM_EXTABLE_UA(.Lbytes, .Lbytes_exception)
-SYM_FUNC_END(clear_user_original)
-EXPORT_SYMBOL(clear_user_original)
-
-/*
- * Alternative clear user-space when CPU feature X86_FEATURE_REP_GOOD is
- * present.
- * Input:
- * rdi destination
- * rcx count
- *
- * Output:
- * rcx: uncleared bytes or 0 if successful.
- */
-SYM_FUNC_START(clear_user_rep_good)
-       # call the original thing for less than a cacheline
-       cmp $64, %rcx
-       jb clear_user_original
-
-.Lprep:
-       # copy lower 32-bits for rest bytes
-       mov %ecx, %edx
-       shr $3, %rcx
-       jz .Lrep_good_rest_bytes
-
-.Lrep_good_qwords:
-       rep stosq
-
-.Lrep_good_rest_bytes:
-       and $7, %edx
-       jz .Lrep_good_exit
-
-.Lrep_good_bytes:
-       mov %edx, %ecx
-       rep stosb
-
-.Lrep_good_exit:
-       # see .Lexit comment above
-       xor %eax, %eax
        RET
 
-.Lrep_good_qwords_exception:
-       # convert remaining qwords back into bytes to return to caller
-       shl $3, %rcx
-       and $7, %edx
-       add %rdx, %rcx
-       jmp .Lrep_good_exit
+       _ASM_EXTABLE_UA( 0b, .Lexit)
 
-       _ASM_EXTABLE_UA(.Lrep_good_qwords, .Lrep_good_qwords_exception)
-       _ASM_EXTABLE_UA(.Lrep_good_bytes, .Lrep_good_exit)
-SYM_FUNC_END(clear_user_rep_good)
-EXPORT_SYMBOL(clear_user_rep_good)
+.Lword:
+1:     movq %rax,(%rdi)
+       addq $8,%rdi
+       sub $8,%ecx
+       je .Lexit
+       cmp $8,%ecx
+       jae .Lword
+       jmp .Lclear_user_tail
 
-/*
- * Alternative clear user-space when CPU feature X86_FEATURE_ERMS is present.
- * Input:
- * rdi destination
- * rcx count
- *
- * Output:
- * rcx: uncleared bytes or 0 if successful.
- *
- */
-SYM_FUNC_START(clear_user_erms)
-       # call the original thing for less than a cacheline
-       cmp $64, %rcx
-       jb clear_user_original
-
-.Lerms_bytes:
-       rep stosb
-
-.Lerms_exit:
-       xorl %eax,%eax
+       .p2align 4
+.Lunrolled:
+10:    movq %rax,(%rdi)
+11:    movq %rax,8(%rdi)
+12:    movq %rax,16(%rdi)
+13:    movq %rax,24(%rdi)
+14:    movq %rax,32(%rdi)
+15:    movq %rax,40(%rdi)
+16:    movq %rax,48(%rdi)
+17:    movq %rax,56(%rdi)
+       addq $64,%rdi
+       subq $64,%rcx
+       cmpq $64,%rcx
+       jae .Lunrolled
+       cmpl $8,%ecx
+       jae .Lword
+       testl %ecx,%ecx
+       jne .Lclear_user_tail
        RET
 
-       _ASM_EXTABLE_UA(.Lerms_bytes, .Lerms_exit)
-SYM_FUNC_END(clear_user_erms)
-EXPORT_SYMBOL(clear_user_erms)
+       /*
+        * If we take an exception on any of the
+        * word stores, we know that %rcx isn't zero,
+        * so we can just go to the tail clearing to
+        * get the exact count.
+        *
+        * The unrolled case might end up clearing
+        * some bytes twice. Don't care.
+        *
+        * We could use the value in %rdi to avoid
+        * a second fault on the exact count case,
+        * but do we really care? No.
+        *
+        * Finally, we could try to align %rdi at the
+        * top of the unrolling. But unaligned stores
+        * just aren't that common or expensive.
+        */
+       _ASM_EXTABLE_UA( 1b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(10b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(11b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(12b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(13b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(14b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(15b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(16b, .Lclear_user_tail)
+       _ASM_EXTABLE_UA(17b, .Lclear_user_tail)
+SYM_FUNC_END(rep_stos_alternative)
+EXPORT_SYMBOL(rep_stos_alternative)
index 9dec1b38a98fcdd756b170fdd1b3a3243640c6c3..4fc5c2de2de467c689ddf91eb1684eeb00aeb9db 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/current.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/cpufeatures.h>
-#include <asm/alternative.h>
 #include <asm/asm.h>
-#include <asm/smap.h>
 #include <asm/export.h>
-#include <asm/trapnr.h>
-
-.macro ALIGN_DESTINATION
-       /* check for bad alignment of destination */
-       movl %edi,%ecx
-       andl $7,%ecx
-       jz 102f                         /* already aligned */
-       subl $8,%ecx
-       negl %ecx
-       subl %ecx,%edx
-100:   movb (%rsi),%al
-101:   movb %al,(%rdi)
-       incq %rsi
-       incq %rdi
-       decl %ecx
-       jnz 100b
-102:
-
-       _ASM_EXTABLE_CPY(100b, .Lcopy_user_handle_align)
-       _ASM_EXTABLE_CPY(101b, .Lcopy_user_handle_align)
-.endm
 
 /*
- * copy_user_generic_unrolled - memory copy with exception handling.
- * This version is for CPUs like P4 that don't have efficient micro
- * code for rep movsq
- *
- * Input:
- * rdi destination
- * rsi source
- * rdx count
- *
- * Output:
- * eax uncopied bytes or 0 if successful.
- */
-SYM_FUNC_START(copy_user_generic_unrolled)
-       ASM_STAC
-       cmpl $8,%edx
-       jb .Lcopy_user_short_string_bytes
-       ALIGN_DESTINATION
-       movl %edx,%ecx
-       andl $63,%edx
-       shrl $6,%ecx
-       jz copy_user_short_string
-1:     movq (%rsi),%r8
-2:     movq 1*8(%rsi),%r9
-3:     movq 2*8(%rsi),%r10
-4:     movq 3*8(%rsi),%r11
-5:     movq %r8,(%rdi)
-6:     movq %r9,1*8(%rdi)
-7:     movq %r10,2*8(%rdi)
-8:     movq %r11,3*8(%rdi)
-9:     movq 4*8(%rsi),%r8
-10:    movq 5*8(%rsi),%r9
-11:    movq 6*8(%rsi),%r10
-12:    movq 7*8(%rsi),%r11
-13:    movq %r8,4*8(%rdi)
-14:    movq %r9,5*8(%rdi)
-15:    movq %r10,6*8(%rdi)
-16:    movq %r11,7*8(%rdi)
-       leaq 64(%rsi),%rsi
-       leaq 64(%rdi),%rdi
-       decl %ecx
-       jnz 1b
-       jmp copy_user_short_string
-
-30:    shll $6,%ecx
-       addl %ecx,%edx
-       jmp .Lcopy_user_handle_tail
-
-       _ASM_EXTABLE_CPY(1b, 30b)
-       _ASM_EXTABLE_CPY(2b, 30b)
-       _ASM_EXTABLE_CPY(3b, 30b)
-       _ASM_EXTABLE_CPY(4b, 30b)
-       _ASM_EXTABLE_CPY(5b, 30b)
-       _ASM_EXTABLE_CPY(6b, 30b)
-       _ASM_EXTABLE_CPY(7b, 30b)
-       _ASM_EXTABLE_CPY(8b, 30b)
-       _ASM_EXTABLE_CPY(9b, 30b)
-       _ASM_EXTABLE_CPY(10b, 30b)
-       _ASM_EXTABLE_CPY(11b, 30b)
-       _ASM_EXTABLE_CPY(12b, 30b)
-       _ASM_EXTABLE_CPY(13b, 30b)
-       _ASM_EXTABLE_CPY(14b, 30b)
-       _ASM_EXTABLE_CPY(15b, 30b)
-       _ASM_EXTABLE_CPY(16b, 30b)
-SYM_FUNC_END(copy_user_generic_unrolled)
-EXPORT_SYMBOL(copy_user_generic_unrolled)
-
-/* Some CPUs run faster using the string copy instructions.
- * This is also a lot simpler. Use them when possible.
- *
- * Only 4GB of copy is supported. This shouldn't be a problem
- * because the kernel normally only writes from/to page sized chunks
- * even if user space passed a longer buffer.
- * And more would be dangerous because both Intel and AMD have
- * errata with rep movsq > 4GB. If someone feels the need to fix
- * this please consider this.
+ * rep_movs_alternative - memory copy with exception handling.
+ * This version is for CPUs that don't have FSRM (Fast Short Rep Movs)
  *
  * Input:
  * rdi destination
  * rsi source
- * rdx count
+ * rcx count
  *
  * Output:
- * eax uncopied bytes or 0 if successful.
- */
-SYM_FUNC_START(copy_user_generic_string)
-       ASM_STAC
-       cmpl $8,%edx
-       jb 2f           /* less than 8 bytes, go to byte copy loop */
-       ALIGN_DESTINATION
-       movl %edx,%ecx
-       shrl $3,%ecx
-       andl $7,%edx
-1:     rep movsq
-2:     movl %edx,%ecx
-3:     rep movsb
-       xorl %eax,%eax
-       ASM_CLAC
-       RET
-
-11:    leal (%rdx,%rcx,8),%ecx
-12:    movl %ecx,%edx          /* ecx is zerorest also */
-       jmp .Lcopy_user_handle_tail
-
-       _ASM_EXTABLE_CPY(1b, 11b)
-       _ASM_EXTABLE_CPY(3b, 12b)
-SYM_FUNC_END(copy_user_generic_string)
-EXPORT_SYMBOL(copy_user_generic_string)
-
-/*
- * Some CPUs are adding enhanced REP MOVSB/STOSB instructions.
- * It's recommended to use enhanced REP MOVSB/STOSB if it's enabled.
- *
- * Input:
- * rdi destination
- * rsi source
- * rdx count
+ * rcx uncopied bytes or 0 if successful.
  *
- * Output:
- * eax uncopied bytes or 0 if successful.
+ * NOTE! The calling convention is very intentionally the same as
+ * for 'rep movs', so that we can rewrite the function call with
+ * just a plain 'rep movs' on machines that have FSRM.  But to make
+ * it simpler for us, we can clobber rsi/rdi and rax/r8-r11 freely.
  */
-SYM_FUNC_START(copy_user_enhanced_fast_string)
-       ASM_STAC
-       /* CPUs without FSRM should avoid rep movsb for short copies */
-       ALTERNATIVE "cmpl $64, %edx; jb copy_user_short_string", "", X86_FEATURE_FSRM
-       movl %edx,%ecx
-1:     rep movsb
-       xorl %eax,%eax
-       ASM_CLAC
+SYM_FUNC_START(rep_movs_alternative)
+       cmpq $64,%rcx
+       jae .Lunrolled
+
+       cmp $8,%ecx
+       jae .Lword
+
+       testl %ecx,%ecx
+       je .Lexit
+
+.Lcopy_user_tail:
+0:     movb (%rsi),%al
+1:     movb %al,(%rdi)
+       inc %rdi
+       inc %rsi
+       dec %rcx
+       jne .Lcopy_user_tail
+.Lexit:
        RET
 
-12:    movl %ecx,%edx          /* ecx is zerorest also */
-       jmp .Lcopy_user_handle_tail
-
-       _ASM_EXTABLE_CPY(1b, 12b)
-SYM_FUNC_END(copy_user_enhanced_fast_string)
-EXPORT_SYMBOL(copy_user_enhanced_fast_string)
-
-/*
- * Try to copy last bytes and clear the rest if needed.
- * Since protection fault in copy_from/to_user is not a normal situation,
- * it is not necessary to optimize tail handling.
- * Don't try to copy the tail if machine check happened
- *
- * Input:
- * eax trap number written by ex_handler_copy()
- * rdi destination
- * rsi source
- * rdx count
- *
- * Output:
- * eax uncopied bytes or 0 if successful.
- */
-SYM_CODE_START_LOCAL(.Lcopy_user_handle_tail)
-       cmp $X86_TRAP_MC,%eax
-       je 3f
-
-       movl %edx,%ecx
-1:     rep movsb
-2:     mov %ecx,%eax
-       ASM_CLAC
+       _ASM_EXTABLE_UA( 0b, .Lexit)
+       _ASM_EXTABLE_UA( 1b, .Lexit)
+
+       .p2align 4
+.Lword:
+2:     movq (%rsi),%rax
+3:     movq %rax,(%rdi)
+       addq $8,%rsi
+       addq $8,%rdi
+       sub $8,%ecx
+       je .Lexit
+       cmp $8,%ecx
+       jae .Lword
+       jmp .Lcopy_user_tail
+
+       _ASM_EXTABLE_UA( 2b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA( 3b, .Lcopy_user_tail)
+
+       .p2align 4
+.Lunrolled:
+10:    movq (%rsi),%r8
+11:    movq 8(%rsi),%r9
+12:    movq 16(%rsi),%r10
+13:    movq 24(%rsi),%r11
+14:    movq %r8,(%rdi)
+15:    movq %r9,8(%rdi)
+16:    movq %r10,16(%rdi)
+17:    movq %r11,24(%rdi)
+20:    movq 32(%rsi),%r8
+21:    movq 40(%rsi),%r9
+22:    movq 48(%rsi),%r10
+23:    movq 56(%rsi),%r11
+24:    movq %r8,32(%rdi)
+25:    movq %r9,40(%rdi)
+26:    movq %r10,48(%rdi)
+27:    movq %r11,56(%rdi)
+       addq $64,%rsi
+       addq $64,%rdi
+       subq $64,%rcx
+       cmpq $64,%rcx
+       jae .Lunrolled
+       cmpl $8,%ecx
+       jae .Lword
+       testl %ecx,%ecx
+       jne .Lcopy_user_tail
        RET
 
-3:
-       movl %edx,%eax
-       ASM_CLAC
-       RET
-
-       _ASM_EXTABLE_CPY(1b, 2b)
-
-.Lcopy_user_handle_align:
-       addl %ecx,%edx                  /* ecx is zerorest also */
-       jmp .Lcopy_user_handle_tail
-
-SYM_CODE_END(.Lcopy_user_handle_tail)
-
-/*
- * Finish memcpy of less than 64 bytes.  #AC should already be set.
- *
- * Input:
- * rdi destination
- * rsi source
- * rdx count (< 64)
- *
- * Output:
- * eax uncopied bytes or 0 if successful.
- */
-SYM_CODE_START_LOCAL(copy_user_short_string)
-       movl %edx,%ecx
-       andl $7,%edx
-       shrl $3,%ecx
-       jz .Lcopy_user_short_string_bytes
-18:    movq (%rsi),%r8
-19:    movq %r8,(%rdi)
-       leaq 8(%rsi),%rsi
-       leaq 8(%rdi),%rdi
-       decl %ecx
-       jnz 18b
-.Lcopy_user_short_string_bytes:
-       andl %edx,%edx
-       jz 23f
-       movl %edx,%ecx
-21:    movb (%rsi),%al
-22:    movb %al,(%rdi)
-       incq %rsi
-       incq %rdi
-       decl %ecx
-       jnz 21b
-23:    xor %eax,%eax
-       ASM_CLAC
-       RET
-
-40:    leal (%rdx,%rcx,8),%edx
-       jmp 60f
-50:    movl %ecx,%edx          /* ecx is zerorest also */
-60:    jmp .Lcopy_user_handle_tail
-
-       _ASM_EXTABLE_CPY(18b, 40b)
-       _ASM_EXTABLE_CPY(19b, 40b)
-       _ASM_EXTABLE_CPY(21b, 50b)
-       _ASM_EXTABLE_CPY(22b, 50b)
-SYM_CODE_END(copy_user_short_string)
-
-/*
- * copy_user_nocache - Uncached memory copy with exception handling
- * This will force destination out of cache for more performance.
- *
- * Note: Cached memory copy is used when destination or size is not
- * naturally aligned. That is:
- *  - Require 8-byte alignment when size is 8 bytes or larger.
- *  - Require 4-byte alignment when size is 4 bytes.
- */
-SYM_FUNC_START(__copy_user_nocache)
-       ASM_STAC
-
-       /* If size is less than 8 bytes, go to 4-byte copy */
-       cmpl $8,%edx
-       jb .L_4b_nocache_copy_entry
-
-       /* If destination is not 8-byte aligned, "cache" copy to align it */
-       ALIGN_DESTINATION
-
-       /* Set 4x8-byte copy count and remainder */
-       movl %edx,%ecx
-       andl $63,%edx
-       shrl $6,%ecx
-       jz .L_8b_nocache_copy_entry     /* jump if count is 0 */
-
-       /* Perform 4x8-byte nocache loop-copy */
-.L_4x8b_nocache_copy_loop:
-1:     movq (%rsi),%r8
-2:     movq 1*8(%rsi),%r9
-3:     movq 2*8(%rsi),%r10
-4:     movq 3*8(%rsi),%r11
-5:     movnti %r8,(%rdi)
-6:     movnti %r9,1*8(%rdi)
-7:     movnti %r10,2*8(%rdi)
-8:     movnti %r11,3*8(%rdi)
-9:     movq 4*8(%rsi),%r8
-10:    movq 5*8(%rsi),%r9
-11:    movq 6*8(%rsi),%r10
-12:    movq 7*8(%rsi),%r11
-13:    movnti %r8,4*8(%rdi)
-14:    movnti %r9,5*8(%rdi)
-15:    movnti %r10,6*8(%rdi)
-16:    movnti %r11,7*8(%rdi)
-       leaq 64(%rsi),%rsi
-       leaq 64(%rdi),%rdi
-       decl %ecx
-       jnz .L_4x8b_nocache_copy_loop
-
-       /* Set 8-byte copy count and remainder */
-.L_8b_nocache_copy_entry:
-       movl %edx,%ecx
-       andl $7,%edx
-       shrl $3,%ecx
-       jz .L_4b_nocache_copy_entry     /* jump if count is 0 */
-
-       /* Perform 8-byte nocache loop-copy */
-.L_8b_nocache_copy_loop:
-20:    movq (%rsi),%r8
-21:    movnti %r8,(%rdi)
-       leaq 8(%rsi),%rsi
-       leaq 8(%rdi),%rdi
-       decl %ecx
-       jnz .L_8b_nocache_copy_loop
-
-       /* If no byte left, we're done */
-.L_4b_nocache_copy_entry:
-       andl %edx,%edx
-       jz .L_finish_copy
-
-       /* If destination is not 4-byte aligned, go to byte copy: */
-       movl %edi,%ecx
-       andl $3,%ecx
-       jnz .L_1b_cache_copy_entry
-
-       /* Set 4-byte copy count (1 or 0) and remainder */
-       movl %edx,%ecx
-       andl $3,%edx
-       shrl $2,%ecx
-       jz .L_1b_cache_copy_entry       /* jump if count is 0 */
-
-       /* Perform 4-byte nocache copy: */
-30:    movl (%rsi),%r8d
-31:    movnti %r8d,(%rdi)
-       leaq 4(%rsi),%rsi
-       leaq 4(%rdi),%rdi
-
-       /* If no bytes left, we're done: */
-       andl %edx,%edx
-       jz .L_finish_copy
-
-       /* Perform byte "cache" loop-copy for the remainder */
-.L_1b_cache_copy_entry:
-       movl %edx,%ecx
-.L_1b_cache_copy_loop:
-40:    movb (%rsi),%al
-41:    movb %al,(%rdi)
-       incq %rsi
-       incq %rdi
-       decl %ecx
-       jnz .L_1b_cache_copy_loop
-
-       /* Finished copying; fence the prior stores */
-.L_finish_copy:
-       xorl %eax,%eax
-       ASM_CLAC
-       sfence
-       RET
-
-.L_fixup_4x8b_copy:
-       shll $6,%ecx
-       addl %ecx,%edx
-       jmp .L_fixup_handle_tail
-.L_fixup_8b_copy:
-       lea (%rdx,%rcx,8),%rdx
-       jmp .L_fixup_handle_tail
-.L_fixup_4b_copy:
-       lea (%rdx,%rcx,4),%rdx
-       jmp .L_fixup_handle_tail
-.L_fixup_1b_copy:
-       movl %ecx,%edx
-.L_fixup_handle_tail:
-       sfence
-       jmp .Lcopy_user_handle_tail
-
-       _ASM_EXTABLE_CPY(1b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(2b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(3b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(4b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(5b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(6b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(7b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(8b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(9b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(10b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(11b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(12b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(13b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(14b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(15b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(16b, .L_fixup_4x8b_copy)
-       _ASM_EXTABLE_CPY(20b, .L_fixup_8b_copy)
-       _ASM_EXTABLE_CPY(21b, .L_fixup_8b_copy)
-       _ASM_EXTABLE_CPY(30b, .L_fixup_4b_copy)
-       _ASM_EXTABLE_CPY(31b, .L_fixup_4b_copy)
-       _ASM_EXTABLE_CPY(40b, .L_fixup_1b_copy)
-       _ASM_EXTABLE_CPY(41b, .L_fixup_1b_copy)
-SYM_FUNC_END(__copy_user_nocache)
-EXPORT_SYMBOL(__copy_user_nocache)
+       _ASM_EXTABLE_UA(10b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(11b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(12b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(13b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(14b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(15b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(16b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(17b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(20b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(21b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(22b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(23b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(24b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(25b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(26b, .Lcopy_user_tail)
+       _ASM_EXTABLE_UA(27b, .Lcopy_user_tail)
+SYM_FUNC_END(rep_movs_alternative)
+EXPORT_SYMBOL(rep_movs_alternative)
diff --git a/arch/x86/lib/copy_user_uncached_64.S b/arch/x86/lib/copy_user_uncached_64.S
new file mode 100644 (file)
index 0000000..5c5f38d
--- /dev/null
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright 2023 Linus Torvalds <torvalds@linux-foundation.org>
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+#include <asm/export.h>
+
+/*
+ * copy_user_nocache - Uncached memory copy with exception handling
+ *
+ * This copies from user space into kernel space, but the kernel
+ * space accesses can take a machine check exception, so they too
+ * need exception handling.
+ *
+ * Note: only 32-bit and 64-bit stores have non-temporal versions,
+ * and we only use aligned versions. Any unaligned parts at the
+ * start or end of the copy will be done using normal cached stores.
+ *
+ * Input:
+ * rdi destination
+ * rsi source
+ * edx count
+ *
+ * Output:
+ * rax uncopied bytes or 0 if successful.
+ */
+SYM_FUNC_START(__copy_user_nocache)
+       /* If destination is not 7-byte aligned, we'll have to align it */
+       testb $7,%dil
+       jne .Lalign
+
+.Lis_aligned:
+       cmp $64,%edx
+       jb .Lquadwords
+
+       .p2align 4,0x90
+.Lunrolled:
+10:    movq (%rsi),%r8
+11:    movq 8(%rsi),%r9
+12:    movq 16(%rsi),%r10
+13:    movq 24(%rsi),%r11
+20:    movnti %r8,(%rdi)
+21:    movnti %r9,8(%rdi)
+22:    movnti %r10,16(%rdi)
+23:    movnti %r11,24(%rdi)
+30:    movq 32(%rsi),%r8
+31:    movq 40(%rsi),%r9
+32:    movq 48(%rsi),%r10
+33:    movq 56(%rsi),%r11
+40:    movnti %r8,32(%rdi)
+41:    movnti %r9,40(%rdi)
+42:    movnti %r10,48(%rdi)
+43:    movnti %r11,56(%rdi)
+
+       addq $64,%rsi
+       addq $64,%rdi
+       sub $64,%edx
+       cmp $64,%edx
+       jae .Lunrolled
+
+/*
+ * First set of user mode loads have been done
+ * without any stores, so if they fail, we can
+ * just try the non-unrolled loop.
+ */
+_ASM_EXTABLE_UA(10b, .Lquadwords)
+_ASM_EXTABLE_UA(11b, .Lquadwords)
+_ASM_EXTABLE_UA(12b, .Lquadwords)
+_ASM_EXTABLE_UA(13b, .Lquadwords)
+
+/*
+ * The second set of user mode loads have been
+ * done with 32 bytes stored to the destination,
+ * so we need to take that into account before
+ * falling back to the unrolled loop.
+ */
+_ASM_EXTABLE_UA(30b, .Lfixup32)
+_ASM_EXTABLE_UA(31b, .Lfixup32)
+_ASM_EXTABLE_UA(32b, .Lfixup32)
+_ASM_EXTABLE_UA(33b, .Lfixup32)
+
+/*
+ * An exception on a write means that we're
+ * done, but we need to update the count
+ * depending on where in the unrolled loop
+ * we were.
+ */
+_ASM_EXTABLE_UA(20b, .Ldone0)
+_ASM_EXTABLE_UA(21b, .Ldone8)
+_ASM_EXTABLE_UA(22b, .Ldone16)
+_ASM_EXTABLE_UA(23b, .Ldone24)
+_ASM_EXTABLE_UA(40b, .Ldone32)
+_ASM_EXTABLE_UA(41b, .Ldone40)
+_ASM_EXTABLE_UA(42b, .Ldone48)
+_ASM_EXTABLE_UA(43b, .Ldone56)
+
+.Lquadwords:
+       cmp $8,%edx
+       jb .Llong
+50:    movq (%rsi),%rax
+51:    movnti %rax,(%rdi)
+       addq $8,%rsi
+       addq $8,%rdi
+       sub $8,%edx
+       jmp .Lquadwords
+
+/*
+ * If we fail on the last full quadword, we will
+ * not try to do any byte-wise cached accesses.
+ * We will try to do one more 4-byte uncached
+ * one, though.
+ */
+_ASM_EXTABLE_UA(50b, .Llast4)
+_ASM_EXTABLE_UA(51b, .Ldone0)
+
+.Llong:
+       test $4,%dl
+       je .Lword
+60:    movl (%rsi),%eax
+61:    movnti %eax,(%rdi)
+       addq $4,%rsi
+       addq $4,%rdi
+       sub $4,%edx
+.Lword:
+       sfence
+       test $2,%dl
+       je .Lbyte
+70:    movw (%rsi),%ax
+71:    movw %ax,(%rdi)
+       addq $2,%rsi
+       addq $2,%rdi
+       sub $2,%edx
+.Lbyte:
+       test $1,%dl
+       je .Ldone
+80:    movb (%rsi),%al
+81:    movb %al,(%rdi)
+       dec %edx
+.Ldone:
+       mov %edx,%eax
+       RET
+
+/*
+ * If we fail on the last four bytes, we won't
+ * bother with any fixups. It's dead, Jim. Note
+ * that there's no need for 'sfence' for any
+ * of this, since the exception will have been
+ * serializing.
+ */
+_ASM_EXTABLE_UA(60b, .Ldone)
+_ASM_EXTABLE_UA(61b, .Ldone)
+_ASM_EXTABLE_UA(70b, .Ldone)
+_ASM_EXTABLE_UA(71b, .Ldone)
+_ASM_EXTABLE_UA(80b, .Ldone)
+_ASM_EXTABLE_UA(81b, .Ldone)
+
+/*
+ * This is the "head needs aliging" case when
+ * the destination isn't 8-byte aligned. The
+ * 4-byte case can be done uncached, but any
+ * smaller alignment is done with regular stores.
+ */
+.Lalign:
+       test $1,%dil
+       je .Lalign_word
+       test %edx,%edx
+       je .Ldone
+90:    movb (%rsi),%al
+91:    movb %al,(%rdi)
+       inc %rsi
+       inc %rdi
+       dec %edx
+.Lalign_word:
+       test $2,%dil
+       je .Lalign_long
+       cmp $2,%edx
+       jb .Lbyte
+92:    movw (%rsi),%ax
+93:    movw %ax,(%rdi)
+       addq $2,%rsi
+       addq $2,%rdi
+       sub $2,%edx
+.Lalign_long:
+       test $4,%dil
+       je .Lis_aligned
+       cmp $4,%edx
+       jb .Lword
+94:    movl (%rsi),%eax
+95:    movnti %eax,(%rdi)
+       addq $4,%rsi
+       addq $4,%rdi
+       sub $4,%edx
+       jmp .Lis_aligned
+
+/*
+ * If we fail on the initial alignment accesses,
+ * we're all done. Again, no point in trying to
+ * do byte-by-byte probing if the 4-byte load
+ * fails - we're not doing any uncached accesses
+ * any more.
+ */
+_ASM_EXTABLE_UA(90b, .Ldone)
+_ASM_EXTABLE_UA(91b, .Ldone)
+_ASM_EXTABLE_UA(92b, .Ldone)
+_ASM_EXTABLE_UA(93b, .Ldone)
+_ASM_EXTABLE_UA(94b, .Ldone)
+_ASM_EXTABLE_UA(95b, .Ldone)
+
+/*
+ * Exception table fixups for faults in the middle
+ */
+.Ldone56: sub $8,%edx
+.Ldone48: sub $8,%edx
+.Ldone40: sub $8,%edx
+.Ldone32: sub $8,%edx
+.Ldone24: sub $8,%edx
+.Ldone16: sub $8,%edx
+.Ldone8: sub $8,%edx
+.Ldone0:
+       mov %edx,%eax
+       RET
+
+.Lfixup32:
+       addq $32,%rsi
+       addq $32,%rdi
+       sub $32,%edx
+       jmp .Lquadwords
+
+.Llast4:
+52:    movl (%rsi),%eax
+53:    movnti %eax,(%rdi)
+       sfence
+       sub $4,%edx
+       mov %edx,%eax
+       RET
+_ASM_EXTABLE_UA(52b, .Ldone0)
+_ASM_EXTABLE_UA(53b, .Ldone0)
+
+SYM_FUNC_END(__copy_user_nocache)
+EXPORT_SYMBOL(__copy_user_nocache)
index a64017602010ea8a4b61538f25918c6e58da7887..8f95fb267caa7c91d066002838198106ef052199 100644 (file)
 
 .section .noinstr.text, "ax"
 
-/*
- * We build a jump to memcpy_orig by default which gets NOPped out on
- * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
- * have the enhanced REP MOVSB/STOSB feature (ERMS), change those NOPs
- * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
- */
-
 /*
  * memcpy - Copy a memory block.
  *
  *
  * Output:
  * rax original destination
+ *
+ * The FSRM alternative should be done inline (avoiding the call and
+ * the disgusting return handling), but that would require some help
+ * from the compiler for better calling conventions.
+ *
+ * The 'rep movsb' itself is small enough to replace the call, but the
+ * two register moves blow up the code. And one of them is "needed"
+ * only for the return value that is the same as the source input,
+ * which the compiler could/should do much better anyway.
  */
 SYM_TYPED_FUNC_START(__memcpy)
-       ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
-                     "jmp memcpy_erms", X86_FEATURE_ERMS
+       ALTERNATIVE "jmp memcpy_orig", "", X86_FEATURE_FSRM
 
        movq %rdi, %rax
        movq %rdx, %rcx
-       shrq $3, %rcx
-       andl $7, %edx
-       rep movsq
-       movl %edx, %ecx
        rep movsb
        RET
 SYM_FUNC_END(__memcpy)
@@ -46,17 +43,6 @@ EXPORT_SYMBOL(__memcpy)
 SYM_FUNC_ALIAS(memcpy, __memcpy)
 EXPORT_SYMBOL(memcpy)
 
-/*
- * memcpy_erms() - enhanced fast string memcpy. This is faster and
- * simpler than memcpy. Use memcpy_erms when possible.
- */
-SYM_FUNC_START_LOCAL(memcpy_erms)
-       movq %rdi, %rax
-       movq %rdx, %rcx
-       rep movsb
-       RET
-SYM_FUNC_END(memcpy_erms)
-
 SYM_FUNC_START_LOCAL(memcpy_orig)
        movq %rdi, %rax
 
index 6143b1a6fa2caa0d5977d22c3f1c23456ff6d3bf..7c59a704c4584bf7ef3e6a50f2021c31e6f15029 100644 (file)
  * rdx   count (bytes)
  *
  * rax   original destination
+ *
+ * The FSRS alternative should be done inline (avoiding the call and
+ * the disgusting return handling), but that would require some help
+ * from the compiler for better calling conventions.
+ *
+ * The 'rep stosb' itself is small enough to replace the call, but all
+ * the register moves blow up the code. And two of them are "needed"
+ * only for the return value that is the same as the source input,
+ * which the compiler could/should do much better anyway.
  */
 SYM_FUNC_START(__memset)
-       /*
-        * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
-        * to use it when possible. If not available, use fast string instructions.
-        *
-        * Otherwise, use original memset function.
-        */
-       ALTERNATIVE_2 "jmp memset_orig", "", X86_FEATURE_REP_GOOD, \
-                     "jmp memset_erms", X86_FEATURE_ERMS
+       ALTERNATIVE "jmp memset_orig", "", X86_FEATURE_FSRS
 
        movq %rdi,%r9
+       movb %sil,%al
        movq %rdx,%rcx
-       andl $7,%edx
-       shrq $3,%rcx
-       /* expand byte value  */
-       movzbl %sil,%esi
-       movabs $0x0101010101010101,%rax
-       imulq %rsi,%rax
-       rep stosq
-       movl %edx,%ecx
        rep stosb
        movq %r9,%rax
        RET
@@ -48,26 +43,6 @@ EXPORT_SYMBOL(__memset)
 SYM_FUNC_ALIAS(memset, __memset)
 EXPORT_SYMBOL(memset)
 
-/*
- * ISO C memset - set a memory block to a byte value. This function uses
- * enhanced rep stosb to override the fast string function.
- * The code is simpler and shorter than the fast string function as well.
- *
- * rdi   destination
- * rsi   value (char)
- * rdx   count (bytes)
- *
- * rax   original destination
- */
-SYM_FUNC_START_LOCAL(memset_erms)
-       movq %rdi,%r9
-       movb %sil,%al
-       movq %rdx,%rcx
-       rep stosb
-       movq %r9,%rax
-       RET
-SYM_FUNC_END(memset_erms)
-
 SYM_FUNC_START_LOCAL(memset_orig)
        movq %rdi,%r10
 
index 6c1f8ac5e7214496d3ac953d6c64866574eefbba..c3a5bbc0b41ef4c82163a33cbc5171968c8e4f3b 100644 (file)
@@ -45,7 +45,11 @@ EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
 long __copy_user_flushcache(void *dst, const void __user *src, unsigned size)
 {
        unsigned long flushed, dest = (unsigned long) dst;
-       long rc = __copy_user_nocache(dst, src, size, 0);
+       long rc;
+
+       stac();
+       rc = __copy_user_nocache(dst, src, size);
+       clac();
 
        /*
         * __copy_user_nocache() uses non-temporal stores for the bulk
index 7316a822425992efec14fb5598d42f32eac43f6c..e91500a80963945c1558707404703cd69a045bb4 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/fixmap.h>
 #include <asm/desc.h>
 #include <asm/kasan.h>
+#include <asm/setup.h>
 
 static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage);
 
@@ -29,6 +30,12 @@ static __init void init_cea_offsets(void)
        unsigned int max_cea;
        unsigned int i, j;
 
+       if (!kaslr_enabled()) {
+               for_each_possible_cpu(i)
+                       per_cpu(_cea_offset, i) = i;
+               return;
+       }
+
        max_cea = (CPU_ENTRY_AREA_MAP_SIZE - PAGE_SIZE) / CPU_ENTRY_AREA_SIZE;
 
        /* O(sodding terrible) */
index cb258f58fdc87935500c28053eef87ce1b02e206..cbc53da4c1b42544fdcbc489938d83ce72bd2c67 100644 (file)
@@ -806,7 +806,7 @@ void __init poking_init(void)
        BUG_ON(!poking_mm);
 
        /* Xen PV guests need the PGD to be pinned. */
-       paravirt_arch_dup_mmap(NULL, poking_mm);
+       paravirt_enter_mmap(poking_mm);
 
        /*
         * Randomize the poking address, but make sure that the following page
index 6453fbaedb081d204d49985dbbc73cb867ea736c..aa7d279321ea0cca935374b16b96fa349cdaacd2 100644 (file)
@@ -116,6 +116,11 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des
        if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
                return;
 
+       if (x86_platform.hyper.is_private_mmio(addr)) {
+               desc->flags |= IORES_MAP_ENCRYPTED;
+               return;
+       }
+
        if (!IS_ENABLED(CONFIG_EFI))
                return;
 
index 9c4d8dbcb129697a3ea47aa1f8184add79909892..e0b51c09109f66ea6d04300e5c9afc3e98a7ff95 100644 (file)
@@ -513,10 +513,14 @@ void __init mem_encrypt_free_decrypted_mem(void)
        npages = (vaddr_end - vaddr) >> PAGE_SHIFT;
 
        /*
-        * The unused memory range was mapped decrypted, change the encryption
-        * attribute from decrypted to encrypted before freeing it.
+        * If the unused memory range was mapped decrypted, change the encryption
+        * attribute from decrypted to encrypted before freeing it. Base the
+        * re-encryption on the same condition used for the decryption in
+        * sme_postprocess_startup(). Higher level abstractions, such as
+        * CC_ATTR_MEM_ENCRYPT, aren't necessarily equivalent in a Hyper-V VM
+        * using vTOM, where sme_me_mask is always zero.
         */
-       if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) {
+       if (sme_me_mask) {
                r = set_memory_encrypted(vaddr, npages);
                if (r) {
                        pr_warn("failed to free unused decrypted pages\n");
index 88cccd65029dba414912656310c3e72313a4aa4b..c6efcf559d8821261cb1724bf45275101a351238 100644 (file)
@@ -600,7 +600,8 @@ void __init sme_enable(struct boot_params *bp)
        cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
                                     ((u64)bp->ext_cmd_line_ptr << 32));
 
-       cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
+       if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
+               return;
 
        if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
                sme_me_mask = me_mask;
index 356758b7d4b4766bef29dc899d6505f85b40157d..7159cf7876130abde0acadd3c34e0a1b86eb41e1 100644 (file)
@@ -234,7 +234,7 @@ within_inclusive(unsigned long addr, unsigned long start, unsigned long end)
  * take full advantage of the the limited (s32) immediate addressing range (2G)
  * of x86_64.
  *
- * See Documentation/x86/x86_64/mm.rst for more detail.
+ * See Documentation/arch/x86/x86_64/mm.rst for more detail.
  */
 
 static inline unsigned long highmap_start_pfn(void)
@@ -2175,9 +2175,6 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc)
 
 static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)
 {
-       if (hv_is_isolation_supported())
-               return hv_set_mem_host_visibility(addr, numpages, !enc);
-
        if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
                return __set_memory_enc_pgtable(addr, numpages, enc);
 
index 92d73ccede70d6c6fba85fff37170aba8df963e6..16c5292d227d2fd8f87d966fec5a2e9c4b41d8f8 100644 (file)
@@ -925,7 +925,7 @@ void flush_tlb_multi(const struct cpumask *cpumask,
 }
 
 /*
- * See Documentation/x86/tlb.rst for details.  We choose 33
+ * See Documentation/arch/x86/tlb.rst for details.  We choose 33
  * because it is large enough to cover the vast majority (at
  * least 95%) of allocations, and is small enough that we are
  * confident it will not cause too much overhead.  Each single
index 615a76d70019470b286d90fa91079836d46ea0ce..bf5161dcf89e7ebf9c454456252a856c8aa9bfab 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/dmi.h>
 #include <linux/pci.h>
 #include <linux/vgaarb.h>
+#include <asm/amd_nb.h>
 #include <asm/hpet.h>
 #include <asm/pci_x86.h>
 
@@ -824,3 +825,23 @@ static void rs690_fix_64bit_dma(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7910, rs690_fix_64bit_dma);
 
 #endif
+
+#ifdef CONFIG_AMD_NB
+
+#define AMD_15B8_RCC_DEV2_EPF0_STRAP2                                  0x10136008
+#define AMD_15B8_RCC_DEV2_EPF0_STRAP2_NO_SOFT_RESET_DEV2_F0_MASK       0x00000080L
+
+static void quirk_clear_strap_no_soft_reset_dev2_f0(struct pci_dev *dev)
+{
+       u32 data;
+
+       if (!amd_smn_read(0, AMD_15B8_RCC_DEV2_EPF0_STRAP2, &data)) {
+               data &= ~AMD_15B8_RCC_DEV2_EPF0_STRAP2_NO_SOFT_RESET_DEV2_F0_MASK;
+               if (amd_smn_write(0, AMD_15B8_RCC_DEV2_EPF0_STRAP2, data))
+                       pci_err(dev, "Failed to write data 0x%x\n", data);
+       } else {
+               pci_err(dev, "Failed to read data\n");
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15b8, quirk_clear_strap_no_soft_reset_dev2_f0);
+#endif
index ed0442e354344fad84fce7fcc29c67934828a9f9..00a92cb2c81474782146b801f56a5d5880c8afb7 100644 (file)
@@ -86,7 +86,7 @@ static void __init init_pvh_bootparams(bool xen_guest)
        }
 
        /*
-        * See Documentation/x86/boot.rst.
+        * See Documentation/arch/x86/boot.rst.
         *
         * Version 2.12 supports Xen entry point but we will use default x86/PC
         * environment (i.e. hardware_subarch 0).
index 17f09dc263811ab18f949af7303189263763a0e5..82fec66d46d29ee7e41e392fd5f22c524ad4f727 100644 (file)
@@ -69,8 +69,7 @@ CFLAGS_sha256.o                       += $(PURGATORY_CFLAGS)
 CFLAGS_REMOVE_string.o         += $(PURGATORY_CFLAGS_REMOVE)
 CFLAGS_string.o                        += $(PURGATORY_CFLAGS)
 
-AFLAGS_REMOVE_setup-x86_$(BITS).o      += -Wa,-gdwarf-2
-AFLAGS_REMOVE_entry64.o                        += -Wa,-gdwarf-2
+asflags-remove-y               += $(foreach x, -g -gdwarf-4 -gdwarf-5, $(x) -Wa,$(x))
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
index 3c5b52fbe4a7f9f69b98487d78c066f94a4064c9..a9ec8c9f5c5dd04fd7747d943b791adf9d9b1025 100644 (file)
@@ -45,6 +45,6 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
 
 obj-$(CONFIG_XEN_DEBUG_FS)     += debugfs.o
 
-obj-$(CONFIG_XEN_PV_DOM0)      += vga.o
+obj-$(CONFIG_XEN_DOM0)         += vga.o
 
 obj-$(CONFIG_XEN_EFI)          += efi.o
index bb59cc6ddb2d425d4a782eb443969910e4508d83..093b78c8bbec0724e59947211b55e3eaae76cc8c 100644 (file)
@@ -1390,7 +1390,8 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
 
                x86_platform.set_legacy_features =
                                xen_dom0_set_legacy_features;
-               xen_init_vga(info, xen_start_info->console.dom0.info_size);
+               xen_init_vga(info, xen_start_info->console.dom0.info_size,
+                            &boot_params.screen_info);
                xen_start_info->console.domU.mfn = 0;
                xen_start_info->console.domU.evtchn = 0;
 
index bcae606bbc5cfd3145aefb4f3bf2c11b5e07afe0..ada3868c02c231d0f10863cabf71a076f003acb5 100644 (file)
@@ -43,6 +43,19 @@ void __init xen_pvh_init(struct boot_params *boot_params)
        x86_init.oem.banner = xen_banner;
 
        xen_efi_init(boot_params);
+
+       if (xen_initial_domain()) {
+               struct xen_platform_op op = {
+                       .cmd = XENPF_get_dom0_console,
+               };
+               int ret = HYPERVISOR_platform_op(&op);
+
+               if (ret > 0)
+                       xen_init_vga(&op.u.dom0_console,
+                                    min(ret * sizeof(char),
+                                        sizeof(op.u.dom0_console)),
+                                    &boot_params->screen_info);
+       }
 }
 
 void __init mem_map_via_hcall(struct boot_params *boot_params_p)
index ee29fb558f2e66368da45ce590582457638e465e..b3b8d289b9abfcac97604501adf9efccb04e0644 100644 (file)
@@ -885,14 +885,7 @@ void xen_mm_unpin_all(void)
        spin_unlock(&pgd_lock);
 }
 
-static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
-{
-       spin_lock(&next->page_table_lock);
-       xen_pgd_pin(next);
-       spin_unlock(&next->page_table_lock);
-}
-
-static void xen_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+static void xen_enter_mmap(struct mm_struct *mm)
 {
        spin_lock(&mm->page_table_lock);
        xen_pgd_pin(mm);
@@ -2153,8 +2146,7 @@ static const typeof(pv_ops) xen_mmu_ops __initconst = {
                .make_p4d = PV_CALLEE_SAVE(xen_make_p4d),
 #endif
 
-               .activate_mm = xen_activate_mm,
-               .dup_mmap = xen_dup_mmap,
+               .enter_mmap = xen_enter_mmap,
                .exit_mmap = xen_exit_mmap,
 
                .lazy_mode = {
index 1d597364b49dc3f9b7e8d259f1300181d4beab8e..b74ac2562cfbafddf4be10d53983515febbc7276 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/pvclock.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
+#include <asm/xen/cpuid.h>
 
 #include <xen/events.h>
 #include <xen/features.h>
@@ -503,11 +504,7 @@ static int __init xen_tsc_safe_clocksource(void)
        /* Leaf 4, sub-leaf 0 (0x40000x03) */
        cpuid_count(xen_cpuid_base() + 3, 0, &eax, &ebx, &ecx, &edx);
 
-       /* tsc_mode = no_emulate (2) */
-       if (ebx != 2)
-               return 0;
-
-       return 1;
+       return ebx == XEN_CPUID_TSC_MODE_NEVER_EMULATE;
 }
 
 static void __init xen_time_init(void)
index 14ea32e734d59315c5aa70e1ba484be3468a5550..d97adab8420f4c248011e87d7c43417ad3b2ca6e 100644 (file)
@@ -9,10 +9,9 @@
 
 #include "xen-ops.h"
 
-void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size)
+void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size,
+                        struct screen_info *screen_info)
 {
-       struct screen_info *screen_info = &boot_params.screen_info;
-
        /* This is drawn from a dump from vgacon:startup in
         * standard Linux. */
        screen_info->orig_video_mode = 3;
index e36ea4268bd2b7910e3c5ce35297853772c8e182..91f7a53519a78e78ddfa79c8712d8aeb8d2536f6 100644 (file)
@@ -49,7 +49,7 @@ SYM_CODE_START(startup_xen)
        ANNOTATE_NOENDBR
        cld
 
-       mov initial_stack(%rip), %rsp
+       leaq    (__end_init_task - PTREGS_SIZE)(%rip), %rsp
 
        /* Set up %gs.
         *
index 9a8bb972193d884e097adb1b58d71d7aa9d614e0..a10903785a33863c358de6d73ede4dd38a82be80 100644 (file)
@@ -108,11 +108,12 @@ static inline void xen_uninit_lock_cpu(int cpu)
 
 struct dom0_vga_console_info;
 
-#ifdef CONFIG_XEN_PV_DOM0
-void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
+#ifdef CONFIG_XEN_DOM0
+void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size,
+                        struct screen_info *);
 #else
 static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
-                                      size_t size)
+                                      size_t size, struct screen_info *si)
 {
 }
 #endif
index 9793b49fc641755099094331c2b5efde94720d8f..574795a20d6f66df74f0bd80af515c3847d8b969 100644 (file)
@@ -43,7 +43,7 @@
 #if XCHAL_HAVE_S32C1I && (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RC_2009_0)
 /*
  * We Have Atomic Operation Control (ATOMCTL) Register; Initialize it.
- * For details see Documentation/xtensa/atomctl.rst
+ * For details see Documentation/arch/xtensa/atomctl.rst
  */
 #if XCHAL_DCACHE_IS_COHERENT
        movi    a3, 0x25        /* For SMP/MX -- internal for writeback,
index cd98366a9b238841c7e4aaa021fb623d3eb52136..f0a7d1c2641e0c67f9a652f9c0626a85f7c43184 100644 (file)
@@ -539,7 +539,7 @@ static size_t kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
 
 void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
 {
-       size_t len;
+       size_t len, off = 0;
 
        if (!sp)
                sp = stack_pointer(task);
@@ -548,9 +548,17 @@ void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
                  kstack_depth_to_print * STACK_DUMP_ENTRY_SIZE);
 
        printk("%sStack:\n", loglvl);
-       print_hex_dump(loglvl, " ", DUMP_PREFIX_NONE,
-                      STACK_DUMP_LINE_SIZE, STACK_DUMP_ENTRY_SIZE,
-                      sp, len, false);
+       while (off < len) {
+               u8 line[STACK_DUMP_LINE_SIZE];
+               size_t line_len = len - off > STACK_DUMP_LINE_SIZE ?
+                       STACK_DUMP_LINE_SIZE : len - off;
+
+               __memcpy(line, (u8 *)sp + off, line_len);
+               print_hex_dump(loglvl, " ", DUMP_PREFIX_NONE,
+                              STACK_DUMP_LINE_SIZE, STACK_DUMP_ENTRY_SIZE,
+                              line, line_len, false);
+               off += STACK_DUMP_LINE_SIZE;
+       }
        show_trace(task, sp, loglvl);
 }
 
index 5d9d9c84d51657f1c6d9e5b25bd3cac406308d76..941b2dca70db7337122df8ad9cdd1fb30bdeed1a 100644 (file)
@@ -204,9 +204,6 @@ config BLK_INLINE_ENCRYPTION_FALLBACK
 
 source "block/partitions/Kconfig"
 
-config BLOCK_COMPAT
-       def_bool COMPAT
-
 config BLK_MQ_PCI
        def_bool PCI
 
index 9e5e0277a4d95a5e2f09b6cafaf4d8cd97ee5983..42926e6cb83c8e328cfd1e904989430737cc9326 100644 (file)
@@ -959,16 +959,11 @@ again:
        }
 }
 
-unsigned long bdev_start_io_acct(struct block_device *bdev,
-                                unsigned int sectors, enum req_op op,
+unsigned long bdev_start_io_acct(struct block_device *bdev, enum req_op op,
                                 unsigned long start_time)
 {
-       const int sgrp = op_stat_group(op);
-
        part_stat_lock();
        update_io_ticks(bdev, start_time, false);
-       part_stat_inc(bdev, ios[sgrp]);
-       part_stat_add(bdev, sectors[sgrp], sectors);
        part_stat_local_inc(bdev, in_flight[op_is_write(op)]);
        part_stat_unlock();
 
@@ -984,13 +979,12 @@ EXPORT_SYMBOL(bdev_start_io_acct);
  */
 unsigned long bio_start_io_acct(struct bio *bio)
 {
-       return bdev_start_io_acct(bio->bi_bdev, bio_sectors(bio),
-                                 bio_op(bio), jiffies);
+       return bdev_start_io_acct(bio->bi_bdev, bio_op(bio), jiffies);
 }
 EXPORT_SYMBOL_GPL(bio_start_io_acct);
 
 void bdev_end_io_acct(struct block_device *bdev, enum req_op op,
-                     unsigned long start_time)
+                     unsigned int sectors, unsigned long start_time)
 {
        const int sgrp = op_stat_group(op);
        unsigned long now = READ_ONCE(jiffies);
@@ -998,6 +992,8 @@ void bdev_end_io_acct(struct block_device *bdev, enum req_op op,
 
        part_stat_lock();
        update_io_ticks(bdev, now, true);
+       part_stat_inc(bdev, ios[sgrp]);
+       part_stat_add(bdev, sectors[sgrp], sectors);
        part_stat_add(bdev, nsecs[sgrp], jiffies_to_nsecs(duration));
        part_stat_local_dec(bdev, in_flight[op_is_write(op)]);
        part_stat_unlock();
@@ -1007,7 +1003,7 @@ EXPORT_SYMBOL(bdev_end_io_acct);
 void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time,
                              struct block_device *orig_bdev)
 {
-       bdev_end_io_acct(orig_bdev, bio_op(bio), start_time);
+       bdev_end_io_acct(orig_bdev, bio_op(bio), bio_sectors(bio), start_time);
 }
 EXPORT_SYMBOL_GPL(bio_end_io_acct_remapped);
 
index 9137d16cecdc38bb130a9592fa690a005ed72827..04c55f1c492eb144b332139478b5cc390dbbf075 100644 (file)
@@ -29,10 +29,11 @@ static struct bio_map_data *bio_alloc_map_data(struct iov_iter *data,
        bmd = kmalloc(struct_size(bmd, iov, data->nr_segs), gfp_mask);
        if (!bmd)
                return NULL;
-       memcpy(bmd->iov, data->iov, sizeof(struct iovec) * data->nr_segs);
        bmd->iter = *data;
-       if (iter_is_iovec(data))
-               bmd->iter.iov = bmd->iov;
+       if (iter_is_iovec(data)) {
+               memcpy(bmd->iov, iter_iov(data), sizeof(struct iovec) * data->nr_segs);
+               bmd->iter.__iov = bmd->iov;
+       }
        return bmd;
 }
 
index d0cb2ef18fe21dfa07fe4eec5c76bde6d6286f05..2831f78f86a033dbd0131a5da659741728d6a2c6 100644 (file)
@@ -1359,8 +1359,6 @@ bool blk_rq_is_poll(struct request *rq)
                return false;
        if (rq->mq_hctx->type != HCTX_TYPE_POLL)
                return false;
-       if (WARN_ON_ONCE(!rq->bio))
-               return false;
        return true;
 }
 EXPORT_SYMBOL_GPL(blk_rq_is_poll);
@@ -1368,7 +1366,7 @@ EXPORT_SYMBOL_GPL(blk_rq_is_poll);
 static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
 {
        do {
-               bio_poll(rq->bio, NULL, 0);
+               blk_mq_poll(rq->q, blk_rq_to_qc(rq), NULL, 0);
                cond_resched();
        } while (!completion_done(wait));
 }
@@ -2725,6 +2723,7 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
        struct blk_mq_hw_ctx *this_hctx = NULL;
        struct blk_mq_ctx *this_ctx = NULL;
        struct request *requeue_list = NULL;
+       struct request **requeue_lastp = &requeue_list;
        unsigned int depth = 0;
        LIST_HEAD(list);
 
@@ -2735,10 +2734,10 @@ static void blk_mq_dispatch_plug_list(struct blk_plug *plug, bool from_sched)
                        this_hctx = rq->mq_hctx;
                        this_ctx = rq->mq_ctx;
                } else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) {
-                       rq_list_add(&requeue_list, rq);
+                       rq_list_add_tail(&requeue_lastp, rq);
                        continue;
                }
-               list_add_tail(&rq->queuelist, &list);
+               list_add(&rq->queuelist, &list);
                depth++;
        } while (!rq_list_empty(plug->mq_list));
 
@@ -2879,16 +2878,15 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
 
        if (!plug)
                return NULL;
+       rq = rq_list_peek(&plug->cached_rq);
+       if (!rq || rq->q != q)
+               return NULL;
 
        if (blk_mq_attempt_bio_merge(q, *bio, nsegs)) {
                *bio = NULL;
                return NULL;
        }
 
-       rq = rq_list_peek(&plug->cached_rq);
-       if (!rq || rq->q != q)
-               return NULL;
-
        type = blk_mq_get_hctx_type((*bio)->bi_opf);
        hctx_type = rq->mq_hctx->type;
        if (type != hctx_type &&
index ef59fee62780d301d4756000e660464078a6eaa2..a7482d2cc82e721a4c1acf8a0884b22ae9e195ac 100644 (file)
@@ -378,12 +378,13 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
 #define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops)        \
 do {                                                           \
        if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) {          \
+               struct blk_mq_tag_set *__tag_set = (q)->tag_set; \
                int srcu_idx;                                   \
                                                                \
                might_sleep_if(check_sleep);                    \
-               srcu_idx = srcu_read_lock((q)->tag_set->srcu);  \
+               srcu_idx = srcu_read_lock(__tag_set->srcu);     \
                (dispatch_ops);                                 \
-               srcu_read_unlock((q)->tag_set->srcu, srcu_idx); \
+               srcu_read_unlock(__tag_set->srcu, srcu_idx);    \
        } else {                                                \
                rcu_read_lock();                                \
                (dispatch_ops);                                 \
index 02d9cfb9e077aaa5877aad060036191324d2e7a0..7f874737af6824fff5d58946993e20c9d51d136c 100644 (file)
@@ -368,7 +368,6 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
        if (disk->open_partitions)
                return -EBUSY;
 
-       set_bit(GD_NEED_PART_SCAN, &disk->state);
        /*
         * If the device is opened exclusively by current thread already, it's
         * safe to scan partitons, otherwise, use bd_prepare_to_claim() to
@@ -381,12 +380,19 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
                        return ret;
        }
 
+       set_bit(GD_NEED_PART_SCAN, &disk->state);
        bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~FMODE_EXCL, NULL);
        if (IS_ERR(bdev))
                ret =  PTR_ERR(bdev);
        else
                blkdev_put(bdev, mode & ~FMODE_EXCL);
 
+       /*
+        * If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set,
+        * and this will cause that re-assemble partitioned raid device will
+        * creat partition for underlying disk.
+        */
+       clear_bit(GD_NEED_PART_SCAN, &disk->state);
        if (!(mode & FMODE_EXCL))
                bd_abort_claiming(disk->part0, disk_scan_partitions);
        return ret;
index 5042cc54fa5ec68d71d54185f438df3959479865..a7a49b17ceb1fe837b786597170826e87dac33e4 100644 (file)
@@ -33,7 +33,11 @@ extern __initconst const unsigned long system_certificate_list_size;
 extern __initconst const unsigned long module_cert_size;
 
 /**
- * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
+ * restrict_link_by_builtin_trusted - Restrict keyring addition by built-in CA
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @restriction_key: A ring of keys that can be used to vouch for the new cert.
  *
  * Restrict the addition of keys into a keyring based on the key-to-be-added
  * being vouched for by a key in the built in system keyring.
@@ -50,7 +54,11 @@ int restrict_link_by_builtin_trusted(struct key *dest_keyring,
 #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
 /**
  * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
- *   addition by both builtin and secondary keyrings
+ *   addition by both built-in and secondary keyrings.
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @restrict_key: A ring of keys that can be used to vouch for the new cert.
  *
  * Restrict the addition of keys into a keyring based on the key-to-be-added
  * being vouched for by a key in either the built-in or the secondary system
@@ -75,7 +83,7 @@ int restrict_link_by_builtin_and_secondary_trusted(
                                          secondary_trusted_keys);
 }
 
-/**
+/*
  * Allocate a struct key_restriction for the "builtin and secondary trust"
  * keyring. Only for use in system_trusted_keyring_init().
  */
index 4fa769c4bcdb78c46c9fb1e124736ae39a32fbec..f0d4ff3c20a83275d5161e8e5c8d87793aa46ae7 100644 (file)
@@ -79,16 +79,16 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
                }
 
                if (sinfo->msgdigest_len != sig->digest_size) {
-                       pr_debug("Sig %u: Invalid digest size (%u)\n",
-                                sinfo->index, sinfo->msgdigest_len);
+                       pr_warn("Sig %u: Invalid digest size (%u)\n",
+                               sinfo->index, sinfo->msgdigest_len);
                        ret = -EBADMSG;
                        goto error;
                }
 
                if (memcmp(sig->digest, sinfo->msgdigest,
                           sinfo->msgdigest_len) != 0) {
-                       pr_debug("Sig %u: Message digest doesn't match\n",
-                                sinfo->index);
+                       pr_warn("Sig %u: Message digest doesn't match\n",
+                               sinfo->index);
                        ret = -EKEYREJECTED;
                        goto error;
                }
@@ -478,7 +478,7 @@ int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
                               const void *data, size_t datalen)
 {
        if (pkcs7->data) {
-               pr_debug("Data already supplied\n");
+               pr_warn("Data already supplied\n");
                return -EINVAL;
        }
        pkcs7->data = data;
index 6b1ac5f5896a7f830d61f97cd645d15c9d105331..276bdb62749882a838d3305461e3eb3a58e8ab89 100644 (file)
@@ -108,6 +108,46 @@ int restrict_link_by_signature(struct key *dest_keyring,
        return ret;
 }
 
+/**
+ * restrict_link_by_ca - Restrict additions to a ring of CA keys
+ * @dest_keyring: Keyring being linked to.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ * @trust_keyring: Unused.
+ *
+ * Check if the new certificate is a CA. If it is a CA, then mark the new
+ * certificate as being ok to link.
+ *
+ * Returns 0 if the new certificate was accepted, -ENOKEY if the
+ * certificate is not a CA. -ENOPKG if the signature uses unsupported
+ * crypto, or some other error if there is a matching certificate but
+ * the signature check cannot be performed.
+ */
+int restrict_link_by_ca(struct key *dest_keyring,
+                       const struct key_type *type,
+                       const union key_payload *payload,
+                       struct key *trust_keyring)
+{
+       const struct public_key *pkey;
+
+       if (type != &key_type_asymmetric)
+               return -EOPNOTSUPP;
+
+       pkey = payload->data[asym_crypto];
+       if (!pkey)
+               return -ENOPKG;
+       if (!test_bit(KEY_EFLAG_CA, &pkey->key_eflags))
+               return -ENOKEY;
+       if (!test_bit(KEY_EFLAG_KEYCERTSIGN, &pkey->key_eflags))
+               return -ENOKEY;
+       if (!IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING_MAX))
+               return 0;
+       if (test_bit(KEY_EFLAG_DIGITALSIG, &pkey->key_eflags))
+               return -ENOKEY;
+
+       return 0;
+}
+
 static bool match_either_id(const struct asymmetric_key_id **pair,
                            const struct asymmetric_key_id *single)
 {
index 7553ab18db898ffd887b7a7c487506780eb409e6..22beaf2213a224da9ca8f8fdf3519b071ac64a95 100644 (file)
@@ -74,7 +74,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
                break;
 
        default:
-               pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
+               pr_warn("Unknown PEOPT magic = %04hx\n", pe32->magic);
                return -ELIBBAD;
        }
 
@@ -95,7 +95,7 @@ static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
        ctx->certs_size = ddir->certs.size;
 
        if (!ddir->certs.virtual_address || !ddir->certs.size) {
-               pr_debug("Unsigned PE binary\n");
+               pr_warn("Unsigned PE binary\n");
                return -ENODATA;
        }
 
@@ -127,7 +127,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
        unsigned len;
 
        if (ctx->sig_len < sizeof(wrapper)) {
-               pr_debug("Signature wrapper too short\n");
+               pr_warn("Signature wrapper too short\n");
                return -ELIBBAD;
        }
 
@@ -135,19 +135,23 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
        pr_debug("sig wrapper = { %x, %x, %x }\n",
                 wrapper.length, wrapper.revision, wrapper.cert_type);
 
-       /* Both pesign and sbsign round up the length of certificate table
-        * (in optional header data directories) to 8 byte alignment.
+       /* sbsign rounds up the length of certificate table (in optional
+        * header data directories) to 8 byte alignment.  However, the PE
+        * specification states that while entries are 8-byte aligned, this is
+        * not included in their length, and as a result, pesign has not
+        * rounded up since 0.110.
         */
-       if (round_up(wrapper.length, 8) != ctx->sig_len) {
-               pr_debug("Signature wrapper len wrong\n");
+       if (wrapper.length > ctx->sig_len) {
+               pr_warn("Signature wrapper bigger than sig len (%x > %x)\n",
+                       ctx->sig_len, wrapper.length);
                return -ELIBBAD;
        }
        if (wrapper.revision != WIN_CERT_REVISION_2_0) {
-               pr_debug("Signature is not revision 2.0\n");
+               pr_warn("Signature is not revision 2.0\n");
                return -ENOTSUPP;
        }
        if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
-               pr_debug("Signature certificate type is not PKCS\n");
+               pr_warn("Signature certificate type is not PKCS\n");
                return -ENOTSUPP;
        }
 
@@ -160,7 +164,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
        ctx->sig_offset += sizeof(wrapper);
        ctx->sig_len -= sizeof(wrapper);
        if (ctx->sig_len < 4) {
-               pr_debug("Signature data missing\n");
+               pr_warn("Signature data missing\n");
                return -EKEYREJECTED;
        }
 
@@ -194,7 +198,7 @@ check_len:
                return 0;
        }
 not_pkcs7:
-       pr_debug("Signature data not PKCS#7\n");
+       pr_warn("Signature data not PKCS#7\n");
        return -ELIBBAD;
 }
 
@@ -337,8 +341,8 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
        digest_size = crypto_shash_digestsize(tfm);
 
        if (digest_size != ctx->digest_len) {
-               pr_debug("Digest size mismatch (%zx != %x)\n",
-                        digest_size, ctx->digest_len);
+               pr_warn("Digest size mismatch (%zx != %x)\n",
+                       digest_size, ctx->digest_len);
                ret = -EBADMSG;
                goto error_no_desc;
        }
@@ -369,7 +373,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
         * PKCS#7 certificate.
         */
        if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
-               pr_debug("Digest mismatch\n");
+               pr_warn("Digest mismatch\n");
                ret = -EKEYREJECTED;
        } else {
                pr_debug("The digests match!\n");
index 7a9b084e2043d72fa8859f6220316ab44ac79f92..0a7049b470c1812a710b9815a052e02b253e8f44 100644 (file)
@@ -579,6 +579,34 @@ int x509_process_extension(void *context, size_t hdrlen,
                return 0;
        }
 
+       if (ctx->last_oid == OID_keyUsage) {
+               /*
+                * Get hold of the keyUsage bit string
+                * v[1] is the encoding size
+                *       (Expect either 0x02 or 0x03, making it 1 or 2 bytes)
+                * v[2] is the number of unused bits in the bit string
+                *       (If >= 3 keyCertSign is missing when v[1] = 0x02)
+                * v[3] and possibly v[4] contain the bit string
+                *
+                * From RFC 5280 4.2.1.3:
+                *   0x04 is where keyCertSign lands in this bit string
+                *   0x80 is where digitalSignature lands in this bit string
+                */
+               if (v[0] != ASN1_BTS)
+                       return -EBADMSG;
+               if (vlen < 4)
+                       return -EBADMSG;
+               if (v[2] >= 8)
+                       return -EBADMSG;
+               if (v[3] & 0x80)
+                       ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_DIGITALSIG;
+               if (v[1] == 0x02 && v[2] <= 2 && (v[3] & 0x04))
+                       ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN;
+               else if (vlen > 4 && v[1] == 0x03 && (v[3] & 0x04))
+                       ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN;
+               return 0;
+       }
+
        if (ctx->last_oid == OID_authorityKeyIdentifier) {
                /* Get hold of the CA key fingerprint */
                ctx->raw_akid = v;
@@ -586,6 +614,28 @@ int x509_process_extension(void *context, size_t hdrlen,
                return 0;
        }
 
+       if (ctx->last_oid == OID_basicConstraints) {
+               /*
+                * Get hold of the basicConstraints
+                * v[1] is the encoding size
+                *      (Expect 0x2 or greater, making it 1 or more bytes)
+                * v[2] is the encoding type
+                *      (Expect an ASN1_BOOL for the CA)
+                * v[3] is the contents of the ASN1_BOOL
+                *      (Expect 1 if the CA is TRUE)
+                * vlen should match the entire extension size
+                */
+               if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ))
+                       return -EBADMSG;
+               if (vlen < 2)
+                       return -EBADMSG;
+               if (v[1] != vlen - 2)
+                       return -EBADMSG;
+               if (vlen >= 4 && v[1] != 0 && v[2] == ASN1_BOOL && v[3] == 1)
+                       ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_CA;
+               return 0;
+       }
+
        return 0;
 }
 
index 07aa77aed1c8dd27dd63b0ed658cb923c5cde5f4..f22fd44d586b2eab2ed203819588fc494c22014b 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-obj-y  += habanalabs/
-obj-y  += ivpu/
+obj-$(CONFIG_DRM_ACCEL_HABANALABS)     += habanalabs/
+obj-$(CONFIG_DRM_ACCEL_IVPU)           += ivpu/
index 231f29bb50257e9595f856e29cc312f937c33cb4..6a320a73e3ccf17b09209284883774c991e2ef9f 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/pci.h>
 
 #include <drm/drm_accel.h>
-#include <drm/drm_drv.h>
 #include <drm/drm_file.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_ioctl.h>
@@ -118,6 +117,10 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
        struct pci_dev *pdev = to_pci_dev(vdev->drm.dev);
        struct drm_ivpu_param *args = data;
        int ret = 0;
+       int idx;
+
+       if (!drm_dev_enter(dev, &idx))
+               return -ENODEV;
 
        switch (args->param) {
        case DRM_IVPU_PARAM_DEVICE_ID:
@@ -171,6 +174,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
                break;
        }
 
+       drm_dev_exit(idx);
        return ret;
 }
 
@@ -470,8 +474,8 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
 
        vdev->hw->ops = &ivpu_hw_mtl_ops;
        vdev->platform = IVPU_PLATFORM_INVALID;
-       vdev->context_xa_limit.min = IVPU_GLOBAL_CONTEXT_MMU_SSID + 1;
-       vdev->context_xa_limit.max = IVPU_CONTEXT_LIMIT;
+       vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID;
+       vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID;
        atomic64_set(&vdev->unique_id_counter, 0);
        xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC);
        xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1);
@@ -565,6 +569,8 @@ err_mmu_gctx_fini:
        ivpu_mmu_global_context_fini(vdev);
 err_power_down:
        ivpu_hw_power_down(vdev);
+       if (IVPU_WA(d3hot_after_power_off))
+               pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
 err_xa_destroy:
        xa_destroy(&vdev->submitted_jobs_xa);
        xa_destroy(&vdev->context_xa);
@@ -575,7 +581,11 @@ static void ivpu_dev_fini(struct ivpu_device *vdev)
 {
        ivpu_pm_disable(vdev);
        ivpu_shutdown(vdev);
+       if (IVPU_WA(d3hot_after_power_off))
+               pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
        ivpu_job_done_thread_fini(vdev);
+       ivpu_pm_cancel_recovery(vdev);
+
        ivpu_ipc_fini(vdev);
        ivpu_fw_fini(vdev);
        ivpu_mmu_global_context_fini(vdev);
@@ -622,7 +632,7 @@ static void ivpu_remove(struct pci_dev *pdev)
 {
        struct ivpu_device *vdev = pci_get_drvdata(pdev);
 
-       drm_dev_unregister(&vdev->drm);
+       drm_dev_unplug(&vdev->drm);
        ivpu_dev_fini(vdev);
 }
 
index f47b4965db2e33ced85211672116e7c7a0cc3aad..d3013fbd13b32fbaaffd2886b27eaaca6f9bf011 100644 (file)
@@ -7,6 +7,7 @@
 #define __IVPU_DRV_H__
 
 #include <drm/drm_device.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_print.h>
 #define PCI_DEVICE_ID_MTL   0x7d1d
 
 #define IVPU_GLOBAL_CONTEXT_MMU_SSID 0
-#define IVPU_CONTEXT_LIMIT          64
+/* SSID 1 is used by the VPU to represent invalid context */
+#define IVPU_USER_CONTEXT_MIN_SSID   2
+#define IVPU_USER_CONTEXT_MAX_SSID   (IVPU_USER_CONTEXT_MIN_SSID + 63)
+
 #define IVPU_NUM_ENGINES            2
 
 #define IVPU_PLATFORM_SILICON 0
@@ -70,6 +74,7 @@
 struct ivpu_wa_table {
        bool punit_disabled;
        bool clear_runtime_mem;
+       bool d3hot_after_power_off;
 };
 
 struct ivpu_hw_info;
index 62bfaa9081c4f8b6df89e038e26bceeec6a5eea9..382ec127be8ea1081f3a4446a82553c536b40f0e 100644 (file)
 #include "ivpu_mmu.h"
 #include "ivpu_pm.h"
 
-#define TILE_FUSE_ENABLE_BOTH       0x0
-#define TILE_FUSE_ENABLE_UPPER      0x1
-#define TILE_FUSE_ENABLE_LOWER      0x2
-
-#define TILE_SKU_BOTH_MTL           0x3630
-#define TILE_SKU_LOWER_MTL          0x3631
-#define TILE_SKU_UPPER_MTL          0x3632
+#define TILE_FUSE_ENABLE_BOTH        0x0
+#define TILE_SKU_BOTH_MTL            0x3630
 
 /* Work point configuration values */
-#define WP_CONFIG_1_TILE_5_3_RATIO   0x0101
-#define WP_CONFIG_1_TILE_4_3_RATIO   0x0102
-#define WP_CONFIG_2_TILE_5_3_RATIO   0x0201
-#define WP_CONFIG_2_TILE_4_3_RATIO   0x0202
-#define WP_CONFIG_0_TILE_PLL_OFF     0x0000
+#define CONFIG_1_TILE                0x01
+#define CONFIG_2_TILE                0x02
+#define PLL_RATIO_5_3                0x01
+#define PLL_RATIO_4_3                0x02
+#define WP_CONFIG(tile, ratio)       (((tile) << 8) | (ratio))
+#define WP_CONFIG_1_TILE_5_3_RATIO   WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_5_3)
+#define WP_CONFIG_1_TILE_4_3_RATIO   WP_CONFIG(CONFIG_1_TILE, PLL_RATIO_4_3)
+#define WP_CONFIG_2_TILE_5_3_RATIO   WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_5_3)
+#define WP_CONFIG_2_TILE_4_3_RATIO   WP_CONFIG(CONFIG_2_TILE, PLL_RATIO_4_3)
+#define WP_CONFIG_0_TILE_PLL_OFF     WP_CONFIG(0, 0)
 
 #define PLL_REF_CLK_FREQ            (50 * 1000000)
 #define PLL_SIMULATION_FREQ         (10 * 1000000)
-#define PLL_RATIO_TO_FREQ(x)        ((x) * PLL_REF_CLK_FREQ)
 #define PLL_DEFAULT_EPP_VALUE       0x80
 
 #define TIM_SAFE_ENABLE                     0xf1d0dead
@@ -101,6 +100,7 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
 {
        vdev->wa.punit_disabled = ivpu_is_fpga(vdev);
        vdev->wa.clear_runtime_mem = false;
+       vdev->wa.d3hot_after_power_off = true;
 }
 
 static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
@@ -218,7 +218,8 @@ static int ivpu_pll_drive(struct ivpu_device *vdev, bool enable)
                config = 0;
        }
 
-       ivpu_dbg(vdev, PM, "PLL workpoint request: %d Hz\n", PLL_RATIO_TO_FREQ(target_ratio));
+       ivpu_dbg(vdev, PM, "PLL workpoint request: config 0x%04x pll ratio 0x%x\n",
+                config, target_ratio);
 
        ret = ivpu_pll_cmd_send(vdev, hw->pll.min_ratio, hw->pll.max_ratio, target_ratio, config);
        if (ret) {
@@ -403,11 +404,6 @@ static int ivpu_boot_host_ss_axi_enable(struct ivpu_device *vdev)
        return ivpu_boot_host_ss_axi_drive(vdev, true);
 }
 
-static int ivpu_boot_host_ss_axi_disable(struct ivpu_device *vdev)
-{
-       return ivpu_boot_host_ss_axi_drive(vdev, false);
-}
-
 static int ivpu_boot_host_ss_top_noc_drive(struct ivpu_device *vdev, bool enable)
 {
        int ret;
@@ -441,11 +437,6 @@ static int ivpu_boot_host_ss_top_noc_enable(struct ivpu_device *vdev)
        return ivpu_boot_host_ss_top_noc_drive(vdev, true);
 }
 
-static int ivpu_boot_host_ss_top_noc_disable(struct ivpu_device *vdev)
-{
-       return ivpu_boot_host_ss_top_noc_drive(vdev, false);
-}
-
 static void ivpu_boot_pwr_island_trickle_drive(struct ivpu_device *vdev, bool enable)
 {
        u32 val = REGV_RD32(MTL_VPU_HOST_SS_AON_PWR_ISLAND_TRICKLE_EN0);
@@ -504,16 +495,6 @@ static void ivpu_boot_dpu_active_drive(struct ivpu_device *vdev, bool enable)
        REGV_WR32(MTL_VPU_HOST_SS_AON_DPU_ACTIVE, val);
 }
 
-static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev)
-{
-       ivpu_boot_dpu_active_drive(vdev, false);
-       ivpu_boot_pwr_island_isolation_drive(vdev, true);
-       ivpu_boot_pwr_island_trickle_drive(vdev, false);
-       ivpu_boot_pwr_island_drive(vdev, false);
-
-       return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0);
-}
-
 static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev)
 {
        int ret;
@@ -629,34 +610,10 @@ static int ivpu_boot_d0i3_drive(struct ivpu_device *vdev, bool enable)
 static int ivpu_hw_mtl_info_init(struct ivpu_device *vdev)
 {
        struct ivpu_hw_info *hw = vdev->hw;
-       u32 tile_fuse;
-
-       tile_fuse = REGB_RD32(MTL_BUTTRESS_TILE_FUSE);
-       if (!REG_TEST_FLD(MTL_BUTTRESS_TILE_FUSE, VALID, tile_fuse))
-               ivpu_warn(vdev, "Tile Fuse: Invalid (0x%x)\n", tile_fuse);
-
-       hw->tile_fuse = REG_GET_FLD(MTL_BUTTRESS_TILE_FUSE, SKU, tile_fuse);
-       switch (hw->tile_fuse) {
-       case TILE_FUSE_ENABLE_LOWER:
-               hw->sku = TILE_SKU_LOWER_MTL;
-               hw->config = WP_CONFIG_1_TILE_5_3_RATIO;
-               ivpu_dbg(vdev, MISC, "Tile Fuse: Enable Lower\n");
-               break;
-       case TILE_FUSE_ENABLE_UPPER:
-               hw->sku = TILE_SKU_UPPER_MTL;
-               hw->config = WP_CONFIG_1_TILE_4_3_RATIO;
-               ivpu_dbg(vdev, MISC, "Tile Fuse: Enable Upper\n");
-               break;
-       case TILE_FUSE_ENABLE_BOTH:
-               hw->sku = TILE_SKU_BOTH_MTL;
-               hw->config = WP_CONFIG_2_TILE_5_3_RATIO;
-               ivpu_dbg(vdev, MISC, "Tile Fuse: Enable Both\n");
-               break;
-       default:
-               hw->config = WP_CONFIG_0_TILE_PLL_OFF;
-               ivpu_dbg(vdev, MISC, "Tile Fuse: Disable\n");
-               break;
-       }
+
+       hw->tile_fuse = TILE_FUSE_ENABLE_BOTH;
+       hw->sku = TILE_SKU_BOTH_MTL;
+       hw->config = WP_CONFIG_2_TILE_4_3_RATIO;
 
        ivpu_pll_init_frequency_ratios(vdev);
 
@@ -797,21 +754,8 @@ static int ivpu_hw_mtl_power_down(struct ivpu_device *vdev)
 {
        int ret = 0;
 
-       /* FPGA requires manual clearing of IP_Reset bit by enabling quiescent state */
-       if (ivpu_is_fpga(vdev)) {
-               if (ivpu_boot_host_ss_top_noc_disable(vdev)) {
-                       ivpu_err(vdev, "Failed to disable TOP NOC\n");
-                       ret = -EIO;
-               }
-
-               if (ivpu_boot_host_ss_axi_disable(vdev)) {
-                       ivpu_err(vdev, "Failed to disable AXI\n");
-                       ret = -EIO;
-               }
-       }
-
-       if (ivpu_boot_pwr_domain_disable(vdev)) {
-               ivpu_err(vdev, "Failed to disable power domain\n");
+       if (ivpu_hw_mtl_reset(vdev)) {
+               ivpu_err(vdev, "Failed to reset the VPU\n");
                ret = -EIO;
        }
 
@@ -844,6 +788,19 @@ static void ivpu_hw_mtl_wdt_disable(struct ivpu_device *vdev)
        REGV_WR32(MTL_VPU_CPU_SS_TIM_GEN_CONFIG, val);
 }
 
+static u32 ivpu_hw_mtl_pll_to_freq(u32 ratio, u32 config)
+{
+       u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
+       u32 cpu_clock;
+
+       if ((config & 0xff) == PLL_RATIO_4_3)
+               cpu_clock = pll_clock * 2 / 4;
+       else
+               cpu_clock = pll_clock * 2 / 5;
+
+       return cpu_clock;
+}
+
 /* Register indirect accesses */
 static u32 ivpu_hw_mtl_reg_pll_freq_get(struct ivpu_device *vdev)
 {
@@ -855,7 +812,7 @@ static u32 ivpu_hw_mtl_reg_pll_freq_get(struct ivpu_device *vdev)
        if (!ivpu_is_silicon(vdev))
                return PLL_SIMULATION_FREQ;
 
-       return PLL_RATIO_TO_FREQ(pll_curr_ratio);
+       return ivpu_hw_mtl_pll_to_freq(pll_curr_ratio, vdev->hw->config);
 }
 
 static u32 ivpu_hw_mtl_reg_telemetry_offset_get(struct ivpu_device *vdev)
index 9838202ecfadf27fc0fe3a74495e145a08dea500..68f5b6668e00b9812864db1c9e432adc4f9d6c3c 100644 (file)
@@ -21,7 +21,7 @@ struct ivpu_bo;
 #define IVPU_IPC_ALIGNMENT        64
 
 #define IVPU_IPC_HDR_FREE         0
-#define IVPU_IPC_HDR_ALLOCATED    0
+#define IVPU_IPC_HDR_ALLOCATED    1
 
 /**
  * struct ivpu_ipc_hdr - The IPC message header structure, exchanged
index 94068aedf97cfee791469f5aa908c118ce2c355d..3c6f1e16cf2ff7a1090cd471cb84f93d26feba21 100644 (file)
@@ -461,26 +461,22 @@ ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct ivpu_job *job, u32
 
        job->cmd_buf_vpu_addr = bo->vpu_addr + commands_offset;
 
-       ret = drm_gem_lock_reservations((struct drm_gem_object **)job->bos, buf_count,
-                                       &acquire_ctx);
+       ret = drm_gem_lock_reservations((struct drm_gem_object **)job->bos, 1, &acquire_ctx);
        if (ret) {
                ivpu_warn(vdev, "Failed to lock reservations: %d\n", ret);
                return ret;
        }
 
-       for (i = 0; i < buf_count; i++) {
-               ret = dma_resv_reserve_fences(job->bos[i]->base.resv, 1);
-               if (ret) {
-                       ivpu_warn(vdev, "Failed to reserve fences: %d\n", ret);
-                       goto unlock_reservations;
-               }
+       ret = dma_resv_reserve_fences(bo->base.resv, 1);
+       if (ret) {
+               ivpu_warn(vdev, "Failed to reserve fences: %d\n", ret);
+               goto unlock_reservations;
        }
 
-       for (i = 0; i < buf_count; i++)
-               dma_resv_add_fence(job->bos[i]->base.resv, job->done_fence, DMA_RESV_USAGE_WRITE);
+       dma_resv_add_fence(bo->base.resv, job->done_fence, DMA_RESV_USAGE_WRITE);
 
 unlock_reservations:
-       drm_gem_unlock_reservations((struct drm_gem_object **)job->bos, buf_count, &acquire_ctx);
+       drm_gem_unlock_reservations((struct drm_gem_object **)job->bos, 1, &acquire_ctx);
 
        wmb(); /* Flush write combining buffers */
 
@@ -489,12 +485,12 @@ unlock_reservations:
 
 int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 {
-       int ret = 0;
        struct ivpu_file_priv *file_priv = file->driver_priv;
        struct ivpu_device *vdev = file_priv->vdev;
        struct drm_ivpu_submit *params = data;
        struct ivpu_job *job;
        u32 *buf_handles;
+       int idx, ret;
 
        if (params->engine > DRM_IVPU_ENGINE_COPY)
                return -EINVAL;
@@ -523,6 +519,11 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
                goto free_handles;
        }
 
+       if (!drm_dev_enter(&vdev->drm, &idx)) {
+               ret = -ENODEV;
+               goto free_handles;
+       }
+
        ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u buf_count %u\n",
                 file_priv->ctx.id, params->buffer_count);
 
@@ -530,7 +531,7 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
        if (!job) {
                ivpu_err(vdev, "Failed to create job\n");
                ret = -ENOMEM;
-               goto free_handles;
+               goto dev_exit;
        }
 
        ret = ivpu_job_prepare_bos_for_submit(file, job, buf_handles, params->buffer_count,
@@ -548,6 +549,8 @@ int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 
 job_put:
        job_put(job);
+dev_exit:
+       drm_dev_exit(idx);
 free_handles:
        kfree(buf_handles);
 
index 553bcbd787b3c868fdc3c9ca6ccb85ade4b644cf..bde42d6383da66beed974d42754f0bb445275f7f 100644 (file)
@@ -98,12 +98,18 @@ retry:
 static void ivpu_pm_recovery_work(struct work_struct *work)
 {
        struct ivpu_pm_info *pm = container_of(work, struct ivpu_pm_info, recovery_work);
-       struct ivpu_device *vdev =  pm->vdev;
+       struct ivpu_device *vdev = pm->vdev;
        char *evt[2] = {"IVPU_PM_EVENT=IVPU_RECOVER", NULL};
        int ret;
 
-       ret = pci_reset_function(to_pci_dev(vdev->drm.dev));
-       if (ret)
+retry:
+       ret = pci_try_reset_function(to_pci_dev(vdev->drm.dev));
+       if (ret == -EAGAIN && !drm_dev_is_unplugged(&vdev->drm)) {
+               cond_resched();
+               goto retry;
+       }
+
+       if (ret && ret != -EAGAIN)
                ivpu_err(vdev, "Failed to reset VPU: %d\n", ret);
 
        kobject_uevent_env(&vdev->drm.dev->kobj, KOBJ_CHANGE, evt);
@@ -134,32 +140,28 @@ int ivpu_pm_suspend_cb(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
        struct ivpu_device *vdev = to_ivpu_device(drm);
-       int ret;
+       unsigned long timeout;
 
        ivpu_dbg(vdev, PM, "Suspend..\n");
 
-       ret = ivpu_suspend(vdev);
-       if (ret && vdev->pm->suspend_reschedule_counter) {
-               ivpu_dbg(vdev, PM, "Failed to enter idle, rescheduling suspend, retries left %d\n",
-                        vdev->pm->suspend_reschedule_counter);
-               pm_schedule_suspend(dev, vdev->timeout.reschedule_suspend);
-               vdev->pm->suspend_reschedule_counter--;
-               return -EBUSY;
-       } else if (!vdev->pm->suspend_reschedule_counter) {
-               ivpu_warn(vdev, "Failed to enter idle, force suspend\n");
-               ivpu_pm_prepare_cold_boot(vdev);
-       } else {
-               ivpu_pm_prepare_warm_boot(vdev);
+       timeout = jiffies + msecs_to_jiffies(vdev->timeout.tdr);
+       while (!ivpu_hw_is_idle(vdev)) {
+               cond_resched();
+               if (time_after_eq(jiffies, timeout)) {
+                       ivpu_err(vdev, "Failed to enter idle on system suspend\n");
+                       return -EBUSY;
+               }
        }
 
-       vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
+       ivpu_suspend(vdev);
+       ivpu_pm_prepare_warm_boot(vdev);
 
        pci_save_state(to_pci_dev(dev));
        pci_set_power_state(to_pci_dev(dev), PCI_D3hot);
 
        ivpu_dbg(vdev, PM, "Suspend done.\n");
 
-       return ret;
+       return 0;
 }
 
 int ivpu_pm_resume_cb(struct device *dev)
@@ -306,6 +308,11 @@ int ivpu_pm_init(struct ivpu_device *vdev)
        return 0;
 }
 
+void ivpu_pm_cancel_recovery(struct ivpu_device *vdev)
+{
+       cancel_work_sync(&vdev->pm->recovery_work);
+}
+
 void ivpu_pm_enable(struct ivpu_device *vdev)
 {
        struct device *dev = vdev->drm.dev;
index dc1b3758e13f4ab47218e3813bcb6d0f62745bbc..baca981872551cc6e9a1380075c4fc749a735515 100644 (file)
@@ -21,6 +21,7 @@ struct ivpu_pm_info {
 int ivpu_pm_init(struct ivpu_device *vdev);
 void ivpu_pm_enable(struct ivpu_device *vdev);
 void ivpu_pm_disable(struct ivpu_device *vdev);
+void ivpu_pm_cancel_recovery(struct ivpu_device *vdev);
 
 int ivpu_pm_suspend_cb(struct device *dev);
 int ivpu_pm_resume_cb(struct device *dev);
index 97b711e57bff457bbfec645aeee7ca2efd668229..c7a6d0b69dabd4426cd6811176929abbaaaa2439 100644 (file)
@@ -1984,6 +1984,7 @@ static int instance;
 static int acpi_video_bus_add(struct acpi_device *device)
 {
        struct acpi_video_bus *video;
+       bool auto_detect;
        int error;
        acpi_status status;
 
@@ -2045,10 +2046,20 @@ static int acpi_video_bus_add(struct acpi_device *device)
        mutex_unlock(&video_list_lock);
 
        /*
-        * The userspace visible backlight_device gets registered separately
-        * from acpi_video_register_backlight().
+        * If backlight-type auto-detection is used then a native backlight may
+        * show up later and this may change the result from video to native.
+        * Therefor normally the userspace visible /sys/class/backlight device
+        * gets registered separately by the GPU driver calling
+        * acpi_video_register_backlight() when an internal panel is detected.
+        * Register the backlight now when not using auto-detection, so that
+        * when the kernel cmdline or DMI-quirks are used the backlight will
+        * get registered even if acpi_video_register_backlight() is not called.
         */
        acpi_video_run_bcl_for_osi(video);
+       if (__acpi_video_get_backlight_type(false, &auto_detect) == acpi_backlight_video &&
+           !auto_detect)
+               acpi_video_bus_register_backlight(video);
+
        acpi_video_bus_add_notify_handler(video);
 
        return 0;
index 82d1728b9bc6a65ca8512da50153959f039e1a7b..df596d46dd974eba813e0431fdf5cda2e21f9445 100644 (file)
@@ -142,9 +142,6 @@ static acpi_status acpi_ev_fixed_event_initialize(void)
                        status =
                            acpi_write_bit_register(acpi_gbl_fixed_event_info
                                                    [i].enable_register_id,
-                                                   (i ==
-                                                    ACPI_EVENT_PCIE_WAKE) ?
-                                                   ACPI_ENABLE_EVENT :
                                                    ACPI_DISABLE_EVENT);
                        if (ACPI_FAILURE(status)) {
                                return (status);
@@ -188,11 +185,6 @@ u32 acpi_ev_fixed_event_detect(void)
                return (int_status);
        }
 
-       if (fixed_enable & ACPI_BITMASK_PCIEXP_WAKE_DISABLE)
-               fixed_enable &= ~ACPI_BITMASK_PCIEXP_WAKE_DISABLE;
-       else
-               fixed_enable |= ACPI_BITMASK_PCIEXP_WAKE_DISABLE;
-
        ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
                          "Fixed Event Block: Enable %08X Status %08X\n",
                          fixed_enable, fixed_status));
@@ -258,9 +250,6 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
        if (!acpi_gbl_fixed_event_handlers[event].handler) {
                (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
                                              enable_register_id,
-                                             (event ==
-                                              ACPI_EVENT_PCIE_WAKE) ?
-                                             ACPI_ENABLE_EVENT :
                                              ACPI_DISABLE_EVENT);
 
                ACPI_ERROR((AE_INFO,
index 37b3f641feaab238f50895cb8202af42d13588f1..bd936476dda9667c1b28714c867dce9703761479 100644 (file)
@@ -311,20 +311,6 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state)
                                    [ACPI_EVENT_SLEEP_BUTTON].
                                    status_register_id, ACPI_CLEAR_STATUS);
 
-       /* Enable pcie wake event if support */
-       if ((acpi_gbl_FADT.flags & ACPI_FADT_PCI_EXPRESS_WAKE)) {
-               (void)
-                   acpi_write_bit_register(acpi_gbl_fixed_event_info
-                                           [ACPI_EVENT_PCIE_WAKE].
-                                           enable_register_id,
-                                           ACPI_DISABLE_EVENT);
-               (void)
-                   acpi_write_bit_register(acpi_gbl_fixed_event_info
-                                           [ACPI_EVENT_PCIE_WAKE].
-                                           status_register_id,
-                                           ACPI_CLEAR_STATUS);
-       }
-
        acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
        return_ACPI_STATUS(status);
 }
index 53afa5edb6ecb79131626ac96dc0d9ccc4ba3ab1..cda6e16dddf78c8cc9c0dd1b04fb2563ecfe8e54 100644 (file)
@@ -186,10 +186,6 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
                                        ACPI_BITREG_RT_CLOCK_ENABLE,
                                        ACPI_BITMASK_RT_CLOCK_STATUS,
                                        ACPI_BITMASK_RT_CLOCK_ENABLE},
-       /* ACPI_EVENT_PCIE_WAKE     */ {ACPI_BITREG_PCIEXP_WAKE_STATUS,
-                                       ACPI_BITREG_PCIEXP_WAKE_DISABLE,
-                                       ACPI_BITMASK_PCIEXP_WAKE_STATUS,
-                                       ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
 };
 #endif                         /* !ACPI_REDUCED_HARDWARE */
 
index 9531dd0fef5099715a594be4fa4e30f826ad1f8c..a96da65057b19bfb46f390966831a23509291dcb 100644 (file)
@@ -459,85 +459,67 @@ out_free:
                              Notification Handling
    -------------------------------------------------------------------------- */
 
-/*
- * acpi_bus_notify
- * ---------------
- * Callback for all 'system-level' device notifications (values 0x00-0x7F).
+/**
+ * acpi_bus_notify - Global system-level (0x00-0x7F) notifications handler
+ * @handle: Target ACPI object.
+ * @type: Notification type.
+ * @data: Ignored.
+ *
+ * This only handles notifications related to device hotplug.
  */
 static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
 {
        struct acpi_device *adev;
-       u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-       bool hotplug_event = false;
 
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
-               hotplug_event = true;
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK:
                acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
-               hotplug_event = true;
                break;
 
        case ACPI_NOTIFY_DEVICE_WAKE:
                acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event\n");
-               break;
+               return;
 
        case ACPI_NOTIFY_EJECT_REQUEST:
                acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-               hotplug_event = true;
                break;
 
        case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
                acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event\n");
                /* TBD: Exactly what does 'light' mean? */
-               break;
+               return;
 
        case ACPI_NOTIFY_FREQUENCY_MISMATCH:
                acpi_handle_err(handle, "Device cannot be configured due "
                                "to a frequency mismatch\n");
-               break;
+               return;
 
        case ACPI_NOTIFY_BUS_MODE_MISMATCH:
                acpi_handle_err(handle, "Device cannot be configured due "
                                "to a bus mode mismatch\n");
-               break;
+               return;
 
        case ACPI_NOTIFY_POWER_FAULT:
                acpi_handle_err(handle, "Device has suffered a power fault\n");
-               break;
+               return;
 
        default:
                acpi_handle_debug(handle, "Unknown event type 0x%x\n", type);
-               break;
+               return;
        }
 
        adev = acpi_get_acpi_dev(handle);
-       if (!adev)
-               goto err;
-
-       if (adev->dev.driver) {
-               struct acpi_driver *driver = to_acpi_driver(adev->dev.driver);
-
-               if (driver && driver->ops.notify &&
-                   (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
-                       driver->ops.notify(adev, type);
-       }
-
-       if (!hotplug_event) {
-               acpi_put_acpi_dev(adev);
-               return;
-       }
 
-       if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
+       if (adev && ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
                return;
 
        acpi_put_acpi_dev(adev);
 
- err:
-       acpi_evaluate_ost(handle, type, ost_code, NULL);
+       acpi_evaluate_ost(handle, type, ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
 }
 
 static void acpi_notify_device(acpi_handle handle, u32 event, void *data)
@@ -562,42 +544,51 @@ static u32 acpi_device_fixed_event(void *data)
        return ACPI_INTERRUPT_HANDLED;
 }
 
-static int acpi_device_install_notify_handler(struct acpi_device *device)
+static int acpi_device_install_notify_handler(struct acpi_device *device,
+                                             struct acpi_driver *acpi_drv)
 {
        acpi_status status;
 
-       if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+       if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
                status =
                    acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
                                                     acpi_device_fixed_event,
                                                     device);
-       else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+       } else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
                status =
                    acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
                                                     acpi_device_fixed_event,
                                                     device);
-       else
-               status = acpi_install_notify_handler(device->handle,
-                                                    ACPI_DEVICE_NOTIFY,
+       } else {
+               u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
+                               ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
+
+               status = acpi_install_notify_handler(device->handle, type,
                                                     acpi_notify_device,
                                                     device);
+       }
 
        if (ACPI_FAILURE(status))
                return -EINVAL;
        return 0;
 }
 
-static void acpi_device_remove_notify_handler(struct acpi_device *device)
+static void acpi_device_remove_notify_handler(struct acpi_device *device,
+                                             struct acpi_driver *acpi_drv)
 {
-       if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+       if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON) {
                acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
                                                acpi_device_fixed_event);
-       else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+       } else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON) {
                acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
                                                acpi_device_fixed_event);
-       else
-               acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+       } else {
+               u32 type = acpi_drv->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS ?
+                               ACPI_ALL_NOTIFY : ACPI_DEVICE_NOTIFY;
+
+               acpi_remove_notify_handler(device->handle, type,
                                           acpi_notify_device);
+       }
 }
 
 /* Handle events targeting \_SB device (at present only graceful shutdown) */
@@ -1039,7 +1030,7 @@ static int acpi_device_probe(struct device *dev)
                 acpi_drv->name, acpi_dev->pnp.bus_id);
 
        if (acpi_drv->ops.notify) {
-               ret = acpi_device_install_notify_handler(acpi_dev);
+               ret = acpi_device_install_notify_handler(acpi_dev, acpi_drv);
                if (ret) {
                        if (acpi_drv->ops.remove)
                                acpi_drv->ops.remove(acpi_dev);
@@ -1062,7 +1053,7 @@ static void acpi_device_remove(struct device *dev)
        struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
 
        if (acpi_drv->ops.notify)
-               acpi_device_remove_notify_handler(acpi_dev);
+               acpi_device_remove_notify_handler(acpi_dev, acpi_drv);
 
        if (acpi_drv->ops.remove)
                acpi_drv->ops.remove(acpi_dev);
index 10975bb603fb15c099165ad4fa15b88ab3c794ef..a35dd0e41c27043bc0cb6f8783c1bc0280cb1155 100644 (file)
@@ -536,16 +536,19 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table,
 static struct acpi_table_header *acpi_get_pptt(void)
 {
        static struct acpi_table_header *pptt;
+       static bool is_pptt_checked;
        acpi_status status;
 
        /*
         * PPTT will be used at runtime on every CPU hotplug in path, so we
         * don't need to call acpi_put_table() to release the table mapping.
         */
-       if (!pptt) {
+       if (!pptt && !is_pptt_checked) {
                status = acpi_get_table(ACPI_SIG_PPTT, 0, &pptt);
                if (ACPI_FAILURE(status))
                        acpi_pptt_warn_missing();
+
+               is_pptt_checked = true;
        }
 
        return pptt;
index 1278969eec1f9928ed75dbbd00aefa1620f08575..4bd16b3f0781481f6cfd54d760f47f3ad54b405a 100644 (file)
@@ -263,6 +263,12 @@ static int __init acpi_processor_driver_init(void)
        if (acpi_disabled)
                return 0;
 
+       if (!cpufreq_register_notifier(&acpi_processor_notifier_block,
+                                      CPUFREQ_POLICY_NOTIFIER)) {
+               acpi_processor_cpufreq_init = true;
+               acpi_processor_ignore_ppc_init();
+       }
+
        result = driver_register(&acpi_processor_driver);
        if (result < 0)
                return result;
@@ -276,12 +282,6 @@ static int __init acpi_processor_driver_init(void)
        cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead",
                                  NULL, acpi_soft_cpu_dead);
 
-       if (!cpufreq_register_notifier(&acpi_processor_notifier_block,
-                                      CPUFREQ_POLICY_NOTIFIER)) {
-               acpi_processor_cpufreq_init = true;
-               acpi_processor_ignore_ppc_init();
-       }
-
        acpi_processor_throttling_init();
        return 0;
 err:
index e534fd49a67e50877cc9ecd2672720fceed467f5..b7c6287eccca28c17908646a52af083d9e31a5dd 100644 (file)
@@ -140,9 +140,13 @@ void acpi_thermal_cpufreq_init(struct cpufreq_policy *policy)
                ret = freq_qos_add_request(&policy->constraints,
                                           &pr->thermal_req,
                                           FREQ_QOS_MAX, INT_MAX);
-               if (ret < 0)
+               if (ret < 0) {
                        pr_err("Failed to add freq constraint for CPU%d (%d)\n",
                               cpu, ret);
+                       continue;
+               }
+
+               thermal_cooling_device_update(pr->cdev);
        }
 }
 
@@ -153,8 +157,12 @@ void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
        for_each_cpu(cpu, policy->related_cpus) {
                struct acpi_processor *pr = per_cpu(processors, cpu);
 
-               if (pr)
-                       freq_qos_remove_request(&pr->thermal_req);
+               if (!pr)
+                       continue;
+
+               freq_qos_remove_request(&pr->thermal_req);
+
+               thermal_cooling_device_update(pr->cdev);
        }
 }
 #else                          /* ! CONFIG_CPU_FREQ */
index 7c9125df5a651cfaca6da86adc9d6932cd97fdf4..e8492b3a393ab6932c1f6c791bee1c442688fb64 100644 (file)
@@ -400,6 +400,13 @@ static const struct dmi_system_id medion_laptop[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "M17T"),
                },
        },
+       {
+               .ident = "MEDION S17413",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+                       DMI_MATCH(DMI_BOARD_NAME, "M1xA"),
+               },
+       },
        { }
 };
 
@@ -432,6 +439,13 @@ static const struct dmi_system_id asus_laptop[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),
                },
        },
+       {
+               .ident = "Asus ExpertBook B1502CBA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"),
+               },
+       },
        {
                .ident = "Asus ExpertBook B2402CBA",
                .matches = {
index 710ac640267dd301da56d7e504b1f3435fe91b42..e85729fc481fde1864222e5821d7ccaaf07da509 100644 (file)
@@ -276,6 +276,43 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                },
        },
 
+       /*
+        * Models which need acpi_video backlight control where the GPU drivers
+        * do not call acpi_video_register_backlight() because no internal panel
+        * is detected. Typically these are all-in-ones (monitors with builtin
+        * PC) where the panel connection shows up as regular DP instead of eDP.
+        */
+       {
+        .callback = video_detect_force_video,
+        /* Apple iMac14,1 */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,1"),
+               },
+       },
+       {
+        .callback = video_detect_force_video,
+        /* Apple iMac14,2 */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "iMac14,2"),
+               },
+       },
+
+       /*
+        * Older models with nvidia GPU which need acpi_video backlight
+        * control and where the old nvidia binary driver series does not
+        * call acpi_video_register_backlight().
+        */
+       {
+        .callback = video_detect_force_video,
+        /* ThinkPad W530 */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
+               },
+       },
+
        /*
         * These models have a working acpi_video backlight control, and using
         * native backlight causes a regression where backlight does not work
@@ -495,6 +532,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
                },
        },
+       {
+        .callback = video_detect_force_native,
+        /* Acer Aspire 3830TG */
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3830TG"),
+               },
+       },
        {
         .callback = video_detect_force_native,
         /* Acer Aspire 4810T */
@@ -716,6 +761,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
                },
        },
+       {
+        .callback = video_detect_force_native,
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 15 3535"),
+               },
+       },
 
        /*
         * Desktops which falsely report a backlight and which our heuristics
@@ -767,7 +819,7 @@ static bool prefer_native_over_acpi_video(void)
  * Determine which type of backlight interface to use on this system,
  * First check cmdline, then dmi quirks, then do autodetect.
  */
-static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
+enum acpi_backlight_type __acpi_video_get_backlight_type(bool native, bool *auto_detect)
 {
        static DEFINE_MUTEX(init_mutex);
        static bool nvidia_wmi_ec_present;
@@ -792,6 +844,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
                native_available = true;
        mutex_unlock(&init_mutex);
 
+       if (auto_detect)
+               *auto_detect = false;
+
        /*
         * The below heuristics / detection steps are in order of descending
         * presedence. The commandline takes presedence over anything else.
@@ -803,6 +858,9 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
        if (acpi_backlight_dmi != acpi_backlight_undef)
                return acpi_backlight_dmi;
 
+       if (auto_detect)
+               *auto_detect = true;
+
        /* Special cases such as nvidia_wmi_ec and apple gmux. */
        if (nvidia_wmi_ec_present)
                return acpi_backlight_nvidia_wmi_ec;
@@ -822,15 +880,4 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
        /* No ACPI video/native (old hw), use vendor specific fw methods. */
        return acpi_backlight_vendor;
 }
-
-enum acpi_backlight_type acpi_video_get_backlight_type(void)
-{
-       return __acpi_video_get_backlight_type(false);
-}
-EXPORT_SYMBOL(acpi_video_get_backlight_type);
-
-bool acpi_video_backlight_use_native(void)
-{
-       return __acpi_video_get_backlight_type(true) == acpi_backlight_native;
-}
-EXPORT_SYMBOL(acpi_video_backlight_use_native);
+EXPORT_SYMBOL(__acpi_video_get_backlight_type);
index e45285d4e62a423532414f2c052a6af963c39230..ba420a28a4aadce7c087183d2cb4deb178e3bd08 100644 (file)
@@ -213,6 +213,7 @@ bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *s
       disk in the system.
  */
 static const struct x86_cpu_id storage_d3_cpu_ids[] = {
+       X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 24, NULL),  /* Picasso */
        X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 96, NULL),  /* Renoir */
        X86_MATCH_VENDOR_FAM_MODEL(AMD, 23, 104, NULL), /* Lucienne */
        X86_MATCH_VENDOR_FAM_MODEL(AMD, 25, 80, NULL),  /* Cezanne */
@@ -251,6 +252,7 @@ bool force_storage_d3(void)
 #define ACPI_QUIRK_UART1_TTY_UART2_SKIP                                BIT(1)
 #define ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY                    BIT(2)
 #define ACPI_QUIRK_USE_ACPI_AC_AND_BATTERY                     BIT(3)
+#define ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS                    BIT(4)
 
 static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
        /*
@@ -279,6 +281,16 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
         *    need the x86-android-tablets module to properly work.
         */
 #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
+       {
+               /* Acer Iconia One 7 B1-750 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "VESPA2"),
+               },
+               .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+                                       ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
+       },
        {
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
@@ -286,7 +298,19 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
                },
                .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
                                        ACPI_QUIRK_UART1_TTY_UART2_SKIP |
-                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+                                       ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
+       },
+       {
+               /* Lenovo Yoga Book X90F/L */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+               },
+               .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+                                       ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
        },
        {
                .matches = {
@@ -294,7 +318,8 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
                },
                .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
-                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+                                       ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
        },
        {
                /* Lenovo Yoga Tablet 2 1050F/L */
@@ -336,7 +361,8 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
                },
                .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
-                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+                                       ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY |
+                                       ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS),
        },
        {
                /* Whitelabel (sold as various brands) TM800A550L */
@@ -413,6 +439,20 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
        return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
+
+bool acpi_quirk_skip_gpio_event_handlers(void)
+{
+       const struct dmi_system_id *dmi_id;
+       long quirks;
+
+       dmi_id = dmi_first_match(acpi_quirk_skip_dmi_ids);
+       if (!dmi_id)
+               return false;
+
+       quirks = (unsigned long)dmi_id->driver_data;
+       return (quirks & ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS);
+}
+EXPORT_SYMBOL_GPL(acpi_quirk_skip_gpio_event_handlers);
 #endif
 
 /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
index 0b2c20fddb7c5851e373b901a1330cedf43a93bd..c0e8b765522dc79be3756acf62788812ca6ea7a5 100644 (file)
@@ -285,5 +285,4 @@ module_platform_driver(tegra_ahb_driver);
 
 MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
 MODULE_DESCRIPTION("Tegra AHB driver");
-MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:" DRV_NAME);
index 294a266a0dda579c58475678ade746f2e2c723ff..c1576d943b4364b861c85ec609fd51c21dbe46d4 100644 (file)
@@ -381,6 +381,7 @@ static void pata_parport_dev_release(struct device *dev)
 {
        struct pi_adapter *pi = container_of(dev, struct pi_adapter, dev);
 
+       ida_free(&pata_parport_bus_dev_ids, dev->id);
        kfree(pi);
 }
 
@@ -433,23 +434,27 @@ static struct pi_adapter *pi_init_one(struct parport *parport,
        if (bus_for_each_dev(&pata_parport_bus_type, NULL, &match, pi_find_dev))
                return NULL;
 
+       id = ida_alloc(&pata_parport_bus_dev_ids, GFP_KERNEL);
+       if (id < 0)
+               return NULL;
+
        pi = kzalloc(sizeof(struct pi_adapter), GFP_KERNEL);
-       if (!pi)
+       if (!pi) {
+               ida_free(&pata_parport_bus_dev_ids, id);
                return NULL;
+       }
 
        /* set up pi->dev before pi_probe_unit() so it can use dev_printk() */
        pi->dev.parent = &pata_parport_bus;
        pi->dev.bus = &pata_parport_bus_type;
        pi->dev.driver = &pr->driver;
        pi->dev.release = pata_parport_dev_release;
-       id = ida_alloc(&pata_parport_bus_dev_ids, GFP_KERNEL);
-       if (id < 0)
-               return NULL; /* pata_parport_dev_release will do kfree(pi) */
        pi->dev.id = id;
        dev_set_name(&pi->dev, "pata_parport.%u", pi->dev.id);
        if (device_register(&pi->dev)) {
                put_device(&pi->dev);
-               goto out_ida_free;
+               /* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */
+               return NULL;
        }
 
        pi->proto = pr;
@@ -464,8 +469,7 @@ static struct pi_adapter *pi_init_one(struct parport *parport,
        pi->port = parport->base;
 
        par_cb.private = pi;
-       pi->pardev = parport_register_dev_model(parport, DRV_NAME, &par_cb,
-                                               pi->dev.id);
+       pi->pardev = parport_register_dev_model(parport, DRV_NAME, &par_cb, id);
        if (!pi->pardev)
                goto out_module_put;
 
@@ -487,12 +491,13 @@ static struct pi_adapter *pi_init_one(struct parport *parport,
 
        pi_connect(pi);
        if (ata_host_activate(host, 0, NULL, 0, &pata_parport_sht))
-               goto out_unreg_parport;
+               goto out_disconnect;
 
        return pi;
 
-out_unreg_parport:
+out_disconnect:
        pi_disconnect(pi);
+out_unreg_parport:
        parport_unregister_device(pi->pardev);
        if (pi->proto->release_proto)
                pi->proto->release_proto(pi);
@@ -500,8 +505,7 @@ out_module_put:
        module_put(pi->proto->owner);
 out_unreg_dev:
        device_unregister(&pi->dev);
-out_ida_free:
-       ida_free(&pata_parport_bus_dev_ids, pi->dev.id);
+       /* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */
        return NULL;
 }
 
@@ -626,8 +630,7 @@ static void pi_remove_one(struct device *dev)
        pi_disconnect(pi);
        pi_release(pi);
        device_unregister(dev);
-       ida_free(&pata_parport_bus_dev_ids, dev->id);
-       /* pata_parport_dev_release will do kfree(pi) */
+       /* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */
 }
 
 static ssize_t delete_device_store(struct bus_type *bus, const char *buf,
@@ -643,6 +646,7 @@ static ssize_t delete_device_store(struct bus_type *bus, const char *buf,
        }
 
        pi_remove_one(dev);
+       put_device(dev);
        mutex_unlock(&pi_mutex);
 
        return count;
index eec0cc2144e0227155df540cc2e0e75208e5d37b..e327a0229dc173442b2789a402a8ea0adb931cdd 100644 (file)
@@ -2909,6 +2909,7 @@ close_card_oam(struct idt77252_dev *card)
 
                                recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
                        }
+                       kfree(vc);
                }
        }
 }
@@ -2952,6 +2953,15 @@ open_card_ubr0(struct idt77252_dev *card)
        return 0;
 }
 
+static void
+close_card_ubr0(struct idt77252_dev *card)
+{
+       struct vc_map *vc = card->vcs[0];
+
+       free_scq(card, vc->scq);
+       kfree(vc);
+}
+
 static int
 idt77252_dev_open(struct idt77252_dev *card)
 {
@@ -3001,6 +3011,7 @@ static void idt77252_dev_close(struct atm_dev *dev)
        struct idt77252_dev *card = dev->dev_data;
        u32 conf;
 
+       close_card_ubr0(card);
        close_card_oam(card);
 
        conf = SAR_CFG_RXPTH |  /* enable receive path           */
index f6573c335f4c4c17b6d5277d3af75e9e31226409..f3903d002819e8ef9f7702a4670613319e342267 100644 (file)
@@ -474,12 +474,18 @@ int detect_cache_attributes(unsigned int cpu)
 
 populate_leaves:
        /*
-        * populate_cache_leaves() may completely setup the cache leaves and
-        * shared_cpu_map or it may leave it partially setup.
+        * If LLC is valid the cache leaves were already populated so just go to
+        * update the cpu map.
         */
-       ret = populate_cache_leaves(cpu);
-       if (ret)
-               goto free_ci;
+       if (!last_level_cache_is_valid(cpu)) {
+               /*
+                * populate_cache_leaves() may completely setup the cache leaves and
+                * shared_cpu_map or it may leave it partially setup.
+                */
+               ret = populate_cache_leaves(cpu);
+               if (ret)
+                       goto free_ci;
+       }
 
        /*
         * For systems using DT for cache hierarchy, fw_token
index 182c6122f8152b7b3822562c38e69b0cabc7fb0c..c1815b9dae68efc6810fce4560668f612d5a0db6 100644 (file)
@@ -487,7 +487,8 @@ static const struct attribute_group *cpu_root_attr_groups[] = {
 bool cpu_is_hotpluggable(unsigned int cpu)
 {
        struct device *dev = get_cpu_device(cpu);
-       return dev && container_of(dev, struct cpu, dev)->hotpluggable;
+       return dev && container_of(dev, struct cpu, dev)->hotpluggable
+               && tick_nohz_cpu_hotpluggable(cpu);
 }
 EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
 
index 60757ac31701d220ceb892e4b99f028ab9afdeab..f49f2a5282e1512d99eef768529b71d293b53d4c 100644 (file)
@@ -1615,7 +1615,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
                        drbd_send_sync_param(peer_device);
        }
 
-       kvfree_rcu(old_disk_conf);
+       kvfree_rcu_mightsleep(old_disk_conf);
        kfree(old_plan);
        mod_timer(&device->request_timer, jiffies + HZ);
        goto success;
@@ -2446,7 +2446,7 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
 
        mutex_unlock(&connection->resource->conf_update);
        mutex_unlock(&connection->data.mutex);
-       kvfree_rcu(old_net_conf);
+       kvfree_rcu_mightsleep(old_net_conf);
 
        if (connection->cstate >= C_WF_REPORT_PARAMS) {
                struct drbd_peer_device *peer_device;
@@ -2860,7 +2860,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info)
                new_disk_conf->disk_size = (sector_t)rs.resize_size;
                rcu_assign_pointer(device->ldev->disk_conf, new_disk_conf);
                mutex_unlock(&device->resource->conf_update);
-               kvfree_rcu(old_disk_conf);
+               kvfree_rcu_mightsleep(old_disk_conf);
                new_disk_conf = NULL;
        }
 
index 757f4692b5bd8034909b32334b27f5e952bb935e..e197b2a465d22986a1e9ecb7e273ba12640fde59 100644 (file)
@@ -3759,7 +3759,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in
                drbd_info(connection, "peer data-integrity-alg: %s\n",
                          integrity_alg[0] ? integrity_alg : "(none)");
 
-       kvfree_rcu(old_net_conf);
+       kvfree_rcu_mightsleep(old_net_conf);
        return 0;
 
 disconnect_rcu_unlock:
@@ -4127,7 +4127,7 @@ static int receive_sizes(struct drbd_connection *connection, struct packet_info
 
                        rcu_assign_pointer(device->ldev->disk_conf, new_disk_conf);
                        mutex_unlock(&connection->resource->conf_update);
-                       kvfree_rcu(old_disk_conf);
+                       kvfree_rcu_mightsleep(old_disk_conf);
 
                        drbd_info(device, "Peer sets u_size to %lu sectors (old: %lu)\n",
                                 (unsigned long)p_usize, (unsigned long)my_usize);
index 75d13ea0024f554a2d425c8f3c87ac72aae2c260..2aeea295fa28ec61f4bf62a4d9bd2c76c540970c 100644 (file)
@@ -2071,7 +2071,7 @@ static int w_after_conn_state_ch(struct drbd_work *w, int unused)
                conn_free_crypto(connection);
                mutex_unlock(&connection->resource->conf_update);
 
-               kvfree_rcu(old_conf);
+               kvfree_rcu_mightsleep(old_conf);
        }
 
        if (ns_max.susp_fen) {
index 839373451c2b7dc8d2db845decfeca198fce0452..bc31bb7072a2cb7294d32066f5d0aa14130349b4 100644 (file)
@@ -1010,9 +1010,6 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
        /* This is safe, since we have a reference from open(). */
        __module_get(THIS_MODULE);
 
-       /* suppress uevents while reconfiguring the device */
-       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
-
        /*
         * If we don't hold exclusive handle for the device, upgrade to it
         * here to avoid changing device under exclusive owner.
@@ -1067,6 +1064,9 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
                }
        }
 
+       /* suppress uevents while reconfiguring the device */
+       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1);
+
        disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE);
        set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0);
 
@@ -1109,17 +1109,17 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
        if (partscan)
                clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
 
+       /* enable and uncork uevent now that we are done */
+       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0);
+
        loop_global_unlock(lo, is_loop);
        if (partscan)
                loop_reread_partitions(lo);
+
        if (!(mode & FMODE_EXCL))
                bd_abort_claiming(bdev, loop_configure);
 
-       error = 0;
-done:
-       /* enable and uncork uevent now that we are done */
-       dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 0);
-       return error;
+       return 0;
 
 out_unlock:
        loop_global_unlock(lo, is_loop);
@@ -1130,7 +1130,7 @@ out_putf:
        fput(file);
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
-       goto done;
+       return error;
 }
 
 static void __loop_clr_fd(struct loop_device *lo, bool release)
@@ -1859,35 +1859,44 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
 
 static void loop_handle_cmd(struct loop_cmd *cmd)
 {
+       struct cgroup_subsys_state *cmd_blkcg_css = cmd->blkcg_css;
+       struct cgroup_subsys_state *cmd_memcg_css = cmd->memcg_css;
        struct request *rq = blk_mq_rq_from_pdu(cmd);
        const bool write = op_is_write(req_op(rq));
        struct loop_device *lo = rq->q->queuedata;
        int ret = 0;
        struct mem_cgroup *old_memcg = NULL;
+       const bool use_aio = cmd->use_aio;
 
        if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
                ret = -EIO;
                goto failed;
        }
 
-       if (cmd->blkcg_css)
-               kthread_associate_blkcg(cmd->blkcg_css);
-       if (cmd->memcg_css)
+       if (cmd_blkcg_css)
+               kthread_associate_blkcg(cmd_blkcg_css);
+       if (cmd_memcg_css)
                old_memcg = set_active_memcg(
-                       mem_cgroup_from_css(cmd->memcg_css));
+                       mem_cgroup_from_css(cmd_memcg_css));
 
+       /*
+        * do_req_filebacked() may call blk_mq_complete_request() synchronously
+        * or asynchronously if using aio. Hence, do not touch 'cmd' after
+        * do_req_filebacked() has returned unless we are sure that 'cmd' has
+        * not yet been completed.
+        */
        ret = do_req_filebacked(lo, rq);
 
-       if (cmd->blkcg_css)
+       if (cmd_blkcg_css)
                kthread_associate_blkcg(NULL);
 
-       if (cmd->memcg_css) {
+       if (cmd_memcg_css) {
                set_active_memcg(old_memcg);
-               css_put(cmd->memcg_css);
+               css_put(cmd_memcg_css);
        }
  failed:
        /* complete non-aio request */
-       if (!cmd->use_aio || ret) {
+       if (!use_aio || ret) {
                if (ret == -EOPNOTSUPP)
                        cmd->ret = ret;
                else
index 4c601ca9552a07dd4ae9828c6703d1dc3d694b4c..9e6b032c8ecc2c93a2dffb32dcdcb0e6100f575b 100644 (file)
@@ -1413,8 +1413,7 @@ static inline void nullb_complete_cmd(struct nullb_cmd *cmd)
        case NULL_IRQ_SOFTIRQ:
                switch (cmd->nq->dev->queue_mode) {
                case NULL_Q_MQ:
-                       if (likely(!blk_should_fake_timeout(cmd->rq->q)))
-                               blk_mq_complete_request(cmd->rq);
+                       blk_mq_complete_request(cmd->rq);
                        break;
                case NULL_Q_BIO:
                        /*
@@ -1658,12 +1657,13 @@ static enum blk_eh_timer_return null_timeout_rq(struct request *rq)
 }
 
 static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
-                        const struct blk_mq_queue_data *bd)
+                                 const struct blk_mq_queue_data *bd)
 {
-       struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
+       struct request *rq = bd->rq;
+       struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq);
        struct nullb_queue *nq = hctx->driver_data;
-       sector_t nr_sectors = blk_rq_sectors(bd->rq);
-       sector_t sector = blk_rq_pos(bd->rq);
+       sector_t nr_sectors = blk_rq_sectors(rq);
+       sector_t sector = blk_rq_pos(rq);
        const bool is_poll = hctx->type == HCTX_TYPE_POLL;
 
        might_sleep_if(hctx->flags & BLK_MQ_F_BLOCKING);
@@ -1672,14 +1672,15 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
                hrtimer_init(&cmd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                cmd->timer.function = null_cmd_timer_expired;
        }
-       cmd->rq = bd->rq;
+       cmd->rq = rq;
        cmd->error = BLK_STS_OK;
        cmd->nq = nq;
-       cmd->fake_timeout = should_timeout_request(bd->rq);
+       cmd->fake_timeout = should_timeout_request(rq) ||
+               blk_should_fake_timeout(rq->q);
 
-       blk_mq_start_request(bd->rq);
+       blk_mq_start_request(rq);
 
-       if (should_requeue_request(bd->rq)) {
+       if (should_requeue_request(rq)) {
                /*
                 * Alternate between hitting the core BUSY path, and the
                 * driver driven requeue path
@@ -1687,22 +1688,20 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx,
                nq->requeue_selection++;
                if (nq->requeue_selection & 1)
                        return BLK_STS_RESOURCE;
-               else {
-                       blk_mq_requeue_request(bd->rq, true);
-                       return BLK_STS_OK;
-               }
+               blk_mq_requeue_request(rq, true);
+               return BLK_STS_OK;
        }
 
        if (is_poll) {
                spin_lock(&nq->poll_lock);
-               list_add_tail(&bd->rq->queuelist, &nq->poll_list);
+               list_add_tail(&rq->queuelist, &nq->poll_list);
                spin_unlock(&nq->poll_lock);
                return BLK_STS_OK;
        }
        if (cmd->fake_timeout)
                return BLK_STS_OK;
 
-       return null_handle_cmd(cmd, sector, nr_sectors, req_op(bd->rq));
+       return null_handle_cmd(cmd, sector, nr_sectors, req_op(rq));
 }
 
 static void cleanup_queue(struct nullb_queue *nq)
index fb855da971ee7b388efd1f385fe6c929bda97d4f..9fa821fa76b07b47d673f7d57c591fc8e5ddd4a9 100644 (file)
@@ -972,6 +972,8 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        print_version();
 
        hp = mdesc_grab();
+       if (!hp)
+               return -ENODEV;
 
        err = -ENODEV;
        if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) {
index d1d1c8d606c8d8e9c79f094ffc626e2909df7b14..604c1a13c76efce3a2a3641ac5bf57d68775629d 100644 (file)
@@ -246,7 +246,7 @@ static int ublk_validate_params(const struct ublk_device *ub)
        if (ub->params.types & UBLK_PARAM_TYPE_BASIC) {
                const struct ublk_param_basic *p = &ub->params.basic;
 
-               if (p->logical_bs_shift > PAGE_SHIFT)
+               if (p->logical_bs_shift > PAGE_SHIFT || p->logical_bs_shift < 9)
                        return -EINVAL;
 
                if (p->logical_bs_shift > p->physical_bs_shift)
@@ -715,7 +715,8 @@ static void __ublk_fail_req(struct ublk_queue *ubq, struct ublk_io *io,
        }
 }
 
-static void ubq_complete_io_cmd(struct ublk_io *io, int res)
+static void ubq_complete_io_cmd(struct ublk_io *io, int res,
+                               unsigned issue_flags)
 {
        /* mark this cmd owned by ublksrv */
        io->flags |= UBLK_IO_FLAG_OWNED_BY_SRV;
@@ -727,7 +728,7 @@ static void ubq_complete_io_cmd(struct ublk_io *io, int res)
        io->flags &= ~UBLK_IO_FLAG_ACTIVE;
 
        /* tell ublksrv one io request is coming */
-       io_uring_cmd_done(io->cmd, res, 0);
+       io_uring_cmd_done(io->cmd, res, 0, issue_flags);
 }
 
 #define UBLK_REQUEUE_DELAY_MS  3
@@ -744,7 +745,8 @@ static inline void __ublk_abort_rq(struct ublk_queue *ubq,
        mod_delayed_work(system_wq, &ubq->dev->monitor_work, 0);
 }
 
-static inline void __ublk_rq_task_work(struct request *req)
+static inline void __ublk_rq_task_work(struct request *req,
+                                      unsigned issue_flags)
 {
        struct ublk_queue *ubq = req->mq_hctx->driver_data;
        int tag = req->tag;
@@ -782,7 +784,7 @@ static inline void __ublk_rq_task_work(struct request *req)
                        pr_devel("%s: need get data. op %d, qid %d tag %d io_flags %x\n",
                                        __func__, io->cmd->cmd_op, ubq->q_id,
                                        req->tag, io->flags);
-                       ubq_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA);
+                       ubq_complete_io_cmd(io, UBLK_IO_RES_NEED_GET_DATA, issue_flags);
                        return;
                }
                /*
@@ -820,17 +822,18 @@ static inline void __ublk_rq_task_work(struct request *req)
                        mapped_bytes >> 9;
        }
 
-       ubq_complete_io_cmd(io, UBLK_IO_RES_OK);
+       ubq_complete_io_cmd(io, UBLK_IO_RES_OK, issue_flags);
 }
 
-static inline void ublk_forward_io_cmds(struct ublk_queue *ubq)
+static inline void ublk_forward_io_cmds(struct ublk_queue *ubq,
+                                       unsigned issue_flags)
 {
        struct llist_node *io_cmds = llist_del_all(&ubq->io_cmds);
        struct ublk_rq_data *data, *tmp;
 
        io_cmds = llist_reverse_order(io_cmds);
        llist_for_each_entry_safe(data, tmp, io_cmds, node)
-               __ublk_rq_task_work(blk_mq_rq_from_pdu(data));
+               __ublk_rq_task_work(blk_mq_rq_from_pdu(data), issue_flags);
 }
 
 static inline void ublk_abort_io_cmds(struct ublk_queue *ubq)
@@ -842,12 +845,12 @@ static inline void ublk_abort_io_cmds(struct ublk_queue *ubq)
                __ublk_abort_rq(ubq, blk_mq_rq_from_pdu(data));
 }
 
-static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd)
+static void ublk_rq_task_work_cb(struct io_uring_cmd *cmd, unsigned issue_flags)
 {
        struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd);
        struct ublk_queue *ubq = pdu->ubq;
 
-       ublk_forward_io_cmds(ubq);
+       ublk_forward_io_cmds(ubq, issue_flags);
 }
 
 static void ublk_rq_task_work_fn(struct callback_head *work)
@@ -856,8 +859,9 @@ static void ublk_rq_task_work_fn(struct callback_head *work)
                        struct ublk_rq_data, work);
        struct request *req = blk_mq_rq_from_pdu(data);
        struct ublk_queue *ubq = req->mq_hctx->driver_data;
+       unsigned issue_flags = IO_URING_F_UNLOCKED;
 
-       ublk_forward_io_cmds(ubq);
+       ublk_forward_io_cmds(ubq, issue_flags);
 }
 
 static void ublk_queue_cmd(struct ublk_queue *ubq, struct request *rq)
@@ -1111,7 +1115,8 @@ static void ublk_cancel_queue(struct ublk_queue *ubq)
                struct ublk_io *io = &ubq->ios[i];
 
                if (io->flags & UBLK_IO_FLAG_ACTIVE)
-                       io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0);
+                       io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0,
+                                               IO_URING_F_UNLOCKED);
        }
 
        /* all io commands are canceled */
@@ -1256,9 +1261,10 @@ static void ublk_handle_need_get_data(struct ublk_device *ub, int q_id,
        ublk_queue_cmd(ubq, req);
 }
 
-static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
+                              unsigned int issue_flags,
+                              struct ublksrv_io_cmd *ub_cmd)
 {
-       struct ublksrv_io_cmd *ub_cmd = (struct ublksrv_io_cmd *)cmd->cmd;
        struct ublk_device *ub = cmd->file->private_data;
        struct ublk_queue *ubq;
        struct ublk_io *io;
@@ -1351,12 +1357,29 @@ static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
        return -EIOCBQUEUED;
 
  out:
-       io_uring_cmd_done(cmd, ret, 0);
+       io_uring_cmd_done(cmd, ret, 0, issue_flags);
        pr_devel("%s: complete: cmd op %d, tag %d ret %x io_flags %x\n",
                        __func__, cmd_op, tag, ret, io->flags);
        return -EIOCBQUEUED;
 }
 
+static int ublk_ch_uring_cmd(struct io_uring_cmd *cmd, unsigned int issue_flags)
+{
+       struct ublksrv_io_cmd *ub_src = (struct ublksrv_io_cmd *) cmd->cmd;
+       struct ublksrv_io_cmd ub_cmd;
+
+       /*
+        * Not necessary for async retry, but let's keep it simple and always
+        * copy the values to avoid any potential reuse.
+        */
+       ub_cmd.q_id = READ_ONCE(ub_src->q_id);
+       ub_cmd.tag = READ_ONCE(ub_src->tag);
+       ub_cmd.result = READ_ONCE(ub_src->result);
+       ub_cmd.addr = READ_ONCE(ub_src->addr);
+
+       return __ublk_ch_uring_cmd(cmd, issue_flags, &ub_cmd);
+}
+
 static const struct file_operations ublk_ch_fops = {
        .owner = THIS_MODULE,
        .open = ublk_ch_open,
@@ -1602,17 +1625,18 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
                set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
 
        get_device(&ub->cdev_dev);
+       ub->dev_info.state = UBLK_S_DEV_LIVE;
        ret = add_disk(disk);
        if (ret) {
                /*
                 * Has to drop the reference since ->free_disk won't be
                 * called in case of add_disk failure.
                 */
+               ub->dev_info.state = UBLK_S_DEV_DEAD;
                ublk_put_device(ub);
                goto out_put_disk;
        }
        set_bit(UB_STATE_USED, &ub->state);
-       ub->dev_info.state = UBLK_S_DEV_LIVE;
 out_put_disk:
        if (ret)
                put_disk(disk);
@@ -1946,6 +1970,8 @@ static int ublk_ctrl_set_params(struct ublk_device *ub,
                /* clear all we don't support yet */
                ub->params.types &= UBLK_PARAM_TYPE_ALL;
                ret = ublk_validate_params(ub);
+               if (ret)
+                       ub->params.types = 0;
        }
        mutex_unlock(&ub->mutex);
 
@@ -2233,7 +2259,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
        if (ub)
                ublk_put_device(ub);
  out:
-       io_uring_cmd_done(cmd, ret, 0);
+       io_uring_cmd_done(cmd, ret, 0, issue_flags);
        pr_devel("%s: cmd done ret %d cmd_op %x, dev id %d qid %d\n",
                        __func__, ret, cmd->cmd_op, header->dev_id, header->queue_id);
        return -EIOCBQUEUED;
index 2723eede6f217ea1f8fdf8e46a7965d12fe22ba9..2b918e28acaacd973221e56344977053072f7f7d 100644 (file)
@@ -96,16 +96,14 @@ struct virtblk_req {
 
                /*
                 * The zone append command has an extended in header.
-                * The status field in zone_append_in_hdr must have
-                * the same offset in virtblk_req as the non-zoned
-                * status field above.
+                * The status field in zone_append_in_hdr must always
+                * be the last byte.
                 */
                struct {
+                       __virtio64 sector;
                        u8 status;
-                       u8 reserved[7];
-                       __le64 append_sector;
-               } zone_append_in_hdr;
-       };
+               } zone_append;
+       } in_hdr;
 
        size_t in_hdr_len;
 
@@ -154,7 +152,7 @@ static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr)
                        sgs[num_out + num_in++] = vbr->sg_table.sgl;
        }
 
-       sg_init_one(&in_hdr, &vbr->status, vbr->in_hdr_len);
+       sg_init_one(&in_hdr, &vbr->in_hdr.status, vbr->in_hdr_len);
        sgs[num_out + num_in++] = &in_hdr;
 
        return virtqueue_add_sgs(vq, sgs, num_out, num_in, vbr, GFP_ATOMIC);
@@ -242,11 +240,14 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
                                      struct request *req,
                                      struct virtblk_req *vbr)
 {
-       size_t in_hdr_len = sizeof(vbr->status);
+       size_t in_hdr_len = sizeof(vbr->in_hdr.status);
        bool unmap = false;
        u32 type;
        u64 sector = 0;
 
+       if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) && op_is_zone_mgmt(req_op(req)))
+               return BLK_STS_NOTSUPP;
+
        /* Set fields for all request types */
        vbr->out_hdr.ioprio = cpu_to_virtio32(vdev, req_get_ioprio(req));
 
@@ -287,7 +288,7 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
        case REQ_OP_ZONE_APPEND:
                type = VIRTIO_BLK_T_ZONE_APPEND;
                sector = blk_rq_pos(req);
-               in_hdr_len = sizeof(vbr->zone_append_in_hdr);
+               in_hdr_len = sizeof(vbr->in_hdr.zone_append);
                break;
        case REQ_OP_ZONE_RESET:
                type = VIRTIO_BLK_T_ZONE_RESET;
@@ -297,7 +298,10 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
                type = VIRTIO_BLK_T_ZONE_RESET_ALL;
                break;
        case REQ_OP_DRV_IN:
-               /* Out header already filled in, nothing to do */
+               /*
+                * Out header has already been prepared by the caller (virtblk_get_id()
+                * or virtblk_submit_zone_report()), nothing to do here.
+                */
                return 0;
        default:
                WARN_ON_ONCE(1);
@@ -318,16 +322,28 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
        return 0;
 }
 
+/*
+ * The status byte is always the last byte of the virtblk request
+ * in-header. This helper fetches its value for all in-header formats
+ * that are currently defined.
+ */
+static inline u8 virtblk_vbr_status(struct virtblk_req *vbr)
+{
+       return *((u8 *)&vbr->in_hdr + vbr->in_hdr_len - 1);
+}
+
 static inline void virtblk_request_done(struct request *req)
 {
        struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
-       blk_status_t status = virtblk_result(vbr->status);
+       blk_status_t status = virtblk_result(virtblk_vbr_status(vbr));
+       struct virtio_blk *vblk = req->mq_hctx->queue->queuedata;
 
        virtblk_unmap_data(req, vbr);
        virtblk_cleanup_cmd(req);
 
        if (req_op(req) == REQ_OP_ZONE_APPEND)
-               req->__sector = le64_to_cpu(vbr->zone_append_in_hdr.append_sector);
+               req->__sector = virtio64_to_cpu(vblk->vdev,
+                                               vbr->in_hdr.zone_append.sector);
 
        blk_mq_end_request(req, status);
 }
@@ -355,7 +371,7 @@ static int virtblk_handle_req(struct virtio_blk_vq *vq,
 
                if (likely(!blk_should_fake_timeout(req->q)) &&
                    !blk_mq_complete_request_remote(req) &&
-                   !blk_mq_add_to_batch(req, iob, vbr->status,
+                   !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
                                         virtblk_complete_batch))
                        virtblk_request_done(req);
                req_done++;
@@ -550,7 +566,6 @@ static void virtio_queue_rqs(struct request **rqlist)
 #ifdef CONFIG_BLK_DEV_ZONED
 static void *virtblk_alloc_report_buffer(struct virtio_blk *vblk,
                                          unsigned int nr_zones,
-                                         unsigned int zone_sectors,
                                          size_t *buflen)
 {
        struct request_queue *q = vblk->disk->queue;
@@ -558,7 +573,7 @@ static void *virtblk_alloc_report_buffer(struct virtio_blk *vblk,
        void *buf;
 
        nr_zones = min_t(unsigned int, nr_zones,
-                        get_capacity(vblk->disk) >> ilog2(zone_sectors));
+                        get_capacity(vblk->disk) >> ilog2(vblk->zone_sectors));
 
        bufsize = sizeof(struct virtio_blk_zone_report) +
                nr_zones * sizeof(struct virtio_blk_zone_descriptor);
@@ -592,7 +607,7 @@ static int virtblk_submit_zone_report(struct virtio_blk *vblk,
                return PTR_ERR(req);
 
        vbr = blk_mq_rq_to_pdu(req);
-       vbr->in_hdr_len = sizeof(vbr->status);
+       vbr->in_hdr_len = sizeof(vbr->in_hdr.status);
        vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_ZONE_REPORT);
        vbr->out_hdr.sector = cpu_to_virtio64(vblk->vdev, sector);
 
@@ -601,7 +616,7 @@ static int virtblk_submit_zone_report(struct virtio_blk *vblk,
                goto out;
 
        blk_execute_rq(req, false);
-       err = blk_status_to_errno(virtblk_result(vbr->status));
+       err = blk_status_to_errno(virtblk_result(vbr->in_hdr.status));
 out:
        blk_mq_free_request(req);
        return err;
@@ -609,29 +624,72 @@ out:
 
 static int virtblk_parse_zone(struct virtio_blk *vblk,
                               struct virtio_blk_zone_descriptor *entry,
-                              unsigned int idx, unsigned int zone_sectors,
-                              report_zones_cb cb, void *data)
+                              unsigned int idx, report_zones_cb cb, void *data)
 {
        struct blk_zone zone = { };
 
-       if (entry->z_type != VIRTIO_BLK_ZT_SWR &&
-           entry->z_type != VIRTIO_BLK_ZT_SWP &&
-           entry->z_type != VIRTIO_BLK_ZT_CONV) {
-               dev_err(&vblk->vdev->dev, "invalid zone type %#x\n",
-                       entry->z_type);
-               return -EINVAL;
+       zone.start = virtio64_to_cpu(vblk->vdev, entry->z_start);
+       if (zone.start + vblk->zone_sectors <= get_capacity(vblk->disk))
+               zone.len = vblk->zone_sectors;
+       else
+               zone.len = get_capacity(vblk->disk) - zone.start;
+       zone.capacity = virtio64_to_cpu(vblk->vdev, entry->z_cap);
+       zone.wp = virtio64_to_cpu(vblk->vdev, entry->z_wp);
+
+       switch (entry->z_type) {
+       case VIRTIO_BLK_ZT_SWR:
+               zone.type = BLK_ZONE_TYPE_SEQWRITE_REQ;
+               break;
+       case VIRTIO_BLK_ZT_SWP:
+               zone.type = BLK_ZONE_TYPE_SEQWRITE_PREF;
+               break;
+       case VIRTIO_BLK_ZT_CONV:
+               zone.type = BLK_ZONE_TYPE_CONVENTIONAL;
+               break;
+       default:
+               dev_err(&vblk->vdev->dev, "zone %llu: invalid type %#x\n",
+                       zone.start, entry->z_type);
+               return -EIO;
        }
 
-       zone.type = entry->z_type;
-       zone.cond = entry->z_state;
-       zone.len = zone_sectors;
-       zone.capacity = le64_to_cpu(entry->z_cap);
-       zone.start = le64_to_cpu(entry->z_start);
-       if (zone.cond == BLK_ZONE_COND_FULL)
+       switch (entry->z_state) {
+       case VIRTIO_BLK_ZS_EMPTY:
+               zone.cond = BLK_ZONE_COND_EMPTY;
+               break;
+       case VIRTIO_BLK_ZS_CLOSED:
+               zone.cond = BLK_ZONE_COND_CLOSED;
+               break;
+       case VIRTIO_BLK_ZS_FULL:
+               zone.cond = BLK_ZONE_COND_FULL;
                zone.wp = zone.start + zone.len;
-       else
-               zone.wp = le64_to_cpu(entry->z_wp);
+               break;
+       case VIRTIO_BLK_ZS_EOPEN:
+               zone.cond = BLK_ZONE_COND_EXP_OPEN;
+               break;
+       case VIRTIO_BLK_ZS_IOPEN:
+               zone.cond = BLK_ZONE_COND_IMP_OPEN;
+               break;
+       case VIRTIO_BLK_ZS_NOT_WP:
+               zone.cond = BLK_ZONE_COND_NOT_WP;
+               break;
+       case VIRTIO_BLK_ZS_RDONLY:
+               zone.cond = BLK_ZONE_COND_READONLY;
+               zone.wp = ULONG_MAX;
+               break;
+       case VIRTIO_BLK_ZS_OFFLINE:
+               zone.cond = BLK_ZONE_COND_OFFLINE;
+               zone.wp = ULONG_MAX;
+               break;
+       default:
+               dev_err(&vblk->vdev->dev, "zone %llu: invalid condition %#x\n",
+                       zone.start, entry->z_state);
+               return -EIO;
+       }
 
+       /*
+        * The callback below checks the validity of the reported
+        * entry data, no need to further validate it here.
+        */
        return cb(&zone, idx, data);
 }
 
@@ -641,39 +699,47 @@ static int virtblk_report_zones(struct gendisk *disk, sector_t sector,
 {
        struct virtio_blk *vblk = disk->private_data;
        struct virtio_blk_zone_report *report;
-       unsigned int zone_sectors = vblk->zone_sectors;
-       unsigned int nz, i;
-       int ret, zone_idx = 0;
+       unsigned long long nz, i;
        size_t buflen;
+       unsigned int zone_idx = 0;
+       int ret;
 
        if (WARN_ON_ONCE(!vblk->zone_sectors))
                return -EOPNOTSUPP;
 
-       report = virtblk_alloc_report_buffer(vblk, nr_zones,
-                                            zone_sectors, &buflen);
+       report = virtblk_alloc_report_buffer(vblk, nr_zones, &buflen);
        if (!report)
                return -ENOMEM;
 
+       mutex_lock(&vblk->vdev_mutex);
+
+       if (!vblk->vdev) {
+               ret = -ENXIO;
+               goto fail_report;
+       }
+
        while (zone_idx < nr_zones && sector < get_capacity(vblk->disk)) {
                memset(report, 0, buflen);
 
                ret = virtblk_submit_zone_report(vblk, (char *)report,
                                                 buflen, sector);
-               if (ret) {
-                       if (ret > 0)
-                               ret = -EIO;
-                       goto out_free;
-               }
-               nz = min((unsigned int)le64_to_cpu(report->nr_zones), nr_zones);
+               if (ret)
+                       goto fail_report;
+
+               nz = min_t(u64, virtio64_to_cpu(vblk->vdev, report->nr_zones),
+                          nr_zones);
                if (!nz)
                        break;
 
                for (i = 0; i < nz && zone_idx < nr_zones; i++) {
                        ret = virtblk_parse_zone(vblk, &report->zones[i],
-                                                zone_idx, zone_sectors, cb, data);
+                                                zone_idx, cb, data);
                        if (ret)
-                               goto out_free;
-                       sector = le64_to_cpu(report->zones[i].z_start) + zone_sectors;
+                               goto fail_report;
+
+                       sector = virtio64_to_cpu(vblk->vdev,
+                                                report->zones[i].z_start) +
+                                vblk->zone_sectors;
                        zone_idx++;
                }
        }
@@ -682,7 +748,8 @@ static int virtblk_report_zones(struct gendisk *disk, sector_t sector,
                ret = zone_idx;
        else
                ret = -EINVAL;
-out_free:
+fail_report:
+       mutex_unlock(&vblk->vdev_mutex);
        kvfree(report);
        return ret;
 }
@@ -691,20 +758,28 @@ static void virtblk_revalidate_zones(struct virtio_blk *vblk)
 {
        u8 model;
 
-       if (!vblk->zone_sectors)
-               return;
-
        virtio_cread(vblk->vdev, struct virtio_blk_config,
                     zoned.model, &model);
-       if (!blk_revalidate_disk_zones(vblk->disk, NULL))
-               set_capacity_and_notify(vblk->disk, 0);
+       switch (model) {
+       default:
+               dev_err(&vblk->vdev->dev, "unknown zone model %d\n", model);
+               fallthrough;
+       case VIRTIO_BLK_Z_NONE:
+       case VIRTIO_BLK_Z_HA:
+               disk_set_zoned(vblk->disk, BLK_ZONED_NONE);
+               return;
+       case VIRTIO_BLK_Z_HM:
+               WARN_ON_ONCE(!vblk->zone_sectors);
+               if (!blk_revalidate_disk_zones(vblk->disk, NULL))
+                       set_capacity_and_notify(vblk->disk, 0);
+       }
 }
 
 static int virtblk_probe_zoned_device(struct virtio_device *vdev,
                                       struct virtio_blk *vblk,
                                       struct request_queue *q)
 {
-       u32 v;
+       u32 v, wg;
        u8 model;
        int ret;
 
@@ -713,16 +788,11 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
 
        switch (model) {
        case VIRTIO_BLK_Z_NONE:
+       case VIRTIO_BLK_Z_HA:
+               /* Present the host-aware device as non-zoned */
                return 0;
        case VIRTIO_BLK_Z_HM:
                break;
-       case VIRTIO_BLK_Z_HA:
-               /*
-                * Present the host-aware device as a regular drive.
-                * TODO It is possible to add an option to make it appear
-                * in the system as a zoned drive.
-                */
-               return 0;
        default:
                dev_err(&vdev->dev, "unsupported zone model %d\n", model);
                return -EINVAL;
@@ -735,32 +805,31 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
 
        virtio_cread(vdev, struct virtio_blk_config,
                     zoned.max_open_zones, &v);
-       disk_set_max_open_zones(vblk->disk, le32_to_cpu(v));
-
-       dev_dbg(&vdev->dev, "max open zones = %u\n", le32_to_cpu(v));
+       disk_set_max_open_zones(vblk->disk, v);
+       dev_dbg(&vdev->dev, "max open zones = %u\n", v);
 
        virtio_cread(vdev, struct virtio_blk_config,
                     zoned.max_active_zones, &v);
-       disk_set_max_active_zones(vblk->disk, le32_to_cpu(v));
-       dev_dbg(&vdev->dev, "max active zones = %u\n", le32_to_cpu(v));
+       disk_set_max_active_zones(vblk->disk, v);
+       dev_dbg(&vdev->dev, "max active zones = %u\n", v);
 
        virtio_cread(vdev, struct virtio_blk_config,
-                    zoned.write_granularity, &v);
-       if (!v) {
+                    zoned.write_granularity, &wg);
+       if (!wg) {
                dev_warn(&vdev->dev, "zero write granularity reported\n");
                return -ENODEV;
        }
-       blk_queue_physical_block_size(q, le32_to_cpu(v));
-       blk_queue_io_min(q, le32_to_cpu(v));
+       blk_queue_physical_block_size(q, wg);
+       blk_queue_io_min(q, wg);
 
-       dev_dbg(&vdev->dev, "write granularity = %u\n", le32_to_cpu(v));
+       dev_dbg(&vdev->dev, "write granularity = %u\n", wg);
 
        /*
         * virtio ZBD specification doesn't require zones to be a power of
         * two sectors in size, but the code in this driver expects that.
         */
-       virtio_cread(vdev, struct virtio_blk_config, zoned.zone_sectors, &v);
-       vblk->zone_sectors = le32_to_cpu(v);
+       virtio_cread(vdev, struct virtio_blk_config, zoned.zone_sectors,
+                    &vblk->zone_sectors);
        if (vblk->zone_sectors == 0 || !is_power_of_2(vblk->zone_sectors)) {
                dev_err(&vdev->dev,
                        "zoned device with non power of two zone size %u\n",
@@ -783,36 +852,46 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
                        dev_warn(&vdev->dev, "zero max_append_sectors reported\n");
                        return -ENODEV;
                }
-               blk_queue_max_zone_append_sectors(q, le32_to_cpu(v));
-               dev_dbg(&vdev->dev, "max append sectors = %u\n", le32_to_cpu(v));
+               if ((v << SECTOR_SHIFT) < wg) {
+                       dev_err(&vdev->dev,
+                               "write granularity %u exceeds max_append_sectors %u limit\n",
+                               wg, v);
+                       return -ENODEV;
+               }
+
+               blk_queue_max_zone_append_sectors(q, v);
+               dev_dbg(&vdev->dev, "max append sectors = %u\n", v);
        }
 
        return ret;
 }
 
-static inline bool virtblk_has_zoned_feature(struct virtio_device *vdev)
-{
-       return virtio_has_feature(vdev, VIRTIO_BLK_F_ZONED);
-}
 #else
 
 /*
  * Zoned block device support is not configured in this kernel.
- * We only need to define a few symbols to avoid compilation errors.
+ * Host-managed zoned devices can't be supported, but others are
+ * good to go as regular block devices.
  */
 #define virtblk_report_zones       NULL
+
 static inline void virtblk_revalidate_zones(struct virtio_blk *vblk)
 {
 }
+
 static inline int virtblk_probe_zoned_device(struct virtio_device *vdev,
                        struct virtio_blk *vblk, struct request_queue *q)
 {
-       return -EOPNOTSUPP;
-}
+       u8 model;
 
-static inline bool virtblk_has_zoned_feature(struct virtio_device *vdev)
-{
-       return false;
+       virtio_cread(vdev, struct virtio_blk_config, zoned.model, &model);
+       if (model == VIRTIO_BLK_Z_HM) {
+               dev_err(&vdev->dev,
+                       "virtio_blk: zoned devices are not supported");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
 }
 #endif /* CONFIG_BLK_DEV_ZONED */
 
@@ -831,7 +910,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
                return PTR_ERR(req);
 
        vbr = blk_mq_rq_to_pdu(req);
-       vbr->in_hdr_len = sizeof(vbr->status);
+       vbr->in_hdr_len = sizeof(vbr->in_hdr.status);
        vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_ID);
        vbr->out_hdr.sector = 0;
 
@@ -840,7 +919,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
                goto out;
 
        blk_execute_rq(req, false);
-       err = blk_status_to_errno(virtblk_result(vbr->status));
+       err = blk_status_to_errno(virtblk_result(vbr->in_hdr.status));
 out:
        blk_mq_free_request(req);
        return err;
@@ -1498,15 +1577,16 @@ static int virtblk_probe(struct virtio_device *vdev)
        virtblk_update_capacity(vblk, false);
        virtio_device_ready(vdev);
 
-       if (virtblk_has_zoned_feature(vdev)) {
+       /*
+        * All steps that follow use the VQs therefore they need to be
+        * placed after the virtio_device_ready() call above.
+        */
+       if (virtio_has_feature(vdev, VIRTIO_BLK_F_ZONED)) {
                err = virtblk_probe_zoned_device(vdev, vblk, q);
                if (err)
                        goto out_cleanup_disk;
        }
 
-       dev_info(&vdev->dev, "blk config size: %zu\n",
-               sizeof(struct virtio_blk_config));
-
        err = device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
        if (err)
                goto out_cleanup_disk;
@@ -1607,10 +1687,7 @@ static unsigned int features[] = {
        VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
        VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
        VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES,
-       VIRTIO_BLK_F_SECURE_ERASE,
-#ifdef CONFIG_BLK_DEV_ZONED
-       VIRTIO_BLK_F_ZONED,
-#endif /* CONFIG_BLK_DEV_ZONED */
+       VIRTIO_BLK_F_SECURE_ERASE, VIRTIO_BLK_F_ZONED,
 };
 
 static struct virtio_driver virtio_blk = {
index 3006e2a0f37e1fa960f454ea0376f7e4e758c539..43e98a598bd9a51994bbbed072ad98b0f1a696b2 100644 (file)
@@ -511,7 +511,7 @@ static const char *btbcm_get_board_name(struct device *dev)
        len = strlen(tmp) + 1;
        board_type = devm_kzalloc(dev, len, GFP_KERNEL);
        strscpy(board_type, tmp, len);
-       for (i = 0; i < board_type[i]; i++) {
+       for (i = 0; i < len; i++) {
                if (board_type[i] == '/')
                        board_type[i] = '-';
        }
index bede8b0055940b69ad75c5f02aa6722d26627836..af774688f1c0dacf18e6cce1749c558bfcd6bd3f 100644 (file)
 #define ECDSA_HEADER_LEN       320
 
 #define BTINTEL_PPAG_NAME   "PPAG"
-#define BTINTEL_PPAG_PREFIX "\\_SB_.PCI0.XHCI.RHUB"
+
+/* structure to store the PPAG data read from ACPI table */
+struct btintel_ppag {
+       u32     domain;
+       u32     mode;
+       acpi_status status;
+       struct hci_dev *hdev;
+};
 
 #define CMD_WRITE_BOOT_PARAMS  0xfc0e
 struct cmd_write_boot_params {
@@ -1295,17 +1302,16 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
        if (ACPI_FAILURE(status)) {
-               bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
+               bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status));
                return status;
        }
 
-       if (strncmp(BTINTEL_PPAG_PREFIX, string.pointer,
-                   strlen(BTINTEL_PPAG_PREFIX))) {
+       len = strlen(string.pointer);
+       if (len < strlen(BTINTEL_PPAG_NAME)) {
                kfree(string.pointer);
                return AE_OK;
        }
 
-       len = strlen(string.pointer);
        if (strncmp((char *)string.pointer + len - 4, BTINTEL_PPAG_NAME, 4)) {
                kfree(string.pointer);
                return AE_OK;
@@ -1314,7 +1320,8 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
        if (ACPI_FAILURE(status)) {
-               bt_dev_warn(hdev, "ACPI Failure: %s", acpi_format_exception(status));
+               ppag->status = status;
+               bt_dev_warn(hdev, "PPAG-BT: ACPI Failure: %s", acpi_format_exception(status));
                return status;
        }
 
@@ -1323,8 +1330,9 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        if (p->type != ACPI_TYPE_PACKAGE || p->package.count != 2) {
                kfree(buffer.pointer);
-               bt_dev_warn(hdev, "Invalid object type: %d or package count: %d",
+               bt_dev_warn(hdev, "PPAG-BT: Invalid object type: %d or package count: %d",
                            p->type, p->package.count);
+               ppag->status = AE_ERROR;
                return AE_ERROR;
        }
 
@@ -1335,6 +1343,7 @@ static acpi_status btintel_ppag_callback(acpi_handle handle, u32 lvl, void *data
 
        ppag->domain = (u32)p->package.elements[0].integer.value;
        ppag->mode = (u32)p->package.elements[1].integer.value;
+       ppag->status = AE_OK;
        kfree(buffer.pointer);
        return AE_CTRL_TERMINATE;
 }
@@ -2314,12 +2323,12 @@ error:
 
 static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver)
 {
-       acpi_status status;
        struct btintel_ppag ppag;
        struct sk_buff *skb;
        struct btintel_loc_aware_reg ppag_cmd;
+       acpi_handle handle;
 
-    /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
+       /* PPAG is not supported if CRF is HrP2, Jfp2, JfP1 */
        switch (ver->cnvr_top & 0xFFF) {
        case 0x504:     /* Hrp2 */
        case 0x202:     /* Jfp2 */
@@ -2327,29 +2336,35 @@ static void btintel_set_ppag(struct hci_dev *hdev, struct intel_version_tlv *ver
                return;
        }
 
+       handle = ACPI_HANDLE(GET_HCIDEV_DEV(hdev));
+       if (!handle) {
+               bt_dev_info(hdev, "No support for BT device in ACPI firmware");
+               return;
+       }
+
        memset(&ppag, 0, sizeof(ppag));
 
        ppag.hdev = hdev;
-       status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-                                    ACPI_UINT32_MAX, NULL,
-                                    btintel_ppag_callback, &ppag, NULL);
+       ppag.status = AE_NOT_FOUND;
+       acpi_walk_namespace(ACPI_TYPE_PACKAGE, handle, 1, NULL,
+                           btintel_ppag_callback, &ppag, NULL);
 
-       if (ACPI_FAILURE(status)) {
-               /* Do not log warning message if ACPI entry is not found */
-               if (status == AE_NOT_FOUND)
+       if (ACPI_FAILURE(ppag.status)) {
+               if (ppag.status == AE_NOT_FOUND) {
+                       bt_dev_dbg(hdev, "PPAG-BT: ACPI entry not found");
                        return;
-               bt_dev_warn(hdev, "PPAG: ACPI Failure: %s", acpi_format_exception(status));
+               }
                return;
        }
 
        if (ppag.domain != 0x12) {
-               bt_dev_warn(hdev, "PPAG-BT Domain disabled");
+               bt_dev_warn(hdev, "PPAG-BT: domain is not bluetooth");
                return;
        }
 
        /* PPAG mode, BIT0 = 0 Disabled, BIT0 = 1 Enabled */
        if (!(ppag.mode & BIT(0))) {
-               bt_dev_dbg(hdev, "PPAG disabled");
+               bt_dev_dbg(hdev, "PPAG-BT: disabled");
                return;
        }
 
index 8e7da877efae6a8f114c0b1e95c654a96889a129..8fdb65b66315a7c93d5794a14dfd6e3a894de4fc 100644 (file)
@@ -137,13 +137,6 @@ struct intel_offload_use_cases {
        __u8    preset[8];
 } __packed;
 
-/* structure to store the PPAG data read from ACPI table */
-struct btintel_ppag {
-       u32     domain;
-       u32     mode;
-       struct hci_dev *hdev;
-};
-
 struct btintel_loc_aware_reg {
        __le32 mcc;
        __le32 sel;
index 2acb719e596f59e930c520b5030f0c6d0e5a55cb..11c7e04bf3947e37039e32cbe234b9cabec2e6e6 100644 (file)
@@ -122,6 +122,21 @@ static int btqcomsmd_setup(struct hci_dev *hdev)
        return 0;
 }
 
+static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+       int ret;
+
+       ret = qca_set_bdaddr_rome(hdev, bdaddr);
+       if (ret)
+               return ret;
+
+       /* The firmware stops responding for a while after setting the bdaddr,
+        * causing timeouts for subsequent commands. Sleep a bit to avoid this.
+        */
+       usleep_range(1000, 10000);
+       return 0;
+}
+
 static int btqcomsmd_probe(struct platform_device *pdev)
 {
        struct btqcomsmd *btq;
@@ -162,7 +177,7 @@ static int btqcomsmd_probe(struct platform_device *pdev)
        hdev->close = btqcomsmd_close;
        hdev->send = btqcomsmd_send;
        hdev->setup = btqcomsmd_setup;
-       hdev->set_bdaddr = qca_set_bdaddr_rome;
+       hdev->set_bdaddr = btqcomsmd_set_bdaddr;
 
        ret = hci_register_dev(hdev);
        if (ret < 0)
index 795be33f2892d5ea41afbcb461c4e0c8e939ef2a..51000320e1ea89442af6a46d03974749e9f80fed 100644 (file)
@@ -354,9 +354,11 @@ static void btsdio_remove(struct sdio_func *func)
 
        BT_DBG("func %p", func);
 
+       cancel_work_sync(&data->work);
        if (!data)
                return;
 
+       cancel_work_sync(&data->work);
        hdev = data->hdev;
 
        sdio_set_drvdata(func, NULL);
index 18bc94718711592e2d559077afe010cc50802c4b..5c536151ef8367362517bd8a50a5b47a2b7ce1f9 100644 (file)
@@ -1050,21 +1050,11 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
                hci_skb_expect(skb) -= len;
 
                if (skb->len == HCI_ACL_HDR_SIZE) {
-                       __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
                        __le16 dlen = hci_acl_hdr(skb)->dlen;
-                       __u8 type;
 
                        /* Complete ACL header */
                        hci_skb_expect(skb) = __le16_to_cpu(dlen);
 
-                       /* Detect if ISO packet has been sent over bulk */
-                       if (hci_conn_num(data->hdev, ISO_LINK)) {
-                               type = hci_conn_lookup_type(data->hdev,
-                                                           hci_handle(handle));
-                               if (type == ISO_LINK)
-                                       hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
-                       }
-
                        if (skb_tailroom(skb) < hci_skb_expect(skb)) {
                                kfree_skb(skb);
                                skb = NULL;
index b0c3704777e9929c2b6a3805292f7c721762c099..b6dfe4340da2cbfc9af162f56e9621ffb0c481f6 100644 (file)
@@ -401,12 +401,10 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
        struct device_node *dn = pdev->dev.of_node;
        struct brcmstb_gisb_arb_device *gdev;
        const struct of_device_id *of_id;
-       struct resource *r;
        int err, timeout_irq, tea_irq, bp_irq;
        unsigned int num_masters, j = 0;
        int i, first, last;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        timeout_irq = platform_get_irq(pdev, 0);
        tea_irq = platform_get_irq(pdev, 1);
        bp_irq = platform_get_irq(pdev, 2);
@@ -418,7 +416,7 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
        mutex_init(&gdev->lock);
        INIT_LIST_HEAD(&gdev->next);
 
-       gdev->base = devm_ioremap_resource(&pdev->dev, r);
+       gdev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(gdev->base))
                return PTR_ERR(gdev->base);
 
index 2a6b4f676458612e00b0551fad9aa51ea57ff6b7..52a5d04473908981937a539ad69142467e973a7e 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
@@ -86,8 +87,8 @@ MODULE_DEVICE_TABLE(of, weim_id_table);
 static int imx_weim_gpr_setup(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
-       struct property *prop;
-       const __be32 *p;
+       struct of_range_parser parser;
+       struct of_range range;
        struct regmap *gpr;
        u32 gprvals[4] = {
                05,     /* CS0(128M) CS1(0M)  CS2(0M)  CS3(0M)  */
@@ -106,13 +107,13 @@ static int imx_weim_gpr_setup(struct platform_device *pdev)
                return 0;
        }
 
-       of_property_for_each_u32(np, "ranges", prop, p, val) {
-               if (i % 4 == 0) {
-                       cs = val;
-               } else if (i % 4 == 3 && val) {
-                       val = (val / SZ_32M) | 1;
-                       gprval |= val << cs * 3;
-               }
+       if (of_range_parser_init(&parser, np))
+               goto err;
+
+       for_each_of_range(&parser, &range) {
+               cs = range.bus_addr >> 32;
+               val = (range.size / SZ_32M) | 1;
+               gprval |= val << cs * 3;
                i++;
        }
 
@@ -204,8 +205,8 @@ static int weim_parse_dt(struct platform_device *pdev)
        const struct of_device_id *of_id = of_match_device(weim_id_table,
                                                           &pdev->dev);
        const struct imx_weim_devtype *devtype = of_id->data;
+       int ret = 0, have_child = 0;
        struct device_node *child;
-       int ret, have_child = 0;
        struct weim_priv *priv;
        void __iomem *base;
        u32 reg;
@@ -329,6 +330,12 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action,
                                 "Failed to setup timing for '%pOF'\n", rd->dn);
 
                if (!of_node_check_flag(rd->dn, OF_POPULATED)) {
+                       /*
+                        * Clear the flag before adding the device so that
+                        * fw_devlink doesn't skip adding consumers to this
+                        * device.
+                        */
+                       rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
                        if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) {
                                dev_err(&pdev->dev,
                                        "Failed to create child device '%pOF'\n",
index 6afae98978434e2343e82e97679993bb398899a2..6c49de37d5e90f98cf63b2875bbe3d3ed18c8b76 100644 (file)
@@ -648,43 +648,20 @@ static int sysc_init_resets(struct sysc *ddata)
 static int sysc_parse_and_check_child_range(struct sysc *ddata)
 {
        struct device_node *np = ddata->dev->of_node;
-       const __be32 *ranges;
-       u32 nr_addr, nr_size;
-       int len, error;
-
-       ranges = of_get_property(np, "ranges", &len);
-       if (!ranges) {
-               dev_err(ddata->dev, "missing ranges for %pOF\n", np);
-
-               return -ENOENT;
-       }
-
-       len /= sizeof(*ranges);
-
-       if (len < 3) {
-               dev_err(ddata->dev, "incomplete ranges for %pOF\n", np);
-
-               return -EINVAL;
-       }
-
-       error = of_property_read_u32(np, "#address-cells", &nr_addr);
-       if (error)
-               return -ENOENT;
+       struct of_range_parser parser;
+       struct of_range range;
+       int error;
 
-       error = of_property_read_u32(np, "#size-cells", &nr_size);
+       error = of_range_parser_init(&parser, np);
        if (error)
-               return -ENOENT;
-
-       if (nr_addr != 1 || nr_size != 1) {
-               dev_err(ddata->dev, "invalid ranges for %pOF\n", np);
+               return error;
 
-               return -EINVAL;
+       for_each_of_range(&parser, &range) {
+               ddata->module_pa = range.cpu_addr;
+               ddata->module_size = range.size;
+               break;
        }
 
-       ranges++;
-       ddata->module_pa = of_translate_address(np, ranges++);
-       ddata->module_size = be32_to_cpup(ranges);
-
        return 0;
 }
 
@@ -913,7 +890,7 @@ static int sysc_check_registers(struct sysc *ddata)
  * within the interconnect target module range. For example, SGX has
  * them at offset 0x1fc00 in the 32MB module address space. And cpsw
  * has them at offset 0x1200 in the CPSW_WR child. Usually the
- * the interconnect target module registers are at the beginning of
+ * interconnect target module registers are at the beginning of
  * the module range though.
  */
 static int sysc_ioremap(struct sysc *ddata)
@@ -964,7 +941,7 @@ static int sysc_map_and_check_registers(struct sysc *ddata)
 
        sysc_check_children(ddata);
 
-       if (!of_get_property(np, "reg", NULL))
+       if (!of_property_present(np, "reg"))
                return 0;
 
        error = sysc_parse_registers(ddata);
@@ -2530,11 +2507,9 @@ static struct dev_pm_domain sysc_child_pm_domain = {
 static void sysc_reinit_modules(struct sysc_soc_info *soc)
 {
        struct sysc_module *module;
-       struct list_head *pos;
        struct sysc *ddata;
 
-       list_for_each(pos, &sysc_soc->restored_modules) {
-               module = list_entry(pos, struct sysc_module, node);
+       list_for_each_entry(module, &sysc_soc->restored_modules, node) {
                ddata = module->ddata;
                sysc_reinit_module(ddata, ddata->enabled);
        }
@@ -3214,12 +3189,10 @@ static void sysc_cleanup_static_data(void)
 static int sysc_check_disabled_devices(struct sysc *ddata)
 {
        struct sysc_address *disabled_module;
-       struct list_head *pos;
        int error = 0;
 
        mutex_lock(&sysc_soc->list_lock);
-       list_for_each(pos, &sysc_soc->disabled_modules) {
-               disabled_module = list_entry(pos, struct sysc_address, node);
+       list_for_each_entry(disabled_module, &sysc_soc->disabled_modules, node) {
                if (ddata->module_pa == disabled_module->base) {
                        dev_dbg(ddata->dev, "module disabled for this SoC\n");
                        error = -ENODEV;
index a58ac0c8e2826ada3a63d6557f0dc09e36bf08b8..472a570bd53a98c4a9233496d78d8b1c733b9794 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/sched/signal.h>
 #include <linux/slab.h>
 #include <linux/vexpress.h>
index 8512ec76d5260d6788686b33bd3dc79db34fa937..639c3f395a5afc461e495d5a175f332496ff1f43 100644 (file)
@@ -36,7 +36,7 @@ static int tpm_bios_measurements_open(struct inode *inode,
                inode_unlock(inode);
                return -ENODEV;
        }
-       chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
+       chip_seqops = inode->i_private;
        seqops = chip_seqops->seqops;
        chip = chip_seqops->chip;
        get_device(&chip->dev);
@@ -55,8 +55,8 @@ static int tpm_bios_measurements_open(struct inode *inode,
 static int tpm_bios_measurements_release(struct inode *inode,
                                         struct file *file)
 {
-       struct seq_file *seq = (struct seq_file *)file->private_data;
-       struct tpm_chip *chip = (struct tpm_chip *)seq->private;
+       struct seq_file *seq = file->private_data;
+       struct tpm_chip *chip = seq->private;
 
        put_device(&chip->dev);
 
index c4d0b744e3cc7379b6af00af991df869a88c00a4..2d28f55ef490b3787c0f5c384023f0a99acea951 100644 (file)
@@ -138,13 +138,13 @@ static const struct i2c_device_id st33zp24_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
 
-static const struct of_device_id of_st33zp24_i2c_match[] = {
+static const struct of_device_id of_st33zp24_i2c_match[] __maybe_unused = {
        { .compatible = "st,st33zp24-i2c", },
        {}
 };
 MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
 
-static const struct acpi_device_id st33zp24_i2c_acpi_match[] = {
+static const struct acpi_device_id st33zp24_i2c_acpi_match[] __maybe_unused = {
        {"SMO3324"},
        {}
 };
index 2154059f02351fc2a6b2a4ef702ea7252b6f32c9..f5811b301d3b224ab67621f1cb204c07ecdf954f 100644 (file)
@@ -255,13 +255,13 @@ static const struct spi_device_id st33zp24_spi_id[] = {
 };
 MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
 
-static const struct of_device_id of_st33zp24_spi_match[] = {
+static const struct of_device_id of_st33zp24_spi_match[] __maybe_unused = {
        { .compatible = "st,st33zp24-spi", },
        {}
 };
 MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
 
-static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
+static const struct acpi_device_id st33zp24_spi_acpi_match[] __maybe_unused = {
        {"SMO3324"},
        {}
 };
index 0601e6e5e326312696c0313038394f23fba87737..6fdfa65a00c3797a18c8aa2f5942eaac78623a36 100644 (file)
@@ -605,6 +605,30 @@ static int tpm_get_pcr_allocation(struct tpm_chip *chip)
        return rc;
 }
 
+/*
+ * tpm_chip_startup() - performs auto startup and allocates the PCRs
+ * @chip: TPM chip to use.
+ */
+int tpm_chip_startup(struct tpm_chip *chip)
+{
+       int rc;
+
+       rc = tpm_chip_start(chip);
+       if (rc)
+               return rc;
+
+       rc = tpm_auto_startup(chip);
+       if (rc)
+               goto stop;
+
+       rc = tpm_get_pcr_allocation(chip);
+stop:
+       tpm_chip_stop(chip);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_startup);
+
 /*
  * tpm_chip_register() - create a character device for the TPM chip
  * @chip: TPM chip to use.
@@ -620,20 +644,6 @@ int tpm_chip_register(struct tpm_chip *chip)
 {
        int rc;
 
-       rc = tpm_chip_start(chip);
-       if (rc)
-               return rc;
-       rc = tpm_auto_startup(chip);
-       if (rc) {
-               tpm_chip_stop(chip);
-               return rc;
-       }
-
-       rc = tpm_get_pcr_allocation(chip);
-       tpm_chip_stop(chip);
-       if (rc)
-               return rc;
-
        tpm_sysfs_add_device(chip);
 
        tpm_bios_log_setup(chip);
@@ -682,7 +692,8 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
 void tpm_chip_unregister(struct tpm_chip *chip)
 {
        tpm_del_legacy_sysfs(chip);
-       if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip))
+       if (IS_ENABLED(CONFIG_HW_RANDOM_TPM) && !tpm_is_firmware_upgrade(chip) &&
+           !tpm_amd_is_rng_defective(chip))
                hwrng_unregister(&chip->hwrng);
        tpm_bios_log_teardown(chip);
        if (chip->flags & TPM_CHIP_FLAG_TPM2 && !tpm_is_firmware_upgrade(chip))
index 830014a266090868a6123ed2b3b8043e0ddcc548..88d3bd76e0760dbaabe4f038d06f5ea103835b9c 100644 (file)
@@ -263,6 +263,7 @@ static inline void tpm_msleep(unsigned int delay_msec)
                     delay_msec * 1000);
 };
 
+int tpm_chip_startup(struct tpm_chip *chip);
 int tpm_chip_start(struct tpm_chip *chip);
 void tpm_chip_stop(struct tpm_chip *chip);
 struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
index deff23bb54bf1769ef402076b7a17300ea8c55a4..528f35b14fb636f34697b1167b113dba3e3a9a08 100644 (file)
@@ -334,11 +334,11 @@ static int ftpm_tee_remove(struct device *dev)
        return 0;
 }
 
-static int ftpm_plat_tee_remove(struct platform_device *pdev)
+static void ftpm_plat_tee_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
 
-       return ftpm_tee_remove(dev);
+       ftpm_tee_remove(dev);
 }
 
 /**
@@ -367,7 +367,7 @@ static struct platform_driver ftpm_tee_plat_driver = {
        },
        .shutdown = ftpm_plat_tee_shutdown,
        .probe = ftpm_plat_tee_probe,
-       .remove = ftpm_plat_tee_remove,
+       .remove_new = ftpm_plat_tee_remove,
 };
 
 /* UUID of the fTPM TA */
index ed5dabd3c72d62708a56d813c7713d7bc2c98c0f..7af389806643379fa76507755550fdae92871de9 100644 (file)
@@ -50,6 +50,45 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
        return container_of(data, struct tpm_tis_tcg_phy, priv);
 }
 
+#ifdef CONFIG_PREEMPT_RT
+/*
+ * Flush previous write operations with a dummy read operation to the
+ * TPM MMIO base address.
+ */
+static inline void tpm_tis_flush(void __iomem *iobase)
+{
+       ioread8(iobase + TPM_ACCESS(0));
+}
+#else
+#define tpm_tis_flush(iobase) do { } while (0)
+#endif
+
+/*
+ * Write a byte word to the TPM MMIO address, and flush the write queue.
+ * The flush ensures that the data is sent immediately over the bus and not
+ * aggregated with further requests and transferred later in a batch. The large
+ * write requests can lead to unwanted latency spikes by blocking the CPU until
+ * the complete batch has been transferred.
+ */
+static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr)
+{
+       iowrite8(b, iobase + addr);
+       tpm_tis_flush(iobase);
+}
+
+/*
+ * Write a 32-bit word to the TPM MMIO address, and flush the write queue.
+ * The flush ensures that the data is sent immediately over the bus and not
+ * aggregated with further requests and transferred later in a batch. The large
+ * write requests can lead to unwanted latency spikes by blocking the CPU until
+ * the complete batch has been transferred.
+ */
+static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
+{
+       iowrite32(b, iobase + addr);
+       tpm_tis_flush(iobase);
+}
+
 static int interrupts = -1;
 module_param(interrupts, int, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
@@ -186,12 +225,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
        switch (io_mode) {
        case TPM_TIS_PHYS_8:
                while (len--)
-                       iowrite8(*value++, phy->iobase + addr);
+                       tpm_tis_iowrite8(*value++, phy->iobase, addr);
                break;
        case TPM_TIS_PHYS_16:
                return -EINVAL;
        case TPM_TIS_PHYS_32:
-               iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase + addr);
+               tpm_tis_iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase, addr);
                break;
        }
 
@@ -227,7 +266,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
                irq = tpm_info->irq;
 
        if (itpm || is_itpm(ACPI_COMPANION(dev)))
-               phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND;
+               set_bit(TPM_TIS_ITPM_WORKAROUND, &phy->priv.flags);
 
        return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
                                 ACPI_HANDLE(dev));
@@ -324,14 +363,12 @@ static int tpm_tis_plat_probe(struct platform_device *pdev)
        return tpm_tis_init(&pdev->dev, &tpm_info);
 }
 
-static int tpm_tis_plat_remove(struct platform_device *pdev)
+static void tpm_tis_plat_remove(struct platform_device *pdev)
 {
        struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
 
        tpm_chip_unregister(chip);
        tpm_tis_remove(chip);
-
-       return 0;
 }
 
 #ifdef CONFIG_OF
@@ -344,7 +381,7 @@ MODULE_DEVICE_TABLE(of, tis_of_platform_match);
 
 static struct platform_driver tis_drv = {
        .probe = tpm_tis_plat_probe,
-       .remove = tpm_tis_plat_remove,
+       .remove_new = tpm_tis_plat_remove,
        .driver = {
                .name           = "tpm_tis",
                .pm             = &tpm_tis_pm,
index 3f98e587b3e849aa35346cc8110c17c7c1987cbe..c2421162cf345794b81288bba2b91217666b4dd1 100644 (file)
@@ -44,6 +44,20 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
        return false;
 }
 
+static u8 tpm_tis_filter_sts_mask(u8 int_mask, u8 sts_mask)
+{
+       if (!(int_mask & TPM_INTF_STS_VALID_INT))
+               sts_mask &= ~TPM_STS_VALID;
+
+       if (!(int_mask & TPM_INTF_DATA_AVAIL_INT))
+               sts_mask &= ~TPM_STS_DATA_AVAIL;
+
+       if (!(int_mask & TPM_INTF_CMD_READY_INT))
+               sts_mask &= ~TPM_STS_COMMAND_READY;
+
+       return sts_mask;
+}
+
 static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
                unsigned long timeout, wait_queue_head_t *queue,
                bool check_cancel)
@@ -53,41 +67,56 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
        long rc;
        u8 status;
        bool canceled = false;
+       u8 sts_mask;
+       int ret = 0;
 
        /* check current status */
        status = chip->ops->status(chip);
        if ((status & mask) == mask)
                return 0;
 
-       stop = jiffies + timeout;
+       sts_mask = mask & (TPM_STS_VALID | TPM_STS_DATA_AVAIL |
+                          TPM_STS_COMMAND_READY);
+       /* check what status changes can be handled by irqs */
+       sts_mask = tpm_tis_filter_sts_mask(priv->int_mask, sts_mask);
 
-       if (chip->flags & TPM_CHIP_FLAG_IRQ) {
+       stop = jiffies + timeout;
+       /* process status changes with irq support */
+       if (sts_mask) {
+               ret = -ETIME;
 again:
                timeout = stop - jiffies;
                if ((long)timeout <= 0)
                        return -ETIME;
                rc = wait_event_interruptible_timeout(*queue,
-                       wait_for_tpm_stat_cond(chip, mask, check_cancel,
+                       wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
                                               &canceled),
                        timeout);
                if (rc > 0) {
                        if (canceled)
                                return -ECANCELED;
-                       return 0;
+                       ret = 0;
                }
                if (rc == -ERESTARTSYS && freezing(current)) {
                        clear_thread_flag(TIF_SIGPENDING);
                        goto again;
                }
-       } else {
-               do {
-                       usleep_range(priv->timeout_min,
-                                    priv->timeout_max);
-                       status = chip->ops->status(chip);
-                       if ((status & mask) == mask)
-                               return 0;
-               } while (time_before(jiffies, stop));
        }
+
+       if (ret)
+               return ret;
+
+       mask &= ~sts_mask;
+       if (!mask) /* all done */
+               return 0;
+       /* process status changes without irq support */
+       do {
+               status = chip->ops->status(chip);
+               if ((status & mask) == mask)
+                       return 0;
+               usleep_range(priv->timeout_min,
+                            priv->timeout_max);
+       } while (time_before(jiffies, stop));
        return -ETIME;
 }
 
@@ -136,16 +165,27 @@ static bool check_locality(struct tpm_chip *chip, int l)
        return false;
 }
 
-static int release_locality(struct tpm_chip *chip, int l)
+static int __tpm_tis_relinquish_locality(struct tpm_tis_data *priv, int l)
+{
+       tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
+
+       return 0;
+}
+
+static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
 
-       tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
+       mutex_lock(&priv->locality_count_mutex);
+       priv->locality_count--;
+       if (priv->locality_count == 0)
+               __tpm_tis_relinquish_locality(priv, l);
+       mutex_unlock(&priv->locality_count_mutex);
 
        return 0;
 }
 
-static int request_locality(struct tpm_chip *chip, int l)
+static int __tpm_tis_request_locality(struct tpm_chip *chip, int l)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        unsigned long stop, timeout;
@@ -186,6 +226,20 @@ again:
        return -1;
 }
 
+static int tpm_tis_request_locality(struct tpm_chip *chip, int l)
+{
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       int ret = 0;
+
+       mutex_lock(&priv->locality_count_mutex);
+       if (priv->locality_count == 0)
+               ret = __tpm_tis_request_locality(chip, l);
+       if (!ret)
+               priv->locality_count++;
+       mutex_unlock(&priv->locality_count_mutex);
+       return ret;
+}
+
 static u8 tpm_tis_status(struct tpm_chip *chip)
 {
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
@@ -351,7 +405,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        int rc, status, burstcnt;
        size_t count = 0;
-       bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND;
+       bool itpm = test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
 
        status = tpm_tis_status(chip);
        if ((status & TPM_STS_COMMAND_READY) == 0) {
@@ -484,7 +538,8 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
        int rc, irq;
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
 
-       if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested)
+       if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
+            test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
                return tpm_tis_send_main(chip, buf, len);
 
        /* Verify receipt of the expected IRQ */
@@ -494,11 +549,11 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
        rc = tpm_tis_send_main(chip, buf, len);
        priv->irq = irq;
        chip->flags |= TPM_CHIP_FLAG_IRQ;
-       if (!priv->irq_tested)
+       if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
                tpm_msleep(1);
-       if (!priv->irq_tested)
+       if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
                disable_interrupts(chip);
-       priv->irq_tested = true;
+       set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
        return rc;
 }
 
@@ -641,7 +696,7 @@ static int probe_itpm(struct tpm_chip *chip)
        size_t len = sizeof(cmd_getticks);
        u16 vendor;
 
-       if (priv->flags & TPM_TIS_ITPM_WORKAROUND)
+       if (test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags))
                return 0;
 
        rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor);
@@ -652,7 +707,7 @@ static int probe_itpm(struct tpm_chip *chip)
        if (vendor != TPM_VID_INTEL)
                return 0;
 
-       if (request_locality(chip, 0) != 0)
+       if (tpm_tis_request_locality(chip, 0) != 0)
                return -EBUSY;
 
        rc = tpm_tis_send_data(chip, cmd_getticks, len);
@@ -661,19 +716,19 @@ static int probe_itpm(struct tpm_chip *chip)
 
        tpm_tis_ready(chip);
 
-       priv->flags |= TPM_TIS_ITPM_WORKAROUND;
+       set_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
 
        rc = tpm_tis_send_data(chip, cmd_getticks, len);
        if (rc == 0)
                dev_info(&chip->dev, "Detected an iTPM.\n");
        else {
-               priv->flags &= ~TPM_TIS_ITPM_WORKAROUND;
+               clear_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
                rc = -EFAULT;
        }
 
 out:
        tpm_tis_ready(chip);
-       release_locality(chip, priv->locality);
+       tpm_tis_relinquish_locality(chip, priv->locality);
 
        return rc;
 }
@@ -702,7 +757,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
        struct tpm_chip *chip = dev_id;
        struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
        u32 interrupt;
-       int i, rc;
+       int rc;
 
        rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt);
        if (rc < 0)
@@ -711,20 +766,19 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
        if (interrupt == 0)
                return IRQ_NONE;
 
-       priv->irq_tested = true;
+       set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
        if (interrupt & TPM_INTF_DATA_AVAIL_INT)
                wake_up_interruptible(&priv->read_queue);
-       if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
-               for (i = 0; i < 5; i++)
-                       if (check_locality(chip, i))
-                               break;
+
        if (interrupt &
            (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
             TPM_INTF_CMD_READY_INT))
                wake_up_interruptible(&priv->int_queue);
 
        /* Clear interrupts handled with TPM_EOI */
+       tpm_tis_request_locality(chip, 0);
        rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
+       tpm_tis_relinquish_locality(chip, 0);
        if (rc < 0)
                return IRQ_NONE;
 
@@ -732,25 +786,22 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
+static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
 {
        const char *desc = "attempting to generate an interrupt";
        u32 cap2;
        cap_t cap;
        int ret;
 
-       ret = request_locality(chip, 0);
-       if (ret < 0)
-               return ret;
+       chip->flags |= TPM_CHIP_FLAG_IRQ;
 
        if (chip->flags & TPM_CHIP_FLAG_TPM2)
                ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
        else
                ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
 
-       release_locality(chip, 0);
-
-       return ret;
+       if (ret)
+               chip->flags &= ~TPM_CHIP_FLAG_IRQ;
 }
 
 /* Register the IRQ and issue a command that will cause an interrupt. If an
@@ -765,60 +816,66 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
        int rc;
        u32 int_status;
 
-       if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags,
-                            dev_name(&chip->dev), chip) != 0) {
+
+       rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
+                                      tis_int_handler, IRQF_ONESHOT | flags,
+                                      dev_name(&chip->dev), chip);
+       if (rc) {
                dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
                         irq);
                return -1;
        }
        priv->irq = irq;
 
+       rc = tpm_tis_request_locality(chip, 0);
+       if (rc < 0)
+               return rc;
+
        rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
                           &original_int_vec);
-       if (rc < 0)
+       if (rc < 0) {
+               tpm_tis_relinquish_locality(chip, priv->locality);
                return rc;
+       }
 
        rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
        if (rc < 0)
-               return rc;
+               goto restore_irqs;
 
        rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
        if (rc < 0)
-               return rc;
+               goto restore_irqs;
 
        /* Clear all existing */
        rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
        if (rc < 0)
-               return rc;
-
+               goto restore_irqs;
        /* Turn on */
        rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
                             intmask | TPM_GLOBAL_INT_ENABLE);
        if (rc < 0)
-               return rc;
+               goto restore_irqs;
 
-       priv->irq_tested = false;
+       clear_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
 
        /* Generate an interrupt by having the core call through to
         * tpm_tis_send
         */
-       rc = tpm_tis_gen_interrupt(chip);
-       if (rc < 0)
-               return rc;
+       tpm_tis_gen_interrupt(chip);
 
+restore_irqs:
        /* tpm_tis_send will either confirm the interrupt is working or it
         * will call disable_irq which undoes all of the above.
         */
        if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
-               rc = tpm_tis_write8(priv, original_int_vec,
-                               TPM_INT_VECTOR(priv->locality));
-               if (rc < 0)
-                       return rc;
-
-               return 1;
+               tpm_tis_write8(priv, original_int_vec,
+                              TPM_INT_VECTOR(priv->locality));
+               rc = -1;
        }
 
-       return 0;
+       tpm_tis_relinquish_locality(chip, priv->locality);
+
+       return rc;
 }
 
 /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
@@ -932,8 +989,8 @@ static const struct tpm_class_ops tpm_tis = {
        .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
        .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
        .req_canceled = tpm_tis_req_canceled,
-       .request_locality = request_locality,
-       .relinquish_locality = release_locality,
+       .request_locality = tpm_tis_request_locality,
+       .relinquish_locality = tpm_tis_relinquish_locality,
        .clk_enable = tpm_tis_clkrun_enable,
 };
 
@@ -967,6 +1024,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
        priv->timeout_min = TPM_TIMEOUT_USECS_MIN;
        priv->timeout_max = TPM_TIMEOUT_USECS_MAX;
        priv->phy_ops = phy_ops;
+       priv->locality_count = 0;
+       mutex_init(&priv->locality_count_mutex);
 
        dev_set_drvdata(&chip->dev, priv);
 
@@ -1009,18 +1068,50 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
        if (rc < 0)
                goto out_err;
 
-       intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
-                  TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
+       /* Figure out the capabilities */
+       rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
+       if (rc < 0)
+               goto out_err;
+
+       dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
+               intfcaps);
+       if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+               dev_dbg(dev, "\tBurst Count Static\n");
+       if (intfcaps & TPM_INTF_CMD_READY_INT) {
+               intmask |= TPM_INTF_CMD_READY_INT;
+               dev_dbg(dev, "\tCommand Ready Int Support\n");
+       }
+       if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+               dev_dbg(dev, "\tInterrupt Edge Falling\n");
+       if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+               dev_dbg(dev, "\tInterrupt Edge Rising\n");
+       if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+               dev_dbg(dev, "\tInterrupt Level Low\n");
+       if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+               dev_dbg(dev, "\tInterrupt Level High\n");
+       if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
+               intmask |= TPM_INTF_LOCALITY_CHANGE_INT;
+               dev_dbg(dev, "\tLocality Change Int Support\n");
+       }
+       if (intfcaps & TPM_INTF_STS_VALID_INT) {
+               intmask |= TPM_INTF_STS_VALID_INT;
+               dev_dbg(dev, "\tSts Valid Int Support\n");
+       }
+       if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
+               intmask |= TPM_INTF_DATA_AVAIL_INT;
+               dev_dbg(dev, "\tData Avail Int Support\n");
+       }
+
        intmask &= ~TPM_GLOBAL_INT_ENABLE;
 
-       rc = request_locality(chip, 0);
+       rc = tpm_tis_request_locality(chip, 0);
        if (rc < 0) {
                rc = -ENODEV;
                goto out_err;
        }
 
        tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
-       release_locality(chip, 0);
+       tpm_tis_relinquish_locality(chip, 0);
 
        rc = tpm_chip_start(chip);
        if (rc)
@@ -1044,35 +1135,14 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                goto out_err;
        }
 
-       /* Figure out the capabilities */
-       rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
-       if (rc < 0)
-               goto out_err;
-
-       dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
-               intfcaps);
-       if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
-               dev_dbg(dev, "\tBurst Count Static\n");
-       if (intfcaps & TPM_INTF_CMD_READY_INT)
-               dev_dbg(dev, "\tCommand Ready Int Support\n");
-       if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
-               dev_dbg(dev, "\tInterrupt Edge Falling\n");
-       if (intfcaps & TPM_INTF_INT_EDGE_RISING)
-               dev_dbg(dev, "\tInterrupt Edge Rising\n");
-       if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
-               dev_dbg(dev, "\tInterrupt Level Low\n");
-       if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
-               dev_dbg(dev, "\tInterrupt Level High\n");
-       if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
-               dev_dbg(dev, "\tLocality Change Int Support\n");
-       if (intfcaps & TPM_INTF_STS_VALID_INT)
-               dev_dbg(dev, "\tSts Valid Int Support\n");
-       if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
-               dev_dbg(dev, "\tData Avail Int Support\n");
-
        /* INTERRUPT Setup */
        init_waitqueue_head(&priv->read_queue);
        init_waitqueue_head(&priv->int_queue);
+
+       rc = tpm_chip_startup(chip);
+       if (rc)
+               goto out_err;
+
        if (irq != -1) {
                /*
                 * Before doing irq testing issue a command to the TPM in polling mode
@@ -1080,13 +1150,13 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                 * proper timeouts for the driver.
                 */
 
-               rc = request_locality(chip, 0);
+               rc = tpm_tis_request_locality(chip, 0);
                if (rc < 0)
                        goto out_err;
 
                rc = tpm_get_timeouts(chip);
 
-               release_locality(chip, 0);
+               tpm_tis_relinquish_locality(chip, 0);
 
                if (rc) {
                        dev_err(dev, "Could not get TPM timeouts and durations\n");
@@ -1094,17 +1164,23 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                        goto out_err;
                }
 
-               if (irq) {
+               if (irq)
                        tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
                                                 irq);
-                       if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
-                               dev_err(&chip->dev, FW_BUG
-                                       "TPM interrupt not working, polling instead\n");
+               else
+                       tpm_tis_probe_irq(chip, intmask);
 
-                               disable_interrupts(chip);
-                       }
+               if (chip->flags & TPM_CHIP_FLAG_IRQ) {
+                       priv->int_mask = intmask;
                } else {
-                       tpm_tis_probe_irq(chip, intmask);
+                       dev_err(&chip->dev, FW_BUG
+                                       "TPM interrupt not working, polling instead\n");
+
+                       rc = tpm_tis_request_locality(chip, 0);
+                       if (rc < 0)
+                               goto out_err;
+                       disable_interrupts(chip);
+                       tpm_tis_relinquish_locality(chip, 0);
                }
        }
 
@@ -1143,13 +1219,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
        if (rc < 0)
                goto out;
 
-       rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
-       if (rc < 0)
-               goto out;
-
-       intmask |= TPM_INTF_CMD_READY_INT
-           | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
-           | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
+       intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;
 
        tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
 
@@ -1165,28 +1235,27 @@ int tpm_tis_resume(struct device *dev)
        struct tpm_chip *chip = dev_get_drvdata(dev);
        int ret;
 
+       ret = tpm_tis_request_locality(chip, 0);
+       if (ret < 0)
+               return ret;
+
        if (chip->flags & TPM_CHIP_FLAG_IRQ)
                tpm_tis_reenable_interrupts(chip);
 
        ret = tpm_pm_resume(dev);
        if (ret)
-               return ret;
+               goto out;
 
        /*
         * TPM 1.2 requires self-test on resume. This function actually returns
         * an error code but for unknown reason it isn't handled.
         */
-       if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
-               ret = request_locality(chip, 0);
-               if (ret < 0)
-                       return ret;
-
+       if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
                tpm1_do_selftest(chip);
+out:
+       tpm_tis_relinquish_locality(chip, 0);
 
-               release_locality(chip, 0);
-       }
-
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(tpm_tis_resume);
 #endif
index b68479e0de10f396ea294a0c68988c9a479763d9..e978f457fd4d4ce083a7a9f9689df5f2d7a8ed9d 100644 (file)
@@ -87,13 +87,16 @@ enum tpm_tis_flags {
        TPM_TIS_ITPM_WORKAROUND         = BIT(0),
        TPM_TIS_INVALID_STATUS          = BIT(1),
        TPM_TIS_DEFAULT_CANCELLATION    = BIT(2),
+       TPM_TIS_IRQ_TESTED              = BIT(3),
 };
 
 struct tpm_tis_data {
        u16 manufacturer_id;
+       struct mutex locality_count_mutex;
+       unsigned int locality_count;
        int locality;
        int irq;
-       bool irq_tested;
+       unsigned int int_mask;
        unsigned long flags;
        void __iomem *ilb_base_addr;
        u16 clkrun_enabled;
index 77cea5b31c6e4b67eaabc9ec9839170095018935..376ae18a04ebb7c7a3f5d6116f2a2b7e626634f3 100644 (file)
@@ -100,8 +100,7 @@ static int tpm_cr50_i2c_wait_tpm_ready(struct tpm_chip *chip)
        }
 
        /* Wait for interrupt to indicate TPM is ready to respond */
-       if (!wait_for_completion_timeout(&priv->tpm_ready,
-                                        msecs_to_jiffies(chip->timeout_a))) {
+       if (!wait_for_completion_timeout(&priv->tpm_ready, chip->timeout_a)) {
                dev_warn(&chip->dev, "Timeout waiting for TPM ready\n");
                return -ETIMEDOUT;
        }
index a0963a3e92bdd86da6627412eeff1e0b8a00aa6a..1f5207974a17b6ba0a7835c306b0f17ad6bb991f 100644 (file)
@@ -231,7 +231,7 @@ static const struct spi_device_id tpm_tis_spi_id[] = {
 };
 MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
 
-static const struct of_device_id of_tis_spi_match[] = {
+static const struct of_device_id of_tis_spi_match[] __maybe_unused = {
        { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe },
        { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe },
        { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe },
@@ -240,7 +240,7 @@ static const struct of_device_id of_tis_spi_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_tis_spi_match);
 
-static const struct acpi_device_id acpi_tis_spi_match[] = {
+static const struct acpi_device_id acpi_tis_spi_match[] __maybe_unused = {
        {"SMO0768", 0},
        {}
 };
index 679196c614017aac6994c7402e1612b85a44aa8f..49278746b0e2f97a9b8af1331dc0530ab2a95db5 100644 (file)
@@ -127,14 +127,12 @@ static int tpm_tis_synquacer_probe(struct platform_device *pdev)
        return tpm_tis_synquacer_init(&pdev->dev, &tpm_info);
 }
 
-static int tpm_tis_synquacer_remove(struct platform_device *pdev)
+static void tpm_tis_synquacer_remove(struct platform_device *pdev)
 {
        struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
 
        tpm_chip_unregister(chip);
        tpm_tis_remove(chip);
-
-       return 0;
 }
 
 #ifdef CONFIG_OF
@@ -155,7 +153,7 @@ MODULE_DEVICE_TABLE(acpi, tpm_synquacer_acpi_tbl);
 
 static struct platform_driver tis_synquacer_drv = {
        .probe = tpm_tis_synquacer_probe,
-       .remove = tpm_tis_synquacer_remove,
+       .remove_new = tpm_tis_synquacer_remove,
        .driver = {
                .name           = "tpm_tis_synquacer",
                .pm             = &tpm_tis_synquacer_pm,
index b6c5bf69a2b2c65aa24c2dfcfb6050c1412708d8..1eef05bb1f995eea850c3a18697a6d2f11106215 100644 (file)
@@ -91,7 +91,7 @@ config COMMON_CLK_RK808
 config COMMON_CLK_HI655X
        tristate "Clock driver for Hi655x" if EXPERT
        depends on (MFD_HI655X_PMIC || COMPILE_TEST)
-       depends on REGMAP
+       select REGMAP
        default MFD_HI655X_PMIC
        help
          This driver supports the hi655x PMIC clock. This
index 290a2846a86b654034293308f33602114c85dae1..0fafa5cba4427d219d6337d20b15e26ff09fd32c 100644 (file)
@@ -69,4 +69,3 @@ builtin_platform_driver(bcm2835_aux_clk_driver);
 
 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
 MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver");
-MODULE_LICENSE("GPL");
index e74fe6219d14e2e0c39b65a5e9b2a9cef7c42d9a..8dc476ef5bf975e8251c693304d7f91a1fe57a57 100644 (file)
@@ -2350,4 +2350,3 @@ builtin_platform_driver(bcm2835_clk_driver);
 
 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
 MODULE_DESCRIPTION("BCM2835 clock driver");
-MODULE_LICENSE("GPL");
index 5225d17d6b3f39210dc19de7ffb861f4544e124a..8609fca29cc4e08ddd49066392acf563bc95891e 100644 (file)
@@ -99,4 +99,3 @@ module_platform_driver(of_fixed_mmio_clk_driver);
 
 MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
 MODULE_DESCRIPTION("Memory Mapped IO Fixed clock driver");
-MODULE_LICENSE("GPL v2");
index 6238fcea04673052e60e6a2293f021bd44d34d40..ee5baf993ff21d3b9c6bda31db1a5b6c83a38f49 100644 (file)
@@ -88,5 +88,4 @@ module_platform_driver(fsl_sai_clk_driver);
 
 MODULE_DESCRIPTION("Freescale SAI bitclock-as-a-clock driver");
 MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
-MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:fsl-sai-clk");
index 67a7cb3503c3697b169e436f5aeb361de4e2febe..4eed667eddaf25b4e3bd974ade93a0243109bf6a 100644 (file)
@@ -495,7 +495,7 @@ static unsigned long k210_pll_get_rate(struct clk_hw *hw,
        f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
        od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
 
-       return (u64)parent_rate * f / (r * od);
+       return div_u64((u64)parent_rate * f, r * od);
 }
 
 static const struct clk_ops k210_pll_ops = {
index f91f30560820d529e035c2e62efee3b659acbe6c..ff3a52d48479092257a98ddaaf3b2af701a6bd99 100644 (file)
@@ -143,8 +143,9 @@ static int rs9_regmap_i2c_read(void *context,
 static const struct regmap_config rs9_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
-       .cache_type = REGCACHE_NONE,
+       .cache_type = REGCACHE_FLAT,
        .max_register = RS9_REG_BCP,
+       .num_reg_defaults_raw = 0x8,
        .rd_table = &rs9_readable_table,
        .wr_table = &rs9_writeable_table,
        .reg_write = rs9_regmap_i2c_write,
index 9ea1a80acbe8b5be6475d2f729e5609c0a61d3a9..8036bd8cbb0ac21fbe5688c71809effd85b68224 100644 (file)
@@ -841,5 +841,4 @@ static void __exit hi3559av100_crg_exit(void)
 module_exit(hi3559av100_crg_exit);
 
 
-MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver");
index 2836adb817b70e85c01009926003355506e07ce5..e3696a88b5a36af229370e8b7a996d60a987dcb4 100644 (file)
@@ -95,14 +95,16 @@ static const struct clk_div_table video_div_table[] = {
        { }
 };
 
-static const char * enet1_ref_sels[] = { "enet1_ref_125m", "enet1_ref_pad", };
+static const char * enet1_ref_sels[] = { "enet1_ref_125m", "enet1_ref_pad", "dummy", "dummy"};
 static const u32 enet1_ref_sels_table[] = { IMX6UL_GPR1_ENET1_TX_CLK_DIR,
-                                           IMX6UL_GPR1_ENET1_CLK_SEL };
+                                           IMX6UL_GPR1_ENET1_CLK_SEL, 0,
+                                           IMX6UL_GPR1_ENET1_TX_CLK_DIR | IMX6UL_GPR1_ENET1_CLK_SEL };
 static const u32 enet1_ref_sels_table_mask = IMX6UL_GPR1_ENET1_TX_CLK_DIR |
                                             IMX6UL_GPR1_ENET1_CLK_SEL;
-static const char * enet2_ref_sels[] = { "enet2_ref_125m", "enet2_ref_pad", };
+static const char * enet2_ref_sels[] = { "enet2_ref_125m", "enet2_ref_pad", "dummy", "dummy"};
 static const u32 enet2_ref_sels_table[] = { IMX6UL_GPR1_ENET2_TX_CLK_DIR,
-                                           IMX6UL_GPR1_ENET2_CLK_SEL };
+                                           IMX6UL_GPR1_ENET2_CLK_SEL, 0,
+                                           IMX6UL_GPR1_ENET2_TX_CLK_DIR | IMX6UL_GPR1_ENET2_CLK_SEL };
 static const u32 enet2_ref_sels_table_mask = IMX6UL_GPR1_ENET2_TX_CLK_DIR |
                                             IMX6UL_GPR1_ENET2_CLK_SEL;
 
index 0ddc73e07be429734d32aae75f08534782b3c564..bce61c45e96748d5a7f3e67ec82a5fecdd6f74a3 100644 (file)
@@ -291,4 +291,3 @@ module_exit(clk_ccc_exit);
 
 MODULE_DESCRIPTION("Microchip PolarFire SoC Clock Conditioning Circuitry Driver");
 MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
-MODULE_LICENSE("GPL");
index ce81e4087a8fce2e8d2239e6d706de7f33b24c7d..2bfbab8db94bf54dcb164012d79d45b0b0df3d2f 100644 (file)
@@ -17,7 +17,6 @@ static const struct regmap_config sprdclk_regmap_config = {
        .reg_bits       = 32,
        .reg_stride     = 4,
        .val_bits       = 32,
-       .max_register   = 0xffff,
        .fast_io        = true,
 };
 
@@ -43,6 +42,8 @@ int sprd_clk_regmap_init(struct platform_device *pdev,
        struct device *dev = &pdev->dev;
        struct device_node *node = dev->of_node, *np;
        struct regmap *regmap;
+       struct resource *res;
+       struct regmap_config reg_config = sprdclk_regmap_config;
 
        if (of_find_property(node, "sprd,syscon", NULL)) {
                regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
@@ -59,12 +60,14 @@ int sprd_clk_regmap_init(struct platform_device *pdev,
                        return PTR_ERR(regmap);
                }
        } else {
-               base = devm_platform_ioremap_resource(pdev, 0);
+               base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
                if (IS_ERR(base))
                        return PTR_ERR(base);
 
+               reg_config.max_register = resource_size(res) - reg_config.reg_stride;
+
                regmap = devm_regmap_init_mmio(&pdev->dev, base,
-                                              &sprdclk_regmap_config);
+                                              &reg_config);
                if (IS_ERR(regmap)) {
                        pr_err("failed to init regmap\n");
                        return PTR_ERR(regmap);
index 6cfe2ab73eb0ccbd1bc4a8133c418de39373f7d2..9a55e733ae995dc6d734e9eb14dee295cd59b230 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/sched_clock.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/smp.h>
 #include <linux/timex.h>
@@ -31,6 +34,7 @@
 
 /* CLINT manages IPI and Timer for RISC-V M-mode  */
 static u32 __iomem *clint_ipi_base;
+static unsigned int clint_ipi_irq;
 static u64 __iomem *clint_timer_cmp;
 static u64 __iomem *clint_timer_val;
 static unsigned long clint_timer_freq;
@@ -41,12 +45,10 @@ u64 __iomem *clint_time_val;
 EXPORT_SYMBOL(clint_time_val);
 #endif
 
-static void clint_send_ipi(const struct cpumask *target)
+#ifdef CONFIG_SMP
+static void clint_send_ipi(unsigned int cpu)
 {
-       unsigned int cpu;
-
-       for_each_cpu(cpu, target)
-               writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu));
+       writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu));
 }
 
 static void clint_clear_ipi(void)
@@ -54,10 +56,18 @@ static void clint_clear_ipi(void)
        writel(0, clint_ipi_base + cpuid_to_hartid_map(smp_processor_id()));
 }
 
-static struct riscv_ipi_ops clint_ipi_ops = {
-       .ipi_inject = clint_send_ipi,
-       .ipi_clear = clint_clear_ipi,
-};
+static void clint_ipi_interrupt(struct irq_desc *desc)
+{
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(chip, desc);
+
+       clint_clear_ipi();
+       ipi_mux_process();
+
+       chained_irq_exit(chip, desc);
+}
+#endif
 
 #ifdef CONFIG_64BIT
 #define clint_get_cycles()     readq_relaxed(clint_timer_val)
@@ -125,12 +135,19 @@ static int clint_timer_starting_cpu(unsigned int cpu)
 
        enable_percpu_irq(clint_timer_irq,
                          irq_get_trigger_type(clint_timer_irq));
+       enable_percpu_irq(clint_ipi_irq,
+                         irq_get_trigger_type(clint_ipi_irq));
        return 0;
 }
 
 static int clint_timer_dying_cpu(unsigned int cpu)
 {
        disable_percpu_irq(clint_timer_irq);
+       /*
+        * Don't disable IPI when CPU goes offline because
+        * the masking/unmasking of virtual IPIs is done
+        * via generic IPI-Mux
+        */
        return 0;
 }
 
@@ -170,6 +187,12 @@ static int __init clint_timer_init_dt(struct device_node *np)
                        return -ENODEV;
                }
 
+               /* Find parent irq domain and map ipi irq */
+               if (!clint_ipi_irq &&
+                   oirq.args[0] == RV_IRQ_SOFT &&
+                   irq_find_host(oirq.np))
+                       clint_ipi_irq = irq_of_parse_and_map(np, i);
+
                /* Find parent irq domain and map timer irq */
                if (!clint_timer_irq &&
                    oirq.args[0] == RV_IRQ_TIMER &&
@@ -177,9 +200,9 @@ static int __init clint_timer_init_dt(struct device_node *np)
                        clint_timer_irq = irq_of_parse_and_map(np, i);
        }
 
-       /* If CLINT timer irq not found then fail */
-       if (!clint_timer_irq) {
-               pr_err("%pOFP: timer irq not found\n", np);
+       /* If CLINT ipi or timer irq not found then fail */
+       if (!clint_ipi_irq || !clint_timer_irq) {
+               pr_err("%pOFP: ipi/timer irq not found\n", np);
                return -ENODEV;
        }
 
@@ -219,6 +242,19 @@ static int __init clint_timer_init_dt(struct device_node *np)
                goto fail_iounmap;
        }
 
+#ifdef CONFIG_SMP
+       rc = ipi_mux_create(BITS_PER_BYTE, clint_send_ipi);
+       if (rc <= 0) {
+               pr_err("unable to create muxed IPIs\n");
+               rc = (rc < 0) ? rc : -ENODEV;
+               goto fail_free_irq;
+       }
+
+       irq_set_chained_handler(clint_ipi_irq, clint_ipi_interrupt);
+       riscv_ipi_set_virq_range(rc, BITS_PER_BYTE, true);
+       clint_clear_ipi();
+#endif
+
        rc = cpuhp_setup_state(CPUHP_AP_CLINT_TIMER_STARTING,
                                "clockevents/clint/timer:starting",
                                clint_timer_starting_cpu,
@@ -228,13 +264,10 @@ static int __init clint_timer_init_dt(struct device_node *np)
                goto fail_free_irq;
        }
 
-       riscv_set_ipi_ops(&clint_ipi_ops);
-       clint_clear_ipi();
-
        return 0;
 
 fail_free_irq:
-       free_irq(clint_timer_irq, &clint_clock_event);
+       free_percpu_irq(clint_timer_irq, &clint_clock_event);
 fail_iounmap:
        iounmap(base);
        return rc;
index deed4afadb298e1173a55a729a1708c1e298994c..d9cb937665cfcf657a80bbb150b2b04858599c8c 100644 (file)
@@ -97,10 +97,6 @@ struct quad8 {
        struct quad8_reg __iomem *reg;
 };
 
-/* Borrow Toggle flip-flop */
-#define QUAD8_FLAG_BT BIT(0)
-/* Carry Toggle flip-flop */
-#define QUAD8_FLAG_CT BIT(1)
 /* Error flag */
 #define QUAD8_FLAG_E BIT(4)
 /* Up/Down flag */
@@ -133,6 +129,9 @@ struct quad8 {
 #define QUAD8_CMR_QUADRATURE_X2 0x10
 #define QUAD8_CMR_QUADRATURE_X4 0x18
 
+/* Each Counter is 24 bits wide */
+#define LS7267_CNTR_MAX GENMASK(23, 0)
+
 static int quad8_signal_read(struct counter_device *counter,
                             struct counter_signal *signal,
                             enum counter_signal_level *level)
@@ -156,18 +155,10 @@ static int quad8_count_read(struct counter_device *counter,
 {
        struct quad8 *const priv = counter_priv(counter);
        struct channel_reg __iomem *const chan = priv->reg->channel + count->id;
-       unsigned int flags;
-       unsigned int borrow;
-       unsigned int carry;
        unsigned long irqflags;
        int i;
 
-       flags = ioread8(&chan->control);
-       borrow = flags & QUAD8_FLAG_BT;
-       carry = !!(flags & QUAD8_FLAG_CT);
-
-       /* Borrow XOR Carry effectively doubles count range */
-       *val = (unsigned long)(borrow ^ carry) << 24;
+       *val = 0;
 
        spin_lock_irqsave(&priv->lock, irqflags);
 
@@ -191,8 +182,7 @@ static int quad8_count_write(struct counter_device *counter,
        unsigned long irqflags;
        int i;
 
-       /* Only 24-bit values are supported */
-       if (val > 0xFFFFFF)
+       if (val > LS7267_CNTR_MAX)
                return -ERANGE;
 
        spin_lock_irqsave(&priv->lock, irqflags);
@@ -378,7 +368,7 @@ static int quad8_action_read(struct counter_device *counter,
 
        /* Handle Index signals */
        if (synapse->signal->id >= 16) {
-               if (priv->preset_enable[count->id])
+               if (!priv->preset_enable[count->id])
                        *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
                else
                        *action = COUNTER_SYNAPSE_ACTION_NONE;
@@ -806,8 +796,7 @@ static int quad8_count_preset_write(struct counter_device *counter,
        struct quad8 *const priv = counter_priv(counter);
        unsigned long irqflags;
 
-       /* Only 24-bit values are supported */
-       if (preset > 0xFFFFFF)
+       if (preset > LS7267_CNTR_MAX)
                return -ERANGE;
 
        spin_lock_irqsave(&priv->lock, irqflags);
@@ -834,8 +823,7 @@ static int quad8_count_ceiling_read(struct counter_device *counter,
                *ceiling = priv->preset[count->id];
                break;
        default:
-               /* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
-               *ceiling = 0x1FFFFFF;
+               *ceiling = LS7267_CNTR_MAX;
                break;
        }
 
@@ -850,8 +838,7 @@ static int quad8_count_ceiling_write(struct counter_device *counter,
        struct quad8 *const priv = counter_priv(counter);
        unsigned long irqflags;
 
-       /* Only 24-bit values are supported */
-       if (ceiling > 0xFFFFFF)
+       if (ceiling > LS7267_CNTR_MAX)
                return -ERANGE;
 
        spin_lock_irqsave(&priv->lock, irqflags);
index 73c7643b26972b4f79fa6dc65ee745e48a9aee88..8dd46fad151eb01a823815aa1eb3507f88172312 100644 (file)
@@ -840,22 +840,20 @@ static int amd_pstate_update_status(const char *buf, size_t size)
 
        switch(mode_idx) {
        case AMD_PSTATE_DISABLE:
-               if (!current_pstate_driver)
-                       return -EINVAL;
-               if (cppc_state == AMD_PSTATE_ACTIVE)
-                       return -EBUSY;
-               cpufreq_unregister_driver(current_pstate_driver);
-               amd_pstate_driver_cleanup();
+               if (current_pstate_driver) {
+                       cpufreq_unregister_driver(current_pstate_driver);
+                       amd_pstate_driver_cleanup();
+               }
                break;
        case AMD_PSTATE_PASSIVE:
                if (current_pstate_driver) {
                        if (current_pstate_driver == &amd_pstate_driver)
                                return 0;
                        cpufreq_unregister_driver(current_pstate_driver);
-                       cppc_state = AMD_PSTATE_PASSIVE;
-                       current_pstate_driver = &amd_pstate_driver;
                }
 
+               current_pstate_driver = &amd_pstate_driver;
+               cppc_state = AMD_PSTATE_PASSIVE;
                ret = cpufreq_register_driver(current_pstate_driver);
                break;
        case AMD_PSTATE_ACTIVE:
@@ -863,10 +861,10 @@ static int amd_pstate_update_status(const char *buf, size_t size)
                        if (current_pstate_driver == &amd_pstate_epp_driver)
                                return 0;
                        cpufreq_unregister_driver(current_pstate_driver);
-                       current_pstate_driver = &amd_pstate_epp_driver;
-                       cppc_state = AMD_PSTATE_ACTIVE;
                }
 
+               current_pstate_driver = &amd_pstate_epp_driver;
+               cppc_state = AMD_PSTATE_ACTIVE;
                ret = cpufreq_register_driver(current_pstate_driver);
                break;
        default:
index 6ad2954948a5abb2f9612d4e52832d73ef25020d..11316c3b14ca49806839059a2b754658a4710826 100644 (file)
@@ -106,7 +106,8 @@ static void psci_pd_remove(void)
        struct psci_pd_provider *pd_provider, *it;
        struct generic_pm_domain *genpd;
 
-       list_for_each_entry_safe(pd_provider, it, &psci_pd_providers, link) {
+       list_for_each_entry_safe_reverse(pd_provider, it,
+                                        &psci_pd_providers, link) {
                of_genpd_del_provider(pd_provider->node);
 
                genpd = of_genpd_remove_last(pd_provider->node);
index e2f25926eb514e477f92eac95bb7d54a4eb834b1..e346c00b132af53b47e686b5e34f7a041f67fd66 100644 (file)
@@ -442,12 +442,19 @@ static int __sev_init_ex_locked(int *error)
        return __sev_do_cmd_locked(SEV_CMD_INIT_EX, &data, error);
 }
 
+static inline int __sev_do_init_locked(int *psp_ret)
+{
+       if (sev_init_ex_buffer)
+               return __sev_init_ex_locked(psp_ret);
+       else
+               return __sev_init_locked(psp_ret);
+}
+
 static int __sev_platform_init_locked(int *error)
 {
+       int rc = 0, psp_ret = SEV_RET_NO_FW_CALL;
        struct psp_device *psp = psp_master;
        struct sev_device *sev;
-       int rc = 0, psp_ret = -1;
-       int (*init_function)(int *error);
 
        if (!psp || !psp->sev_data)
                return -ENODEV;
@@ -458,15 +465,12 @@ static int __sev_platform_init_locked(int *error)
                return 0;
 
        if (sev_init_ex_buffer) {
-               init_function = __sev_init_ex_locked;
                rc = sev_read_init_ex_file();
                if (rc)
                        return rc;
-       } else {
-               init_function = __sev_init_locked;
        }
 
-       rc = init_function(&psp_ret);
+       rc = __sev_do_init_locked(&psp_ret);
        if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) {
                /*
                 * Initialization command returned an integrity check failure
@@ -475,9 +479,11 @@ static int __sev_platform_init_locked(int *error)
                 * initialization function should succeed by replacing the state
                 * with a reset state.
                 */
-               dev_err(sev->dev, "SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state.");
-               rc = init_function(&psp_ret);
+               dev_err(sev->dev,
+"SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state.");
+               rc = __sev_do_init_locked(&psp_ret);
        }
+
        if (error)
                *error = psp_ret;
 
index 45deda18ed322ef60af2ddb5bdebf8ec6a8b2448..02cc2c38b44baf8ef37c3dd9c4b4d7806181e3bb 100644 (file)
@@ -101,25 +101,40 @@ static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
                                      BIT(CXL_CM_CAP_CAP_ID_HDM));
 }
 
-static struct cxl_hdm *devm_cxl_setup_emulated_hdm(struct cxl_port *port,
-                                                  struct cxl_endpoint_dvsec_info *info)
+static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
 {
-       struct device *dev = &port->dev;
        struct cxl_hdm *cxlhdm;
+       void __iomem *hdm;
+       u32 ctrl;
+       int i;
 
-       if (!info->mem_enabled)
-               return ERR_PTR(-ENODEV);
+       if (!info)
+               return false;
 
-       cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL);
-       if (!cxlhdm)
-               return ERR_PTR(-ENOMEM);
+       cxlhdm = dev_get_drvdata(&info->port->dev);
+       hdm = cxlhdm->regs.hdm_decoder;
 
-       cxlhdm->port = port;
-       cxlhdm->decoder_count = info->ranges;
-       cxlhdm->target_count = info->ranges;
-       dev_set_drvdata(&port->dev, cxlhdm);
+       if (!hdm)
+               return true;
 
-       return cxlhdm;
+       /*
+        * If HDM decoders are present and the driver is in control of
+        * Mem_Enable skip DVSEC based emulation
+        */
+       if (!info->mem_enabled)
+               return false;
+
+       /*
+        * If any decoders are committed already, there should not be any
+        * emulated DVSEC decoders.
+        */
+       for (i = 0; i < cxlhdm->decoder_count; i++) {
+               ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
+               if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
+                       return false;
+       }
+
+       return true;
 }
 
 /**
@@ -138,13 +153,14 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
        cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL);
        if (!cxlhdm)
                return ERR_PTR(-ENOMEM);
-
        cxlhdm->port = port;
-       crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
-       if (!crb) {
-               if (info && info->mem_enabled)
-                       return devm_cxl_setup_emulated_hdm(port, info);
+       dev_set_drvdata(dev, cxlhdm);
 
+       crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
+       if (!crb && info && info->mem_enabled) {
+               cxlhdm->decoder_count = info->ranges;
+               return cxlhdm;
+       } else if (!crb) {
                dev_err(dev, "No component registers mapped\n");
                return ERR_PTR(-ENXIO);
        }
@@ -160,7 +176,15 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
                return ERR_PTR(-ENXIO);
        }
 
-       dev_set_drvdata(dev, cxlhdm);
+       /*
+        * Now that the hdm capability is parsed, decide if range
+        * register emulation is needed and fixup cxlhdm accordingly.
+        */
+       if (should_emulate_decoders(info)) {
+               dev_dbg(dev, "Fallback map %d range register%s\n", info->ranges,
+                       info->ranges > 1 ? "s" : "");
+               cxlhdm->decoder_count = info->ranges;
+       }
 
        return cxlhdm;
 }
@@ -714,14 +738,20 @@ static int cxl_decoder_reset(struct cxl_decoder *cxld)
        return 0;
 }
 
-static int cxl_setup_hdm_decoder_from_dvsec(struct cxl_port *port,
-                                           struct cxl_decoder *cxld, int which,
-                                           struct cxl_endpoint_dvsec_info *info)
+static int cxl_setup_hdm_decoder_from_dvsec(
+       struct cxl_port *port, struct cxl_decoder *cxld, u64 *dpa_base,
+       int which, struct cxl_endpoint_dvsec_info *info)
 {
+       struct cxl_endpoint_decoder *cxled;
+       u64 len;
+       int rc;
+
        if (!is_cxl_endpoint(port))
                return -EOPNOTSUPP;
 
-       if (!range_len(&info->dvsec_range[which]))
+       cxled = to_cxl_endpoint_decoder(&cxld->dev);
+       len = range_len(&info->dvsec_range[which]);
+       if (!len)
                return -ENOENT;
 
        cxld->target_type = CXL_DECODER_EXPANDER;
@@ -736,40 +766,24 @@ static int cxl_setup_hdm_decoder_from_dvsec(struct cxl_port *port,
        cxld->flags |= CXL_DECODER_F_ENABLE | CXL_DECODER_F_LOCK;
        port->commit_end = cxld->id;
 
-       return 0;
-}
-
-static bool should_emulate_decoders(struct cxl_port *port)
-{
-       struct cxl_hdm *cxlhdm = dev_get_drvdata(&port->dev);
-       void __iomem *hdm = cxlhdm->regs.hdm_decoder;
-       u32 ctrl;
-       int i;
-
-       if (!is_cxl_endpoint(cxlhdm->port))
-               return false;
-
-       if (!hdm)
-               return true;
-
-       /*
-        * If any decoders are committed already, there should not be any
-        * emulated DVSEC decoders.
-        */
-       for (i = 0; i < cxlhdm->decoder_count; i++) {
-               ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(i));
-               if (FIELD_GET(CXL_HDM_DECODER0_CTRL_COMMITTED, ctrl))
-                       return false;
+       rc = devm_cxl_dpa_reserve(cxled, *dpa_base, len, 0);
+       if (rc) {
+               dev_err(&port->dev,
+                       "decoder%d.%d: Failed to reserve DPA range %#llx - %#llx\n (%d)",
+                       port->id, cxld->id, *dpa_base, *dpa_base + len - 1, rc);
+               return rc;
        }
+       *dpa_base += len;
+       cxled->state = CXL_DECODER_STATE_AUTO;
 
-       return true;
+       return 0;
 }
 
 static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                            int *target_map, void __iomem *hdm, int which,
                            u64 *dpa_base, struct cxl_endpoint_dvsec_info *info)
 {
-       struct cxl_endpoint_decoder *cxled = NULL;
+       struct cxl_endpoint_decoder *cxled;
        u64 size, base, skip, dpa_size;
        bool committed;
        u32 remainder;
@@ -780,11 +794,9 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                unsigned char target_id[8];
        } target_list;
 
-       if (should_emulate_decoders(port))
-               return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
-
-       if (is_endpoint_decoder(&cxld->dev))
-               cxled = to_cxl_endpoint_decoder(&cxld->dev);
+       if (should_emulate_decoders(info))
+               return cxl_setup_hdm_decoder_from_dvsec(port, cxld, dpa_base,
+                                                       which, info);
 
        ctrl = readl(hdm + CXL_HDM_DECODER0_CTRL_OFFSET(which));
        base = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_BASE_LOW_OFFSET(which));
@@ -806,9 +818,6 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                .end = base + size - 1,
        };
 
-       if (cxled && !committed && range_len(&info->dvsec_range[which]))
-               return cxl_setup_hdm_decoder_from_dvsec(port, cxld, which, info);
-
        /* decoders are enabled if committed */
        if (committed) {
                cxld->flags |= CXL_DECODER_F_ENABLE;
@@ -846,7 +855,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
        if (rc)
                return rc;
 
-       if (!cxled) {
+       if (!info) {
                target_list.value =
                        ioread64_hi_lo(hdm + CXL_HDM_DECODER0_TL_LOW(which));
                for (i = 0; i < cxld->interleave_ways; i++)
@@ -866,6 +875,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
                return -ENXIO;
        }
        skip = ioread64_hi_lo(hdm + CXL_HDM_DECODER0_SKIP_LOW(which));
+       cxled = to_cxl_endpoint_decoder(&cxld->dev);
        rc = devm_cxl_dpa_reserve(cxled, *dpa_base + skip, dpa_size, skip);
        if (rc) {
                dev_err(&port->dev,
index 7328a255241138d8d2f0f963b7139a8281a82c0a..523d5b9fd7fcf2a1fb0b62c85dabac13c63b3c00 100644 (file)
@@ -462,7 +462,7 @@ static struct pci_doe_mb *find_cdat_doe(struct device *uport)
        return NULL;
 }
 
-#define CDAT_DOE_REQ(entry_handle)                                     \
+#define CDAT_DOE_REQ(entry_handle) cpu_to_le32                         \
        (FIELD_PREP(CXL_DOE_TABLE_ACCESS_REQ_CODE,                      \
                    CXL_DOE_TABLE_ACCESS_REQ_CODE_READ) |               \
         FIELD_PREP(CXL_DOE_TABLE_ACCESS_TABLE_TYPE,                    \
@@ -475,8 +475,8 @@ static void cxl_doe_task_complete(struct pci_doe_task *task)
 }
 
 struct cdat_doe_task {
-       u32 request_pl;
-       u32 response_pl[32];
+       __le32 request_pl;
+       __le32 response_pl[32];
        struct completion c;
        struct pci_doe_task task;
 };
@@ -510,10 +510,10 @@ static int cxl_cdat_get_length(struct device *dev,
                return rc;
        }
        wait_for_completion(&t.c);
-       if (t.task.rv < sizeof(u32))
+       if (t.task.rv < 2 * sizeof(__le32))
                return -EIO;
 
-       *length = t.response_pl[1];
+       *length = le32_to_cpu(t.response_pl[1]);
        dev_dbg(dev, "CDAT length %zu\n", *length);
 
        return 0;
@@ -524,13 +524,13 @@ static int cxl_cdat_read_table(struct device *dev,
                               struct cxl_cdat *cdat)
 {
        size_t length = cdat->length;
-       u32 *data = cdat->table;
+       __le32 *data = cdat->table;
        int entry_handle = 0;
 
        do {
                DECLARE_CDAT_DOE_TASK(CDAT_DOE_REQ(entry_handle), t);
+               struct cdat_entry_header *entry;
                size_t entry_dw;
-               u32 *entry;
                int rc;
 
                rc = pci_doe_submit_task(cdat_doe, &t.task);
@@ -539,26 +539,34 @@ static int cxl_cdat_read_table(struct device *dev,
                        return rc;
                }
                wait_for_completion(&t.c);
-               /* 1 DW header + 1 DW data min */
-               if (t.task.rv < (2 * sizeof(u32)))
+
+               /* 1 DW Table Access Response Header + CDAT entry */
+               entry = (struct cdat_entry_header *)(t.response_pl + 1);
+               if ((entry_handle == 0 &&
+                    t.task.rv != sizeof(__le32) + sizeof(struct cdat_header)) ||
+                   (entry_handle > 0 &&
+                    (t.task.rv < sizeof(__le32) + sizeof(*entry) ||
+                     t.task.rv != sizeof(__le32) + le16_to_cpu(entry->length))))
                        return -EIO;
 
                /* Get the CXL table access header entry handle */
                entry_handle = FIELD_GET(CXL_DOE_TABLE_ACCESS_ENTRY_HANDLE,
-                                        t.response_pl[0]);
-               entry = t.response_pl + 1;
-               entry_dw = t.task.rv / sizeof(u32);
+                                        le32_to_cpu(t.response_pl[0]));
+               entry_dw = t.task.rv / sizeof(__le32);
                /* Skip Header */
                entry_dw -= 1;
-               entry_dw = min(length / sizeof(u32), entry_dw);
+               entry_dw = min(length / sizeof(__le32), entry_dw);
                /* Prevent length < 1 DW from causing a buffer overflow */
                if (entry_dw) {
-                       memcpy(data, entry, entry_dw * sizeof(u32));
-                       length -= entry_dw * sizeof(u32);
+                       memcpy(data, entry, entry_dw * sizeof(__le32));
+                       length -= entry_dw * sizeof(__le32);
                        data += entry_dw;
                }
        } while (entry_handle != CXL_DOE_TABLE_ACCESS_LAST_ENTRY);
 
+       /* Length in CDAT header may exceed concatenation of CDAT entries */
+       cdat->length -= length;
+
        return 0;
 }
 
index c2e4b10937884a7ec3cc1266f395ce2dedcbe209..f8c38d9972522a605e9bf94f436343f62df0e64f 100644 (file)
@@ -62,9 +62,9 @@ static int match_nvdimm_bridge(struct device *dev, void *data)
        return is_cxl_nvdimm_bridge(dev);
 }
 
-struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct device *start)
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd)
 {
-       struct cxl_port *port = find_cxl_root(start);
+       struct cxl_port *port = find_cxl_root(dev_get_drvdata(&cxlmd->dev));
        struct device *dev;
 
        if (!port)
@@ -253,7 +253,7 @@ int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd)
        struct device *dev;
        int rc;
 
-       cxl_nvb = cxl_find_nvdimm_bridge(&cxlmd->dev);
+       cxl_nvb = cxl_find_nvdimm_bridge(cxlmd);
        if (!cxl_nvb)
                return -ENODEV;
 
index 8ee6b6e2e2a4edd698e6812e75fa68902ff833fe..4d1f9c5b5029a594835b0ed251fe229648cc4853 100644 (file)
@@ -823,41 +823,17 @@ static bool dev_is_cxl_root_child(struct device *dev)
        return false;
 }
 
-/* Find a 2nd level CXL port that has a dport that is an ancestor of @match */
-static int match_root_child(struct device *dev, const void *match)
+struct cxl_port *find_cxl_root(struct cxl_port *port)
 {
-       const struct device *iter = NULL;
-       struct cxl_dport *dport;
-       struct cxl_port *port;
-
-       if (!dev_is_cxl_root_child(dev))
-               return 0;
-
-       port = to_cxl_port(dev);
-       iter = match;
-       while (iter) {
-               dport = cxl_find_dport_by_dev(port, iter);
-               if (dport)
-                       break;
-               iter = iter->parent;
-       }
-
-       return !!iter;
-}
+       struct cxl_port *iter = port;
 
-struct cxl_port *find_cxl_root(struct device *dev)
-{
-       struct device *port_dev;
-       struct cxl_port *root;
+       while (iter && !is_cxl_root(iter))
+               iter = to_cxl_port(iter->dev.parent);
 
-       port_dev = bus_find_device(&cxl_bus_type, NULL, dev, match_root_child);
-       if (!port_dev)
+       if (!iter)
                return NULL;
-
-       root = to_cxl_port(port_dev->parent);
-       get_device(&root->dev);
-       put_device(port_dev);
-       return root;
+       get_device(&iter->dev);
+       return iter;
 }
 EXPORT_SYMBOL_NS_GPL(find_cxl_root, CXL);
 
index f29028148806baa2982eaf5b3a9e92840f8bff92..b2fd67fcebfb5742ce2095d062b7201075e4b10f 100644 (file)
@@ -134,9 +134,13 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
                struct cxl_endpoint_decoder *cxled = p->targets[i];
                struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
                struct cxl_port *iter = cxled_to_port(cxled);
+               struct cxl_dev_state *cxlds = cxlmd->cxlds;
                struct cxl_ep *ep;
                int rc = 0;
 
+               if (cxlds->rcd)
+                       goto endpoint_reset;
+
                while (!is_cxl_root(to_cxl_port(iter->dev.parent)))
                        iter = to_cxl_port(iter->dev.parent);
 
@@ -153,6 +157,7 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
                                return rc;
                }
 
+endpoint_reset:
                rc = cxled->cxld.reset(&cxled->cxld);
                if (rc)
                        return rc;
@@ -1199,6 +1204,7 @@ static void cxl_region_teardown_targets(struct cxl_region *cxlr)
 {
        struct cxl_region_params *p = &cxlr->params;
        struct cxl_endpoint_decoder *cxled;
+       struct cxl_dev_state *cxlds;
        struct cxl_memdev *cxlmd;
        struct cxl_port *iter;
        struct cxl_ep *ep;
@@ -1214,6 +1220,10 @@ static void cxl_region_teardown_targets(struct cxl_region *cxlr)
        for (i = 0; i < p->nr_targets; i++) {
                cxled = p->targets[i];
                cxlmd = cxled_to_memdev(cxled);
+               cxlds = cxlmd->cxlds;
+
+               if (cxlds->rcd)
+                       continue;
 
                iter = cxled_to_port(cxled);
                while (!is_cxl_root(to_cxl_port(iter->dev.parent)))
@@ -1229,14 +1239,24 @@ static int cxl_region_setup_targets(struct cxl_region *cxlr)
 {
        struct cxl_region_params *p = &cxlr->params;
        struct cxl_endpoint_decoder *cxled;
+       struct cxl_dev_state *cxlds;
+       int i, rc, rch = 0, vh = 0;
        struct cxl_memdev *cxlmd;
        struct cxl_port *iter;
        struct cxl_ep *ep;
-       int i, rc;
 
        for (i = 0; i < p->nr_targets; i++) {
                cxled = p->targets[i];
                cxlmd = cxled_to_memdev(cxled);
+               cxlds = cxlmd->cxlds;
+
+               /* validate that all targets agree on topology */
+               if (!cxlds->rcd) {
+                       vh++;
+               } else {
+                       rch++;
+                       continue;
+               }
 
                iter = cxled_to_port(cxled);
                while (!is_cxl_root(to_cxl_port(iter->dev.parent)))
@@ -1256,6 +1276,12 @@ static int cxl_region_setup_targets(struct cxl_region *cxlr)
                }
        }
 
+       if (rch && vh) {
+               dev_err(&cxlr->dev, "mismatched CXL topologies detected\n");
+               cxl_region_teardown_targets(cxlr);
+               return -ENXIO;
+       }
+
        return 0;
 }
 
@@ -1648,6 +1674,7 @@ static int cxl_region_attach(struct cxl_region *cxlr,
                if (rc)
                        goto err_decrement;
                p->state = CXL_CONFIG_ACTIVE;
+               set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
        }
 
        cxled->cxld.interleave_ways = p->interleave_ways;
@@ -1749,8 +1776,6 @@ static int attach_target(struct cxl_region *cxlr,
 
        down_read(&cxl_dpa_rwsem);
        rc = cxl_region_attach(cxlr, cxled, pos);
-       if (rc == 0)
-               set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
        up_read(&cxl_dpa_rwsem);
        up_write(&cxl_region_rwsem);
        return rc;
@@ -2251,7 +2276,7 @@ static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)
                 * bridge for one device is the same for all.
                 */
                if (i == 0) {
-                       cxl_nvb = cxl_find_nvdimm_bridge(&cxlmd->dev);
+                       cxl_nvb = cxl_find_nvdimm_bridge(cxlmd);
                        if (!cxl_nvb) {
                                cxlr_pmem = ERR_PTR(-ENODEV);
                                goto out;
index f2b0962a552d582cd190f028cc54f76cfbc9cffb..044a92d9813e239d1b97e7a4935f36850c30e154 100644 (file)
@@ -658,7 +658,7 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port);
 struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport,
                                   resource_size_t component_reg_phys,
                                   struct cxl_dport *parent_dport);
-struct cxl_port *find_cxl_root(struct device *dev);
+struct cxl_port *find_cxl_root(struct cxl_port *port);
 int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
 void cxl_bus_rescan(void);
 void cxl_bus_drain(void);
@@ -695,13 +695,15 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
 
 /**
  * struct cxl_endpoint_dvsec_info - Cached DVSEC info
- * @mem_enabled: cached value of mem_enabled in the DVSEC, PCIE_DEVICE
+ * @mem_enabled: cached value of mem_enabled in the DVSEC at init time
  * @ranges: Number of active HDM ranges this device uses.
+ * @port: endpoint port associated with this info instance
  * @dvsec_range: cached attributes of the ranges in the DVSEC, PCIE_DEVICE
  */
 struct cxl_endpoint_dvsec_info {
        bool mem_enabled;
        int ranges;
+       struct cxl_port *port;
        struct range dvsec_range[2];
 };
 
@@ -758,7 +760,7 @@ struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
 bool is_cxl_nvdimm(struct device *dev);
 bool is_cxl_nvdimm_bridge(struct device *dev);
 int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd);
-struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct device *dev);
+struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_memdev *cxlmd);
 
 #ifdef CONFIG_CXL_REGION
 bool is_cxl_pmem_region(struct device *dev);
index be6a2ef3cce3738a45cc19d8c9cb54aff93af693..0465ef963cd6a0b23dae3cfb7177d9a033dcde18 100644 (file)
@@ -68,6 +68,20 @@ enum cxl_regloc_type {
        CXL_REGLOC_RBI_TYPES
 };
 
+struct cdat_header {
+       __le32 length;
+       u8 revision;
+       u8 checksum;
+       u8 reserved[6];
+       __le32 sequence;
+} __packed;
+
+struct cdat_entry_header {
+       u8 type;
+       u8 reserved;
+       __le16 length;
+} __packed;
+
 int devm_cxl_port_enumerate_dports(struct cxl_port *port);
 struct cxl_dev_state;
 int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
index 1049bb5ea496129177e3db06fae3b64198548483..22a7ab2bae7c7e53878faf3b372718f50ea1457f 100644 (file)
@@ -78,8 +78,8 @@ static int cxl_switch_port_probe(struct cxl_port *port)
 
 static int cxl_endpoint_port_probe(struct cxl_port *port)
 {
+       struct cxl_endpoint_dvsec_info info = { .port = port };
        struct cxl_memdev *cxlmd = to_cxl_memdev(port->uport);
-       struct cxl_endpoint_dvsec_info info = { 0 };
        struct cxl_dev_state *cxlds = cxlmd->cxlds;
        struct cxl_hdm *cxlhdm;
        struct cxl_port *root;
@@ -119,7 +119,7 @@ static int cxl_endpoint_port_probe(struct cxl_port *port)
         * This can't fail in practice as CXL root exit unregisters all
         * descendant ports and that in turn synchronizes with cxl_port_probe()
         */
-       root = find_cxl_root(&cxlmd->dev);
+       root = find_cxl_root(port);
 
        /*
         * Now that all endpoint decoders are successfully enumerated, try to
index 90f28bda29c8bd41e19b340e779c351634d29283..4cf8da77bdd91329012579de26bb7aa01f7979f4 100644 (file)
@@ -75,6 +75,7 @@
 
 #define REG_TX_INTSTATE(idx)           (0x0030 + (idx) * 4)
 #define REG_RX_INTSTATE(idx)           (0x0040 + (idx) * 4)
+#define REG_GLOBAL_INTSTATE(idx)       (0x0050 + (idx) * 4)
 #define REG_CHAN_INTSTATUS(ch, idx)    (0x8010 + (ch) * 0x200 + (idx) * 4)
 #define REG_CHAN_INTMASK(ch, idx)      (0x8020 + (ch) * 0x200 + (idx) * 4)
 
@@ -511,7 +512,10 @@ static int admac_terminate_all(struct dma_chan *chan)
        admac_stop_chan(adchan);
        admac_reset_rings(adchan);
 
-       adchan->current_tx = NULL;
+       if (adchan->current_tx) {
+               list_add_tail(&adchan->current_tx->node, &adchan->to_free);
+               adchan->current_tx = NULL;
+       }
        /*
         * Descriptors can only be freed after the tasklet
         * has been killed (in admac_synchronize).
@@ -672,13 +676,14 @@ static void admac_handle_chan_int(struct admac_data *ad, int no)
 static irqreturn_t admac_interrupt(int irq, void *devid)
 {
        struct admac_data *ad = devid;
-       u32 rx_intstate, tx_intstate;
+       u32 rx_intstate, tx_intstate, global_intstate;
        int i;
 
        rx_intstate = readl_relaxed(ad->base + REG_RX_INTSTATE(ad->irq_index));
        tx_intstate = readl_relaxed(ad->base + REG_TX_INTSTATE(ad->irq_index));
+       global_intstate = readl_relaxed(ad->base + REG_GLOBAL_INTSTATE(ad->irq_index));
 
-       if (!tx_intstate && !rx_intstate)
+       if (!tx_intstate && !rx_intstate && !global_intstate)
                return IRQ_NONE;
 
        for (i = 0; i < ad->nchannels; i += 2) {
@@ -693,6 +698,12 @@ static irqreturn_t admac_interrupt(int irq, void *devid)
                rx_intstate >>= 1;
        }
 
+       if (global_intstate) {
+               dev_warn(ad->dev, "clearing unknown global interrupt flag: %x\n",
+                        global_intstate);
+               writel_relaxed(~(u32) 0, ad->base + REG_GLOBAL_INTSTATE(ad->irq_index));
+       }
+
        return IRQ_HANDLED;
 }
 
@@ -850,6 +861,9 @@ static int admac_probe(struct platform_device *pdev)
 
        dma->directions = BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
        dma->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+       dma->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                       BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                       BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
        dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
                        BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
                        BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
index c24bca210104c1e92a46da5ef8340489e27d5da7..826b98284fa1f845698cc996035d5f6bb56fdcc5 100644 (file)
@@ -1342,7 +1342,7 @@ int dmaenginem_async_device_register(struct dma_device *device)
        if (ret)
                return ret;
 
-       return devm_add_action(device->dev, dmaenginem_async_device_unregister, device);
+       return devm_add_action_or_reset(device->dev, dmaenginem_async_device_unregister, device);
 }
 EXPORT_SYMBOL(dmaenginem_async_device_register);
 
index 462109c61653752b698558421a0192124ae0e20c..93ee298d52b894f1a7200844168c2baaf0406763 100644 (file)
@@ -277,7 +277,7 @@ failed:
 
 /**
  * xdma_xfer_start - Start DMA transfer
- * @xdma_chan: DMA channel pointer
+ * @xchan: DMA channel pointer
  */
 static int xdma_xfer_start(struct xdma_chan *xchan)
 {
index e7e8e624a4362b3ee6a60998a1ddf0928f682d4e..8b31cd54bdb6de4a483fca1fbdc1499aa64321bb 100644 (file)
@@ -2149,10 +2149,8 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
        }
 
        edac->sb_irq = platform_get_irq(pdev, 0);
-       if (edac->sb_irq < 0) {
-               dev_err(&pdev->dev, "No SBERR IRQ resource\n");
+       if (edac->sb_irq < 0)
                return edac->sb_irq;
-       }
 
        irq_set_chained_handler_and_data(edac->sb_irq,
                                         altr_edac_a10_irq_handler,
@@ -2184,10 +2182,9 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
        }
 #else
        edac->db_irq = platform_get_irq(pdev, 1);
-       if (edac->db_irq < 0) {
-               dev_err(&pdev->dev, "No DBERR IRQ resource\n");
+       if (edac->db_irq < 0)
                return edac->db_irq;
-       }
+
        irq_set_chained_handler_and_data(edac->db_irq,
                                         altr_edac_a10_irq_handler, edac);
 #endif
@@ -2226,6 +2223,5 @@ static struct platform_driver altr_edac_a10_driver = {
 };
 module_platform_driver(altr_edac_a10_driver);
 
-MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Thor Thayer");
 MODULE_DESCRIPTION("EDAC Driver for Altera Memories");
index 5b42533f306a793b7e28035174b9a9afa3df35e8..5c4292e65b96e09fde948b7301b348f971b798b1 100644 (file)
@@ -13,11 +13,9 @@ module_param(ecc_enable_override, int, 0644);
 
 static struct msr __percpu *msrs;
 
-static struct amd64_family_type *fam_type;
-
-static inline u32 get_umc_reg(u32 reg)
+static inline u32 get_umc_reg(struct amd64_pvt *pvt, u32 reg)
 {
-       if (!fam_type->flags.zn_regs_v2)
+       if (!pvt->flags.zn_regs_v2)
                return reg;
 
        switch (reg) {
@@ -437,7 +435,7 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
        for (i = 0; i < pvt->csels[dct].m_cnt; i++)
 
 #define for_each_umc(i) \
-       for (i = 0; i < fam_type->max_mcs; i++)
+       for (i = 0; i < pvt->max_mcs; i++)
 
 /*
  * @input_addr is an InputAddr associated with the node given by mci. Return the
@@ -1258,40 +1256,102 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
  * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
  * are ECC capable.
  */
-static unsigned long determine_edac_cap(struct amd64_pvt *pvt)
+static unsigned long dct_determine_edac_cap(struct amd64_pvt *pvt)
 {
        unsigned long edac_cap = EDAC_FLAG_NONE;
        u8 bit;
 
-       if (pvt->umc) {
-               u8 i, umc_en_mask = 0, dimm_ecc_en_mask = 0;
+       bit = (pvt->fam > 0xf || pvt->ext_model >= K8_REV_F)
+               ? 19
+               : 17;
 
-               for_each_umc(i) {
-                       if (!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT))
-                               continue;
+       if (pvt->dclr0 & BIT(bit))
+               edac_cap = EDAC_FLAG_SECDED;
 
-                       umc_en_mask |= BIT(i);
+       return edac_cap;
+}
 
-                       /* UMC Configuration bit 12 (DimmEccEn) */
-                       if (pvt->umc[i].umc_cfg & BIT(12))
-                               dimm_ecc_en_mask |= BIT(i);
-               }
+static unsigned long umc_determine_edac_cap(struct amd64_pvt *pvt)
+{
+       u8 i, umc_en_mask = 0, dimm_ecc_en_mask = 0;
+       unsigned long edac_cap = EDAC_FLAG_NONE;
 
-               if (umc_en_mask == dimm_ecc_en_mask)
-                       edac_cap = EDAC_FLAG_SECDED;
-       } else {
-               bit = (pvt->fam > 0xf || pvt->ext_model >= K8_REV_F)
-                       ? 19
-                       : 17;
+       for_each_umc(i) {
+               if (!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT))
+                       continue;
 
-               if (pvt->dclr0 & BIT(bit))
-                       edac_cap = EDAC_FLAG_SECDED;
+               umc_en_mask |= BIT(i);
+
+               /* UMC Configuration bit 12 (DimmEccEn) */
+               if (pvt->umc[i].umc_cfg & BIT(12))
+                       dimm_ecc_en_mask |= BIT(i);
        }
 
+       if (umc_en_mask == dimm_ecc_en_mask)
+               edac_cap = EDAC_FLAG_SECDED;
+
        return edac_cap;
 }
 
-static void debug_display_dimm_sizes(struct amd64_pvt *, u8);
+/*
+ * debug routine to display the memory sizes of all logical DIMMs and its
+ * CSROWs
+ */
+static void dct_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
+{
+       u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
+       u32 dbam  = ctrl ? pvt->dbam1 : pvt->dbam0;
+       int dimm, size0, size1;
+
+       if (pvt->fam == 0xf) {
+               /* K8 families < revF not supported yet */
+               if (pvt->ext_model < K8_REV_F)
+                       return;
+
+               WARN_ON(ctrl != 0);
+       }
+
+       if (pvt->fam == 0x10) {
+               dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1
+                                                          : pvt->dbam0;
+               dcsb = (ctrl && !dct_ganging_enabled(pvt)) ?
+                                pvt->csels[1].csbases :
+                                pvt->csels[0].csbases;
+       } else if (ctrl) {
+               dbam = pvt->dbam0;
+               dcsb = pvt->csels[1].csbases;
+       }
+       edac_dbg(1, "F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n",
+                ctrl, dbam);
+
+       edac_printk(KERN_DEBUG, EDAC_MC, "DCT%d chip selects:\n", ctrl);
+
+       /* Dump memory sizes for DIMM and its CSROWs */
+       for (dimm = 0; dimm < 4; dimm++) {
+               size0 = 0;
+               if (dcsb[dimm * 2] & DCSB_CS_ENABLE)
+                       /*
+                        * For F15m60h, we need multiplier for LRDIMM cs_size
+                        * calculation. We pass dimm value to the dbam_to_cs
+                        * mapper so we can find the multiplier from the
+                        * corresponding DCSM.
+                        */
+                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
+                                                    DBAM_DIMM(dimm, dbam),
+                                                    dimm);
+
+               size1 = 0;
+               if (dcsb[dimm * 2 + 1] & DCSB_CS_ENABLE)
+                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
+                                                    DBAM_DIMM(dimm, dbam),
+                                                    dimm);
+
+               amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
+                          dimm * 2,     size0,
+                          dimm * 2 + 1, size1);
+       }
+}
+
 
 static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 {
@@ -1334,7 +1394,7 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 #define CS_EVEN                        (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
 #define CS_ODD                 (CS_ODD_PRIMARY | CS_ODD_SECONDARY)
 
-static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
+static int umc_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
 {
        u8 base, count = 0;
        int cs_mode = 0;
@@ -1366,7 +1426,85 @@ static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
        return cs_mode;
 }
 
-static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
+static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
+                                   unsigned int cs_mode, int csrow_nr)
+{
+       u32 addr_mask_orig, addr_mask_deinterleaved;
+       u32 msb, weight, num_zero_bits;
+       int cs_mask_nr = csrow_nr;
+       int dimm, size = 0;
+
+       /* No Chip Selects are enabled. */
+       if (!cs_mode)
+               return size;
+
+       /* Requested size of an even CS but none are enabled. */
+       if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1))
+               return size;
+
+       /* Requested size of an odd CS but none are enabled. */
+       if (!(cs_mode & CS_ODD) && (csrow_nr & 1))
+               return size;
+
+       /*
+        * Family 17h introduced systems with one mask per DIMM,
+        * and two Chip Selects per DIMM.
+        *
+        *      CS0 and CS1 -> MASK0 / DIMM0
+        *      CS2 and CS3 -> MASK1 / DIMM1
+        *
+        * Family 19h Model 10h introduced systems with one mask per Chip Select,
+        * and two Chip Selects per DIMM.
+        *
+        *      CS0 -> MASK0 -> DIMM0
+        *      CS1 -> MASK1 -> DIMM0
+        *      CS2 -> MASK2 -> DIMM1
+        *      CS3 -> MASK3 -> DIMM1
+        *
+        * Keep the mask number equal to the Chip Select number for newer systems,
+        * and shift the mask number for older systems.
+        */
+       dimm = csrow_nr >> 1;
+
+       if (!pvt->flags.zn_regs_v2)
+               cs_mask_nr >>= 1;
+
+       /* Asymmetric dual-rank DIMM support. */
+       if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
+               addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
+       else
+               addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];
+
+       /*
+        * The number of zero bits in the mask is equal to the number of bits
+        * in a full mask minus the number of bits in the current mask.
+        *
+        * The MSB is the number of bits in the full mask because BIT[0] is
+        * always 0.
+        *
+        * In the special 3 Rank interleaving case, a single bit is flipped
+        * without swapping with the most significant bit. This can be handled
+        * by keeping the MSB where it is and ignoring the single zero bit.
+        */
+       msb = fls(addr_mask_orig) - 1;
+       weight = hweight_long(addr_mask_orig);
+       num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
+
+       /* Take the number of zero bits off from the top of the mask. */
+       addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
+
+       edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
+       edac_dbg(1, "  Original AddrMask: 0x%x\n", addr_mask_orig);
+       edac_dbg(1, "  Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
+
+       /* Register [31:1] = Address [39:9]. Size is in kBs here. */
+       size = (addr_mask_deinterleaved >> 2) + 1;
+
+       /* Return size in MBs. */
+       return size >> 10;
+}
+
+static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 {
        int dimm, size0, size1, cs0, cs1, cs_mode;
 
@@ -1376,10 +1514,10 @@ static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
                cs0 = dimm * 2;
                cs1 = dimm * 2 + 1;
 
-               cs_mode = f17_get_cs_mode(dimm, ctrl, pvt);
+               cs_mode = umc_get_cs_mode(dimm, ctrl, pvt);
 
-               size0 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs0);
-               size1 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs1);
+               size0 = umc_addr_mask_to_cs_size(pvt, ctrl, cs_mode, cs0);
+               size1 = umc_addr_mask_to_cs_size(pvt, ctrl, cs_mode, cs1);
 
                amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
                                cs0,    size0,
@@ -1387,7 +1525,7 @@ static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
        }
 }
 
-static void __dump_misc_regs_df(struct amd64_pvt *pvt)
+static void umc_dump_misc_regs(struct amd64_pvt *pvt)
 {
        struct amd64_umc *umc;
        u32 i, tmp, umc_base;
@@ -1420,18 +1558,17 @@ static void __dump_misc_regs_df(struct amd64_pvt *pvt)
 
                if (umc->dram_type == MEM_LRDDR4 || umc->dram_type == MEM_LRDDR5) {
                        amd_smn_read(pvt->mc_node_id,
-                                    umc_base + get_umc_reg(UMCCH_ADDR_CFG),
+                                    umc_base + get_umc_reg(pvt, UMCCH_ADDR_CFG),
                                     &tmp);
                        edac_dbg(1, "UMC%d LRDIMM %dx rank multiply\n",
                                        i, 1 << ((tmp >> 4) & 0x3));
                }
 
-               debug_display_dimm_sizes_df(pvt, i);
+               umc_debug_display_dimm_sizes(pvt, i);
        }
 }
 
-/* Display and decode various NB registers for debug purposes. */
-static void __dump_misc_regs(struct amd64_pvt *pvt)
+static void dct_dump_misc_regs(struct amd64_pvt *pvt)
 {
        edac_dbg(1, "F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap);
 
@@ -1451,28 +1588,19 @@ static void __dump_misc_regs(struct amd64_pvt *pvt)
                 (pvt->fam == 0xf) ? k8_dhar_offset(pvt)
                                   : f10_dhar_offset(pvt));
 
-       debug_display_dimm_sizes(pvt, 0);
+       dct_debug_display_dimm_sizes(pvt, 0);
 
        /* everything below this point is Fam10h and above */
        if (pvt->fam == 0xf)
                return;
 
-       debug_display_dimm_sizes(pvt, 1);
+       dct_debug_display_dimm_sizes(pvt, 1);
 
        /* Only if NOT ganged does dclr1 have valid info */
        if (!dct_ganging_enabled(pvt))
                debug_dump_dramcfg_low(pvt, pvt->dclr1, 1);
 
        edac_dbg(1, "  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
-}
-
-/* Display and decode various NB registers for debug purposes. */
-static void dump_misc_regs(struct amd64_pvt *pvt)
-{
-       if (pvt->umc)
-               __dump_misc_regs_df(pvt);
-       else
-               __dump_misc_regs(pvt);
 
        amd64_info("using x%u syndromes.\n", pvt->ecc_sym_sz);
 }
@@ -1480,7 +1608,7 @@ static void dump_misc_regs(struct amd64_pvt *pvt)
 /*
  * See BKDG, F2x[1,0][5C:40], F2[1,0][6C:60]
  */
-static void prep_chip_selects(struct amd64_pvt *pvt)
+static void dct_prep_chip_selects(struct amd64_pvt *pvt)
 {
        if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) {
                pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
@@ -1488,21 +1616,23 @@ static void prep_chip_selects(struct amd64_pvt *pvt)
        } else if (pvt->fam == 0x15 && pvt->model == 0x30) {
                pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4;
                pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2;
-       } else if (pvt->fam >= 0x17) {
-               int umc;
-
-               for_each_umc(umc) {
-                       pvt->csels[umc].b_cnt = 4;
-                       pvt->csels[umc].m_cnt = fam_type->flags.zn_regs_v2 ? 4 : 2;
-               }
-
        } else {
                pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
                pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4;
        }
 }
 
-static void read_umc_base_mask(struct amd64_pvt *pvt)
+static void umc_prep_chip_selects(struct amd64_pvt *pvt)
+{
+       int umc;
+
+       for_each_umc(umc) {
+               pvt->csels[umc].b_cnt = 4;
+               pvt->csels[umc].m_cnt = pvt->flags.zn_regs_v2 ? 4 : 2;
+       }
+}
+
+static void umc_read_base_mask(struct amd64_pvt *pvt)
 {
        u32 umc_base_reg, umc_base_reg_sec;
        u32 umc_mask_reg, umc_mask_reg_sec;
@@ -1533,7 +1663,7 @@ static void read_umc_base_mask(struct amd64_pvt *pvt)
                }
 
                umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK;
-               umc_mask_reg_sec = get_umc_base(umc) + get_umc_reg(UMCCH_ADDR_MASK_SEC);
+               umc_mask_reg_sec = get_umc_base(umc) + get_umc_reg(pvt, UMCCH_ADDR_MASK_SEC);
 
                for_each_chip_select_mask(cs, umc, pvt) {
                        mask = &pvt->csels[umc].csmasks[cs];
@@ -1556,15 +1686,10 @@ static void read_umc_base_mask(struct amd64_pvt *pvt)
 /*
  * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers
  */
-static void read_dct_base_mask(struct amd64_pvt *pvt)
+static void dct_read_base_mask(struct amd64_pvt *pvt)
 {
        int cs;
 
-       prep_chip_selects(pvt);
-
-       if (pvt->umc)
-               return read_umc_base_mask(pvt);
-
        for_each_chip_select(cs, 0, pvt) {
                int reg0   = DCSB0 + (cs * 4);
                int reg1   = DCSB1 + (cs * 4);
@@ -1604,7 +1729,7 @@ static void read_dct_base_mask(struct amd64_pvt *pvt)
        }
 }
 
-static void determine_memory_type_df(struct amd64_pvt *pvt)
+static void umc_determine_memory_type(struct amd64_pvt *pvt)
 {
        struct amd64_umc *umc;
        u32 i;
@@ -1621,7 +1746,7 @@ static void determine_memory_type_df(struct amd64_pvt *pvt)
                 * Check if the system supports the "DDR Type" field in UMC Config
                 * and has DDR5 DIMMs in use.
                 */
-               if (fam_type->flags.zn_regs_v2 && ((umc->umc_cfg & GENMASK(2, 0)) == 0x1)) {
+               if (pvt->flags.zn_regs_v2 && ((umc->umc_cfg & GENMASK(2, 0)) == 0x1)) {
                        if (umc->dimm_cfg & BIT(5))
                                umc->dram_type = MEM_LRDDR5;
                        else if (umc->dimm_cfg & BIT(4))
@@ -1641,13 +1766,10 @@ static void determine_memory_type_df(struct amd64_pvt *pvt)
        }
 }
 
-static void determine_memory_type(struct amd64_pvt *pvt)
+static void dct_determine_memory_type(struct amd64_pvt *pvt)
 {
        u32 dram_ctrl, dcsm;
 
-       if (pvt->umc)
-               return determine_memory_type_df(pvt);
-
        switch (pvt->fam) {
        case 0xf:
                if (pvt->ext_model >= K8_REV_F)
@@ -1697,6 +1819,8 @@ static void determine_memory_type(struct amd64_pvt *pvt)
                WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
                pvt->dram_type = MEM_EMPTY;
        }
+
+       edac_dbg(1, "  DIMM type: %s\n", edac_mem_types[pvt->dram_type]);
        return;
 
 ddr3:
@@ -2081,84 +2205,6 @@ static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
                return ddr3_cs_size(cs_mode, false);
 }
 
-static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc,
-                                   unsigned int cs_mode, int csrow_nr)
-{
-       u32 addr_mask_orig, addr_mask_deinterleaved;
-       u32 msb, weight, num_zero_bits;
-       int cs_mask_nr = csrow_nr;
-       int dimm, size = 0;
-
-       /* No Chip Selects are enabled. */
-       if (!cs_mode)
-               return size;
-
-       /* Requested size of an even CS but none are enabled. */
-       if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1))
-               return size;
-
-       /* Requested size of an odd CS but none are enabled. */
-       if (!(cs_mode & CS_ODD) && (csrow_nr & 1))
-               return size;
-
-       /*
-        * Family 17h introduced systems with one mask per DIMM,
-        * and two Chip Selects per DIMM.
-        *
-        *      CS0 and CS1 -> MASK0 / DIMM0
-        *      CS2 and CS3 -> MASK1 / DIMM1
-        *
-        * Family 19h Model 10h introduced systems with one mask per Chip Select,
-        * and two Chip Selects per DIMM.
-        *
-        *      CS0 -> MASK0 -> DIMM0
-        *      CS1 -> MASK1 -> DIMM0
-        *      CS2 -> MASK2 -> DIMM1
-        *      CS3 -> MASK3 -> DIMM1
-        *
-        * Keep the mask number equal to the Chip Select number for newer systems,
-        * and shift the mask number for older systems.
-        */
-       dimm = csrow_nr >> 1;
-
-       if (!fam_type->flags.zn_regs_v2)
-               cs_mask_nr >>= 1;
-
-       /* Asymmetric dual-rank DIMM support. */
-       if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY))
-               addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr];
-       else
-               addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr];
-
-       /*
-        * The number of zero bits in the mask is equal to the number of bits
-        * in a full mask minus the number of bits in the current mask.
-        *
-        * The MSB is the number of bits in the full mask because BIT[0] is
-        * always 0.
-        *
-        * In the special 3 Rank interleaving case, a single bit is flipped
-        * without swapping with the most significant bit. This can be handled
-        * by keeping the MSB where it is and ignoring the single zero bit.
-        */
-       msb = fls(addr_mask_orig) - 1;
-       weight = hweight_long(addr_mask_orig);
-       num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
-
-       /* Take the number of zero bits off from the top of the mask. */
-       addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
-
-       edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm);
-       edac_dbg(1, "  Original AddrMask: 0x%x\n", addr_mask_orig);
-       edac_dbg(1, "  Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved);
-
-       /* Register [31:1] = Address [39:9]. Size is in kBs here. */
-       size = (addr_mask_deinterleaved >> 2) + 1;
-
-       /* Return size in MBs. */
-       return size >> 10;
-}
-
 static void read_dram_ctl_register(struct amd64_pvt *pvt)
 {
 
@@ -2681,196 +2727,6 @@ static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
                err->channel = get_channel_from_ecc_syndrome(mci, err->syndrome);
 }
 
-/*
- * debug routine to display the memory sizes of all logical DIMMs and its
- * CSROWs
- */
-static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
-{
-       int dimm, size0, size1;
-       u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
-       u32 dbam  = ctrl ? pvt->dbam1 : pvt->dbam0;
-
-       if (pvt->fam == 0xf) {
-               /* K8 families < revF not supported yet */
-              if (pvt->ext_model < K8_REV_F)
-                       return;
-              else
-                      WARN_ON(ctrl != 0);
-       }
-
-       if (pvt->fam == 0x10) {
-               dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1
-                                                          : pvt->dbam0;
-               dcsb = (ctrl && !dct_ganging_enabled(pvt)) ?
-                                pvt->csels[1].csbases :
-                                pvt->csels[0].csbases;
-       } else if (ctrl) {
-               dbam = pvt->dbam0;
-               dcsb = pvt->csels[1].csbases;
-       }
-       edac_dbg(1, "F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n",
-                ctrl, dbam);
-
-       edac_printk(KERN_DEBUG, EDAC_MC, "DCT%d chip selects:\n", ctrl);
-
-       /* Dump memory sizes for DIMM and its CSROWs */
-       for (dimm = 0; dimm < 4; dimm++) {
-
-               size0 = 0;
-               if (dcsb[dimm*2] & DCSB_CS_ENABLE)
-                       /*
-                        * For F15m60h, we need multiplier for LRDIMM cs_size
-                        * calculation. We pass dimm value to the dbam_to_cs
-                        * mapper so we can find the multiplier from the
-                        * corresponding DCSM.
-                        */
-                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
-                                                    DBAM_DIMM(dimm, dbam),
-                                                    dimm);
-
-               size1 = 0;
-               if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
-                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
-                                                    DBAM_DIMM(dimm, dbam),
-                                                    dimm);
-
-               amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-                               dimm * 2,     size0,
-                               dimm * 2 + 1, size1);
-       }
-}
-
-static struct amd64_family_type family_types[] = {
-       [K8_CPUS] = {
-               .ctl_name = "K8",
-               .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
-               .f2_id = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = k8_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = k8_dbam_to_chip_select,
-               }
-       },
-       [F10_CPUS] = {
-               .ctl_name = "F10h",
-               .f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP,
-               .f2_id = PCI_DEVICE_ID_AMD_10H_NB_DRAM,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = f10_dbam_to_chip_select,
-               }
-       },
-       [F15_CPUS] = {
-               .ctl_name = "F15h",
-               .f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1,
-               .f2_id = PCI_DEVICE_ID_AMD_15H_NB_F2,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = f15_dbam_to_chip_select,
-               }
-       },
-       [F15_M30H_CPUS] = {
-               .ctl_name = "F15h_M30h",
-               .f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1,
-               .f2_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = f16_dbam_to_chip_select,
-               }
-       },
-       [F15_M60H_CPUS] = {
-               .ctl_name = "F15h_M60h",
-               .f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1,
-               .f2_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F2,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = f15_m60h_dbam_to_chip_select,
-               }
-       },
-       [F16_CPUS] = {
-               .ctl_name = "F16h",
-               .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
-               .f2_id = PCI_DEVICE_ID_AMD_16H_NB_F2,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = f16_dbam_to_chip_select,
-               }
-       },
-       [F16_M30H_CPUS] = {
-               .ctl_name = "F16h_M30h",
-               .f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1,
-               .f2_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2,
-               .max_mcs = 2,
-               .ops = {
-                       .map_sysaddr_to_csrow   = f1x_map_sysaddr_to_csrow,
-                       .dbam_to_cs             = f16_dbam_to_chip_select,
-               }
-       },
-       [F17_CPUS] = {
-               .ctl_name = "F17h",
-               .max_mcs = 2,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F17_M10H_CPUS] = {
-               .ctl_name = "F17h_M10h",
-               .max_mcs = 2,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F17_M30H_CPUS] = {
-               .ctl_name = "F17h_M30h",
-               .max_mcs = 8,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F17_M60H_CPUS] = {
-               .ctl_name = "F17h_M60h",
-               .max_mcs = 2,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F17_M70H_CPUS] = {
-               .ctl_name = "F17h_M70h",
-               .max_mcs = 2,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F19_CPUS] = {
-               .ctl_name = "F19h",
-               .max_mcs = 8,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F19_M10H_CPUS] = {
-               .ctl_name = "F19h_M10h",
-               .max_mcs = 12,
-               .flags.zn_regs_v2 = 1,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-       [F19_M50H_CPUS] = {
-               .ctl_name = "F19h_M50h",
-               .max_mcs = 2,
-               .ops = {
-                       .dbam_to_cs             = f17_addr_mask_to_cs_size,
-               }
-       },
-};
-
 /*
  * These are tables of eigenvectors (one per line) which can be used for the
  * construction of the syndrome tables. The modified syndrome search algorithm
@@ -3118,10 +2974,14 @@ static inline void decode_bus_error(int node_id, struct mce *m)
  * Currently, we can derive the channel number by looking at the 6th nibble in
  * the instance_id. For example, instance_id=0xYXXXXX where Y is the channel
  * number.
+ *
+ * For DRAM ECC errors, the Chip Select number is given in bits [2:0] of
+ * the MCA_SYND[ErrorInformation] field.
  */
-static int find_umc_channel(struct mce *m)
+static void umc_get_err_info(struct mce *m, struct err_info *err)
 {
-       return (m->ipid & GENMASK(31, 0)) >> 20;
+       err->channel = (m->ipid & GENMASK(31, 0)) >> 20;
+       err->csrow = m->synd & 0x7;
 }
 
 static void decode_umc_error(int node_id, struct mce *m)
@@ -3143,8 +3003,6 @@ static void decode_umc_error(int node_id, struct mce *m)
        if (m->status & MCI_STATUS_DEFERRED)
                ecc_type = 3;
 
-       err.channel = find_umc_channel(m);
-
        if (!(m->status & MCI_STATUS_SYNDV)) {
                err.err_code = ERR_SYND;
                goto log_error;
@@ -3159,7 +3017,7 @@ static void decode_umc_error(int node_id, struct mce *m)
                        err.err_code = ERR_CHANNEL;
        }
 
-       err.csrow = m->synd & 0x7;
+       pvt->ops->get_err_info(m, &err);
 
        if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
                err.err_code = ERR_NORM_ADDR;
@@ -3179,9 +3037,6 @@ log_error:
 static int
 reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2)
 {
-       if (pvt->umc)
-               return 0;
-
        /* Reserve the ADDRESS MAP Device */
        pvt->F1 = pci_get_related_function(pvt->F3->vendor, pci_id1, pvt->F3);
        if (!pvt->F1) {
@@ -3209,36 +3064,11 @@ reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2)
        return 0;
 }
 
-static void free_mc_sibling_devs(struct amd64_pvt *pvt)
-{
-       if (pvt->umc) {
-               return;
-       } else {
-               pci_dev_put(pvt->F1);
-               pci_dev_put(pvt->F2);
-       }
-}
-
 static void determine_ecc_sym_sz(struct amd64_pvt *pvt)
 {
        pvt->ecc_sym_sz = 4;
 
-       if (pvt->umc) {
-               u8 i;
-
-               for_each_umc(i) {
-                       /* Check enabled channels only: */
-                       if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) {
-                               if (pvt->umc[i].ecc_ctrl & BIT(9)) {
-                                       pvt->ecc_sym_sz = 16;
-                                       return;
-                               } else if (pvt->umc[i].ecc_ctrl & BIT(7)) {
-                                       pvt->ecc_sym_sz = 8;
-                                       return;
-                               }
-                       }
-               }
-       } else if (pvt->fam >= 0x10) {
+       if (pvt->fam >= 0x10) {
                u32 tmp;
 
                amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
@@ -3255,7 +3085,7 @@ static void determine_ecc_sym_sz(struct amd64_pvt *pvt)
 /*
  * Retrieve the hardware registers of the memory controller.
  */
-static void __read_mc_regs_df(struct amd64_pvt *pvt)
+static void umc_read_mc_regs(struct amd64_pvt *pvt)
 {
        u8 nid = pvt->mc_node_id;
        struct amd64_umc *umc;
@@ -3267,7 +3097,7 @@ static void __read_mc_regs_df(struct amd64_pvt *pvt)
                umc_base = get_umc_base(i);
                umc = &pvt->umc[i];
 
-               amd_smn_read(nid, umc_base + get_umc_reg(UMCCH_DIMM_CFG), &umc->dimm_cfg);
+               amd_smn_read(nid, umc_base + get_umc_reg(pvt, UMCCH_DIMM_CFG), &umc->dimm_cfg);
                amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg);
                amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl);
                amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl);
@@ -3279,7 +3109,7 @@ static void __read_mc_regs_df(struct amd64_pvt *pvt)
  * Retrieve the hardware registers of the memory controller (this includes the
  * 'Address Map' and 'Misc' device regs)
  */
-static void read_mc_regs(struct amd64_pvt *pvt)
+static void dct_read_mc_regs(struct amd64_pvt *pvt)
 {
        unsigned int range;
        u64 msr_val;
@@ -3300,12 +3130,6 @@ static void read_mc_regs(struct amd64_pvt *pvt)
                edac_dbg(0, "  TOP_MEM2 disabled\n");
        }
 
-       if (pvt->umc) {
-               __read_mc_regs_df(pvt);
-
-               goto skip;
-       }
-
        amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap);
 
        read_dram_ctl_register(pvt);
@@ -3346,14 +3170,6 @@ static void read_mc_regs(struct amd64_pvt *pvt)
                amd64_read_dct_pci_cfg(pvt, 1, DCHR0, &pvt->dchr1);
        }
 
-skip:
-       read_dct_base_mask(pvt);
-
-       determine_memory_type(pvt);
-
-       if (!pvt->umc)
-               edac_dbg(1, "  DIMM type: %s\n", edac_mem_types[pvt->dram_type]);
-
        determine_ecc_sym_sz(pvt);
 }
 
@@ -3391,36 +3207,47 @@ skip:
  *     encompasses
  *
  */
-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
+static u32 dct_get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
 {
        u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
-       int csrow_nr = csrow_nr_orig;
        u32 cs_mode, nr_pages;
 
-       if (!pvt->umc) {
-               csrow_nr >>= 1;
-               cs_mode = DBAM_DIMM(csrow_nr, dbam);
-       } else {
-               cs_mode = f17_get_cs_mode(csrow_nr >> 1, dct, pvt);
-       }
+       csrow_nr >>= 1;
+       cs_mode = DBAM_DIMM(csrow_nr, dbam);
 
        nr_pages   = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
        nr_pages <<= 20 - PAGE_SHIFT;
 
        edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
-                   csrow_nr_orig, dct,  cs_mode);
+                   csrow_nr, dct,  cs_mode);
        edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
        return nr_pages;
 }
 
-static int init_csrows_df(struct mem_ctl_info *mci)
+static u32 umc_get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
+{
+       int csrow_nr = csrow_nr_orig;
+       u32 cs_mode, nr_pages;
+
+       cs_mode = umc_get_cs_mode(csrow_nr >> 1, dct, pvt);
+
+       nr_pages   = umc_addr_mask_to_cs_size(pvt, dct, cs_mode, csrow_nr);
+       nr_pages <<= 20 - PAGE_SHIFT;
+
+       edac_dbg(0, "csrow: %d, channel: %d, cs_mode %d\n",
+                csrow_nr_orig, dct,  cs_mode);
+       edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
+
+       return nr_pages;
+}
+
+static void umc_init_csrows(struct mem_ctl_info *mci)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
        enum edac_type edac_mode = EDAC_NONE;
        enum dev_type dev_type = DEV_UNKNOWN;
        struct dimm_info *dimm;
-       int empty = 1;
        u8 umc, cs;
 
        if (mci->edac_ctl_cap & EDAC_FLAG_S16ECD16ED) {
@@ -3441,40 +3268,34 @@ static int init_csrows_df(struct mem_ctl_info *mci)
                        if (!csrow_enabled(cs, umc, pvt))
                                continue;
 
-                       empty = 0;
                        dimm = mci->csrows[cs]->channels[umc]->dimm;
 
                        edac_dbg(1, "MC node: %d, csrow: %d\n",
                                        pvt->mc_node_id, cs);
 
-                       dimm->nr_pages = get_csrow_nr_pages(pvt, umc, cs);
+                       dimm->nr_pages = umc_get_csrow_nr_pages(pvt, umc, cs);
                        dimm->mtype = pvt->umc[umc].dram_type;
                        dimm->edac_mode = edac_mode;
                        dimm->dtype = dev_type;
                        dimm->grain = 64;
                }
        }
-
-       return empty;
 }
 
 /*
  * Initialize the array of csrow attribute instances, based on the values
  * from pci config hardware registers.
  */
-static int init_csrows(struct mem_ctl_info *mci)
+static void dct_init_csrows(struct mem_ctl_info *mci)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
        enum edac_type edac_mode = EDAC_NONE;
        struct csrow_info *csrow;
        struct dimm_info *dimm;
-       int i, j, empty = 1;
        int nr_pages = 0;
+       int i, j;
        u32 val;
 
-       if (pvt->umc)
-               return init_csrows_df(mci);
-
        amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
 
        pvt->nbcfg = val;
@@ -3497,19 +3318,18 @@ static int init_csrows(struct mem_ctl_info *mci)
                        continue;
 
                csrow = mci->csrows[i];
-               empty = 0;
 
                edac_dbg(1, "MC node: %d, csrow: %d\n",
                            pvt->mc_node_id, i);
 
                if (row_dct0) {
-                       nr_pages = get_csrow_nr_pages(pvt, 0, i);
+                       nr_pages = dct_get_csrow_nr_pages(pvt, 0, i);
                        csrow->channels[0]->dimm->nr_pages = nr_pages;
                }
 
                /* K8 has only one DCT */
                if (pvt->fam != 0xf && row_dct1) {
-                       int row_dct1_pages = get_csrow_nr_pages(pvt, 1, i);
+                       int row_dct1_pages = dct_get_csrow_nr_pages(pvt, 1, i);
 
                        csrow->channels[1]->dimm->nr_pages = row_dct1_pages;
                        nr_pages += row_dct1_pages;
@@ -3524,15 +3344,13 @@ static int init_csrows(struct mem_ctl_info *mci)
                                        : EDAC_SECDED;
                }
 
-               for (j = 0; j < fam_type->max_mcs; j++) {
+               for (j = 0; j < pvt->max_mcs; j++) {
                        dimm = csrow->channels[j]->dimm;
                        dimm->mtype = pvt->dram_type;
                        dimm->edac_mode = edac_mode;
                        dimm->grain = 64;
                }
        }
-
-       return empty;
 }
 
 /* get all cores on this DCT */
@@ -3695,59 +3513,66 @@ static void restore_ecc_error_reporting(struct ecc_settings *s, u16 nid,
                amd64_warn("Error restoring NB MCGCTL settings!\n");
 }
 
-static bool ecc_enabled(struct amd64_pvt *pvt)
+static bool dct_ecc_enabled(struct amd64_pvt *pvt)
 {
        u16 nid = pvt->mc_node_id;
        bool nb_mce_en = false;
-       u8 ecc_en = 0, i;
+       u8 ecc_en = 0;
        u32 value;
 
-       if (boot_cpu_data.x86 >= 0x17) {
-               u8 umc_en_mask = 0, ecc_en_mask = 0;
-               struct amd64_umc *umc;
+       amd64_read_pci_cfg(pvt->F3, NBCFG, &value);
 
-               for_each_umc(i) {
-                       umc = &pvt->umc[i];
+       ecc_en = !!(value & NBCFG_ECC_ENABLE);
 
-                       /* Only check enabled UMCs. */
-                       if (!(umc->sdp_ctrl & UMC_SDP_INIT))
-                               continue;
+       nb_mce_en = nb_mce_bank_enabled_on_node(nid);
+       if (!nb_mce_en)
+               edac_dbg(0, "NB MCE bank disabled, set MSR 0x%08x[4] on node %d to enable.\n",
+                        MSR_IA32_MCG_CTL, nid);
 
-                       umc_en_mask |= BIT(i);
+       edac_dbg(3, "Node %d: DRAM ECC %s.\n", nid, (ecc_en ? "enabled" : "disabled"));
 
-                       if (umc->umc_cap_hi & UMC_ECC_ENABLED)
-                               ecc_en_mask |= BIT(i);
-               }
+       if (!ecc_en || !nb_mce_en)
+               return false;
+       else
+               return true;
+}
 
-               /* Check whether at least one UMC is enabled: */
-               if (umc_en_mask)
-                       ecc_en = umc_en_mask == ecc_en_mask;
-               else
-                       edac_dbg(0, "Node %d: No enabled UMCs.\n", nid);
+static bool umc_ecc_enabled(struct amd64_pvt *pvt)
+{
+       u8 umc_en_mask = 0, ecc_en_mask = 0;
+       u16 nid = pvt->mc_node_id;
+       struct amd64_umc *umc;
+       u8 ecc_en = 0, i;
 
-               /* Assume UMC MCA banks are enabled. */
-               nb_mce_en = true;
-       } else {
-               amd64_read_pci_cfg(pvt->F3, NBCFG, &value);
+       for_each_umc(i) {
+               umc = &pvt->umc[i];
 
-               ecc_en = !!(value & NBCFG_ECC_ENABLE);
+               /* Only check enabled UMCs. */
+               if (!(umc->sdp_ctrl & UMC_SDP_INIT))
+                       continue;
+
+               umc_en_mask |= BIT(i);
 
-               nb_mce_en = nb_mce_bank_enabled_on_node(nid);
-               if (!nb_mce_en)
-                       edac_dbg(0, "NB MCE bank disabled, set MSR 0x%08x[4] on node %d to enable.\n",
-                                    MSR_IA32_MCG_CTL, nid);
+               if (umc->umc_cap_hi & UMC_ECC_ENABLED)
+                       ecc_en_mask |= BIT(i);
        }
 
+       /* Check whether at least one UMC is enabled: */
+       if (umc_en_mask)
+               ecc_en = umc_en_mask == ecc_en_mask;
+       else
+               edac_dbg(0, "Node %d: No enabled UMCs.\n", nid);
+
        edac_dbg(3, "Node %d: DRAM ECC %s.\n", nid, (ecc_en ? "enabled" : "disabled"));
 
-       if (!ecc_en || !nb_mce_en)
+       if (!ecc_en)
                return false;
        else
                return true;
 }
 
 static inline void
-f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
+umc_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
 {
        u8 i, ecc_en = 1, cpk_en = 1, dev_x4 = 1, dev_x16 = 1;
 
@@ -3777,145 +3602,234 @@ f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
        }
 }
 
-static void setup_mci_misc_attrs(struct mem_ctl_info *mci)
+static void dct_setup_mci_misc_attrs(struct mem_ctl_info *mci)
 {
        struct amd64_pvt *pvt = mci->pvt_info;
 
        mci->mtype_cap          = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2;
        mci->edac_ctl_cap       = EDAC_FLAG_NONE;
 
-       if (pvt->umc) {
-               f17h_determine_edac_ctl_cap(mci, pvt);
-       } else {
-               if (pvt->nbcap & NBCAP_SECDED)
-                       mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+       if (pvt->nbcap & NBCAP_SECDED)
+               mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
 
-               if (pvt->nbcap & NBCAP_CHIPKILL)
-                       mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
-       }
+       if (pvt->nbcap & NBCAP_CHIPKILL)
+               mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
 
-       mci->edac_cap           = determine_edac_cap(pvt);
+       mci->edac_cap           = dct_determine_edac_cap(pvt);
        mci->mod_name           = EDAC_MOD_STR;
-       mci->ctl_name           = fam_type->ctl_name;
+       mci->ctl_name           = pvt->ctl_name;
        mci->dev_name           = pci_name(pvt->F3);
        mci->ctl_page_to_phys   = NULL;
 
-       if (pvt->fam >= 0x17)
-               return;
-
        /* memory scrubber interface */
        mci->set_sdram_scrub_rate = set_scrub_rate;
        mci->get_sdram_scrub_rate = get_scrub_rate;
+
+       dct_init_csrows(mci);
 }
 
-/*
- * returns a pointer to the family descriptor on success, NULL otherwise.
- */
-static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
+static void umc_setup_mci_misc_attrs(struct mem_ctl_info *mci)
+{
+       struct amd64_pvt *pvt = mci->pvt_info;
+
+       mci->mtype_cap          = MEM_FLAG_DDR4 | MEM_FLAG_RDDR4;
+       mci->edac_ctl_cap       = EDAC_FLAG_NONE;
+
+       umc_determine_edac_ctl_cap(mci, pvt);
+
+       mci->edac_cap           = umc_determine_edac_cap(pvt);
+       mci->mod_name           = EDAC_MOD_STR;
+       mci->ctl_name           = pvt->ctl_name;
+       mci->dev_name           = pci_name(pvt->F3);
+       mci->ctl_page_to_phys   = NULL;
+
+       umc_init_csrows(mci);
+}
+
+static int dct_hw_info_get(struct amd64_pvt *pvt)
+{
+       int ret = reserve_mc_sibling_devs(pvt, pvt->f1_id, pvt->f2_id);
+
+       if (ret)
+               return ret;
+
+       dct_prep_chip_selects(pvt);
+       dct_read_base_mask(pvt);
+       dct_read_mc_regs(pvt);
+       dct_determine_memory_type(pvt);
+
+       return 0;
+}
+
+static int umc_hw_info_get(struct amd64_pvt *pvt)
+{
+       pvt->umc = kcalloc(pvt->max_mcs, sizeof(struct amd64_umc), GFP_KERNEL);
+       if (!pvt->umc)
+               return -ENOMEM;
+
+       umc_prep_chip_selects(pvt);
+       umc_read_base_mask(pvt);
+       umc_read_mc_regs(pvt);
+       umc_determine_memory_type(pvt);
+
+       return 0;
+}
+
+static void hw_info_put(struct amd64_pvt *pvt)
+{
+       pci_dev_put(pvt->F1);
+       pci_dev_put(pvt->F2);
+       kfree(pvt->umc);
+}
+
+static struct low_ops umc_ops = {
+       .hw_info_get                    = umc_hw_info_get,
+       .ecc_enabled                    = umc_ecc_enabled,
+       .setup_mci_misc_attrs           = umc_setup_mci_misc_attrs,
+       .dump_misc_regs                 = umc_dump_misc_regs,
+       .get_err_info                   = umc_get_err_info,
+};
+
+/* Use Family 16h versions for defaults and adjust as needed below. */
+static struct low_ops dct_ops = {
+       .map_sysaddr_to_csrow           = f1x_map_sysaddr_to_csrow,
+       .dbam_to_cs                     = f16_dbam_to_chip_select,
+       .hw_info_get                    = dct_hw_info_get,
+       .ecc_enabled                    = dct_ecc_enabled,
+       .setup_mci_misc_attrs           = dct_setup_mci_misc_attrs,
+       .dump_misc_regs                 = dct_dump_misc_regs,
+};
+
+static int per_family_init(struct amd64_pvt *pvt)
 {
        pvt->ext_model  = boot_cpu_data.x86_model >> 4;
        pvt->stepping   = boot_cpu_data.x86_stepping;
        pvt->model      = boot_cpu_data.x86_model;
        pvt->fam        = boot_cpu_data.x86;
+       pvt->max_mcs    = 2;
+
+       /*
+        * Decide on which ops group to use here and do any family/model
+        * overrides below.
+        */
+       if (pvt->fam >= 0x17)
+               pvt->ops = &umc_ops;
+       else
+               pvt->ops = &dct_ops;
 
        switch (pvt->fam) {
        case 0xf:
-               fam_type        = &family_types[K8_CPUS];
-               pvt->ops        = &family_types[K8_CPUS].ops;
+               pvt->ctl_name                           = (pvt->ext_model >= K8_REV_F) ?
+                                                         "K8 revF or later" : "K8 revE or earlier";
+               pvt->f1_id                              = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP;
+               pvt->f2_id                              = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL;
+               pvt->ops->map_sysaddr_to_csrow          = k8_map_sysaddr_to_csrow;
+               pvt->ops->dbam_to_cs                    = k8_dbam_to_chip_select;
                break;
 
        case 0x10:
-               fam_type        = &family_types[F10_CPUS];
-               pvt->ops        = &family_types[F10_CPUS].ops;
+               pvt->ctl_name                           = "F10h";
+               pvt->f1_id                              = PCI_DEVICE_ID_AMD_10H_NB_MAP;
+               pvt->f2_id                              = PCI_DEVICE_ID_AMD_10H_NB_DRAM;
+               pvt->ops->dbam_to_cs                    = f10_dbam_to_chip_select;
                break;
 
        case 0x15:
-               if (pvt->model == 0x30) {
-                       fam_type = &family_types[F15_M30H_CPUS];
-                       pvt->ops = &family_types[F15_M30H_CPUS].ops;
+               switch (pvt->model) {
+               case 0x30:
+                       pvt->ctl_name                   = "F15h_M30h";
+                       pvt->f1_id                      = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1;
+                       pvt->f2_id                      = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2;
                        break;
-               } else if (pvt->model == 0x60) {
-                       fam_type = &family_types[F15_M60H_CPUS];
-                       pvt->ops = &family_types[F15_M60H_CPUS].ops;
+               case 0x60:
+                       pvt->ctl_name                   = "F15h_M60h";
+                       pvt->f1_id                      = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1;
+                       pvt->f2_id                      = PCI_DEVICE_ID_AMD_15H_M60H_NB_F2;
+                       pvt->ops->dbam_to_cs            = f15_m60h_dbam_to_chip_select;
+                       break;
+               case 0x13:
+                       /* Richland is only client */
+                       return -ENODEV;
+               default:
+                       pvt->ctl_name                   = "F15h";
+                       pvt->f1_id                      = PCI_DEVICE_ID_AMD_15H_NB_F1;
+                       pvt->f2_id                      = PCI_DEVICE_ID_AMD_15H_NB_F2;
+                       pvt->ops->dbam_to_cs            = f15_dbam_to_chip_select;
                        break;
-               /* Richland is only client */
-               } else if (pvt->model == 0x13) {
-                       return NULL;
-               } else {
-                       fam_type        = &family_types[F15_CPUS];
-                       pvt->ops        = &family_types[F15_CPUS].ops;
                }
                break;
 
        case 0x16:
-               if (pvt->model == 0x30) {
-                       fam_type = &family_types[F16_M30H_CPUS];
-                       pvt->ops = &family_types[F16_M30H_CPUS].ops;
+               switch (pvt->model) {
+               case 0x30:
+                       pvt->ctl_name                   = "F16h_M30h";
+                       pvt->f1_id                      = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1;
+                       pvt->f2_id                      = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2;
+                       break;
+               default:
+                       pvt->ctl_name                   = "F16h";
+                       pvt->f1_id                      = PCI_DEVICE_ID_AMD_16H_NB_F1;
+                       pvt->f2_id                      = PCI_DEVICE_ID_AMD_16H_NB_F2;
                        break;
                }
-               fam_type        = &family_types[F16_CPUS];
-               pvt->ops        = &family_types[F16_CPUS].ops;
                break;
 
        case 0x17:
-               if (pvt->model >= 0x10 && pvt->model <= 0x2f) {
-                       fam_type = &family_types[F17_M10H_CPUS];
-                       pvt->ops = &family_types[F17_M10H_CPUS].ops;
+               switch (pvt->model) {
+               case 0x10 ... 0x2f:
+                       pvt->ctl_name                   = "F17h_M10h";
                        break;
-               } else if (pvt->model >= 0x30 && pvt->model <= 0x3f) {
-                       fam_type = &family_types[F17_M30H_CPUS];
-                       pvt->ops = &family_types[F17_M30H_CPUS].ops;
+               case 0x30 ... 0x3f:
+                       pvt->ctl_name                   = "F17h_M30h";
+                       pvt->max_mcs                    = 8;
                        break;
-               } else if (pvt->model >= 0x60 && pvt->model <= 0x6f) {
-                       fam_type = &family_types[F17_M60H_CPUS];
-                       pvt->ops = &family_types[F17_M60H_CPUS].ops;
+               case 0x60 ... 0x6f:
+                       pvt->ctl_name                   = "F17h_M60h";
                        break;
-               } else if (pvt->model >= 0x70 && pvt->model <= 0x7f) {
-                       fam_type = &family_types[F17_M70H_CPUS];
-                       pvt->ops = &family_types[F17_M70H_CPUS].ops;
+               case 0x70 ... 0x7f:
+                       pvt->ctl_name                   = "F17h_M70h";
+                       break;
+               default:
+                       pvt->ctl_name                   = "F17h";
                        break;
                }
-               fallthrough;
-       case 0x18:
-               fam_type        = &family_types[F17_CPUS];
-               pvt->ops        = &family_types[F17_CPUS].ops;
+               break;
 
-               if (pvt->fam == 0x18)
-                       family_types[F17_CPUS].ctl_name = "F18h";
+       case 0x18:
+               pvt->ctl_name                           = "F18h";
                break;
 
        case 0x19:
-               if (pvt->model >= 0x10 && pvt->model <= 0x1f) {
-                       fam_type = &family_types[F19_M10H_CPUS];
-                       pvt->ops = &family_types[F19_M10H_CPUS].ops;
+               switch (pvt->model) {
+               case 0x00 ... 0x0f:
+                       pvt->ctl_name                   = "F19h";
+                       pvt->max_mcs                    = 8;
                        break;
-               } else if (pvt->model >= 0x20 && pvt->model <= 0x2f) {
-                       fam_type = &family_types[F17_M70H_CPUS];
-                       pvt->ops = &family_types[F17_M70H_CPUS].ops;
-                       fam_type->ctl_name = "F19h_M20h";
+               case 0x10 ... 0x1f:
+                       pvt->ctl_name                   = "F19h_M10h";
+                       pvt->max_mcs                    = 12;
+                       pvt->flags.zn_regs_v2           = 1;
                        break;
-               } else if (pvt->model >= 0x50 && pvt->model <= 0x5f) {
-                       fam_type = &family_types[F19_M50H_CPUS];
-                       pvt->ops = &family_types[F19_M50H_CPUS].ops;
-                       fam_type->ctl_name = "F19h_M50h";
+               case 0x20 ... 0x2f:
+                       pvt->ctl_name                   = "F19h_M20h";
                        break;
-               } else if (pvt->model >= 0xa0 && pvt->model <= 0xaf) {
-                       fam_type = &family_types[F19_M10H_CPUS];
-                       pvt->ops = &family_types[F19_M10H_CPUS].ops;
-                       fam_type->ctl_name = "F19h_MA0h";
+               case 0x50 ... 0x5f:
+                       pvt->ctl_name                   = "F19h_M50h";
+                       break;
+               case 0xa0 ... 0xaf:
+                       pvt->ctl_name                   = "F19h_MA0h";
+                       pvt->max_mcs                    = 12;
+                       pvt->flags.zn_regs_v2           = 1;
                        break;
                }
-               fam_type        = &family_types[F19_CPUS];
-               pvt->ops        = &family_types[F19_CPUS].ops;
-               family_types[F19_CPUS].ctl_name = "F19h";
                break;
 
        default:
                amd64_err("Unsupported family!\n");
-               return NULL;
+               return -ENODEV;
        }
 
-       return fam_type;
+       return 0;
 }
 
 static const struct attribute_group *amd64_edac_attr_groups[] = {
@@ -3926,37 +3840,6 @@ static const struct attribute_group *amd64_edac_attr_groups[] = {
        NULL
 };
 
-static int hw_info_get(struct amd64_pvt *pvt)
-{
-       u16 pci_id1 = 0, pci_id2 = 0;
-       int ret;
-
-       if (pvt->fam >= 0x17) {
-               pvt->umc = kcalloc(fam_type->max_mcs, sizeof(struct amd64_umc), GFP_KERNEL);
-               if (!pvt->umc)
-                       return -ENOMEM;
-       } else {
-               pci_id1 = fam_type->f1_id;
-               pci_id2 = fam_type->f2_id;
-       }
-
-       ret = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2);
-       if (ret)
-               return ret;
-
-       read_mc_regs(pvt);
-
-       return 0;
-}
-
-static void hw_info_put(struct amd64_pvt *pvt)
-{
-       if (pvt->F1)
-               free_mc_sibling_devs(pvt);
-
-       kfree(pvt->umc);
-}
-
 static int init_one_instance(struct amd64_pvt *pvt)
 {
        struct mem_ctl_info *mci = NULL;
@@ -3967,7 +3850,7 @@ static int init_one_instance(struct amd64_pvt *pvt)
        layers[0].size = pvt->csels[0].b_cnt;
        layers[0].is_virt_csrow = true;
        layers[1].type = EDAC_MC_LAYER_CHANNEL;
-       layers[1].size = fam_type->max_mcs;
+       layers[1].size = pvt->max_mcs;
        layers[1].is_virt_csrow = false;
 
        mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0);
@@ -3977,10 +3860,7 @@ static int init_one_instance(struct amd64_pvt *pvt)
        mci->pvt_info = pvt;
        mci->pdev = &pvt->F3->dev;
 
-       setup_mci_misc_attrs(mci);
-
-       if (init_csrows(mci))
-               mci->edac_cap = EDAC_FLAG_NONE;
+       pvt->ops->setup_mci_misc_attrs(mci);
 
        ret = -ENODEV;
        if (edac_mc_add_mc_with_groups(mci, amd64_edac_attr_groups)) {
@@ -3997,7 +3877,7 @@ static bool instance_has_memory(struct amd64_pvt *pvt)
        bool cs_enabled = false;
        int cs = 0, dct = 0;
 
-       for (dct = 0; dct < fam_type->max_mcs; dct++) {
+       for (dct = 0; dct < pvt->max_mcs; dct++) {
                for_each_chip_select(cs, dct, pvt)
                        cs_enabled |= csrow_enabled(cs, dct, pvt);
        }
@@ -4026,12 +3906,11 @@ static int probe_one_instance(unsigned int nid)
        pvt->mc_node_id = nid;
        pvt->F3 = F3;
 
-       ret = -ENODEV;
-       fam_type = per_family_init(pvt);
-       if (!fam_type)
+       ret = per_family_init(pvt);
+       if (ret < 0)
                goto err_enable;
 
-       ret = hw_info_get(pvt);
+       ret = pvt->ops->hw_info_get(pvt);
        if (ret < 0)
                goto err_enable;
 
@@ -4041,7 +3920,7 @@ static int probe_one_instance(unsigned int nid)
                goto err_enable;
        }
 
-       if (!ecc_enabled(pvt)) {
+       if (!pvt->ops->ecc_enabled(pvt)) {
                ret = -ENODEV;
 
                if (!ecc_enable_override)
@@ -4067,13 +3946,10 @@ static int probe_one_instance(unsigned int nid)
                goto err_enable;
        }
 
-       amd64_info("%s %sdetected (node %d).\n", fam_type->ctl_name,
-                    (pvt->fam == 0xf ?
-                               (pvt->ext_model >= K8_REV_F  ? "revF or later "
-                                                            : "revE or earlier ")
-                                : ""), pvt->mc_node_id);
+       amd64_info("%s detected (node %d).\n", pvt->ctl_name, pvt->mc_node_id);
 
-       dump_misc_regs(pvt);
+       /* Display and decode various registers for debug purposes. */
+       pvt->ops->dump_misc_regs(pvt);
 
        return ret;
 
@@ -4244,10 +4120,8 @@ module_init(amd64_edac_init);
 module_exit(amd64_edac_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("SoftwareBitMaker: Doug Thompson, "
-               "Dave Peterson, Thayne Harbaugh");
-MODULE_DESCRIPTION("MC support for AMD64 memory controllers - "
-               EDAC_AMD64_VERSION);
+MODULE_AUTHOR("SoftwareBitMaker: Doug Thompson, Dave Peterson, Thayne Harbaugh; AMD");
+MODULE_DESCRIPTION("MC support for AMD64 memory controllers - " EDAC_AMD64_VERSION);
 
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index e4329dff8cf2ef90a1f5fbf9c347ff94bc60cbfa..e84fe0d4120a2c24769be988d445a2f1d9564784 100644 (file)
 
 #define UMC_SDP_INIT                   BIT(31)
 
-enum amd_families {
-       K8_CPUS = 0,
-       F10_CPUS,
-       F15_CPUS,
-       F15_M30H_CPUS,
-       F15_M60H_CPUS,
-       F16_CPUS,
-       F16_M30H_CPUS,
-       F17_CPUS,
-       F17_M10H_CPUS,
-       F17_M30H_CPUS,
-       F17_M60H_CPUS,
-       F17_M70H_CPUS,
-       F19_CPUS,
-       F19_M10H_CPUS,
-       F19_M50H_CPUS,
-       NUM_FAMILIES,
-};
-
 /* Error injection control structure */
 struct error_injection {
        u32      section;
@@ -334,6 +315,16 @@ struct amd64_umc {
        enum mem_type dram_type;
 };
 
+struct amd64_family_flags {
+       /*
+        * Indicates that the system supports the new register offsets, etc.
+        * first introduced with Family 19h Model 10h.
+        */
+       __u64 zn_regs_v2        : 1,
+
+             __reserved        : 63;
+};
+
 struct amd64_pvt {
        struct low_ops *ops;
 
@@ -375,6 +366,12 @@ struct amd64_pvt {
        /* x4, x8, or x16 syndromes in use */
        u8 ecc_sym_sz;
 
+       const char *ctl_name;
+       u16 f1_id, f2_id;
+       /* Maximum number of memory controllers per die/node. */
+       u8 max_mcs;
+
+       struct amd64_family_flags flags;
        /* place to store error injection parameters prior to issue */
        struct error_injection injection;
 
@@ -465,29 +462,15 @@ struct ecc_settings {
  * functions and per device encoding/decoding logic.
  */
 struct low_ops {
-       void (*map_sysaddr_to_csrow)    (struct mem_ctl_info *mci, u64 sys_addr,
-                                        struct err_info *);
-       int (*dbam_to_cs)               (struct amd64_pvt *pvt, u8 dct,
-                                        unsigned cs_mode, int cs_mask_nr);
-};
-
-struct amd64_family_flags {
-       /*
-        * Indicates that the system supports the new register offsets, etc.
-        * first introduced with Family 19h Model 10h.
-        */
-       __u64 zn_regs_v2        : 1,
-
-             __reserved        : 63;
-};
-
-struct amd64_family_type {
-       const char *ctl_name;
-       u16 f1_id, f2_id;
-       /* Maximum number of memory controllers per die/node. */
-       u8 max_mcs;
-       struct amd64_family_flags flags;
-       struct low_ops ops;
+       void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci, u64 sys_addr,
+                                    struct err_info *err);
+       int  (*dbam_to_cs)(struct amd64_pvt *pvt, u8 dct,
+                          unsigned int cs_mode, int cs_mask_nr);
+       int (*hw_info_get)(struct amd64_pvt *pvt);
+       bool (*ecc_enabled)(struct amd64_pvt *pvt);
+       void (*setup_mci_misc_attrs)(struct mem_ctl_info *mci);
+       void (*dump_misc_regs)(struct amd64_pvt *pvt);
+       void (*get_err_info)(struct mce *m, struct err_info *err);
 };
 
 int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
index 7508aa416ddbd7b7bdcf5535c2f59d471c137e6a..ca718f63fcbcdd4e96b46da6b498533e8e4ebecb 100644 (file)
@@ -593,5 +593,5 @@ module_init(amd8111_edac_init);
 module_exit(amd8111_edac_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>\n");
+MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
 MODULE_DESCRIPTION("AMD8111 HyperTransport I/O Hub EDAC kernel module");
index 169353710982643222ff75d986f71e3d582ef8f5..28610ba514f4d4b18413e7956d13ba89f26f6f65 100644 (file)
@@ -354,5 +354,5 @@ module_init(amd8131_edac_init);
 module_exit(amd8131_edac_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>\n");
+MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>");
 MODULE_DESCRIPTION("AMD8131 HyperTransport PCI-X Tunnel EDAC kernel module");
index ac7c9b42d4c74b816ca39b015fafd404e207e983..7221b4bb6df2a1d80a5b48c8a1deddead6386457 100644 (file)
@@ -1462,7 +1462,7 @@ module_init(e752x_init);
 module_exit(e752x_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman");
 MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
 
 module_param(force_function_unhide, int, 0444);
index 497e710fca3df585207dbca5f256fc3e9d4c23af..5852b95fa4708309918bdcc6d03b09bcd5dfee5d 100644 (file)
@@ -596,8 +596,7 @@ module_init(e7xxx_init);
 module_exit(e7xxx_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
-               "Based on.work by Dan Hollis et al");
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al");
 MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
index 0a4691792801d3da92aaaa31f598f5c4b0633212..a897b6aff368681d2385bb4a1857e53c34631ca3 100644 (file)
@@ -906,6 +906,7 @@ static const struct x86_cpu_id i10nm_cpuids[] = {
        X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SAPPHIRERAPIDS_X,  X86_STEPPINGS(0x0, 0xf), &spr_cfg),
        X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(EMERALDRAPIDS_X,   X86_STEPPINGS(0x0, 0xf), &spr_cfg),
        X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(GRANITERAPIDS_X,   X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
+       X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SIERRAFOREST_X,    X86_STEPPINGS(0x0, 0xf), &gnr_cfg),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
index ba46057d422076aa16efb38efe01aa1da9d943a9..4b5a71f8739d908c86d8026ced495732088256cc 100644 (file)
@@ -1573,13 +1573,10 @@ module_init(i5000_init);
 module_exit(i5000_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR
-    ("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
-MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
-               I5000_REVISION);
+MODULE_AUTHOR("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
+MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - " I5000_REVISION);
 
 module_param(edac_op_state, int, 0444);
 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
 module_param(misc_messages, int, 0444);
 MODULE_PARM_DESC(misc_messages, "Log miscellaneous non fatal messages");
-
index f5d82518c15e5b0138cef472b0de1349c5198171..d470afe65001865f6e3f2ce701f1fc74356fda02 100644 (file)
@@ -909,7 +909,7 @@ static void i5100_do_inject(struct mem_ctl_info *mci)
         *
         * The injection code don't work without setting this register.
         * The register needs to be flipped off then on else the hardware
-        * will only preform the first injection.
+        * will only perform the first injection.
         *
         * Stop condition bits 7:4
         * 1010 - Stop after one injection
@@ -1220,6 +1220,5 @@ module_init(i5100_init);
 module_exit(i5100_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR
-    ("Arthur Jones <ajones@riverbed.com>");
+MODULE_AUTHOR("Arthur Jones <ajones@riverbed.com>");
 MODULE_DESCRIPTION("MC Driver for Intel I5100 memory controllers");
index fbec90d00f1eef7a30dad2e14f95a0b66afcc31a..b8a497f0de284c35ac578f5102bfa99a5e751750 100644 (file)
@@ -355,8 +355,7 @@ module_init(i82860_init);
 module_exit(i82860_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
-               "Ben Woodard <woodard@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) Ben Woodard <woodard@redhat.com>");
 MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
 
 module_param(edac_op_state, int, 0444);
index 35ceaca578e1506b28146607e90bdaea3f8de658..7c5e2b3c0daa0c7e09ae58aee84679ea8b30f9cf 100644 (file)
@@ -72,5 +72,4 @@ module_exit(fsl_ddr_mc_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("NXP Semiconductor");
 module_param(edac_op_state, int, 0444);
-MODULE_PARM_DESC(edac_op_state,
-                "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
index e50d7928bf8fb7632035d9d1104496ec14db847c..55320546c17420b86817d1ad61f66aa363635532 100644 (file)
@@ -711,5 +711,4 @@ module_exit(mpc85xx_mc_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Montavista Software, Inc.");
 module_param(edac_op_state, int, 0444);
-MODULE_PARM_DESC(edac_op_state,
-                "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
+MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
index 3256254c3722c6f7efffa42bd9328505e9b27ee4..265e0fb39bc7dcf87f682f5145d7c1274602f00a 100644 (file)
@@ -76,6 +76,8 @@
 #define DRP0_INTERRUPT_ENABLE           BIT(6)
 #define SB_DB_DRP_INTERRUPT_ENABLE      0x3
 
+#define ECC_POLL_MSEC                  5000
+
 enum {
        LLCC_DRAM_CE = 0,
        LLCC_DRAM_UE,
@@ -213,7 +215,7 @@ dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
 
        for (i = 0; i < reg_data.reg_cnt; i++) {
                synd_reg = reg_data.synd_reg + (i * 4);
-               ret = regmap_read(drv->regmap, drv->offsets[bank] + synd_reg,
+               ret = regmap_read(drv->regmaps[bank], synd_reg,
                                  &synd_val);
                if (ret)
                        goto clear;
@@ -222,8 +224,7 @@ dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
                            reg_data.name, i, synd_val);
        }
 
-       ret = regmap_read(drv->regmap,
-                         drv->offsets[bank] + reg_data.count_status_reg,
+       ret = regmap_read(drv->regmaps[bank], reg_data.count_status_reg,
                          &err_cnt);
        if (ret)
                goto clear;
@@ -233,8 +234,7 @@ dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
        edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error count: 0x%4x\n",
                    reg_data.name, err_cnt);
 
-       ret = regmap_read(drv->regmap,
-                         drv->offsets[bank] + reg_data.ways_status_reg,
+       ret = regmap_read(drv->regmaps[bank], reg_data.ways_status_reg,
                          &err_ways);
        if (ret)
                goto clear;
@@ -285,8 +285,7 @@ dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
        return ret;
 }
 
-static irqreturn_t
-llcc_ecc_irq_handler(int irq, void *edev_ctl)
+static irqreturn_t llcc_ecc_irq_handler(int irq, void *edev_ctl)
 {
        struct edac_device_ctl_info *edac_dev_ctl = edev_ctl;
        struct llcc_drv_data *drv = edac_dev_ctl->dev->platform_data;
@@ -296,8 +295,7 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl)
 
        /* Iterate over the banks and look for Tag RAM or Data RAM errors */
        for (i = 0; i < drv->num_banks; i++) {
-               ret = regmap_read(drv->regmap,
-                                 drv->offsets[i] + DRP_INTERRUPT_STATUS,
+               ret = regmap_read(drv->regmaps[i], DRP_INTERRUPT_STATUS,
                                  &drp_error);
 
                if (!ret && (drp_error & SB_ECC_ERROR)) {
@@ -312,8 +310,7 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl)
                if (!ret)
                        irq_rc = IRQ_HANDLED;
 
-               ret = regmap_read(drv->regmap,
-                                 drv->offsets[i] + TRP_INTERRUPT_0_STATUS,
+               ret = regmap_read(drv->regmaps[i], TRP_INTERRUPT_0_STATUS,
                                  &trp_error);
 
                if (!ret && (trp_error & SB_ECC_ERROR)) {
@@ -332,6 +329,11 @@ llcc_ecc_irq_handler(int irq, void *edev_ctl)
        return irq_rc;
 }
 
+static void llcc_ecc_check(struct edac_device_ctl_info *edev_ctl)
+{
+       llcc_ecc_irq_handler(0, edev_ctl);
+}
+
 static int qcom_llcc_edac_probe(struct platform_device *pdev)
 {
        struct llcc_drv_data *llcc_driv_data = pdev->dev.platform_data;
@@ -359,29 +361,31 @@ static int qcom_llcc_edac_probe(struct platform_device *pdev)
        edev_ctl->ctl_name = "llcc";
        edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
 
-       rc = edac_device_add_device(edev_ctl);
-       if (rc)
-               goto out_mem;
-
-       platform_set_drvdata(pdev, edev_ctl);
-
-       /* Request for ecc irq */
+       /* Check if LLCC driver has passed ECC IRQ */
        ecc_irq = llcc_driv_data->ecc_irq;
-       if (ecc_irq < 0) {
-               rc = -ENODEV;
-               goto out_dev;
-       }
-       rc = devm_request_irq(dev, ecc_irq, llcc_ecc_irq_handler,
+       if (ecc_irq > 0) {
+               /* Use interrupt mode if IRQ is available */
+               rc = devm_request_irq(dev, ecc_irq, llcc_ecc_irq_handler,
                              IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
-       if (rc)
-               goto out_dev;
+               if (!rc) {
+                       edac_op_state = EDAC_OPSTATE_INT;
+                       goto irq_done;
+               }
+       }
 
-       return rc;
+       /* Fall back to polling mode otherwise */
+       edev_ctl->poll_msec = ECC_POLL_MSEC;
+       edev_ctl->edac_check = llcc_ecc_check;
+       edac_op_state = EDAC_OPSTATE_POLL;
 
-out_dev:
-       edac_device_del_device(edev_ctl->dev);
-out_mem:
-       edac_device_free_ctl_info(edev_ctl);
+irq_done:
+       rc = edac_device_add_device(edev_ctl);
+       if (rc) {
+               edac_device_free_ctl_info(edev_ctl);
+               return rc;
+       }
+
+       platform_set_drvdata(pdev, edev_ctl);
 
        return rc;
 }
index d0aef83dca2a2b047648fb932dbdaedd6b844f70..61e979d5437a0b06ef38e6d99bfb8d15c7c6d4c5 100644 (file)
@@ -415,8 +415,7 @@ module_init(r82600_init);
 module_exit(r82600_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
-               "on behalf of EADS Astrium");
+MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. on behalf of EADS Astrium");
 MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
 
 module_param(disable_hardware_scrub, bool, 0644);
index 9397abb42c4980d20eb20589a9279b52ce2b999c..0a862336a7ce86b435e0e1838124e958dfb63cb6 100644 (file)
@@ -510,7 +510,7 @@ rir_found:
 }
 
 static u8 skx_close_row[] = {
-       15, 16, 17, 18, 20, 21, 22, 28, 10, 11, 12, 13, 29, 30, 31, 32, 33
+       15, 16, 17, 18, 20, 21, 22, 28, 10, 11, 12, 13, 29, 30, 31, 32, 33, 34
 };
 
 static u8 skx_close_column[] = {
@@ -518,7 +518,7 @@ static u8 skx_close_column[] = {
 };
 
 static u8 skx_open_row[] = {
-       14, 15, 16, 20, 28, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33
+       14, 15, 16, 20, 28, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34
 };
 
 static u8 skx_open_column[] = {
index 73140b854b313f53736c690162a05595a036e6b8..c15928b8c5cc9976b9f12ca5a7e4154dcbb0e888 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/device.h>
-#include <linux/of.h>
 
 #include "common.h"
 
@@ -436,7 +435,7 @@ struct scmi_device *scmi_device_create(struct device_node *np,
        /* Nothing to do. */
        if (!phead) {
                mutex_unlock(&scmi_requested_devices_mtx);
-               return scmi_dev;
+               return NULL;
        }
 
        /* Walk the list of requested devices for protocol and create them */
index d21c7eafd641c228ce7e156ee516f5b645376c9b..e7d97b59963b0ba989798ba9e31bb14458ad2871 100644 (file)
@@ -2221,8 +2221,8 @@ static int __scmi_xfer_info_init(struct scmi_info *sinfo,
        hash_init(info->pending_xfers);
 
        /* Allocate a bitmask sized to hold MSG_TOKEN_MAX tokens */
-       info->xfer_alloc_table = devm_kcalloc(dev, BITS_TO_LONGS(MSG_TOKEN_MAX),
-                                             sizeof(long), GFP_KERNEL);
+       info->xfer_alloc_table = devm_bitmap_zalloc(dev, MSG_TOKEN_MAX,
+                                                   GFP_KERNEL);
        if (!info->xfer_alloc_table)
                return -ENOMEM;
 
@@ -2289,7 +2289,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
                return ret;
 
        ret = __scmi_xfer_info_init(sinfo, &sinfo->tx_minfo);
-       if (!ret && idr_find(&sinfo->rx_idr, SCMI_PROTOCOL_BASE))
+       if (!ret && !idr_is_empty(&sinfo->rx_idr))
                ret = __scmi_xfer_info_init(sinfo, &sinfo->rx_minfo);
 
        return ret;
@@ -2657,6 +2657,7 @@ static int scmi_probe(struct platform_device *pdev)
        struct scmi_handle *handle;
        const struct scmi_desc *desc;
        struct scmi_info *info;
+       bool coex = IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
        struct device *dev = &pdev->dev;
        struct device_node *child, *np = dev->of_node;
 
@@ -2731,16 +2732,13 @@ static int scmi_probe(struct platform_device *pdev)
                        dev_warn(dev, "Failed to setup SCMI debugfs.\n");
 
                if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
-                       bool coex =
-                             IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT_COEX);
-
                        ret = scmi_debugfs_raw_mode_setup(info);
                        if (!coex) {
                                if (ret)
                                        goto clear_dev_req_notifier;
 
-                               /* Bail out anyway when coex enabled */
-                               return ret;
+                               /* Bail out anyway when coex disabled. */
+                               return 0;
                        }
 
                        /* Coex enabled, carry on in any case. */
@@ -2764,6 +2762,8 @@ static int scmi_probe(struct platform_device *pdev)
        ret = scmi_protocol_acquire(handle, SCMI_PROTOCOL_BASE);
        if (ret) {
                dev_err(dev, "unable to communicate with SCMI\n");
+               if (coex)
+                       return 0;
                goto notification_exit;
        }
 
index 0d9c9538b7f4175e0139563649ff2c687721f72e..1efa5e9392c4214439f9bb9100e2fbff12e8e839 100644 (file)
  * struct scmi_mailbox - Structure representing a SCMI mailbox transport
  *
  * @cl: Mailbox Client
- * @chan: Transmit/Receive mailbox channel
+ * @chan: Transmit/Receive mailbox uni/bi-directional channel
+ * @chan_receiver: Optional Receiver mailbox unidirectional channel
  * @cinfo: SCMI channel info
  * @shmem: Transmit/Receive shared memory area
  */
 struct scmi_mailbox {
        struct mbox_client cl;
        struct mbox_chan *chan;
+       struct mbox_chan *chan_receiver;
        struct scmi_chan_info *cinfo;
        struct scmi_shared_mem __iomem *shmem;
 };
@@ -48,10 +50,98 @@ static void rx_callback(struct mbox_client *cl, void *m)
 
 static bool mailbox_chan_available(struct device_node *of_node, int idx)
 {
+       int num_mb;
+
+       /*
+        * Just check if bidirrectional channels are involved, and check the
+        * index accordingly; proper full validation will be made later
+        * in mailbox_chan_setup().
+        */
+       num_mb = of_count_phandle_with_args(of_node, "mboxes", "#mbox-cells");
+       if (num_mb == 3 && idx == 1)
+               idx = 2;
+
        return !of_parse_phandle_with_args(of_node, "mboxes",
                                           "#mbox-cells", idx, NULL);
 }
 
+/**
+ * mailbox_chan_validate  - Validate transport configuration and map channels
+ *
+ * @cdev: Reference to the underlying transport device carrying the
+ *       of_node descriptor to analyze.
+ * @a2p_rx_chan: A reference to an optional unidirectional channel to use
+ *              for replies on the a2p channel. Set as zero if not present.
+ * @p2a_chan: A reference to the optional p2a channel.
+ *           Set as zero if not present.
+ *
+ * At first, validate the transport configuration as described in terms of
+ * 'mboxes' and 'shmem', then determin which mailbox channel indexes are
+ * appropriate to be use in the current configuration.
+ *
+ * Return: 0 on Success or error
+ */
+static int mailbox_chan_validate(struct device *cdev,
+                                int *a2p_rx_chan, int *p2a_chan)
+{
+       int num_mb, num_sh, ret = 0;
+       struct device_node *np = cdev->of_node;
+
+       num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+       num_sh = of_count_phandle_with_args(np, "shmem", NULL);
+       dev_dbg(cdev, "Found %d mboxes and %d shmems !\n", num_mb, num_sh);
+
+       /* Bail out if mboxes and shmem descriptors are inconsistent */
+       if (num_mb <= 0 || num_sh <= 0 || num_sh > 2 || num_mb > 3 ||
+           (num_mb == 1 && num_sh != 1) || (num_mb == 3 && num_sh != 2)) {
+               dev_warn(cdev,
+                        "Invalid channel descriptor for '%s' - mbs:%d  shm:%d\n",
+                        of_node_full_name(np), num_mb, num_sh);
+               return -EINVAL;
+       }
+
+       /* Bail out if provided shmem descriptors do not refer distinct areas  */
+       if (num_sh > 1) {
+               struct device_node *np_tx, *np_rx;
+
+               np_tx = of_parse_phandle(np, "shmem", 0);
+               np_rx = of_parse_phandle(np, "shmem", 1);
+               if (!np_tx || !np_rx || np_tx == np_rx) {
+                       dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
+                                of_node_full_name(np));
+                       ret = -EINVAL;
+               }
+
+               of_node_put(np_tx);
+               of_node_put(np_rx);
+       }
+
+       /* Calculate channels IDs to use depending on mboxes/shmem layout */
+       if (!ret) {
+               switch (num_mb) {
+               case 1:
+                       *a2p_rx_chan = 0;
+                       *p2a_chan = 0;
+                       break;
+               case 2:
+                       if (num_sh == 2) {
+                               *a2p_rx_chan = 0;
+                               *p2a_chan = 1;
+                       } else {
+                               *a2p_rx_chan = 1;
+                               *p2a_chan = 0;
+                       }
+                       break;
+               case 3:
+                       *a2p_rx_chan = 1;
+                       *p2a_chan = 2;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
 static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                              bool tx)
 {
@@ -59,11 +149,18 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        struct device *cdev = cinfo->dev;
        struct scmi_mailbox *smbox;
        struct device_node *shmem;
-       int ret, idx = tx ? 0 : 1;
+       int ret, a2p_rx_chan, p2a_chan, idx = tx ? 0 : 1;
        struct mbox_client *cl;
        resource_size_t size;
        struct resource res;
 
+       ret = mailbox_chan_validate(cdev, &a2p_rx_chan, &p2a_chan);
+       if (ret)
+               return ret;
+
+       if (!tx && !p2a_chan)
+               return -ENODEV;
+
        smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
        if (!smbox)
                return -ENOMEM;
@@ -93,15 +190,26 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        cl->tx_block = false;
        cl->knows_txdone = tx;
 
-       smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
+       smbox->chan = mbox_request_channel(cl, tx ? 0 : p2a_chan);
        if (IS_ERR(smbox->chan)) {
                ret = PTR_ERR(smbox->chan);
                if (ret != -EPROBE_DEFER)
-                       dev_err(cdev, "failed to request SCMI %s mailbox\n",
-                               tx ? "Tx" : "Rx");
+                       dev_err(cdev,
+                               "failed to request SCMI %s mailbox\n", desc);
                return ret;
        }
 
+       /* Additional unidirectional channel for TX if needed */
+       if (tx && a2p_rx_chan) {
+               smbox->chan_receiver = mbox_request_channel(cl, a2p_rx_chan);
+               if (IS_ERR(smbox->chan_receiver)) {
+                       ret = PTR_ERR(smbox->chan_receiver);
+                       if (ret != -EPROBE_DEFER)
+                               dev_err(cdev, "failed to request SCMI Tx Receiver mailbox\n");
+                       return ret;
+               }
+       }
+
        cinfo->transport_info = smbox;
        smbox->cinfo = cinfo;
 
@@ -115,8 +223,10 @@ static int mailbox_chan_free(int id, void *p, void *data)
 
        if (smbox && !IS_ERR(smbox->chan)) {
                mbox_free_channel(smbox->chan);
+               mbox_free_channel(smbox->chan_receiver);
                cinfo->transport_info = NULL;
                smbox->chan = NULL;
+               smbox->chan_receiver = NULL;
                smbox->cinfo = NULL;
        }
 
index 929720387102e6b85ffd709affdb9365f7ab27f0..e123de6e8c67a9719542666bd93116fe9cc41347 100644 (file)
@@ -403,7 +403,7 @@ out:
 static int setup_shmem(struct device *dev, struct scmi_chan_info *cinfo,
                       struct scmi_optee_channel *channel)
 {
-       if (of_find_property(cinfo->dev->of_node, "shmem", NULL))
+       if (of_property_present(cinfo->dev->of_node, "shmem"))
                return setup_static_shmem(dev, cinfo, channel);
        else
                return setup_dynamic_shmem(dev, channel);
index f54e6fdf08e2bf4c62c4b93f7550b6f47074d361..f80a9af3d16e94de51e4f124ec4ff40a43eaa31a 100644 (file)
@@ -215,6 +215,14 @@ efi_earlycon_write(struct console *con, const char *str, unsigned int num)
        }
 }
 
+static bool __initdata fb_probed;
+
+void __init efi_earlycon_reprobe(void)
+{
+       if (fb_probed)
+               setup_earlycon("efifb");
+}
+
 static int __init efi_earlycon_setup(struct earlycon_device *device,
                                     const char *opt)
 {
@@ -222,15 +230,17 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
        u16 xres, yres;
        u32 i;
 
-       if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+       fb_wb = opt && !strcmp(opt, "ram");
+
+       if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) {
+               fb_probed = true;
                return -ENODEV;
+       }
 
        fb_base = screen_info.lfb_base;
        if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
                fb_base |= (u64)screen_info.ext_lfb_base << 32;
 
-       fb_wb = opt && !strcmp(opt, "ram");
-
        si = &screen_info;
        xres = si->lfb_width;
        yres = si->lfb_height;
index 2c16080e1f71907c6f7b03434c4cd2ac47a6ea62..ef0820f1a9246ede74aa4a7aec41938628d2c755 100644 (file)
@@ -72,6 +72,9 @@ static void __init init_screen_info(void)
                if (memblock_is_map_memory(screen_info.lfb_base))
                        memblock_mark_nomap(screen_info.lfb_base,
                                            screen_info.lfb_size);
+
+               if (IS_ENABLED(CONFIG_EFI_EARLYCON))
+                       efi_earlycon_reprobe();
        }
 }
 
index 43e9a4cab9f5dcf169d158929bb3d9711817621b..ccdd6a130d98618ec52098bcc1cfc7f4f588c400 100644 (file)
@@ -44,4 +44,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
 $(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
        $(call if_changed,objcopy)
 
-targets += zboot-header.o vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
+targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
index d4a6b12a87413024a9c1df0b7a1744e8d0cd8f1a..770b8ecb73984c6115a5c37e2105637d4ec9bfd6 100644 (file)
@@ -85,8 +85,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                }
        }
 
-       if (image->image_base != _text)
+       if (image->image_base != _text) {
                efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
+               image->image_base = _text;
+       }
 
        if (!IS_ALIGNED((u64)_text, SEGMENT_ALIGN))
                efi_err("FIRMWARE BUG: kernel image not aligned on %dk boundary\n",
@@ -139,6 +141,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        *image_addr = *reserve_addr;
        memcpy((void *)*image_addr, _text, kernel_size);
        caches_clean_inval_pou(*image_addr, *image_addr + kernel_codesize);
+       efi_remap_image(*image_addr, *reserve_size, kernel_codesize);
 
        return EFI_SUCCESS;
 }
index 3997702663727e30948d9083bad6e70e1498af02..8aad8c49d43f18e0903e055ecfbf38740c957fa0 100644 (file)
 
 static bool system_needs_vamap(void)
 {
-       const u8 *type1_family = efi_get_smbios_string(1, family);
+       const struct efi_smbios_type4_record *record;
+       const u32 __aligned(1) *socid;
+       const u8 *version;
 
        /*
         * Ampere eMAG, Altra, and Altra Max machines crash in SetTime() if
-        * SetVirtualAddressMap() has not been called prior.
+        * SetVirtualAddressMap() has not been called prior. Most Altra systems
+        * can be identified by the SMCCC soc ID, which is conveniently exposed
+        * via the type 4 SMBIOS records. Otherwise, test the processor version
+        * field. eMAG systems all appear to have the processor version field
+        * set to "eMAG".
         */
-       if (!type1_family || (
-           strcmp(type1_family, "eMAG") &&
-           strcmp(type1_family, "Altra") &&
-           strcmp(type1_family, "Altra Max")))
+       record = (struct efi_smbios_type4_record *)efi_get_smbios_record(4);
+       if (!record)
                return false;
 
-       efi_warn("Working around broken SetVirtualAddressMap()\n");
-       return true;
+       socid = (u32 *)record->processor_id;
+       switch (*socid & 0xffff000f) {
+               static char const altra[] = "Ampere(TM) Altra(TM) Processor";
+               static char const emag[] = "eMAG";
+
+       default:
+               version = efi_get_smbios_string(&record->header, 4,
+                                               processor_version);
+               if (!version || (strncmp(version, altra, sizeof(altra) - 1) &&
+                                strncmp(version, emag, sizeof(emag) - 1)))
+                       break;
+
+               fallthrough;
+
+       case 0x0a160001:        // Altra
+       case 0x0a160002:        // Altra Max
+               efi_warn("Working around broken SetVirtualAddressMap()\n");
+               return true;
+       }
+
+       return false;
 }
 
 efi_status_t check_platform_features(void)
index 5245c4f031c0a70a5a8aa1146a7da3b5abb7d933..cc4dcaea67fa67f4ae5ba312a6c3cdb575663a45 100644 (file)
@@ -5,6 +5,15 @@
 
 #include "efistub.h"
 
+static unsigned long screen_info_offset;
+
+struct screen_info *alloc_screen_info(void)
+{
+       if (IS_ENABLED(CONFIG_ARM))
+               return __alloc_screen_info();
+       return (void *)&screen_info + screen_info_offset;
+}
+
 /*
  * EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
  * LoongArch. This is the entrypoint that is described in the PE/COFF header
@@ -56,6 +65,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
                return status;
        }
 
+       screen_info_offset = image_addr - (unsigned long)image->image_base;
+
        status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
 
        efi_free(image_size, image_addr);
index 2955c1ac6a36ee00cff656f63eb79c57a98fb10d..f9c1e8a2bd1d3e49b5e98bfa6d419fe9b74b075d 100644 (file)
 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
 static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
 
-struct screen_info * __weak alloc_screen_info(void)
-{
-       return &screen_info;
-}
-
 void __weak free_screen_info(struct screen_info *si)
 {
 }
index 6bd3bb86d9679a1c26f6fa7416536f91e8762ba0..148013bcb5f89fdd90de221f4d88da83f6e75337 100644 (file)
@@ -1062,6 +1062,7 @@ efi_enable_reset_attack_mitigation(void) { }
 void efi_retrieve_tpm2_eventlog(void);
 
 struct screen_info *alloc_screen_info(void);
+struct screen_info *__alloc_screen_info(void);
 void free_screen_info(struct screen_info *si);
 
 void efi_cache_sync_image(unsigned long image_base,
@@ -1074,6 +1075,8 @@ struct efi_smbios_record {
        u16     handle;
 };
 
+const struct efi_smbios_record *efi_get_smbios_record(u8 type);
+
 struct efi_smbios_type1_record {
        struct efi_smbios_record        header;
 
@@ -1087,14 +1090,46 @@ struct efi_smbios_type1_record {
        u8                              family;
 };
 
-#define efi_get_smbios_string(__type, __name) ({                       \
-       int size = sizeof(struct efi_smbios_type ## __type ## _record); \
+struct efi_smbios_type4_record {
+       struct efi_smbios_record        header;
+
+       u8                              socket;
+       u8                              processor_type;
+       u8                              processor_family;
+       u8                              processor_manufacturer;
+       u8                              processor_id[8];
+       u8                              processor_version;
+       u8                              voltage;
+       u16                             external_clock;
+       u16                             max_speed;
+       u16                             current_speed;
+       u8                              status;
+       u8                              processor_upgrade;
+       u16                             l1_cache_handle;
+       u16                             l2_cache_handle;
+       u16                             l3_cache_handle;
+       u8                              serial_number;
+       u8                              asset_tag;
+       u8                              part_number;
+       u8                              core_count;
+       u8                              enabled_core_count;
+       u8                              thread_count;
+       u16                             processor_characteristics;
+       u16                             processor_family2;
+       u16                             core_count2;
+       u16                             enabled_core_count2;
+       u16                             thread_count2;
+       u16                             thread_enabled;
+};
+
+#define efi_get_smbios_string(__record, __type, __name) ({             \
        int off = offsetof(struct efi_smbios_type ## __type ## _record, \
                           __name);                                     \
-       __efi_get_smbios_string(__type, off, size);                     \
+       __efi_get_smbios_string((__record), __type, off);               \
 })
 
-const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize);
+const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
+                                 u8 type, int offset);
 
 void efi_remap_image(unsigned long image_base, unsigned alloc_size,
                     unsigned long code_size);
index 1692d19ae80f0065627650344aa6dbae92180928..32c7a54923b4c1273feee1db101accd48083256c 100644 (file)
@@ -101,6 +101,7 @@ efi_status_t efi_random_alloc(unsigned long size,
         * to calculate the randomly chosen address, and allocate it directly
         * using EFI_ALLOCATE_ADDRESS.
         */
+       status = EFI_OUT_OF_RESOURCES;
        for (map_offset = 0; map_offset < map->map_size; map_offset += map->desc_size) {
                efi_memory_desc_t *md = (void *)map->map + map_offset;
                efi_physical_addr_t target;
index 8e76a8b384ba142d6967b59e9dc310b4828f60f7..4be1c4d1f922becd08ddd13d542f4d2fbd6e1883 100644 (file)
  * early, but it only works if the EFI stub is part of the core kernel image
  * itself. The zboot decompressor can only use the configuration table
  * approach.
- *
- * In order to support both methods from the same build of the EFI stub
- * library, provide this dummy global definition of struct screen_info. If it
- * is required to satisfy a link dependency, it means we need to override the
- * __weak alloc and free methods with the ones below, and those will be pulled
- * in as well.
  */
-struct screen_info screen_info;
 
 static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID;
 
-struct screen_info *alloc_screen_info(void)
+struct screen_info *__alloc_screen_info(void)
 {
        struct screen_info *si;
        efi_status_t status;
index 460418b7f5f5e9ab1d721ec096eaa77bb2462c58..c217de2cc8d56dc2796679f207772ff1288ba3d4 100644 (file)
@@ -22,21 +22,30 @@ struct efi_smbios_protocol {
        u8 minor_version;
 };
 
-const u8 *__efi_get_smbios_string(u8 type, int offset, int recsize)
+const struct efi_smbios_record *efi_get_smbios_record(u8 type)
 {
        struct efi_smbios_record *record;
        efi_smbios_protocol_t *smbios;
        efi_status_t status;
        u16 handle = 0xfffe;
-       const u8 *strtable;
 
        status = efi_bs_call(locate_protocol, &EFI_SMBIOS_PROTOCOL_GUID, NULL,
                             (void **)&smbios) ?:
                 efi_call_proto(smbios, get_next, &handle, &type, &record, NULL);
        if (status != EFI_SUCCESS)
                return NULL;
+       return record;
+}
+
+const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record,
+                                 u8 type, int offset)
+{
+       const u8 *strtable;
+
+       if (!record)
+               return NULL;
 
-       strtable = (u8 *)record + recsize;
+       strtable = (u8 *)record + record->length;
        for (int i = 1; i < ((u8 *)record)[offset]; i++) {
                int len = strlen(strtable);
 
index ec4525d40e0cf6d635161da889f14862d7a5610d..445cb646eaaaf1c657f572e0f2d42c63962bfe27 100644 (file)
@@ -63,7 +63,7 @@ __efistub_efi_zboot_header:
        .long           .Lefi_header_end - .Ldoshdr
        .long           0
        .short          IMAGE_SUBSYSTEM_EFI_APPLICATION
-       .short          0
+       .short          IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
 #ifdef CONFIG_64BIT
        .quad           0, 0, 0, 0
 #else
index ba234e062a1a29dae5618fa9c85bb65ff96fbee5..6105e5e2eda4612b3aa59e9c3e10e25f81075d7d 100644 (file)
@@ -57,6 +57,11 @@ void __weak efi_cache_sync_image(unsigned long image_base,
        // executable code loaded into memory to be safe for execution.
 }
 
+struct screen_info *alloc_screen_info(void)
+{
+       return __alloc_screen_info();
+}
+
 asmlinkage efi_status_t __efiapi
 efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
 {
index f06fdacc9bc830c8f89916a342f795fc33d988cb..456d0e5eaf78b595a66c622103b719e0fd2d3a69 100644 (file)
@@ -272,6 +272,14 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
                                        "IdeaPad Duet 3 10IGL5"),
                },
        },
+       {
+               /* Lenovo Yoga Book X91F / X91L */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       /* Non exact match to match F + L versions */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
+               },
+       },
        {},
 };
 
@@ -341,7 +349,7 @@ static const struct fwnode_operations efifb_fwnode_ops = {
 #ifdef CONFIG_EFI
 static struct fwnode_handle efifb_fwnode;
 
-__init void sysfb_apply_efi_quirks(struct platform_device *pd)
+__init void sysfb_apply_efi_quirks(void)
 {
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
            !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
@@ -355,7 +363,10 @@ __init void sysfb_apply_efi_quirks(struct platform_device *pd)
                screen_info.lfb_height = temp;
                screen_info.lfb_linelength = 4 * screen_info.lfb_width;
        }
+}
 
+__init void sysfb_set_efifb_fwnode(struct platform_device *pd)
+{
        if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && IS_ENABLED(CONFIG_PCI)) {
                fwnode_init(&efifb_fwnode, &efifb_fwnode_ops);
                pd->dev.fwnode = &efifb_fwnode;
index dca79caccd01c15ff5761423e24a247a858abf7a..47db49911e7b89a05747da22f1858ccd3e32067a 100644 (file)
@@ -310,9 +310,8 @@ static int imx_scu_probe(struct platform_device *pdev)
                sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
                if (IS_ERR(sc_chan->ch)) {
                        ret = PTR_ERR(sc_chan->ch);
-                       if (ret != -EPROBE_DEFER)
-                               dev_err(dev, "Failed to request mbox chan %s ret %d\n",
-                                       chan_name, ret);
+                       dev_err_probe(dev, ret, "Failed to request mbox chan %s\n",
+                                     chan_name);
                        kfree(chan_name);
                        return ret;
                }
index 2a4f07423365aa29a42b49c6782aaec14f48332e..84b67342707333c68aaeb392ba3e710236cfebd0 100644 (file)
@@ -180,7 +180,11 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
 
        /* LVDS SS */
        { "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
+       { "lvds0-pwm", IMX_SC_R_LVDS_0_PWM_0, 1, false, 0 },
+       { "lvds0-lpi2c", IMX_SC_R_LVDS_0_I2C_0, 2, true, 0 },
        { "lvds1", IMX_SC_R_LVDS_1, 1, false, 0 },
+       { "lvds1-pwm", IMX_SC_R_LVDS_1_PWM_0, 1, false, 0 },
+       { "lvds1-lpi2c", IMX_SC_R_LVDS_1_I2C_0, 2, true, 0 },
 
        /* DC SS */
        { "dc0", IMX_SC_R_DC_0, 1, false, 0 },
index 3f5ff9ed668ef54bebcaadfe4e179fb13c3ce162..798bcdb05d84ee067b6e7fb6c16a998ed4e9582a 100644 (file)
@@ -311,11 +311,14 @@ static int __init meson_sm_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, fw);
 
-       pr_info("secure-monitor enabled\n");
+       if (devm_of_platform_populate(dev))
+               goto out_in_base;
 
        if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group))
                goto out_in_base;
 
+       pr_info("secure-monitor enabled\n");
+
        return 0;
 
 out_in_base:
index 29619f49873a18abd897c7f84751fb266a8e9cac..d9629ff8786199c33500b154616584013c8d1d1e 100644 (file)
@@ -167,7 +167,8 @@ int psci_set_osi_mode(bool enable)
 
        err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, suspend_mode, 0, 0);
        if (err < 0)
-               pr_warn("failed to set %s mode: %d\n", enable ? "OSI" : "PC", err);
+               pr_info(FW_BUG "failed to set %s mode: %d\n",
+                               enable ? "OSI" : "PC", err);
        return psci_to_linux_errno(err);
 }
 
index 468d4d5ab550c91cfa415418cc5333746dc596c8..fde33acd46b756f2b9ac2bd1c9a2341084bcb974 100644 (file)
@@ -905,7 +905,7 @@ static int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region,
  * Return negative errno on failure or 0 on success with @srcvm updated.
  */
 int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
-                       unsigned int *srcvm,
+                       u64 *srcvm,
                        const struct qcom_scm_vmperm *newvm,
                        unsigned int dest_cnt)
 {
@@ -922,9 +922,9 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
        __le32 *src;
        void *ptr;
        int ret, i, b;
-       unsigned long srcvm_bits = *srcvm;
+       u64 srcvm_bits = *srcvm;
 
-       src_sz = hweight_long(srcvm_bits) * sizeof(*src);
+       src_sz = hweight64(srcvm_bits) * sizeof(*src);
        mem_to_map_sz = sizeof(*mem_to_map);
        dest_sz = dest_cnt * sizeof(*destvm);
        ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
@@ -937,8 +937,10 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
        /* Fill source vmid detail */
        src = ptr;
        i = 0;
-       for_each_set_bit(b, &srcvm_bits, BITS_PER_LONG)
-               src[i++] = cpu_to_le32(b);
+       for (b = 0; b < BITS_PER_TYPE(u64); b++) {
+               if (srcvm_bits & BIT(b))
+                       src[i++] = cpu_to_le32(b);
+       }
 
        /* Fill details of mem buff to map */
        mem_to_map = ptr + ALIGN(src_sz, SZ_64);
@@ -1479,7 +1481,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
 
        init_completion(&__scm->waitq_comp);
 
-       irq = platform_get_irq(pdev, 0);
+       irq = platform_get_irq_optional(pdev, 0);
        if (irq < 0) {
                if (irq != -ENXIO)
                        return irq;
@@ -1506,8 +1508,7 @@ static int qcom_scm_probe(struct platform_device *pdev)
 static void qcom_scm_shutdown(struct platform_device *pdev)
 {
        /* Clean shutdown, disable download mode to allow normal restart */
-       if (download_mode)
-               qcom_scm_set_download_mode(false);
+       qcom_scm_set_download_mode(false);
 }
 
 static const struct of_device_id qcom_scm_dt_match[] = {
@@ -1542,6 +1543,7 @@ static const struct of_device_id qcom_scm_dt_match[] = {
        },
        { .compatible = "qcom,scm-msm8994" },
        { .compatible = "qcom,scm-msm8996" },
+       { .compatible = "qcom,scm-sm6375", .data = (void *)SCM_HAS_CORE_CLK },
        { .compatible = "qcom,scm" },
        {}
 };
index 60ccf3e90d7de541b87fda5c157624751dbc0980..db818f9dcb8ee7d8183eacd1a7837e1b341f9039 100644 (file)
@@ -17,9 +17,13 @@ static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
 
 bool __ro_after_init smccc_trng_available = false;
 u64 __ro_after_init smccc_has_sve_hint = false;
+s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED;
+s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED;
 
 void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
 {
+       struct arm_smccc_res res;
+
        smccc_version = version;
        smccc_conduit = conduit;
 
@@ -27,6 +31,18 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
        if (IS_ENABLED(CONFIG_ARM64_SVE) &&
            smccc_version >= ARM_SMCCC_VERSION_1_3)
                smccc_has_sve_hint = true;
+
+       if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
+           (smccc_conduit != SMCCC_CONDUIT_NONE)) {
+               arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+                                    ARM_SMCCC_ARCH_SOC_ID, &res);
+               if ((s32)res.a0 >= 0) {
+                       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 0, &res);
+                       smccc_soc_id_version = (s32)res.a0;
+                       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 1, &res);
+                       smccc_soc_id_revision = (s32)res.a0;
+               }
+       }
 }
 
 enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void)
@@ -44,6 +60,16 @@ u32 arm_smccc_get_version(void)
 }
 EXPORT_SYMBOL_GPL(arm_smccc_get_version);
 
+s32 arm_smccc_get_soc_id_version(void)
+{
+       return smccc_soc_id_version;
+}
+
+s32 arm_smccc_get_soc_id_revision(void)
+{
+       return smccc_soc_id_revision;
+}
+
 static int __init smccc_devices_init(void)
 {
        struct platform_device *pdev;
index dd7c3d5e8b0bbabd32cf9395e3e39f6bf5c77d20..890eb454599a33ba5100a0e299eaed004d1d88ee 100644 (file)
@@ -42,41 +42,23 @@ static int __init smccc_soc_init(void)
        if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
                return 0;
 
-       if (arm_smccc_1_1_get_conduit() == SMCCC_CONDUIT_NONE) {
-               pr_err("%s: invalid SMCCC conduit\n", __func__);
-               return -EOPNOTSUPP;
-       }
-
-       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
-                            ARM_SMCCC_ARCH_SOC_ID, &res);
-
-       if ((int)res.a0 == SMCCC_RET_NOT_SUPPORTED) {
+       soc_id_version = arm_smccc_get_soc_id_version();
+       if (soc_id_version == SMCCC_RET_NOT_SUPPORTED) {
                pr_info("ARCH_SOC_ID not implemented, skipping ....\n");
                return 0;
        }
 
-       if ((int)res.a0 < 0) {
-               pr_info("ARCH_FEATURES(ARCH_SOC_ID) returned error: %lx\n",
-                       res.a0);
-               return -EINVAL;
-       }
-
-       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 0, &res);
-       if ((int)res.a0 < 0) {
+       if (soc_id_version < 0) {
                pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0);
                return -EINVAL;
        }
 
-       soc_id_version = res.a0;
-
-       arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 1, &res);
-       if ((int)res.a0 < 0) {
+       soc_id_rev = arm_smccc_get_soc_id_revision();
+       if (soc_id_rev < 0) {
                pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0);
                return -EINVAL;
        }
 
-       soc_id_rev = res.a0;
-
        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
        if (!soc_dev_attr)
                return -ENOMEM;
index 3fd3563d962b87d73ff2fc2bb3079461cd9f22e0..3c197db42c9d936866f9ff68cf7561e4735cfe1e 100644 (file)
@@ -81,6 +81,8 @@ static __init int sysfb_init(void)
        if (disabled)
                goto unlock_mutex;
 
+       sysfb_apply_efi_quirks();
+
        /* try to create a simple-framebuffer device */
        compatible = sysfb_parse_mode(si, &mode);
        if (compatible) {
@@ -107,7 +109,7 @@ static __init int sysfb_init(void)
                goto unlock_mutex;
        }
 
-       sysfb_apply_efi_quirks(pd);
+       sysfb_set_efifb_fwnode(pd);
 
        ret = platform_device_add_data(pd, si, sizeof(*si));
        if (ret)
index ce9c007ed66ff76d64bf3fd4c023198152a32459..82c64cb9f5316c230fcb25b34936f96f92e215d1 100644 (file)
@@ -141,7 +141,7 @@ __init struct platform_device *sysfb_create_simplefb(const struct screen_info *s
        if (!pd)
                return ERR_PTR(-ENOMEM);
 
-       sysfb_apply_efi_quirks(pd);
+       sysfb_set_efifb_fwnode(pd);
 
        ret = platform_device_add_resources(pd, &res, 1);
        if (ret)
index 3ca2b5d9e66f5e058e6e5884e1852244790e2e8e..6dfe3d34109ee91a31d4fb0f515980e7c12a1765 100644 (file)
@@ -193,7 +193,7 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
                },
        };
        u32 fd = 0, len = 0;
-       int remaining, err;
+       int remaining, err, close_err;
 
        mutex_lock(&bpmp_debug_lock);
        err = mrq_debug_open(bpmp, name, &fd, &len, 0);
@@ -231,7 +231,9 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
        *nbytes = len;
 
 close:
-       err = mrq_debug_close(bpmp, fd);
+       close_err = mrq_debug_close(bpmp, fd);
+       if (!err)
+               err = close_err;
 out:
        mutex_unlock(&bpmp_debug_lock);
        return err;
@@ -319,7 +321,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
                },
        };
        u32 fd = 0, len = 0;
-       int remaining, err;
+       int remaining, err, close_err;
 
        filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
        if (!filename)
@@ -353,7 +355,9 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
        }
 
 close:
-       err = mrq_debug_close(bpmp, fd);
+       close_err = mrq_debug_close(bpmp, fd);
+       if (!err)
+               err = close_err;
 out:
        mutex_unlock(&bpmp_debug_lock);
        return err;
index 042c2043929d702763d6a4ff84819a0ad85b69a9..8b5e5daa9fae346ce42ea2fb69978364ae87ab91 100644 (file)
@@ -764,19 +764,19 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
        if (err < 0)
                goto free_mrq;
 
-       if (of_find_property(pdev->dev.of_node, "#clock-cells", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "#clock-cells")) {
                err = tegra_bpmp_init_clocks(bpmp);
                if (err < 0)
                        goto free_mrq;
        }
 
-       if (of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "#reset-cells")) {
                err = tegra_bpmp_init_resets(bpmp);
                if (err < 0)
                        goto free_mrq;
        }
 
-       if (of_find_property(pdev->dev.of_node, "#power-domain-cells", NULL)) {
+       if (of_property_present(pdev->dev.of_node, "#power-domain-cells")) {
                err = tegra_bpmp_init_powergates(bpmp);
                if (err < 0)
                        goto free_mrq;
index 6ea5789a89e2be9626928847456a3bc3b7cae47c..2de0fb139ce1762164d3e64b56793558c6917b4a 100644 (file)
@@ -104,7 +104,7 @@ static void mox_kobj_release(struct kobject *kobj)
        kfree(to_rwtm(kobj)->kobj);
 }
 
-static struct kobj_type mox_kobj_ktype = {
+static const struct kobj_type mox_kobj_ktype = {
        .release        = mox_kobj_release,
        .sysfs_ops      = &kobj_sysfs_ops,
 };
index acd83d29c8667d86b7d854e8f240a16123afa21f..ce86a18503054110062a315c2449c6ce57bad26a 100644 (file)
@@ -206,7 +206,7 @@ static int do_feature_check_call(const u32 api_id)
        }
 
        /* Add new entry if not present */
-       feature_data = kmalloc(sizeof(*feature_data), GFP_KERNEL);
+       feature_data = kmalloc(sizeof(*feature_data), GFP_ATOMIC);
        if (!feature_data)
                return -ENOMEM;
 
index 0914e7328b1a53664d233b5f2bd52576b09d397b..1bc04378118c7b2d6c672a31b8550c448edfa58b 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/stddef.h>
 #include <linux/errno.h>
-#include <linux/aer.h>
 
 #include "dfl.h"
 
@@ -376,10 +375,6 @@ int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
                return ret;
        }
 
-       ret = pci_enable_pcie_error_reporting(pcidev);
-       if (ret && ret != -EINVAL)
-               dev_info(&pcidev->dev, "PCIE AER unavailable %d.\n", ret);
-
        pci_set_master(pcidev);
 
        ret = dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(64));
@@ -387,24 +382,22 @@ int cci_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *pcidevid)
                ret = dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(32));
        if (ret) {
                dev_err(&pcidev->dev, "No suitable DMA support available.\n");
-               goto disable_error_report_exit;
+               return ret;
        }
 
        ret = cci_init_drvdata(pcidev);
        if (ret) {
                dev_err(&pcidev->dev, "Fail to init drvdata %d.\n", ret);
-               goto disable_error_report_exit;
+               return ret;
        }
 
        ret = cci_enumerate_feature_devs(pcidev);
-       if (!ret)
+       if (ret) {
+               dev_err(&pcidev->dev, "enumeration failure %d.\n", ret);
                return ret;
+       }
 
-       dev_err(&pcidev->dev, "enumeration failure %d.\n", ret);
-
-disable_error_report_exit:
-       pci_disable_pcie_error_reporting(pcidev);
-       return ret;
+       return 0;
 }
 
 static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
@@ -448,7 +441,6 @@ static void cci_pci_remove(struct pci_dev *pcidev)
                cci_pci_sriov_configure(pcidev, 0);
 
        cci_remove_feature_devs(pcidev);
-       pci_disable_pcie_error_reporting(pcidev);
 }
 
 static struct pci_driver cci_pci_driver = {
index 5cd40acab5bfb85f52302ea244c2906af1213f1f..0953e6e4db041d635a349b4a45fe9714e7343755 100644 (file)
@@ -363,7 +363,6 @@ fpga_bridge_register(struct device *parent, const char *name,
        bridge->dev.parent = parent;
        bridge->dev.of_node = parent->of_node;
        bridge->dev.id = id;
-       of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
 
        ret = dev_set_name(&bridge->dev, "br%d", id);
        if (ret)
@@ -375,6 +374,8 @@ fpga_bridge_register(struct device *parent, const char *name,
                return ERR_PTR(ret);
        }
 
+       of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
+
        return bridge;
 
 error_device:
index f0acedc801827a3c268eedee45264781b14c6cf1..d7e2f9f461bcab3bd196699076ba47e660f82719 100644 (file)
@@ -474,7 +474,7 @@ static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec)
 
        ret = sec->ops->rsu_status(sec);
        if (ret < 0)
-               return ret;
+               return FW_UPLOAD_ERR_HW_ERROR;
        status = ret;
 
        if (!rsu_status_ok(status)) {
index 2d9c491f7be9477be2bf187c1d28941395bb968f..b76d85449b8fb2a15e9cea2cd563663ccbd8f61e 100644 (file)
@@ -69,7 +69,7 @@ static int xlnx_pr_decoupler_enable_show(struct fpga_bridge *bridge)
        if (err)
                return err;
 
-       status = readl(priv->io_base);
+       status = xlnx_pr_decouple_read(priv, CTRL_OFFSET);
 
        clk_disable(priv->clk);
 
index 13be729710f28250fad8772c6a9b80a1be984a47..badbe05823180507916c95eca9013b0841374a83 100644 (file)
@@ -100,7 +100,7 @@ config GPIO_GENERIC
        tristate
 
 config GPIO_REGMAP
-       depends on REGMAP
+       select REGMAP
        tristate
 
 # put drivers in the right section, in alphabetical order
index a3846faf3780dcbe7337fe5db085c657eed89fe0..11c48130bb8f16a88e1bee7bc4659475f92e1dbe 100644 (file)
@@ -86,6 +86,7 @@ static const struct regmap_config dio48e_regmap_config = {
        .volatile_table = &dio48e_volatile_table,
        .precious_table = &dio48e_precious_table,
        .cache_type = REGCACHE_FLAT,
+       .use_raw_spinlock = true,
 };
 
 /* only bit 3 on each respective Port C supports interrupts */
index ca2175b84e2417593bbc3292c524b9f68823c997..ba73ee9c0c291508516bf18839dba413e5933294 100644 (file)
@@ -81,6 +81,7 @@ static const struct regmap_config idi48_regmap_config = {
        .wr_table = &idi_48_wr_table,
        .rd_table = &idi_48_rd_table,
        .precious_table = &idi_48_precious_table,
+       .use_raw_spinlock = true,
 };
 
 #define IDI48_NGPIO 48
index 26b1f7465e09176fe56cd9456a55665a1a0cc033..43b2dc8821e6b59eb849d5301cd3456f21d64af0 100644 (file)
@@ -324,7 +324,7 @@ static struct irq_chip gpio_irqchip = {
        .irq_enable     = gpio_irq_enable,
        .irq_disable    = gpio_irq_disable,
        .irq_set_type   = gpio_irq_type,
-       .flags          = IRQCHIP_SET_TYPE_MASKED,
+       .flags          = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE,
 };
 
 static void gpio_irq_handler(struct irq_desc *desc)
@@ -641,9 +641,6 @@ static void davinci_gpio_save_context(struct davinci_gpio_controller *chips,
                context->set_falling = readl_relaxed(&g->set_falling);
        }
 
-       /* Clear Bank interrupt enable bit */
-       writel_relaxed(0, base + BINTEN);
-
        /* Clear all interrupt status registers */
        writel_relaxed(GENMASK(31, 0), &g->intstat);
 }
index d8a421ce26a83e1b9f98dfbc37bd4135cbf34497..31ae0adbb295ab190bd69ef37ffbb02062536d1a 100644 (file)
@@ -536,6 +536,9 @@ void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
        if (ACPI_FAILURE(status))
                return;
 
+       if (acpi_quirk_skip_gpio_event_handlers())
+               return;
+
        acpi_walk_resources(handle, METHOD_NAME__AEI,
                            acpi_gpiochip_alloc_event, acpi_gpio);
 
index 164141bc8b4ad1e145ead120d3094ea02efa40bb..39018f784f9c01d430472a7541c03ec645d35ce5 100644 (file)
@@ -1272,6 +1272,7 @@ void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
 int amdgpu_device_pci_reset(struct amdgpu_device *adev);
 bool amdgpu_device_need_post(struct amdgpu_device *adev);
 bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
+bool amdgpu_device_aspm_support_quirk(void);
 
 void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes,
                                  u64 num_vis_bytes);
@@ -1391,10 +1392,12 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta
 int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev);
 
 void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps);
+bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
 void amdgpu_acpi_detect(void);
 #else
 static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; }
 static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { }
+static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
 static inline void amdgpu_acpi_detect(void) { }
 static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; }
 static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev,
@@ -1405,11 +1408,9 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev,
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND)
 bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev);
-bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev);
 bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev);
 #else
 static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; }
-static inline bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev) { return false; }
 static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; }
 #endif
 
index d4196fcb85a08a364a4a7b235c30a62dde7fa8f8..aeeec211861c434bae58aae748586e4a608360d5 100644 (file)
@@ -971,6 +971,34 @@ static bool amdgpu_atcs_pci_probe_handle(struct pci_dev *pdev)
        return true;
 }
 
+
+/**
+ * amdgpu_acpi_should_gpu_reset
+ *
+ * @adev: amdgpu_device_pointer
+ *
+ * returns true if should reset GPU, false if not
+ */
+bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
+{
+       if ((adev->flags & AMD_IS_APU) &&
+           adev->gfx.imu.funcs) /* Not need to do mode2 reset for IMU enabled APUs */
+               return false;
+
+       if ((adev->flags & AMD_IS_APU) &&
+           amdgpu_acpi_is_s3_active(adev))
+               return false;
+
+       if (amdgpu_sriov_vf(adev))
+               return false;
+
+#if IS_ENABLED(CONFIG_SUSPEND)
+       return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
+#else
+       return true;
+#endif
+}
+
 /*
  * amdgpu_acpi_detect - detect ACPI ATIF/ATCS methods
  *
@@ -1042,24 +1070,6 @@ bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev)
                (pm_suspend_target_state == PM_SUSPEND_MEM);
 }
 
-/**
- * amdgpu_acpi_should_gpu_reset
- *
- * @adev: amdgpu_device_pointer
- *
- * returns true if should reset GPU, false if not
- */
-bool amdgpu_acpi_should_gpu_reset(struct amdgpu_device *adev)
-{
-       if (adev->flags & AMD_IS_APU)
-               return false;
-
-       if (amdgpu_sriov_vf(adev))
-               return false;
-
-       return pm_suspend_target_state != PM_SUSPEND_TO_IDLE;
-}
-
 /**
  * amdgpu_acpi_is_s0ix_active
  *
index c4a4e2fe66814ccf07a2edd13a00bd5bbf8bedd2..3d98fc2ad36b04eb0d44fbc0e897608e5122a8c7 100644 (file)
 
 #include <drm/drm_drv.h>
 
+#if IS_ENABLED(CONFIG_X86)
+#include <asm/intel-family.h>
+#endif
+
 MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/vega12_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
@@ -1356,6 +1360,17 @@ bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev)
        return pcie_aspm_enabled(adev->pdev);
 }
 
+bool amdgpu_device_aspm_support_quirk(void)
+{
+#if IS_ENABLED(CONFIG_X86)
+       struct cpuinfo_x86 *c = &cpu_data(0);
+
+       return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE);
+#else
+       return true;
+#endif
+}
+
 /* if we get transitioned to only one device, take VGA back */
 /**
  * amdgpu_device_vga_set_decode - enable/disable vga decode
@@ -4145,8 +4160,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
        if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D3))
                DRM_WARN("smart shift update failed\n");
 
-       drm_kms_helper_poll_disable(dev);
-
        if (fbcon)
                drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, true);
 
@@ -4243,8 +4256,6 @@ exit:
        if (fbcon)
                drm_fb_helper_set_suspend_unlocked(adev_to_drm(adev)->fb_helper, false);
 
-       drm_kms_helper_poll_enable(dev);
-
        amdgpu_ras_resume(adev);
 
        if (adev->mode_info.num_crtc) {
index 503f89a766c3774e4626b70f7ea49cacd7e31b2f..d60fe7eb5579aeae48961105b832e1a47fe1300c 100644 (file)
@@ -1618,6 +1618,8 @@ int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
        struct drm_connector_list_iter iter;
        int r;
 
+       drm_kms_helper_poll_disable(dev);
+
        /* turn off display hw */
        drm_modeset_lock_all(dev);
        drm_connector_list_iter_begin(dev, &iter);
@@ -1694,6 +1696,8 @@ int amdgpu_display_resume_helper(struct amdgpu_device *adev)
 
        drm_modeset_unlock_all(dev);
 
+       drm_kms_helper_poll_enable(dev);
+
        return 0;
 }
 
index f5ffca24def4000f42043d4c09e5f05fe86f8876..ba5def374368e578ba842f20bbeab6d38777f52e 100644 (file)
@@ -2467,7 +2467,10 @@ static int amdgpu_pmops_freeze(struct device *dev)
        adev->in_s4 = false;
        if (r)
                return r;
-       return amdgpu_asic_reset(adev);
+
+       if (amdgpu_acpi_should_gpu_reset(adev))
+               return amdgpu_asic_reset(adev);
+       return 0;
 }
 
 static int amdgpu_pmops_thaw(struct device *dev)
index faff4a3f96e6e8911e573daf46b4b894103a76e3..f52d0ba91a770a4b437a1137aa88cf6a7113cf53 100644 (file)
@@ -678,6 +678,15 @@ void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring)
                ptr = &ring->fence_drv.fences[i];
                old = rcu_dereference_protected(*ptr, 1);
                if (old && old->ops == &amdgpu_job_fence_ops) {
+                       struct amdgpu_job *job;
+
+                       /* For non-scheduler bad job, i.e. failed ib test, we need to signal
+                        * it right here or we won't be able to track them in fence_drv
+                        * and they will remain unsignaled during sa_bo free.
+                        */
+                       job = container_of(old, struct amdgpu_job, hw_fence);
+                       if (!job->base.s_fence && !dma_fence_is_signaled(old))
+                               dma_fence_signal(old);
                        RCU_INIT_POINTER(*ptr, NULL);
                        dma_fence_put(old);
                }
index d0a1cc88832cc4bd3c53ddf6f5f1127d491bcb2a..fafebec5b7b66da8911ffb2f112817a1f1f626ae 100644 (file)
@@ -596,6 +596,9 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
        if (!src->enabled_types || !src->funcs->set)
                return -EINVAL;
 
+       if (WARN_ON(!amdgpu_irq_enabled(adev, src, type)))
+               return -EINVAL;
+
        if (atomic_dec_and_test(&src->enabled_types[type]))
                return amdgpu_irq_update(adev, src, type);
 
index 25217b05c0ea8dabd5c4ef4fd22885e875d2af2c..e7974de8b035d6f356db79549408e6fef9755364 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/firmware.h>
 #include <linux/module.h>
+#include <linux/dmi.h>
 #include <linux/pci.h>
 #include <linux/debugfs.h>
 #include <drm/drm_drv.h>
@@ -114,6 +115,24 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
            (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
                adev->vcn.indirect_sram = true;
 
+       /*
+        * Some Steam Deck's BIOS versions are incompatible with the
+        * indirect SRAM mode, leading to amdgpu being unable to get
+        * properly probed (and even potentially crashing the kernel).
+        * Hence, check for these versions here - notice this is
+        * restricted to Vangogh (Deck's APU).
+        */
+       if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 0, 2)) {
+               const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);
+
+               if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||
+                    !strncmp("F7A0114", bios_ver, 7))) {
+                       adev->vcn.indirect_sram = false;
+                       dev_info(adev->dev,
+                               "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);
+               }
+       }
+
        hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
        adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
 
index b9e9480448afe9e56324daf866deb77eb2d34063..4f7bab52282ac1b6463fb2420315bbdf4b92b0ba 100644 (file)
@@ -124,6 +124,8 @@ enum AMDGIM_FEATURE_FLAG {
        AMDGIM_FEATURE_PP_ONE_VF = (1 << 4),
        /* Indirect Reg Access enabled */
        AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5),
+       /* AV1 Support MODE*/
+       AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6),
 };
 
 enum AMDGIM_REG_ACCESS_FLAG {
@@ -322,6 +324,8 @@ static inline bool is_virtual_machine(void)
        ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug)
 #define amdgpu_sriov_is_normal(adev) \
        ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug))
+#define amdgpu_sriov_is_av1_support(adev) \
+       ((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT)
 bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev);
 void amdgpu_virt_init_setting(struct amdgpu_device *adev);
 void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
index 6c97148ca0ed35dc9c66c828bd45a870281a5c44..24d42d24e6a01e033a84edbbfe561e0878dd6049 100644 (file)
@@ -93,7 +93,8 @@ union amd_sriov_msg_feature_flags {
                uint32_t mm_bw_management  : 1;
                uint32_t pp_one_vf_mode    : 1;
                uint32_t reg_indirect_acc  : 1;
-               uint32_t reserved          : 26;
+               uint32_t av1_support       : 1;
+               uint32_t reserved          : 25;
        } flags;
        uint32_t all;
 };
index 3bf697a80cf2fc30a4dcc49e154ee87b5ffe4370..ecf8ceb53311ac2d1dbb09b80244fef86dc3bca3 100644 (file)
@@ -1287,6 +1287,11 @@ static int gfx_v11_0_sw_init(void *handle)
                break;
        }
 
+       /* Enable CG flag in one VF mode for enabling RLC safe mode enter/exit */
+       if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3) &&
+               amdgpu_sriov_is_pp_one_vf(adev))
+               adev->cg_flags = AMD_CG_SUPPORT_GFX_CGCG;
+
        /* EOP Event */
        r = amdgpu_irq_add_id(adev, SOC21_IH_CLIENTID_GRBM_CP,
                              GFX_11_0_0__SRCID__CP_EOP_INTERRUPT,
@@ -4655,6 +4660,14 @@ static bool gfx_v11_0_check_soft_reset(void *handle)
        return false;
 }
 
+static int gfx_v11_0_post_soft_reset(void *handle)
+{
+       /**
+        * GFX soft reset will impact MES, need resume MES when do GFX soft reset
+        */
+       return amdgpu_mes_resume((struct amdgpu_device *)handle);
+}
+
 static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
        uint64_t clock;
@@ -6166,6 +6179,7 @@ static const struct amd_ip_funcs gfx_v11_0_ip_funcs = {
        .wait_for_idle = gfx_v11_0_wait_for_idle,
        .soft_reset = gfx_v11_0_soft_reset,
        .check_soft_reset = gfx_v11_0_check_soft_reset,
+       .post_soft_reset = gfx_v11_0_post_soft_reset,
        .set_clockgating_state = gfx_v11_0_set_clockgating_state,
        .set_powergating_state = gfx_v11_0_set_powergating_state,
        .get_clockgating_state = gfx_v11_0_get_clockgating_state,
index 855d390c41de159c85b3341289da14c7671931f4..ebe0e2d7dbd1b59d772ae52d641f43a9914921b3 100644 (file)
@@ -578,7 +578,7 @@ static void nv_pcie_gen3_enable(struct amdgpu_device *adev)
 
 static void nv_program_aspm(struct amdgpu_device *adev)
 {
-       if (!amdgpu_device_should_use_aspm(adev))
+       if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())
                return;
 
        if (!(adev->flags & AMD_IS_APU) &&
@@ -1055,8 +1055,8 @@ static int nv_common_late_init(void *handle)
                        amdgpu_virt_update_sriov_video_codec(adev,
                                                             sriov_sc_video_codecs_encode_array,
                                                             ARRAY_SIZE(sriov_sc_video_codecs_encode_array),
-                                                            sriov_sc_video_codecs_decode_array_vcn1,
-                                                            ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn1));
+                                                            sriov_sc_video_codecs_decode_array_vcn0,
+                                                            ARRAY_SIZE(sriov_sc_video_codecs_decode_array_vcn0));
                }
        }
 
index 061793d390ccc5d38eb25e252bd92852366aaa57..c82b3a7ea5f0840c2f894ac6fc77b2c92f488840 100644 (file)
@@ -102,6 +102,59 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_decode_vcn1 =
        .codec_array = vcn_4_0_0_video_codecs_decode_array_vcn1,
 };
 
+/* SRIOV SOC21, not const since data is controlled by host */
+static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn0[] = {
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
+};
+
+static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_encode_array_vcn1[] = {
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 2304, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 2304, 0)},
+};
+
+static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn0 = {
+       .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0),
+       .codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn0,
+};
+
+static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_encode_vcn1 = {
+       .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1),
+       .codec_array = sriov_vcn_4_0_0_video_codecs_encode_array_vcn1,
+};
+
+static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn0[] = {
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)},
+};
+
+static struct amdgpu_video_codec_info sriov_vcn_4_0_0_video_codecs_decode_array_vcn1[] = {
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
+       {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
+};
+
+static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn0 = {
+       .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0),
+       .codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn0,
+};
+
+static struct amdgpu_video_codecs sriov_vcn_4_0_0_video_codecs_decode_vcn1 = {
+       .codec_count = ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1),
+       .codec_array = sriov_vcn_4_0_0_video_codecs_decode_array_vcn1,
+};
+
 static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
                                 const struct amdgpu_video_codecs **codecs)
 {
@@ -112,16 +165,31 @@ static int soc21_query_video_codecs(struct amdgpu_device *adev, bool encode,
        case IP_VERSION(4, 0, 0):
        case IP_VERSION(4, 0, 2):
        case IP_VERSION(4, 0, 4):
-               if (adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) {
-                       if (encode)
-                               *codecs = &vcn_4_0_0_video_codecs_encode_vcn1;
-                       else
-                               *codecs = &vcn_4_0_0_video_codecs_decode_vcn1;
+               if (amdgpu_sriov_vf(adev)) {
+                       if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
+                       !amdgpu_sriov_is_av1_support(adev)) {
+                               if (encode)
+                                       *codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn1;
+                               else
+                                       *codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn1;
+                       } else {
+                               if (encode)
+                                       *codecs = &sriov_vcn_4_0_0_video_codecs_encode_vcn0;
+                               else
+                                       *codecs = &sriov_vcn_4_0_0_video_codecs_decode_vcn0;
+                       }
                } else {
-                       if (encode)
-                               *codecs = &vcn_4_0_0_video_codecs_encode_vcn0;
-                       else
-                               *codecs = &vcn_4_0_0_video_codecs_decode_vcn0;
+                       if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0)) {
+                               if (encode)
+                                       *codecs = &vcn_4_0_0_video_codecs_encode_vcn1;
+                               else
+                                       *codecs = &vcn_4_0_0_video_codecs_decode_vcn1;
+                       } else {
+                               if (encode)
+                                       *codecs = &vcn_4_0_0_video_codecs_encode_vcn0;
+                               else
+                                       *codecs = &vcn_4_0_0_video_codecs_decode_vcn0;
+                       }
                }
                return 0;
        default:
@@ -730,8 +798,23 @@ static int soc21_common_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (amdgpu_sriov_vf(adev))
+       if (amdgpu_sriov_vf(adev)) {
                xgpu_nv_mailbox_get_irq(adev);
+               if ((adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) ||
+               !amdgpu_sriov_is_av1_support(adev)) {
+                       amdgpu_virt_update_sriov_video_codec(adev,
+                                                            sriov_vcn_4_0_0_video_codecs_encode_array_vcn1,
+                                                            ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn1),
+                                                            sriov_vcn_4_0_0_video_codecs_decode_array_vcn1,
+                                                            ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn1));
+               } else {
+                       amdgpu_virt_update_sriov_video_codec(adev,
+                                                            sriov_vcn_4_0_0_video_codecs_encode_array_vcn0,
+                                                            ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_encode_array_vcn0),
+                                                            sriov_vcn_4_0_0_video_codecs_decode_array_vcn0,
+                                                            ARRAY_SIZE(sriov_vcn_4_0_0_video_codecs_decode_array_vcn0));
+               }
+       }
 
        return 0;
 }
index 12ef782eb4785d38d830de14e2d70b58d749a80b..ceab8783575ca701d0df16d6413f8a9b770d5f9a 100644 (file)
 #include "mxgpu_vi.h"
 #include "amdgpu_dm.h"
 
-#if IS_ENABLED(CONFIG_X86)
-#include <asm/intel-family.h>
-#endif
-
 #define ixPCIE_LC_L1_PM_SUBSTATE       0x100100C6
 #define PCIE_LC_L1_PM_SUBSTATE__LC_L1_SUBSTATES_OVERRIDE_EN_MASK       0x00000001L
 #define PCIE_LC_L1_PM_SUBSTATE__LC_PCI_PM_L1_2_OVERRIDE_MASK   0x00000002L
@@ -1138,24 +1134,13 @@ static void vi_enable_aspm(struct amdgpu_device *adev)
                WREG32_PCIE(ixPCIE_LC_CNTL, data);
 }
 
-static bool aspm_support_quirk_check(void)
-{
-#if IS_ENABLED(CONFIG_X86)
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       return !(c->x86 == 6 && c->x86_model == INTEL_FAM6_ALDERLAKE);
-#else
-       return true;
-#endif
-}
-
 static void vi_program_aspm(struct amdgpu_device *adev)
 {
        u32 data, data1, orig;
        bool bL1SS = false;
        bool bClkReqSupport = true;
 
-       if (!amdgpu_device_should_use_aspm(adev) || !aspm_support_quirk_check())
+       if (!amdgpu_device_should_use_aspm(adev) || !amdgpu_device_aspm_support_quirk())
                return;
 
        if (adev->flags & AMD_IS_APU ||
index a0e30f21e12e70a763b0a773895b20daee59b13a..de310ed367ca1dda7c41a437476cf1b70a345677 100644 (file)
@@ -1312,14 +1312,14 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
                args->n_success = i+1;
        }
 
-       mutex_unlock(&p->mutex);
-
        err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true);
        if (err) {
                pr_debug("Sync memory failed, wait interrupted by user signal\n");
                goto sync_memory_failed;
        }
 
+       mutex_unlock(&p->mutex);
+
        /* Flush TLBs after waiting for the page table updates to complete */
        for (i = 0; i < args->n_devices; i++) {
                peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
@@ -1335,9 +1335,9 @@ get_process_device_data_failed:
 bind_process_to_device_failed:
 get_mem_obj_from_handle_failed:
 map_memory_to_gpu_failed:
+sync_memory_failed:
        mutex_unlock(&p->mutex);
 copy_from_user_failed:
-sync_memory_failed:
        kfree(devices_arr);
 
        return err;
@@ -1351,6 +1351,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
        void *mem;
        long err = 0;
        uint32_t *devices_arr = NULL, i;
+       bool flush_tlb;
 
        if (!args->n_devices) {
                pr_debug("Device IDs array empty\n");
@@ -1403,16 +1404,19 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
                }
                args->n_success = i+1;
        }
-       mutex_unlock(&p->mutex);
 
-       if (kfd_flush_tlb_after_unmap(pdd->dev)) {
+       flush_tlb = kfd_flush_tlb_after_unmap(pdd->dev);
+       if (flush_tlb) {
                err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev,
                                (struct kgd_mem *) mem, true);
                if (err) {
                        pr_debug("Sync memory failed, wait interrupted by user signal\n");
                        goto sync_memory_failed;
                }
+       }
+       mutex_unlock(&p->mutex);
 
+       if (flush_tlb) {
                /* Flush TLBs after waiting for the page table updates to complete */
                for (i = 0; i < args->n_devices; i++) {
                        peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
@@ -1428,9 +1432,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
 bind_process_to_device_failed:
 get_mem_obj_from_handle_failed:
 unmap_memory_from_gpu_failed:
+sync_memory_failed:
        mutex_unlock(&p->mutex);
 copy_from_user_failed:
-sync_memory_failed:
        kfree(devices_arr);
        return err;
 }
index 3de7f616a001cf6a8be622f87db2bb286c7e1c3d..ec70a1658dc3871c1dd960af26586a76dbb847a8 100644 (file)
@@ -59,6 +59,7 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
                                unsigned int chunk_size);
 static void kfd_gtt_sa_fini(struct kfd_dev *kfd);
 
+static int kfd_resume_iommu(struct kfd_dev *kfd);
 static int kfd_resume(struct kfd_dev *kfd);
 
 static void kfd_device_info_set_sdma_info(struct kfd_dev *kfd)
@@ -624,7 +625,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
 
        svm_migrate_init(kfd->adev);
 
-       if (kgd2kfd_resume_iommu(kfd))
+       if (kfd_resume_iommu(kfd))
                goto device_iommu_error;
 
        if (kfd_resume(kfd))
@@ -772,6 +773,14 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
 }
 
 int kgd2kfd_resume_iommu(struct kfd_dev *kfd)
+{
+       if (!kfd->init_complete)
+               return 0;
+
+       return kfd_resume_iommu(kfd);
+}
+
+static int kfd_resume_iommu(struct kfd_dev *kfd)
 {
        int err = 0;
 
index de8ce72344fc57f14d3198256f458cfe8891797e..54933903bcb8a3a2547dc31d8354c7b1a31b3850 100644 (file)
@@ -289,7 +289,7 @@ static unsigned long svm_migrate_unsuccessful_pages(struct migrate_vma *migrate)
 static int
 svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
                         struct migrate_vma *migrate, struct dma_fence **mfence,
-                        dma_addr_t *scratch)
+                        dma_addr_t *scratch, uint64_t ttm_res_offset)
 {
        uint64_t npages = migrate->npages;
        struct device *dev = adev->dev;
@@ -299,19 +299,13 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
        uint64_t i, j;
        int r;
 
-       pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
-                prange->last);
+       pr_debug("svms 0x%p [0x%lx 0x%lx 0x%llx]\n", prange->svms, prange->start,
+                prange->last, ttm_res_offset);
 
        src = scratch;
        dst = (uint64_t *)(scratch + npages);
 
-       r = svm_range_vram_node_new(adev, prange, true);
-       if (r) {
-               dev_dbg(adev->dev, "fail %d to alloc vram\n", r);
-               goto out;
-       }
-
-       amdgpu_res_first(prange->ttm_res, prange->offset << PAGE_SHIFT,
+       amdgpu_res_first(prange->ttm_res, ttm_res_offset,
                         npages << PAGE_SHIFT, &cursor);
        for (i = j = 0; i < npages; i++) {
                struct page *spage;
@@ -391,14 +385,14 @@ out_free_vram_pages:
                migrate->dst[i + 3] = 0;
        }
 #endif
-out:
+
        return r;
 }
 
 static long
 svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
                        struct vm_area_struct *vma, uint64_t start,
-                       uint64_t end, uint32_t trigger)
+                       uint64_t end, uint32_t trigger, uint64_t ttm_res_offset)
 {
        struct kfd_process *p = container_of(prange->svms, struct kfd_process, svms);
        uint64_t npages = (end - start) >> PAGE_SHIFT;
@@ -451,7 +445,7 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange,
        else
                pr_debug("0x%lx pages migrated\n", cpages);
 
-       r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch);
+       r = svm_migrate_copy_to_vram(adev, prange, &migrate, &mfence, scratch, ttm_res_offset);
        migrate_vma_pages(&migrate);
 
        pr_debug("successful/cpages/npages 0x%lx/0x%lx/0x%lx\n",
@@ -499,6 +493,7 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
        unsigned long addr, start, end;
        struct vm_area_struct *vma;
        struct amdgpu_device *adev;
+       uint64_t ttm_res_offset;
        unsigned long cpages = 0;
        long r = 0;
 
@@ -520,6 +515,13 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
        start = prange->start << PAGE_SHIFT;
        end = (prange->last + 1) << PAGE_SHIFT;
 
+       r = svm_range_vram_node_new(adev, prange, true);
+       if (r) {
+               dev_dbg(adev->dev, "fail %ld to alloc vram\n", r);
+               return r;
+       }
+       ttm_res_offset = prange->offset << PAGE_SHIFT;
+
        for (addr = start; addr < end;) {
                unsigned long next;
 
@@ -528,18 +530,21 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
                        break;
 
                next = min(vma->vm_end, end);
-               r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger);
+               r = svm_migrate_vma_to_vram(adev, prange, vma, addr, next, trigger, ttm_res_offset);
                if (r < 0) {
                        pr_debug("failed %ld to migrate\n", r);
                        break;
                } else {
                        cpages += r;
                }
+               ttm_res_offset += next - addr;
                addr = next;
        }
 
        if (cpages)
                prange->actual_loc = best_loc;
+       else
+               svm_range_vram_node_free(prange);
 
        return r < 0 ? r : 0;
 }
index 09b966dc376818c08e53020dbea1b0f695f68043..aee2212e52f69aea69b6cd06e476c391713a8a1c 100644 (file)
@@ -77,6 +77,7 @@ err_ioctl:
 
 static void kfd_exit(void)
 {
+       kfd_cleanup_processes();
        kfd_debugfs_fini();
        kfd_process_destroy_wq();
        kfd_procfs_shutdown();
index bfa30d12406b35c7c174a6baa550678e4a31c943..7e4d992e48b3c99495763fbf36508b46fb1e7f78 100644 (file)
@@ -928,6 +928,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev);
 
 int kfd_process_create_wq(void);
 void kfd_process_destroy_wq(void);
+void kfd_cleanup_processes(void);
 struct kfd_process *kfd_create_process(struct file *filep);
 struct kfd_process *kfd_get_process(const struct task_struct *task);
 struct kfd_process *kfd_lookup_process_by_pasid(u32 pasid);
index 7acd55a814b2f32999ba4aa9b68db91da30ccfc7..4208e0f01064dd492e7aa85e28c99622bbee90b4 100644 (file)
@@ -1167,6 +1167,17 @@ static void kfd_process_free_notifier(struct mmu_notifier *mn)
        kfd_unref_process(container_of(mn, struct kfd_process, mmu_notifier));
 }
 
+static void kfd_process_notifier_release_internal(struct kfd_process *p)
+{
+       cancel_delayed_work_sync(&p->eviction_work);
+       cancel_delayed_work_sync(&p->restore_work);
+
+       /* Indicate to other users that MM is no longer valid */
+       p->mm = NULL;
+
+       mmu_notifier_put(&p->mmu_notifier);
+}
+
 static void kfd_process_notifier_release(struct mmu_notifier *mn,
                                        struct mm_struct *mm)
 {
@@ -1181,17 +1192,22 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
                return;
 
        mutex_lock(&kfd_processes_mutex);
+       /*
+        * Do early return if table is empty.
+        *
+        * This could potentially happen if this function is called concurrently
+        * by mmu_notifier and by kfd_cleanup_pocesses.
+        *
+        */
+       if (hash_empty(kfd_processes_table)) {
+               mutex_unlock(&kfd_processes_mutex);
+               return;
+       }
        hash_del_rcu(&p->kfd_processes);
        mutex_unlock(&kfd_processes_mutex);
        synchronize_srcu(&kfd_processes_srcu);
 
-       cancel_delayed_work_sync(&p->eviction_work);
-       cancel_delayed_work_sync(&p->restore_work);
-
-       /* Indicate to other users that MM is no longer valid */
-       p->mm = NULL;
-
-       mmu_notifier_put(&p->mmu_notifier);
+       kfd_process_notifier_release_internal(p);
 }
 
 static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {
@@ -1200,6 +1216,43 @@ static const struct mmu_notifier_ops kfd_process_mmu_notifier_ops = {
        .free_notifier = kfd_process_free_notifier,
 };
 
+/*
+ * This code handles the case when driver is being unloaded before all
+ * mm_struct are released.  We need to safely free the kfd_process and
+ * avoid race conditions with mmu_notifier that might try to free them.
+ *
+ */
+void kfd_cleanup_processes(void)
+{
+       struct kfd_process *p;
+       struct hlist_node *p_temp;
+       unsigned int temp;
+       HLIST_HEAD(cleanup_list);
+
+       /*
+        * Move all remaining kfd_process from the process table to a
+        * temp list for processing.   Once done, callback from mmu_notifier
+        * release will not see the kfd_process in the table and do early return,
+        * avoiding double free issues.
+        */
+       mutex_lock(&kfd_processes_mutex);
+       hash_for_each_safe(kfd_processes_table, temp, p_temp, p, kfd_processes) {
+               hash_del_rcu(&p->kfd_processes);
+               synchronize_srcu(&kfd_processes_srcu);
+               hlist_add_head(&p->kfd_processes, &cleanup_list);
+       }
+       mutex_unlock(&kfd_processes_mutex);
+
+       hlist_for_each_entry_safe(p, p_temp, &cleanup_list, kfd_processes)
+               kfd_process_notifier_release_internal(p);
+
+       /*
+        * Ensures that all outstanding free_notifier get called, triggering
+        * the release of the kfd_process struct.
+        */
+       mmu_notifier_synchronize();
+}
+
 static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep)
 {
        unsigned long  offset;
index 5137476ec18e67d521d0ef590eb6cd8f4de94fd1..4236539d9f932e34c62357767972c53c9498f92a 100644 (file)
@@ -218,8 +218,8 @@ static int init_user_queue(struct process_queue_manager *pqm,
        return 0;
 
 cleanup:
-       if (dev->shared_resources.enable_mes)
-               uninit_queue(*q);
+       uninit_queue(*q);
+       *q = NULL;
        return retval;
 }
 
index 009ef917dad47b3eb1df6c10d82663f7ccac35a6..a01fd41643fc2abd4cc2a058c82498503790e0fe 100644 (file)
@@ -5105,9 +5105,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
 
                for (; flip_addrs->dirty_rect_count < num_clips; clips++)
                        fill_dc_dirty_rect(new_plane_state->plane,
-                                          &dirty_rects[i], clips->x1,
-                                          clips->y1, clips->x2 - clips->x1,
-                                          clips->y2 - clips->y1,
+                                          &dirty_rects[flip_addrs->dirty_rect_count],
+                                          clips->x1, clips->y1,
+                                          clips->x2 - clips->x1, clips->y2 - clips->y1,
                                           &flip_addrs->dirty_rect_count,
                                           false);
                return;
@@ -7244,7 +7244,6 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        if (!aconnector->mst_root)
                drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16);
 
-       /* This defaults to the max in the range, but we want 8bpc for non-edp. */
        aconnector->base.state->max_bpc = 16;
        aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc;
 
index dc4f37240beb4c3a61bfd77386ac548c14be0ebe..8af70feca7205107f03aa1215de09152830210e5 100644 (file)
@@ -169,10 +169,21 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
        if (rc)
                return rc;
 
-       irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
+       if (amdgpu_in_reset(adev)) {
+               irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst;
+               /* During gpu-reset we disable and then enable vblank irq, so
+                * don't use amdgpu_irq_get/put() to avoid refcount change.
+                */
+               if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
+                       rc = -EBUSY;
+       } else {
+               rc = (enable)
+                       ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id)
+                       : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id);
+       }
 
-       if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
-               return -EBUSY;
+       if (rc)
+               return rc;
 
 skip:
        if (amdgpu_in_reset(adev))
index 8e572f07ec476030258036f6538aba733cd1f1d4..4abfd2c9679f456c15c1cb2cb2e9158eb811ba34 100644 (file)
@@ -561,7 +561,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
        link->dp.mst_enabled = config->mst_enabled;
        link->dp.usb4_enabled = config->usb4_enabled;
        display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
-       link->adjust.auth_delay = 0;
+       link->adjust.auth_delay = 2;
        link->adjust.hdcp1.disable = 0;
        conn_state = aconnector->base.state;
 
index 1583157da355b2c7c500ee4b9fb51e7298cd4e71..efd025d8961e682812de5b748e61795e45b7f1cb 100644 (file)
@@ -177,6 +177,40 @@ void dm_helpers_dp_update_branch_info(
        const struct dc_link *link)
 {}
 
+static void dm_helpers_construct_old_payload(
+                       struct dc_link *link,
+                       int pbn_per_slot,
+                       struct drm_dp_mst_atomic_payload *new_payload,
+                       struct drm_dp_mst_atomic_payload *old_payload)
+{
+       struct link_mst_stream_allocation_table current_link_table =
+                                                                       link->mst_stream_alloc_table;
+       struct link_mst_stream_allocation *dc_alloc;
+       int i;
+
+       *old_payload = *new_payload;
+
+       /* Set correct time_slots/PBN of old payload.
+        * other fields (delete & dsc_enabled) in
+        * struct drm_dp_mst_atomic_payload are don't care fields
+        * while calling drm_dp_remove_payload()
+        */
+       for (i = 0; i < current_link_table.stream_count; i++) {
+               dc_alloc =
+                       &current_link_table.stream_allocations[i];
+
+               if (dc_alloc->vcp_id == new_payload->vcpi) {
+                       old_payload->time_slots = dc_alloc->slot_count;
+                       old_payload->pbn = dc_alloc->slot_count * pbn_per_slot;
+                       break;
+               }
+       }
+
+       /* make sure there is an old payload*/
+       ASSERT(i != current_link_table.stream_count);
+
+}
+
 /*
  * Writes payload allocation table in immediate downstream device.
  */
@@ -188,7 +222,7 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
 {
        struct amdgpu_dm_connector *aconnector;
        struct drm_dp_mst_topology_state *mst_state;
-       struct drm_dp_mst_atomic_payload *payload;
+       struct drm_dp_mst_atomic_payload *target_payload, *new_payload, old_payload;
        struct drm_dp_mst_topology_mgr *mst_mgr;
 
        aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
@@ -204,17 +238,26 @@ bool dm_helpers_dp_mst_write_payload_allocation_table(
        mst_state = to_drm_dp_mst_topology_state(mst_mgr->base.state);
 
        /* It's OK for this to fail */
-       payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
-       if (enable)
-               drm_dp_add_payload_part1(mst_mgr, mst_state, payload);
-       else
-               drm_dp_remove_payload(mst_mgr, mst_state, payload, payload);
+       new_payload = drm_atomic_get_mst_payload_state(mst_state, aconnector->mst_output_port);
+
+       if (enable) {
+               target_payload = new_payload;
+
+               drm_dp_add_payload_part1(mst_mgr, mst_state, new_payload);
+       } else {
+               /* construct old payload by VCPI*/
+               dm_helpers_construct_old_payload(stream->link, mst_state->pbn_div,
+                                               new_payload, &old_payload);
+               target_payload = &old_payload;
+
+               drm_dp_remove_payload(mst_mgr, mst_state, &old_payload, new_payload);
+       }
 
        /* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
         * AUX message. The sequence is slot 1-63 allocated sequence for each
         * stream. AMD ASIC stream slot allocation should follow the same
         * sequence. copy DRM MST allocation to dc */
-       fill_dc_mst_payload_table_from_drm(stream->link, enable, payload, proposed_table);
+       fill_dc_mst_payload_table_from_drm(stream->link, enable, target_payload, proposed_table);
 
        return true;
 }
index e25e1b2bf19493b747a623269bb6b967936592d7..8dc442f90eafa14241eb97e29455306200ea298f 100644 (file)
@@ -212,6 +212,21 @@ bool needs_dsc_aux_workaround(struct dc_link *link)
        return false;
 }
 
+bool is_synaptics_cascaded_panamera(struct dc_link *link, struct drm_dp_mst_port *port)
+{
+       u8 branch_vendor_data[4] = { 0 }; // Vendor data 0x50C ~ 0x50F
+
+       if (drm_dp_dpcd_read(port->mgr->aux, DP_BRANCH_VENDOR_SPECIFIC_START, &branch_vendor_data, 4) == 4) {
+               if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
+                               IS_SYNAPTICS_CASCADED_PANAMERA(link->dpcd_caps.branch_dev_name, branch_vendor_data)) {
+                       DRM_INFO("Synaptics Cascaded MST hub\n");
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector)
 {
        struct dc_sink *dc_sink = aconnector->dc_sink;
@@ -235,6 +250,10 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto
            needs_dsc_aux_workaround(aconnector->dc_link))
                aconnector->dsc_aux = &aconnector->mst_root->dm_dp_aux.aux;
 
+       /* synaptics cascaded MST hub case */
+       if (!aconnector->dsc_aux && is_synaptics_cascaded_panamera(aconnector->dc_link, port))
+               aconnector->dsc_aux = port->mgr->aux;
+
        if (!aconnector->dsc_aux)
                return false;
 
@@ -662,12 +681,25 @@ struct dsc_mst_fairness_params {
        struct amdgpu_dm_connector *aconnector;
 };
 
-static int kbps_to_peak_pbn(int kbps)
+static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link)
+{
+       u8 link_coding_cap;
+       uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B;
+
+       link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link);
+       if (link_coding_cap == DP_128b_132b_ENCODING)
+               fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B;
+
+       return fec_overhead_multiplier_x1000;
+}
+
+static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000)
 {
        u64 peak_kbps = kbps;
 
        peak_kbps *= 1006;
-       peak_kbps = div_u64(peak_kbps, 1000);
+       peak_kbps *= fec_overhead_multiplier_x1000;
+       peak_kbps = div_u64(peak_kbps, 1000 * 1000);
        return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000));
 }
 
@@ -761,11 +793,12 @@ static int increase_dsc_bpp(struct drm_atomic_state *state,
        int link_timeslots_used;
        int fair_pbn_alloc;
        int ret = 0;
+       uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
 
        for (i = 0; i < count; i++) {
                if (vars[i + k].dsc_enabled) {
                        initial_slack[i] =
-                       kbps_to_peak_pbn(params[i].bw_range.max_kbps) - vars[i + k].pbn;
+                       kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn;
                        bpp_increased[i] = false;
                        remaining_to_increase += 1;
                } else {
@@ -861,6 +894,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
        int next_index;
        int remaining_to_try = 0;
        int ret;
+       uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
 
        for (i = 0; i < count; i++) {
                if (vars[i + k].dsc_enabled
@@ -890,7 +924,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
                if (next_index == -1)
                        break;
 
-               vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps);
+               vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
                ret = drm_dp_atomic_find_time_slots(state,
                                                    params[next_index].port->mgr,
                                                    params[next_index].port,
@@ -903,7 +937,7 @@ static int try_disable_dsc(struct drm_atomic_state *state,
                        vars[next_index].dsc_enabled = false;
                        vars[next_index].bpp_x16 = 0;
                } else {
-                       vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps);
+                       vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps, fec_overhead_multiplier_x1000);
                        ret = drm_dp_atomic_find_time_slots(state,
                                                            params[next_index].port->mgr,
                                                            params[next_index].port,
@@ -932,6 +966,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        int count = 0;
        int i, k, ret;
        bool debugfs_overwrite = false;
+       uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link);
 
        memset(params, 0, sizeof(params));
 
@@ -993,7 +1028,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        /* Try no compression */
        for (i = 0; i < count; i++) {
                vars[i + k].aconnector = params[i].aconnector;
-               vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
+               vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
                vars[i + k].dsc_enabled = false;
                vars[i + k].bpp_x16 = 0;
                ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port,
@@ -1012,7 +1047,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
        /* Try max compression */
        for (i = 0; i < count; i++) {
                if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) {
-                       vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps);
+                       vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000);
                        vars[i + k].dsc_enabled = true;
                        vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16;
                        ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
@@ -1020,7 +1055,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
                        if (ret < 0)
                                return ret;
                } else {
-                       vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps);
+                       vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000);
                        vars[i + k].dsc_enabled = false;
                        vars[i + k].bpp_x16 = 0;
                        ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr,
index 97fd70df531bf1c4804b23d35301805ae472c8a1..1e4ede1e57abd3f83399f5cb16e2fa42818e9779 100644 (file)
 #define SYNAPTICS_RC_OFFSET        0x4BC
 #define SYNAPTICS_RC_DATA          0x4C0
 
+#define DP_BRANCH_VENDOR_SPECIFIC_START 0x50C
+
+/**
+ * Panamera MST Hub detection
+ * Offset DPCD 050Eh == 0x5A indicates cascaded MST hub case
+ * Check from beginning of branch device vendor specific field (050Ch)
+ */
+#define IS_SYNAPTICS_PANAMERA(branchDevName) (((int)branchDevName[4] & 0xF0) == 0x50 ? 1 : 0)
+#define BRANCH_HW_REVISION_PANAMERA_A2 0x10
+#define SYNAPTICS_CASCADED_HUB_ID  0x5A
+#define IS_SYNAPTICS_CASCADED_PANAMERA(devName, data) ((IS_SYNAPTICS_PANAMERA(devName) && ((int)data[2] == SYNAPTICS_CASCADED_HUB_ID)) ? 1 : 0)
+
+#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B     1031
+#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B  1000
+
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;
 
index 3b4d4d68359bb8f8165ea6b126a3fa6969a6246e..df787fcf8e86e06e17646d09f26cdb938d51a318 100644 (file)
@@ -998,8 +998,5 @@ void dcn30_prepare_bandwidth(struct dc *dc,
                        dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
 
        dcn20_prepare_bandwidth(dc, context);
-
-       dc_dmub_srv_p_state_delegate(dc,
-               context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context);
 }
 
index 54ed3de869d3b001d98d8f8c0ab972fe7d819065..9ffba4c6fe550f3676e587896a8dc2df4f9c971a 100644 (file)
@@ -1697,6 +1697,23 @@ static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_confi
        *panel_config = panel_config_defaults;
 }
 
+static bool filter_modes_for_single_channel_workaround(struct dc *dc,
+               struct dc_state *context)
+{
+       // Filter 2K@240Hz+8K@24fps above combination timing if memory only has single dimm LPDDR
+       if (dc->clk_mgr->bw_params->vram_type == 34 && dc->clk_mgr->bw_params->num_channels < 2) {
+               int total_phy_pix_clk = 0;
+
+               for (int i = 0; i < context->stream_count; i++)
+                       if (context->res_ctx.pipe_ctx[i].stream)
+                               total_phy_pix_clk += context->res_ctx.pipe_ctx[i].stream->phy_pix_clk;
+
+               if (total_phy_pix_clk >= (1148928+826260)) //2K@240Hz+8K@24fps
+                       return true;
+       }
+       return false;
+}
+
 bool dcn314_validate_bandwidth(struct dc *dc,
                struct dc_state *context,
                bool fast_validate)
@@ -1712,6 +1729,9 @@ bool dcn314_validate_bandwidth(struct dc *dc,
 
        BW_VAL_TRACE_COUNT();
 
+       if (filter_modes_for_single_channel_workaround(dc, context))
+               goto validate_fail;
+
        DC_FP_START();
        // do not support self refresh only
        out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, false);
index e4472c6be6c3231a29aa161fcf948f627eb1201f..3fb4bcc343531b6271c4dae8a48802c3426726bf 100644 (file)
@@ -271,8 +271,7 @@ static void dccg32_set_dpstreamclk(
        dccg32_set_dtbclk_p_src(dccg, src, otg_inst);
 
        /* enabled to select one of the DTBCLKs for pipe */
-       switch (otg_inst)
-       {
+       switch (dp_hpo_inst) {
        case 0:
                REG_UPDATE_2(DPSTREAMCLK_CNTL,
                             DPSTREAMCLK0_EN,
index 16f892125b6fac12680d681efa99810bd6847f67..9d14045cccd63e1e2e56307b3e273420d494442a 100644 (file)
@@ -1104,7 +1104,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
                        *k2_div = PIXEL_RATE_DIV_BY_2;
                else
                        *k2_div = PIXEL_RATE_DIV_BY_4;
-       } else if (dc_is_dp_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) {
+       } else if (dc_is_dp_signal(stream->signal)) {
                if (two_pix_per_container) {
                        *k1_div = PIXEL_RATE_DIV_BY_1;
                        *k2_div = PIXEL_RATE_DIV_BY_2;
index 74e50c09bb62f9156a8436d4b86025e5b9b5b8a9..4b7abb4af623599072ec0ede6e300ec82b9c30d8 100644 (file)
@@ -1915,6 +1915,7 @@ int dcn32_populate_dml_pipes_from_context(
        bool subvp_in_use = false;
        uint8_t is_pipe_split_expected[MAX_PIPES] = {0};
        struct dc_crtc_timing *timing;
+       bool vsr_odm_support = false;
 
        dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
 
@@ -1932,12 +1933,15 @@ int dcn32_populate_dml_pipes_from_context(
                timing = &pipe->stream->timing;
 
                pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
+               vsr_odm_support = (res_ctx->pipe_ctx[i].stream->src.width >= 5120 &&
+                               res_ctx->pipe_ctx[i].stream->src.width > res_ctx->pipe_ctx[i].stream->dst.width);
                if (context->stream_count == 1 &&
                                context->stream_status[0].plane_count == 1 &&
                                !dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
                                is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
                                pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
-                               dc->debug.enable_single_display_2to1_odm_policy) {
+                               dc->debug.enable_single_display_2to1_odm_policy &&
+                               !vsr_odm_support) { //excluding 2to1 ODM combine on >= 5k vsr
                        pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1;
                }
                pipe_cnt++;
@@ -2182,6 +2186,7 @@ static bool dcn32_resource_construct(
        dc->caps.edp_dsc_support = true;
        dc->caps.extended_aux_timeout_support = true;
        dc->caps.dmcub_support = true;
+       dc->caps.seamless_odm = true;
 
        /* Color pipeline capabilities */
        dc->caps.color.dpp.dcn_arch = 1;
index b37d14369a622ca27151ac5976e78346f87a1030..59836570603ac6e3aef195b9d62aa8eea92f3b50 100644 (file)
@@ -222,7 +222,7 @@ struct _vcs_dpi_ip_params_st dcn3_15_ip = {
        .maximum_dsc_bits_per_component = 10,
        .dsc422_native_support = false,
        .is_line_buffer_bpp_fixed = true,
-       .line_buffer_fixed_bpp = 49,
+       .line_buffer_fixed_bpp = 48,
        .line_buffer_size_bits = 789504,
        .max_line_buffer_lines = 12,
        .writeback_interface_buffer_size_kbytes = 90,
index 38216c789d7771459162272aa25148497e8a6ea8..f70025ef7b69edfcef5a28e45f384a686cb009a5 100644 (file)
@@ -855,6 +855,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
        struct dc_sink *prev_sink = NULL;
        struct dpcd_caps prev_dpcd_caps;
        enum dc_connection_type new_connection_type = dc_connection_none;
+       enum dc_connection_type pre_connection_type = link->type;
        const uint32_t post_oui_delay = 30; // 30ms
 
        DC_LOGGER_INIT(link->ctx->logger);
@@ -957,6 +958,8 @@ static bool detect_link_and_local_sink(struct dc_link *link,
                        }
 
                        if (!detect_dp(link, &sink_caps, reason)) {
+                               link->type = pre_connection_type;
+
                                if (prev_sink)
                                        dc_sink_release(prev_sink);
                                return false;
@@ -1244,11 +1247,16 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
        bool is_delegated_to_mst_top_mgr = false;
        enum dc_connection_type pre_link_type = link->type;
 
+       DC_LOGGER_INIT(link->ctx->logger);
+
        is_local_sink_detect_success = detect_link_and_local_sink(link, reason);
 
        if (is_local_sink_detect_success && link->local_sink)
                verify_link_capability(link, link->local_sink, reason);
 
+       DC_LOG_DC("%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n", __func__,
+                               link->link_index, is_local_sink_detect_success, pre_link_type, link->type);
+
        if (is_local_sink_detect_success && link->local_sink &&
                        dc_is_dp_signal(link->local_sink->sink_signal) &&
                        link->dpcd_caps.is_mst_capable)
index e39b133d05af4e47f17c8993080160726c8ab3f6..b56f07f99d092bc83819ad7014cbb5492f415483 100644 (file)
@@ -934,6 +934,10 @@ bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
 
        pic_height = stream->timing.v_addressable +
                stream->timing.v_border_top + stream->timing.v_border_bottom;
+
+       if (stream->timing.dsc_cfg.num_slices_v == 0)
+               return false;
+
        slice_height = pic_height / stream->timing.dsc_cfg.num_slices_v;
        config->dsc_slice_height = slice_height;
 
index f77401709d83cccad7e34d4fab6e5a70e81c3af8..2162ecd1057d1c40286644ac4774c0bfb30dcbf9 100644 (file)
@@ -27,7 +27,7 @@
 // *** IMPORTANT ***
 // SMU TEAM: Always increment the interface version if
 // any structure is changed in this file
-#define PMFW_DRIVER_IF_VERSION 7
+#define PMFW_DRIVER_IF_VERSION 8
 
 typedef struct {
   int32_t value;
@@ -198,7 +198,7 @@ typedef struct {
   uint16_t SkinTemp;
   uint16_t DeviceState;
   uint16_t CurTemp;                     //[centi-Celsius]
-  uint16_t spare2;
+  uint16_t FilterAlphaValue;
 
   uint16_t AverageGfxclkFrequency;
   uint16_t AverageFclkFrequency;
index 1c0ae2cb757b8d30fc4974119300e558a521c1b1..85a090b9e3d9745da9e520988f289550c4f2b659 100644 (file)
@@ -29,7 +29,7 @@
 #define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_0 0x37
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x07
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x08
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0_10 0x32
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x37
 #define CTF_OFFSET_HOTSPOT             5
 #define CTF_OFFSET_MEM                 5
 
+static const int pmfw_decoded_link_speed[5] = {1, 2, 3, 4, 5};
+static const int pmfw_decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16};
+
+#define DECODE_GEN_SPEED(gen_speed_idx)                (pmfw_decoded_link_speed[gen_speed_idx])
+#define DECODE_LANE_WIDTH(lane_width_idx)      (pmfw_decoded_link_width[lane_width_idx])
+
 struct smu_13_0_max_sustainable_clocks {
        uint32_t display_clock;
        uint32_t phy_clock;
index 697e98a0a20ab9c5afc74305e2eb5b66e6e34a1e..75f18681e984c33a5c7cf83d7a22aa92b794f3c9 100644 (file)
@@ -2143,16 +2143,9 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)
                (OverDriveTable_t *)smu->smu_table.boot_overdrive_table;
        OverDriveTable_t *user_od_table =
                (OverDriveTable_t *)smu->smu_table.user_overdrive_table;
+       OverDriveTable_t user_od_table_bak;
        int ret = 0;
 
-       /*
-        * For S3/S4/Runpm resume, no need to setup those overdrive tables again as
-        *   - either they already have the default OD settings got during cold bootup
-        *   - or they have some user customized OD settings which cannot be overwritten
-        */
-       if (smu->adev->in_suspend)
-               return 0;
-
        ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE,
                                   0, (void *)boot_od_table, false);
        if (ret) {
@@ -2163,7 +2156,23 @@ static int sienna_cichlid_set_default_od_settings(struct smu_context *smu)
        sienna_cichlid_dump_od_table(smu, boot_od_table);
 
        memcpy(od_table, boot_od_table, sizeof(OverDriveTable_t));
-       memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
+
+       /*
+        * For S3/S4/Runpm resume, we need to setup those overdrive tables again,
+        * but we have to preserve user defined values in "user_od_table".
+        */
+       if (!smu->adev->in_suspend) {
+               memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
+               smu->user_dpm_profile.user_od = false;
+       } else if (smu->user_dpm_profile.user_od) {
+               memcpy(&user_od_table_bak, user_od_table, sizeof(OverDriveTable_t));
+               memcpy(user_od_table, boot_od_table, sizeof(OverDriveTable_t));
+               user_od_table->GfxclkFmin = user_od_table_bak.GfxclkFmin;
+               user_od_table->GfxclkFmax = user_od_table_bak.GfxclkFmax;
+               user_od_table->UclkFmin = user_od_table_bak.UclkFmin;
+               user_od_table->UclkFmax = user_od_table_bak.UclkFmax;
+               user_od_table->VddGfxOffset = user_od_table_bak.VddGfxOffset;
+       }
 
        return 0;
 }
@@ -2373,6 +2382,20 @@ static int sienna_cichlid_od_edit_dpm_table(struct smu_context *smu,
        return ret;
 }
 
+static int sienna_cichlid_restore_user_od_settings(struct smu_context *smu)
+{
+       struct smu_table_context *table_context = &smu->smu_table;
+       OverDriveTable_t *od_table = table_context->overdrive_table;
+       OverDriveTable_t *user_od_table = table_context->user_overdrive_table;
+       int res;
+
+       res = smu_v11_0_restore_user_od_settings(smu);
+       if (res == 0)
+               memcpy(od_table, user_od_table, sizeof(OverDriveTable_t));
+
+       return res;
+}
+
 static int sienna_cichlid_run_btc(struct smu_context *smu)
 {
        int res;
@@ -4400,7 +4423,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
        .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
        .set_default_od_settings = sienna_cichlid_set_default_od_settings,
        .od_edit_dpm_table = sienna_cichlid_od_edit_dpm_table,
-       .restore_user_od_settings = smu_v11_0_restore_user_od_settings,
+       .restore_user_od_settings = sienna_cichlid_restore_user_od_settings,
        .run_btc = sienna_cichlid_run_btc,
        .set_power_source = smu_v11_0_set_power_source,
        .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
index 27448ffe60a43950591badc8a16cbc38ad214fd1..a5c97d61e92a67115208c83e0c59a07c15fdf183 100644 (file)
@@ -1144,8 +1144,8 @@ static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
                                        (pcie_table->pcie_lane[i] == 5) ? "x12" :
                                        (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
                                        pcie_table->clk_freq[i],
-                                       ((gen_speed - 1) == pcie_table->pcie_gen[i]) &&
-                                       (lane_width == link_width[pcie_table->pcie_lane[i]]) ?
+                                       (gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
+                                       (lane_width == DECODE_LANE_WIDTH(link_width[pcie_table->pcie_lane[i]])) ?
                                        "*" : "");
                break;
 
index 9e1967d8049e3a02db79a68563810f713b3292f4..4399416dd9b8f47cadd52b6641edae45a1c6588b 100644 (file)
@@ -575,6 +575,14 @@ static int smu_v13_0_7_set_default_dpm_table(struct smu_context *smu)
                                                     dpm_table);
                if (ret)
                        return ret;
+
+               if (skutable->DriverReportedClocks.GameClockAc &&
+                       (dpm_table->dpm_levels[dpm_table->count - 1].value >
+                       skutable->DriverReportedClocks.GameClockAc)) {
+                       dpm_table->dpm_levels[dpm_table->count - 1].value =
+                               skutable->DriverReportedClocks.GameClockAc;
+                       dpm_table->max = skutable->DriverReportedClocks.GameClockAc;
+               }
        } else {
                dpm_table->count = 1;
                dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
@@ -828,6 +836,57 @@ static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,
        return ret;
 }
 
+static int smu_v13_0_7_get_dpm_ultimate_freq(struct smu_context *smu,
+                                            enum smu_clk_type clk_type,
+                                            uint32_t *min,
+                                            uint32_t *max)
+{
+       struct smu_13_0_dpm_context *dpm_context =
+               smu->smu_dpm.dpm_context;
+       struct smu_13_0_dpm_table *dpm_table;
+
+       switch (clk_type) {
+       case SMU_MCLK:
+       case SMU_UCLK:
+               /* uclk dpm table */
+               dpm_table = &dpm_context->dpm_tables.uclk_table;
+               break;
+       case SMU_GFXCLK:
+       case SMU_SCLK:
+               /* gfxclk dpm table */
+               dpm_table = &dpm_context->dpm_tables.gfx_table;
+               break;
+       case SMU_SOCCLK:
+               /* socclk dpm table */
+               dpm_table = &dpm_context->dpm_tables.soc_table;
+               break;
+       case SMU_FCLK:
+               /* fclk dpm table */
+               dpm_table = &dpm_context->dpm_tables.fclk_table;
+               break;
+       case SMU_VCLK:
+       case SMU_VCLK1:
+               /* vclk dpm table */
+               dpm_table = &dpm_context->dpm_tables.vclk_table;
+               break;
+       case SMU_DCLK:
+       case SMU_DCLK1:
+               /* dclk dpm table */
+               dpm_table = &dpm_context->dpm_tables.dclk_table;
+               break;
+       default:
+               dev_err(smu->adev->dev, "Unsupported clock type!\n");
+               return -EINVAL;
+       }
+
+       if (min)
+               *min = dpm_table->min;
+       if (max)
+               *max = dpm_table->max;
+
+       return 0;
+}
+
 static int smu_v13_0_7_read_sensor(struct smu_context *smu,
                                   enum amd_pp_sensors sensor,
                                   void *data,
@@ -1074,8 +1133,8 @@ static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
                                        (pcie_table->pcie_lane[i] == 5) ? "x12" :
                                        (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
                                        pcie_table->clk_freq[i],
-                                       (gen_speed == pcie_table->pcie_gen[i]) &&
-                                       (lane_width == pcie_table->pcie_lane[i]) ?
+                                       (gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
+                                       (lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
                                        "*" : "");
                break;
 
@@ -1329,9 +1388,17 @@ static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
                                &dpm_context->dpm_tables.fclk_table;
        struct smu_umd_pstate_table *pstate_table =
                                &smu->pstate_table;
+       struct smu_table_context *table_context = &smu->smu_table;
+       PPTable_t *pptable = table_context->driver_pptable;
+       DriverReportedClocks_t driver_clocks =
+               pptable->SkuTable.DriverReportedClocks;
 
        pstate_table->gfxclk_pstate.min = gfx_table->min;
-       pstate_table->gfxclk_pstate.peak = gfx_table->max;
+       if (driver_clocks.GameClockAc &&
+               (driver_clocks.GameClockAc < gfx_table->max))
+               pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc;
+       else
+               pstate_table->gfxclk_pstate.peak = gfx_table->max;
 
        pstate_table->uclk_pstate.min = mem_table->min;
        pstate_table->uclk_pstate.peak = mem_table->max;
@@ -1348,12 +1415,12 @@ static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
        pstate_table->fclk_pstate.min = fclk_table->min;
        pstate_table->fclk_pstate.peak = fclk_table->max;
 
-       /*
-        * For now, just use the mininum clock frequency.
-        * TODO: update them when the real pstate settings available
-        */
-       pstate_table->gfxclk_pstate.standard = gfx_table->min;
-       pstate_table->uclk_pstate.standard = mem_table->min;
+       if (driver_clocks.BaseClockAc &&
+               driver_clocks.BaseClockAc < gfx_table->max)
+               pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc;
+       else
+               pstate_table->gfxclk_pstate.standard = gfx_table->max;
+       pstate_table->uclk_pstate.standard = mem_table->max;
        pstate_table->socclk_pstate.standard = soc_table->min;
        pstate_table->vclk_pstate.standard = vclk_table->min;
        pstate_table->dclk_pstate.standard = dclk_table->min;
@@ -1676,7 +1743,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
        .dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
        .init_pptable_microcode = smu_v13_0_init_pptable_microcode,
        .populate_umd_state_clk = smu_v13_0_7_populate_umd_state_clk,
-       .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq,
+       .get_dpm_ultimate_freq = smu_v13_0_7_get_dpm_ultimate_freq,
        .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
        .read_sensor = smu_v13_0_7_read_sensor,
        .feature_is_enabled = smu_cmn_feature_is_enabled,
index 0643887800b4d33cea277876b604e44a18f76c5c..142668cd6d7cdd079d893a81aa97a459f5838dcc 100644 (file)
@@ -99,7 +99,6 @@ static int armada_drm_bind(struct device *dev)
        if (ret) {
                dev_err(dev, "[" DRM_NAME ":%s] can't kick out simple-fb: %d\n",
                        __func__, ret);
-               kfree(priv);
                return ret;
        }
 
index 2019a8167d693d516b118ae2d1d37ace24276067..b40baced1331666372e98115091e2d08b9ba5a2e 100644 (file)
@@ -676,8 +676,8 @@ static int lt8912_parse_dt(struct lt8912 *lt)
 
        lt->hdmi_port = of_drm_find_bridge(port_node);
        if (!lt->hdmi_port) {
-               dev_err(lt->dev, "%s: Failed to get hdmi port\n", __func__);
-               ret = -ENODEV;
+               ret = -EPROBE_DEFER;
+               dev_err_probe(lt->dev, ret, "%s: Failed to get hdmi port\n", __func__);
                goto err_free_host_node;
        }
 
index 3d1f50f481cfda6d85845c47a95d2218028f6c51..7098f125b54a9a3004ea98345f7ec486cc8ae24a 100644 (file)
@@ -146,8 +146,8 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
                unsigned int order;
                u64 root_size;
 
-               root_size = rounddown_pow_of_two(size);
-               order = ilog2(root_size) - ilog2(chunk_size);
+               order = ilog2(size) - ilog2(chunk_size);
+               root_size = chunk_size << order;
 
                root = drm_block_alloc(mm, NULL, order, offset);
                if (!root)
index 3d0a4da661bc985c5c2b144fecd2d2de80677f26..261a62e1593416e5228b4a859788e798b1e4cf59 100644 (file)
@@ -2796,7 +2796,7 @@ u32 drm_edid_get_panel_id(struct i2c_adapter *adapter)
         * the EDID then we'll just return 0.
         */
 
-       base_block = kmalloc(EDID_LENGTH, GFP_KERNEL);
+       base_block = kzalloc(EDID_LENGTH, GFP_KERNEL);
        if (!base_block)
                return 0;
 
index 7a3cb08dc942e1703b0ab7e2767328d501e44821..a5d392f7e11f6a1bb7ef0578de0f6a6f39e406fd 100644 (file)
@@ -1388,10 +1388,13 @@ EXPORT_SYMBOL(drm_gem_lru_move_tail);
  *
  * @lru: The LRU to scan
  * @nr_to_scan: The number of pages to try to reclaim
+ * @remaining: The number of pages left to reclaim, should be initialized by caller
  * @shrink: Callback to try to shrink/reclaim the object.
  */
 unsigned long
-drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
+drm_gem_lru_scan(struct drm_gem_lru *lru,
+                unsigned int nr_to_scan,
+                unsigned long *remaining,
                 bool (*shrink)(struct drm_gem_object *obj))
 {
        struct drm_gem_lru still_in_lru;
@@ -1430,8 +1433,10 @@ drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
                 * hit shrinker in response to trying to get backing pages
                 * for this obj (ie. while it's lock is already held)
                 */
-               if (!dma_resv_trylock(obj->resv))
+               if (!dma_resv_trylock(obj->resv)) {
+                       *remaining += obj->size >> PAGE_SHIFT;
                        goto tail;
+               }
 
                if (shrink(obj)) {
                        freed += obj->size >> PAGE_SHIFT;
index 75185a960fc408f1042999e4c9b6c04baef6831b..2b2163c8138ef488563c996ff0334cf80add92bb 100644 (file)
@@ -619,11 +619,14 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct
        int ret;
 
        if (obj->import_attach) {
-               /* Drop the reference drm_gem_mmap_obj() acquired.*/
-               drm_gem_object_put(obj);
                vma->vm_private_data = NULL;
+               ret = dma_buf_mmap(obj->dma_buf, vma, 0);
+
+               /* Drop the reference drm_gem_mmap_obj() acquired.*/
+               if (!ret)
+                       drm_gem_object_put(obj);
 
-               return dma_buf_mmap(obj->dma_buf, vma, 0);
+               return ret;
        }
 
        ret = drm_gem_shmem_get_pages(shmem);
index 5522d610c5cfdea29aeb587f93017a55d4224580..b1a38e6ce2f8fad28bbef491a02c29b7257beaa1 100644 (file)
@@ -328,10 +328,17 @@ static const struct dmi_system_id orientation_data[] = {
                  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
                },
                .driver_data = (void *)&lcd1200x1920_rightside_up,
-       }, {    /* Lenovo Yoga Book X90F / X91F / X91L */
+       }, {    /* Lenovo Yoga Book X90F / X90L */
                .matches = {
-                 /* Non exact match to match all versions */
-                 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
+                 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+                 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+               },
+               .driver_data = (void *)&lcd1200x1920_rightside_up,
+       }, {    /* Lenovo Yoga Book X91F / X91L */
+               .matches = {
+                 /* Non exact match to match F + L versions */
+                 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
                },
                .driver_data = (void *)&lcd1200x1920_rightside_up,
        }, {    /* Lenovo Yoga Tablet 2 830F / 830L */
index 44ca803237a5f9c8b43cc92129245beeffc121b9..31a7f59ccb49ee7c552e58991c444dd8754e8582 100644 (file)
@@ -22,7 +22,6 @@
 #include "etnaviv_gem.h"
 #include "etnaviv_mmu.h"
 #include "etnaviv_perfmon.h"
-#include "common.xml.h"
 
 /*
  * DRM operations:
@@ -476,47 +475,7 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
        ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
 };
 
-static void etnaviv_fop_show_fdinfo(struct seq_file *m, struct file *f)
-{
-       struct drm_file *file = f->private_data;
-       struct drm_device *dev = file->minor->dev;
-       struct etnaviv_drm_private *priv = dev->dev_private;
-       struct etnaviv_file_private *ctx = file->driver_priv;
-
-       /*
-        * For a description of the text output format used here, see
-        * Documentation/gpu/drm-usage-stats.rst.
-        */
-       seq_printf(m, "drm-driver:\t%s\n", dev->driver->name);
-       seq_printf(m, "drm-client-id:\t%u\n", ctx->id);
-
-       for (int i = 0; i < ETNA_MAX_PIPES; i++) {
-               struct etnaviv_gpu *gpu = priv->gpu[i];
-               char engine[10] = "UNK";
-               int cur = 0;
-
-               if (!gpu)
-                       continue;
-
-               if (gpu->identity.features & chipFeatures_PIPE_2D)
-                       cur = snprintf(engine, sizeof(engine), "2D");
-               if (gpu->identity.features & chipFeatures_PIPE_3D)
-                       cur = snprintf(engine + cur, sizeof(engine) - cur,
-                                      "%s3D", cur ? "/" : "");
-               if (gpu->identity.nn_core_count > 0)
-                       cur = snprintf(engine + cur, sizeof(engine) - cur,
-                                      "%sNN", cur ? "/" : "");
-
-               seq_printf(m, "drm-engine-%s:\t%llu ns\n", engine,
-                          ctx->sched_entity[i].elapsed_ns);
-       }
-}
-
-static const struct file_operations fops = {
-       .owner = THIS_MODULE,
-       DRM_GEM_FOPS,
-       .show_fdinfo = etnaviv_fop_show_fdinfo,
-};
+DEFINE_DRM_GEM_FOPS(fops);
 
 static const struct drm_driver etnaviv_drm_driver = {
        .driver_features    = DRIVER_GEM | DRIVER_RENDER,
index 7031db145a77a1c33c9175914dc57489abd03342..3524b5811682af447d6809a8dd10c4d736c7b372 100644 (file)
@@ -91,7 +91,15 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
 static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
                struct vm_area_struct *vma)
 {
-       return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+       int ret;
+
+       ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+       if (!ret) {
+               /* Drop the reference acquired by drm_gem_mmap_obj(). */
+               drm_gem_object_put(&etnaviv_obj->base);
+       }
+
+       return ret;
 }
 
 static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
index 468a792e6a405a7f3b18bec607704d1e0c7740ef..fc0eaf40dc941745d43181d60f27db0b6a0f9d64 100644 (file)
@@ -300,9 +300,21 @@ static void configure_dual_link_mode(struct intel_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
+       i915_reg_t dss_ctl1_reg, dss_ctl2_reg;
        u32 dss_ctl1;
 
-       dss_ctl1 = intel_de_read(dev_priv, DSS_CTL1);
+       /* FIXME: Move all DSS handling to intel_vdsc.c */
+       if (DISPLAY_VER(dev_priv) >= 12) {
+               struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
+
+               dss_ctl1_reg = ICL_PIPE_DSS_CTL1(crtc->pipe);
+               dss_ctl2_reg = ICL_PIPE_DSS_CTL2(crtc->pipe);
+       } else {
+               dss_ctl1_reg = DSS_CTL1;
+               dss_ctl2_reg = DSS_CTL2;
+       }
+
+       dss_ctl1 = intel_de_read(dev_priv, dss_ctl1_reg);
        dss_ctl1 |= SPLITTER_ENABLE;
        dss_ctl1 &= ~OVERLAP_PIXELS_MASK;
        dss_ctl1 |= OVERLAP_PIXELS(intel_dsi->pixel_overlap);
@@ -323,16 +335,16 @@ static void configure_dual_link_mode(struct intel_encoder *encoder,
 
                dss_ctl1 &= ~LEFT_DL_BUF_TARGET_DEPTH_MASK;
                dss_ctl1 |= LEFT_DL_BUF_TARGET_DEPTH(dl_buffer_depth);
-               dss_ctl2 = intel_de_read(dev_priv, DSS_CTL2);
+               dss_ctl2 = intel_de_read(dev_priv, dss_ctl2_reg);
                dss_ctl2 &= ~RIGHT_DL_BUF_TARGET_DEPTH_MASK;
                dss_ctl2 |= RIGHT_DL_BUF_TARGET_DEPTH(dl_buffer_depth);
-               intel_de_write(dev_priv, DSS_CTL2, dss_ctl2);
+               intel_de_write(dev_priv, dss_ctl2_reg, dss_ctl2);
        } else {
                /* Interleave */
                dss_ctl1 |= DUAL_LINK_MODE_INTERLEAVE;
        }
 
-       intel_de_write(dev_priv, DSS_CTL1, dss_ctl1);
+       intel_de_write(dev_priv, dss_ctl1_reg, dss_ctl1);
 }
 
 /* aka DSI 8X clock */
index 8d97c299e6577b786dc39aa881e184b386b1ccd9..bd598a7f5047de31d7ded149926ba4c59f4532e1 100644 (file)
@@ -46,6 +46,11 @@ struct intel_color_funcs {
         * registers involved with the same commit.
         */
        void (*color_commit_arm)(const struct intel_crtc_state *crtc_state);
+       /*
+        * Perform any extra tasks needed after all the
+        * double buffered registers have been latched.
+        */
+       void (*color_post_update)(const struct intel_crtc_state *crtc_state);
        /*
         * Load LUTs (and other single buffered color management
         * registers). Will (hopefully) be called during the vblank
@@ -614,9 +619,33 @@ static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
 
 static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
 {
+       /*
+        * Despite Wa_1406463849, ICL no longer suffers from the SKL
+        * DC5/PSR CSC black screen issue (see skl_color_commit_noarm()).
+        * Possibly due to the extra sticky CSC arming
+        * (see icl_color_post_update()).
+        *
+        * On TGL+ all CSC arming issues have been properly fixed.
+        */
        icl_load_csc_matrix(crtc_state);
 }
 
+static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
+{
+       /*
+        * Possibly related to display WA #1184, SKL CSC loses the latched
+        * CSC coeff/offset register values if the CSC registers are disarmed
+        * between DC5 exit and PSR exit. This will cause the plane(s) to
+        * output all black (until CSC_MODE is rearmed and properly latched).
+        * Once PSR exit (and proper register latching) has occurred the
+        * danger is over. Thus when PSR is enabled the CSC coeff/offset
+        * register programming will be peformed from skl_color_commit_arm()
+        * which is called after PSR exit.
+        */
+       if (!crtc_state->has_psr)
+               ilk_load_csc_matrix(crtc_state);
+}
+
 static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
 {
        ilk_load_csc_matrix(crtc_state);
@@ -659,6 +688,9 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
        enum pipe pipe = crtc->pipe;
        u32 val = 0;
 
+       if (crtc_state->has_psr)
+               ilk_load_csc_matrix(crtc_state);
+
        /*
         * We don't (yet) allow userspace to control the pipe background color,
         * so force it to black, but apply pipe gamma and CSC appropriately
@@ -677,6 +709,47 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
                          crtc_state->csc_mode);
 }
 
+static void icl_color_commit_arm(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+       enum pipe pipe = crtc->pipe;
+
+       /*
+        * We don't (yet) allow userspace to control the pipe background color,
+        * so force it to black.
+        */
+       intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), 0);
+
+       intel_de_write(i915, GAMMA_MODE(crtc->pipe),
+                      crtc_state->gamma_mode);
+
+       intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
+                         crtc_state->csc_mode);
+}
+
+static void icl_color_post_update(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+       struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+
+       /*
+        * Despite Wa_1406463849, ICL CSC is no longer disarmed by
+        * coeff/offset register *writes*. Instead, once CSC_MODE
+        * is armed it stays armed, even after it has been latched.
+        * Afterwards the coeff/offset registers become effectively
+        * self-arming. That self-arming must be disabled before the
+        * next icl_color_commit_noarm() tries to write the next set
+        * of coeff/offset registers. Fortunately register *reads*
+        * do still disarm the CSC. Naturally this must not be done
+        * until the previously written CSC registers have actually
+        * been latched.
+        *
+        * TGL+ no longer need this workaround.
+        */
+       intel_de_read_fw(i915, PIPE_CSC_PREOFF_HI(crtc->pipe));
+}
+
 static struct drm_property_blob *
 create_linear_lut(struct drm_i915_private *i915, int lut_size)
 {
@@ -1373,6 +1446,14 @@ void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
        i915->display.funcs.color->color_commit_arm(crtc_state);
 }
 
+void intel_color_post_update(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+       if (i915->display.funcs.color->color_post_update)
+               i915->display.funcs.color->color_post_update(crtc_state);
+}
+
 void intel_color_prepare_commit(struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
@@ -3064,10 +3145,20 @@ static const struct intel_color_funcs i9xx_color_funcs = {
        .lut_equal = i9xx_lut_equal,
 };
 
+static const struct intel_color_funcs tgl_color_funcs = {
+       .color_check = icl_color_check,
+       .color_commit_noarm = icl_color_commit_noarm,
+       .color_commit_arm = icl_color_commit_arm,
+       .load_luts = icl_load_luts,
+       .read_luts = icl_read_luts,
+       .lut_equal = icl_lut_equal,
+};
+
 static const struct intel_color_funcs icl_color_funcs = {
        .color_check = icl_color_check,
        .color_commit_noarm = icl_color_commit_noarm,
-       .color_commit_arm = skl_color_commit_arm,
+       .color_commit_arm = icl_color_commit_arm,
+       .color_post_update = icl_color_post_update,
        .load_luts = icl_load_luts,
        .read_luts = icl_read_luts,
        .lut_equal = icl_lut_equal,
@@ -3075,7 +3166,7 @@ static const struct intel_color_funcs icl_color_funcs = {
 
 static const struct intel_color_funcs glk_color_funcs = {
        .color_check = glk_color_check,
-       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_noarm = skl_color_commit_noarm,
        .color_commit_arm = skl_color_commit_arm,
        .load_luts = glk_load_luts,
        .read_luts = glk_read_luts,
@@ -3084,7 +3175,7 @@ static const struct intel_color_funcs glk_color_funcs = {
 
 static const struct intel_color_funcs skl_color_funcs = {
        .color_check = ivb_color_check,
-       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_noarm = skl_color_commit_noarm,
        .color_commit_arm = skl_color_commit_arm,
        .load_luts = bdw_load_luts,
        .read_luts = bdw_read_luts,
@@ -3180,7 +3271,9 @@ void intel_color_init_hooks(struct drm_i915_private *i915)
                else
                        i915->display.funcs.color = &i9xx_color_funcs;
        } else {
-               if (DISPLAY_VER(i915) >= 11)
+               if (DISPLAY_VER(i915) >= 12)
+                       i915->display.funcs.color = &tgl_color_funcs;
+               else if (DISPLAY_VER(i915) == 11)
                        i915->display.funcs.color = &icl_color_funcs;
                else if (DISPLAY_VER(i915) == 10)
                        i915->display.funcs.color = &glk_color_funcs;
index d620b5b1e2a6ebdc68e98d16c65b3ccaa7e84c09..8002492be709096aec9169c4e89483d8ccac112f 100644 (file)
@@ -21,6 +21,7 @@ void intel_color_prepare_commit(struct intel_crtc_state *crtc_state);
 void intel_color_cleanup_commit(struct intel_crtc_state *crtc_state);
 void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
 void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
+void intel_color_post_update(const struct intel_crtc_state *crtc_state);
 void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
 void intel_color_get_config(struct intel_crtc_state *crtc_state);
 bool intel_color_lut_equal(const struct intel_crtc_state *crtc_state,
index 82be0fbe99342bf901b9473f5f95afe4fedd8b2c..d5b5d40ed817f264fcd0c0219d22bd931caca2f5 100644 (file)
@@ -683,6 +683,14 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
         */
        intel_vrr_send_push(new_crtc_state);
 
+       /*
+        * Seamless M/N update may need to update frame timings.
+        *
+        * FIXME Should be synchronized with the start of vblank somehow...
+        */
+       if (new_crtc_state->seamless_m_n && intel_crtc_needs_fastset(new_crtc_state))
+               intel_crtc_update_active_timings(new_crtc_state);
+
        local_irq_enable();
 
        if (intel_vgpu_active(dev_priv))
index d3994e2a7d6362e77dd50a67f6f2ad070a328f2f..63b4b73f47c6aaf9b235d62f1032806aa59110c2 100644 (file)
@@ -1209,6 +1209,9 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
        if (needs_cursorclk_wa(old_crtc_state) &&
            !needs_cursorclk_wa(new_crtc_state))
                icl_wa_cursorclkgating(dev_priv, pipe, false);
+
+       if (intel_crtc_needs_color_update(new_crtc_state))
+               intel_color_post_update(new_crtc_state);
 }
 
 static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -5145,6 +5148,7 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state,
         * only fields that are know to not cause problems are preserved. */
 
        saved_state->uapi = crtc_state->uapi;
+       saved_state->inherited = crtc_state->inherited;
        saved_state->scaler_state = crtc_state->scaler_state;
        saved_state->shared_dpll = crtc_state->shared_dpll;
        saved_state->dpll_hw_state = crtc_state->dpll_hw_state;
@@ -7090,6 +7094,8 @@ static void intel_update_crtc(struct intel_atomic_state *state,
 
        intel_fbc_update(state, crtc);
 
+       drm_WARN_ON(&i915->drm, !intel_display_power_is_enabled(i915, POWER_DOMAIN_DC_OFF));
+
        if (!modeset &&
            intel_crtc_needs_color_update(new_crtc_state))
                intel_color_commit_noarm(new_crtc_state);
@@ -7457,8 +7463,28 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
        drm_atomic_helper_wait_for_dependencies(&state->base);
        drm_dp_mst_atomic_wait_for_dependencies(&state->base);
 
-       if (state->modeset)
-               wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
+       /*
+        * During full modesets we write a lot of registers, wait
+        * for PLLs, etc. Doing that while DC states are enabled
+        * is not a good idea.
+        *
+        * During fastsets and other updates we also need to
+        * disable DC states due to the following scenario:
+        * 1. DC5 exit and PSR exit happen
+        * 2. Some or all _noarm() registers are written
+        * 3. Due to some long delay PSR is re-entered
+        * 4. DC5 entry -> DMC saves the already written new
+        *    _noarm() registers and the old not yet written
+        *    _arm() registers
+        * 5. DC5 exit -> DMC restores a mixture of old and
+        *    new register values and arms the update
+        * 6. PSR exit -> hardware latches a mixture of old and
+        *    new register values -> corrupted frame, or worse
+        * 7. New _arm() registers are finally written
+        * 8. Hardware finally latches a complete set of new
+        *    register values, and subsequent frames will be OK again
+        */
+       wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DC_OFF);
 
        intel_atomic_prepare_plane_clear_colors(state);
 
@@ -7607,8 +7633,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
                 * the culprit.
                 */
                intel_uncore_arm_unclaimed_mmio_detection(&dev_priv->uncore);
-               intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET, wakeref);
        }
+       intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, wakeref);
        intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref);
 
        /*
index 54c517ca9632fb1be3150c40a3935cbbbf63956c..582234f0c49ace7bb3af97a86565c130a28a52eb 100644 (file)
@@ -1631,6 +1631,8 @@ struct intel_psr {
        bool psr2_sel_fetch_cff_enabled;
        bool req_psr2_sdp_prior_scanline;
        u8 sink_sync_latency;
+       u8 io_wake_lines;
+       u8 fast_wake_lines;
        ktime_t last_entry_attempt;
        ktime_t last_exit;
        bool sink_not_reliable;
index 257aa2b7cf2045d116a98088f8fa6db5a36935dd..3485d5e6dd3c75d21d4dfe9abcf4d7d369f67260 100644 (file)
@@ -384,15 +384,12 @@ static void disable_all_event_handlers(struct drm_i915_private *i915)
        }
 }
 
-static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
+static void adlp_pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
 {
        enum pipe pipe;
 
-       if (DISPLAY_VER(i915) < 13)
-               return;
-
        /*
-        * Wa_16015201720:adl-p,dg2, mtl
+        * Wa_16015201720:adl-p,dg2
         * The WA requires clock gating to be disabled all the time
         * for pipe A and B.
         * For pipe C and D clock gating needs to be disabled only
@@ -408,6 +405,25 @@ static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
                                     PIPEDMC_GATING_DIS, 0);
 }
 
+static void mtl_pipedmc_clock_gating_wa(struct drm_i915_private *i915)
+{
+       /*
+        * Wa_16015201720
+        * The WA requires clock gating to be disabled all the time
+        * for pipe A and B.
+        */
+       intel_de_rmw(i915, GEN9_CLKGATE_DIS_0, 0,
+                    MTL_PIPEDMC_GATING_DIS_A | MTL_PIPEDMC_GATING_DIS_B);
+}
+
+static void pipedmc_clock_gating_wa(struct drm_i915_private *i915, bool enable)
+{
+       if (DISPLAY_VER(i915) >= 14 && enable)
+               mtl_pipedmc_clock_gating_wa(i915);
+       else if (DISPLAY_VER(i915) == 13)
+               adlp_pipedmc_clock_gating_wa(i915, enable);
+}
+
 void intel_dmc_enable_pipe(struct drm_i915_private *i915, enum pipe pipe)
 {
        if (!has_dmc_id_fw(i915, PIPE_TO_DMC_ID(pipe)))
index 5a176bfb10a2b009f9438500548d7a5f1204e57c..30c98810e28bba338603e789152b8d52906b6119 100644 (file)
@@ -163,7 +163,7 @@ static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
              DP_AUX_CH_CTL_TIME_OUT_MAX |
              DP_AUX_CH_CTL_RECEIVE_ERROR |
              (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-             DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
+             DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(24) |
              DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
 
        if (intel_tc_port_in_tbt_alt_mode(dig_port))
index 054a009e800d77e39fdbdd7d94e48f6266779348..7c9b328bc2d733e22f2a4d9012de3a90d636acd4 100644 (file)
@@ -232,7 +232,7 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
                        return slots;
        }
 
-       intel_link_compute_m_n(crtc_state->pipe_bpp,
+       intel_link_compute_m_n(crtc_state->dsc.compressed_bpp,
                               crtc_state->lane_count,
                               adjusted_mode->crtc_clock,
                               crtc_state->port_clock,
@@ -265,6 +265,19 @@ static int intel_dp_mst_update_slots(struct intel_encoder *encoder,
        return 0;
 }
 
+static bool intel_dp_mst_has_audio(const struct drm_connector_state *conn_state)
+{
+       const struct intel_digital_connector_state *intel_conn_state =
+               to_intel_digital_connector_state(conn_state);
+       struct intel_connector *connector =
+               to_intel_connector(conn_state->connector);
+
+       if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
+               return connector->port->has_audio;
+       else
+               return intel_conn_state->force_audio == HDMI_AUDIO_ON;
+}
+
 static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
                                       struct intel_crtc_state *pipe_config,
                                       struct drm_connector_state *conn_state)
@@ -272,10 +285,6 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_dp *intel_dp = &intel_mst->primary->dp;
-       struct intel_connector *connector =
-               to_intel_connector(conn_state->connector);
-       struct intel_digital_connector_state *intel_conn_state =
-               to_intel_digital_connector_state(conn_state);
        const struct drm_display_mode *adjusted_mode =
                &pipe_config->hw.adjusted_mode;
        struct link_config_limits limits;
@@ -287,11 +296,9 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
        pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
        pipe_config->has_pch_encoder = false;
 
-       if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
-               pipe_config->has_audio = connector->port->has_audio;
-       else
-               pipe_config->has_audio =
-                       intel_conn_state->force_audio == HDMI_AUDIO_ON;
+       pipe_config->has_audio =
+               intel_dp_mst_has_audio(conn_state) &&
+               intel_audio_compute_config(encoder, pipe_config, conn_state);
 
        /*
         * for MST we always configure max link bw - the spec doesn't
index ad1a37b515fb1c8991d1832bd99a2d301bc15c20..2a9f40a2b3ed0b75e9d95e087f7532f2f05f99c0 100644 (file)
@@ -301,6 +301,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
        vm->pte_encode = gen8_ggtt_pte_encode;
 
        dpt->obj = dpt_obj;
+       dpt->obj->is_dpt = true;
 
        return &dpt->vm;
 }
@@ -309,5 +310,6 @@ void intel_dpt_destroy(struct i915_address_space *vm)
 {
        struct i915_dpt *dpt = i915_vm_to_dpt(vm);
 
+       dpt->obj->is_dpt = false;
        i915_vm_put(&dpt->vm);
 }
index f76b06293eb94293f222fa64cd3c67f664302862..38825b30db16cc3a87ce84756ec4e089b3c662f1 100644 (file)
@@ -210,6 +210,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
        bool prealloc = false;
        void __iomem *vaddr;
        struct drm_i915_gem_object *obj;
+       struct i915_gem_ww_ctx ww;
        int ret;
 
        mutex_lock(&ifbdev->hpd_lock);
@@ -283,13 +284,24 @@ static int intelfb_create(struct drm_fb_helper *helper,
                info->fix.smem_len = vma->size;
        }
 
-       vaddr = i915_vma_pin_iomap(vma);
-       if (IS_ERR(vaddr)) {
-               drm_err(&dev_priv->drm,
-                       "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
-               ret = PTR_ERR(vaddr);
-               goto out_unpin;
+       for_i915_gem_ww(&ww, ret, false) {
+               ret = i915_gem_object_lock(vma->obj, &ww);
+
+               if (ret)
+                       continue;
+
+               vaddr = i915_vma_pin_iomap(vma);
+               if (IS_ERR(vaddr)) {
+                       drm_err(&dev_priv->drm,
+                               "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
+                       ret = PTR_ERR(vaddr);
+                       continue;
+               }
        }
+
+       if (ret)
+               goto out_unpin;
+
        info->screen_base = vaddr;
        info->screen_size = vma->size;
 
index 7a72e15e68369f2e2bdbf58afabd48ab06c5de68..9f1a0bebae24086964adc83bbacee3668a174105 100644 (file)
@@ -542,6 +542,14 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
        val |= EDP_PSR2_FRAME_BEFORE_SU(max_t(u8, intel_dp->psr.sink_sync_latency + 1, 2));
        val |= intel_psr2_get_tp_time(intel_dp);
 
+       if (DISPLAY_VER(dev_priv) >= 12) {
+               if (intel_dp->psr.io_wake_lines < 9 &&
+                   intel_dp->psr.fast_wake_lines < 9)
+                       val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2;
+               else
+                       val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_3;
+       }
+
        /* Wa_22012278275:adl-p */
        if (IS_ADLP_DISPLAY_STEP(dev_priv, STEP_A0, STEP_E0)) {
                static const u8 map[] = {
@@ -558,31 +566,21 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
                 * Still using the default IO_BUFFER_WAKE and FAST_WAKE, see
                 * comments bellow for more information
                 */
-               u32 tmp, lines = 7;
-
-               val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2;
+               u32 tmp;
 
-               tmp = map[lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
+               tmp = map[intel_dp->psr.io_wake_lines - TGL_EDP_PSR2_IO_BUFFER_WAKE_MIN_LINES];
                tmp = tmp << TGL_EDP_PSR2_IO_BUFFER_WAKE_SHIFT;
                val |= tmp;
 
-               tmp = map[lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
+               tmp = map[intel_dp->psr.fast_wake_lines - TGL_EDP_PSR2_FAST_WAKE_MIN_LINES];
                tmp = tmp << TGL_EDP_PSR2_FAST_WAKE_MIN_SHIFT;
                val |= tmp;
        } else if (DISPLAY_VER(dev_priv) >= 12) {
-               /*
-                * TODO: 7 lines of IO_BUFFER_WAKE and FAST_WAKE are default
-                * values from BSpec. In order to setting an optimal power
-                * consumption, lower than 4k resolution mode needs to decrease
-                * IO_BUFFER_WAKE and FAST_WAKE. And higher than 4K resolution
-                * mode needs to increase IO_BUFFER_WAKE and FAST_WAKE.
-                */
-               val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2;
-               val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(7);
-               val |= TGL_EDP_PSR2_FAST_WAKE(7);
+               val |= TGL_EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines);
+               val |= TGL_EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines);
        } else if (DISPLAY_VER(dev_priv) >= 9) {
-               val |= EDP_PSR2_IO_BUFFER_WAKE(7);
-               val |= EDP_PSR2_FAST_WAKE(7);
+               val |= EDP_PSR2_IO_BUFFER_WAKE(intel_dp->psr.io_wake_lines);
+               val |= EDP_PSR2_FAST_WAKE(intel_dp->psr.fast_wake_lines);
        }
 
        if (intel_dp->psr.req_psr2_sdp_prior_scanline)
@@ -842,6 +840,46 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d
        return true;
 }
 
+static bool _compute_psr2_wake_times(struct intel_dp *intel_dp,
+                                    struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+       int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time;
+       u8 max_wake_lines;
+
+       if (DISPLAY_VER(i915) >= 12) {
+               io_wake_time = 42;
+               /*
+                * According to Bspec it's 42us, but based on testing
+                * it is not enough -> use 45 us.
+                */
+               fast_wake_time = 45;
+               max_wake_lines = 12;
+       } else {
+               io_wake_time = 50;
+               fast_wake_time = 32;
+               max_wake_lines = 8;
+       }
+
+       io_wake_lines = intel_usecs_to_scanlines(
+               &crtc_state->uapi.adjusted_mode, io_wake_time);
+       fast_wake_lines = intel_usecs_to_scanlines(
+               &crtc_state->uapi.adjusted_mode, fast_wake_time);
+
+       if (io_wake_lines > max_wake_lines ||
+           fast_wake_lines > max_wake_lines)
+               return false;
+
+       if (i915->params.psr_safest_params)
+               io_wake_lines = fast_wake_lines = max_wake_lines;
+
+       /* According to Bspec lower limit should be set as 7 lines. */
+       intel_dp->psr.io_wake_lines = max(io_wake_lines, 7);
+       intel_dp->psr.fast_wake_lines = max(fast_wake_lines, 7);
+
+       return true;
+}
+
 static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
                                    struct intel_crtc_state *crtc_state)
 {
@@ -936,6 +974,12 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
                return false;
        }
 
+       if (!_compute_psr2_wake_times(intel_dp, crtc_state)) {
+               drm_dbg_kms(&dev_priv->drm,
+                           "PSR2 not enabled, Unable to use long enough wake times\n");
+               return false;
+       }
+
        if (HAS_PSR2_SEL_FETCH(dev_priv)) {
                if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) &&
                    !HAS_PSR_HW_TRACKING(dev_priv)) {
index c65c771f5c461f018bcc4620809782571109eea0..1cfb94b5cedbdfa757f0a16e3f25f73e5d28e37c 100644 (file)
@@ -1419,6 +1419,36 @@ static const struct intel_mpllb_state dg2_hdmi_262750 = {
                REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
 };
 
+static const struct intel_mpllb_state dg2_hdmi_267300 = {
+       .clock = 267300,
+       .ref_control =
+               REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+       .mpllb_cp =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+       .mpllb_div =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3),
+       .mpllb_div2 =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 74) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+       .mpllb_fracn1 =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535),
+       .mpllb_fracn2 =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 30146) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 36699),
+       .mpllb_sscen =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
 static const struct intel_mpllb_state dg2_hdmi_268500 = {
        .clock = 268500,
        .ref_control =
@@ -1509,6 +1539,36 @@ static const struct intel_mpllb_state dg2_hdmi_241500 = {
                REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
 };
 
+static const struct intel_mpllb_state dg2_hdmi_319890 = {
+       .clock = 319890,
+       .ref_control =
+               REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3),
+       .mpllb_cp =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124),
+       .mpllb_div =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2),
+       .mpllb_div2 =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 94) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1),
+       .mpllb_fracn1 =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535),
+       .mpllb_fracn2 =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 64094) |
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13631),
+       .mpllb_sscen =
+               REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1),
+};
+
 static const struct intel_mpllb_state dg2_hdmi_497750 = {
        .clock = 497750,
        .ref_control =
@@ -1696,8 +1756,10 @@ static const struct intel_mpllb_state * const dg2_hdmi_tables[] = {
        &dg2_hdmi_209800,
        &dg2_hdmi_241500,
        &dg2_hdmi_262750,
+       &dg2_hdmi_267300,
        &dg2_hdmi_268500,
        &dg2_hdmi_296703,
+       &dg2_hdmi_319890,
        &dg2_hdmi_497750,
        &dg2_hdmi_592000,
        &dg2_hdmi_593407,
index f45328712bff1bd582dc8bf4ad2c825923c4cee9..be510b9c0d07e21772ece0ad8e5c6ae257fc78e2 100644 (file)
@@ -418,9 +418,9 @@ static bool icl_tc_phy_is_owned(struct intel_digital_port *dig_port)
        val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
        if (val == 0xffffffff) {
                drm_dbg_kms(&i915->drm,
-                           "Port %s: PHY in TCCOLD, assume safe mode\n",
+                           "Port %s: PHY in TCCOLD, assume not owned\n",
                            dig_port->tc_port_name);
-               return true;
+               return false;
        }
 
        return val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
index 8949fb0a944f6b5a5ea7dd7abd7d2d3cff2f77d5..3198b64ad7dbc3da80b3c33b52492f12dbea9579 100644 (file)
@@ -127,7 +127,8 @@ i915_gem_object_create_lmem_from_data(struct drm_i915_private *i915,
 
        memcpy(map, data, size);
 
-       i915_gem_object_unpin_map(obj);
+       i915_gem_object_flush_map(obj);
+       __i915_gem_object_release_map(obj);
 
        return obj;
 }
index f9a8acbba715e191fee09cc384a425d34f57bacb..885ccde9dc3c0fde4bf313beb82ecf13055bd3f2 100644 (file)
@@ -303,7 +303,7 @@ i915_gem_object_never_mmap(const struct drm_i915_gem_object *obj)
 static inline bool
 i915_gem_object_is_framebuffer(const struct drm_i915_gem_object *obj)
 {
-       return READ_ONCE(obj->frontbuffer);
+       return READ_ONCE(obj->frontbuffer) || obj->is_dpt;
 }
 
 static inline unsigned int
index 19c9bdd8f905f0cbec9ba3d40fa32334c0efd2b5..5dcbbef31d44556b2eb8a1a86df8acd0c733638c 100644 (file)
@@ -491,6 +491,9 @@ struct drm_i915_gem_object {
         */
        unsigned int cache_dirty:1;
 
+       /* @is_dpt: Object houses a display page table (DPT) */
+       unsigned int is_dpt:1;
+
        /**
         * @read_domains: Read memory domains.
         *
index 7420276827a5b7eb61414b6af0b3fa0ed1236c82..4758f21c91e15ea25931527aa8e556217ff59edb 100644 (file)
@@ -1067,11 +1067,12 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
                        .interruptible = true,
                        .no_wait_gpu = true, /* should be idle already */
                };
+               int err;
 
                GEM_BUG_ON(!bo->ttm || !(bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED));
 
-               ret = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);
-               if (ret) {
+               err = ttm_bo_validate(bo, i915_ttm_sys_placement(), &ctx);
+               if (err) {
                        dma_resv_unlock(bo->base.resv);
                        return VM_FAULT_SIGBUS;
                }
index 1bbe6708d0a7f4001747d8bc6b5eb3a12c26162e..750326434677f1703f1c21b8e015a1436fa05f40 100644 (file)
@@ -2018,6 +2018,8 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
         * inspecting the queue to see if we need to resumbit.
         */
        if (*prev != *execlists->active) { /* elide lite-restores */
+               struct intel_context *prev_ce = NULL, *active_ce = NULL;
+
                /*
                 * Note the inherent discrepancy between the HW runtime,
                 * recorded as part of the context switch, and the CPU
@@ -2029,9 +2031,15 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive)
                 * and correct overselves later when updating from HW.
                 */
                if (*prev)
-                       lrc_runtime_stop((*prev)->context);
+                       prev_ce = (*prev)->context;
                if (*execlists->active)
-                       lrc_runtime_start((*execlists->active)->context);
+                       active_ce = (*execlists->active)->context;
+               if (prev_ce != active_ce) {
+                       if (prev_ce)
+                               lrc_runtime_stop(prev_ce);
+                       if (active_ce)
+                               lrc_runtime_start(active_ce);
+               }
                new_timeslice(execlists);
        }
 
index f0dbfc434e077357729e3e3f3f9c9ac50d9e5125..40d357cf8b042f835f9c96943d3b7b0cc5b068d9 100644 (file)
@@ -737,12 +737,12 @@ int intel_gt_init(struct intel_gt *gt)
        if (err)
                goto err_gt;
 
-       intel_uc_init_late(&gt->uc);
-
        err = i915_inject_probe_error(gt->i915, -EIO);
        if (err)
                goto err_gt;
 
+       intel_uc_init_late(&gt->uc);
+
        intel_migrate_init(&gt->migrate, gt);
 
        goto out_fw;
index cef3d6f5c34e0130b4943d48a456c75da31b275e..56b993f6e7dc9337aa98d24b08748606d9e8a922 100644 (file)
 #include "intel_rc6.h"
 #include "intel_rps.h"
 #include "intel_wakeref.h"
-#include "intel_pcode.h"
 #include "pxp/intel_pxp_pm.h"
 
 #define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2)
 
-static void mtl_media_busy(struct intel_gt *gt)
-{
-       /* Wa_14017073508: mtl */
-       if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
-           gt->type == GT_MEDIA)
-               snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE,
-                                 PCODE_MBOX_GT_STATE_MEDIA_BUSY,
-                                 PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0);
-}
-
-static void mtl_media_idle(struct intel_gt *gt)
-{
-       /* Wa_14017073508: mtl */
-       if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
-           gt->type == GT_MEDIA)
-               snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE,
-                                 PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY,
-                                 PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0);
-}
-
 static void user_forcewake(struct intel_gt *gt, bool suspend)
 {
        int count = atomic_read(&gt->user_wakeref);
@@ -93,9 +72,6 @@ static int __gt_unpark(struct intel_wakeref *wf)
 
        GT_TRACE(gt, "\n");
 
-       /* Wa_14017073508: mtl */
-       mtl_media_busy(gt);
-
        /*
         * It seems that the DMC likes to transition between the DC states a lot
         * when there are no connected displays (no active power domains) during
@@ -145,9 +121,6 @@ static int __gt_park(struct intel_wakeref *wf)
        GEM_BUG_ON(!wakeref);
        intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
 
-       /* Wa_14017073508: mtl */
-       mtl_media_idle(gt);
-
        return 0;
 }
 
index 83df4cd5e06cb929f09d79a6a3f14bfb373e38c7..80dbbef86b1dbf2313311bbe82df2a651179120a 100644 (file)
@@ -580,7 +580,7 @@ static bool perf_limit_reasons_eval(void *data)
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(perf_limit_reasons_fops, perf_limit_reasons_get,
-                       perf_limit_reasons_clear, "%llu\n");
+                       perf_limit_reasons_clear, "0x%llx\n");
 
 void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root)
 {
index 5c91622dfca420bc37c7c200b9e20927a14ca720..f4150f61f39c0be7cae48e67fc3430a7640ce0c1 100644 (file)
@@ -486,6 +486,7 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6)
 static bool rc6_supported(struct intel_rc6 *rc6)
 {
        struct drm_i915_private *i915 = rc6_to_i915(rc6);
+       struct intel_gt *gt = rc6_to_gt(rc6);
 
        if (!HAS_RC6(i915))
                return false;
@@ -502,6 +503,13 @@ static bool rc6_supported(struct intel_rc6 *rc6)
                return false;
        }
 
+       if (IS_MTL_MEDIA_STEP(gt->i915, STEP_A0, STEP_B0) &&
+           gt->type == GT_MEDIA) {
+               drm_notice(&i915->drm,
+                          "Media RC6 disabled on A step\n");
+               return false;
+       }
+
        return true;
 }
 
index f5d7b51264331386623fcf8c1efedc9fec6a3792..2c92fa9d194271a7b2a6e5afb57c28b057febba2 100644 (file)
@@ -2075,16 +2075,6 @@ void intel_rps_sanitize(struct intel_rps *rps)
                rps_disable_interrupts(rps);
 }
 
-u32 intel_rps_read_rpstat_fw(struct intel_rps *rps)
-{
-       struct drm_i915_private *i915 = rps_to_i915(rps);
-       i915_reg_t rpstat;
-
-       rpstat = (GRAPHICS_VER(i915) >= 12) ? GEN12_RPSTAT1 : GEN6_RPSTAT1;
-
-       return intel_uncore_read_fw(rps_to_gt(rps)->uncore, rpstat);
-}
-
 u32 intel_rps_read_rpstat(struct intel_rps *rps)
 {
        struct drm_i915_private *i915 = rps_to_i915(rps);
@@ -2095,7 +2085,7 @@ u32 intel_rps_read_rpstat(struct intel_rps *rps)
        return intel_uncore_read(rps_to_gt(rps)->uncore, rpstat);
 }
 
-u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)
+static u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)
 {
        struct drm_i915_private *i915 = rps_to_i915(rps);
        u32 cagf;
@@ -2118,10 +2108,11 @@ u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)
        return cagf;
 }
 
-static u32 read_cagf(struct intel_rps *rps)
+static u32 __read_cagf(struct intel_rps *rps, bool take_fw)
 {
        struct drm_i915_private *i915 = rps_to_i915(rps);
        struct intel_uncore *uncore = rps_to_uncore(rps);
+       i915_reg_t r = INVALID_MMIO_REG;
        u32 freq;
 
        /*
@@ -2129,22 +2120,30 @@ static u32 read_cagf(struct intel_rps *rps)
         * registers will return 0 freq when GT is in RC6
         */
        if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) {
-               freq = intel_uncore_read(uncore, MTL_MIRROR_TARGET_WP1);
+               r = MTL_MIRROR_TARGET_WP1;
        } else if (GRAPHICS_VER(i915) >= 12) {
-               freq = intel_uncore_read(uncore, GEN12_RPSTAT1);
+               r = GEN12_RPSTAT1;
        } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
                vlv_punit_get(i915);
                freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
                vlv_punit_put(i915);
        } else if (GRAPHICS_VER(i915) >= 6) {
-               freq = intel_uncore_read(uncore, GEN6_RPSTAT1);
+               r = GEN6_RPSTAT1;
        } else {
-               freq = intel_uncore_read(uncore, MEMSTAT_ILK);
+               r = MEMSTAT_ILK;
        }
 
+       if (i915_mmio_reg_valid(r))
+               freq = take_fw ? intel_uncore_read(uncore, r) : intel_uncore_read_fw(uncore, r);
+
        return intel_rps_get_cagf(rps, freq);
 }
 
+static u32 read_cagf(struct intel_rps *rps)
+{
+       return __read_cagf(rps, true);
+}
+
 u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
 {
        struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm;
@@ -2157,7 +2156,12 @@ u32 intel_rps_read_actual_frequency(struct intel_rps *rps)
        return freq;
 }
 
-u32 intel_rps_read_punit_req(struct intel_rps *rps)
+u32 intel_rps_read_actual_frequency_fw(struct intel_rps *rps)
+{
+       return intel_gpu_freq(rps, __read_cagf(rps, false));
+}
+
+static u32 intel_rps_read_punit_req(struct intel_rps *rps)
 {
        struct intel_uncore *uncore = rps_to_uncore(rps);
        struct intel_runtime_pm *rpm = rps_to_uncore(rps)->rpm;
index c622962c6befb369bb81b5bd02163bca0d0e92fa..a3fa987aa91f132e9aa6013683e09a6dfcf5710b 100644 (file)
@@ -37,8 +37,8 @@ void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive);
 
 int intel_gpu_freq(struct intel_rps *rps, int val);
 int intel_freq_opcode(struct intel_rps *rps, int val);
-u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat1);
 u32 intel_rps_read_actual_frequency(struct intel_rps *rps);
+u32 intel_rps_read_actual_frequency_fw(struct intel_rps *rps);
 u32 intel_rps_get_requested_frequency(struct intel_rps *rps);
 u32 intel_rps_get_min_frequency(struct intel_rps *rps);
 u32 intel_rps_get_min_raw_freq(struct intel_rps *rps);
@@ -49,10 +49,8 @@ int intel_rps_set_max_frequency(struct intel_rps *rps, u32 val);
 u32 intel_rps_get_rp0_frequency(struct intel_rps *rps);
 u32 intel_rps_get_rp1_frequency(struct intel_rps *rps);
 u32 intel_rps_get_rpn_frequency(struct intel_rps *rps);
-u32 intel_rps_read_punit_req(struct intel_rps *rps);
 u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps);
 u32 intel_rps_read_rpstat(struct intel_rps *rps);
-u32 intel_rps_read_rpstat_fw(struct intel_rps *rps);
 void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps);
 void intel_rps_raise_unslice(struct intel_rps *rps);
 void intel_rps_lower_unslice(struct intel_rps *rps);
index aa87d3832d60d92539413d6cc5f840873c65696a..d7e8c374f153e01ed26d46e3bdb3bd90a72d0651 100644 (file)
@@ -27,7 +27,7 @@ struct drm_printer;
  * is only relevant to pre-Xe_HP platforms (Xe_HP and beyond use the
  * I915_MAX_SS_FUSE_BITS value below).
  */
-#define GEN_MAX_SS_PER_HSW_SLICE       6
+#define GEN_MAX_SS_PER_HSW_SLICE       8
 
 /*
  * Maximum number of 32-bit registers used by hardware to express the
index fc3b994626a4fdc9f3d61fee47c23d304d3a5189..710999d7189ee3537f7436495e3ef70b7182fed4 100644 (file)
@@ -1571,6 +1571,27 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf,
 
 #endif //CONFIG_DRM_I915_CAPTURE_ERROR
 
+static void guc_capture_find_ecode(struct intel_engine_coredump *ee)
+{
+       struct gcap_reg_list_info *reginfo;
+       struct guc_mmio_reg *regs;
+       i915_reg_t reg_ipehr = RING_IPEHR(0);
+       i915_reg_t reg_instdone = RING_INSTDONE(0);
+       int i;
+
+       if (!ee->guc_capture_node)
+               return;
+
+       reginfo = ee->guc_capture_node->reginfo + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE;
+       regs = reginfo->regs;
+       for (i = 0; i < reginfo->num_regs; i++) {
+               if (regs[i].offset == reg_ipehr.reg)
+                       ee->ipehr = regs[i].value;
+               else if (regs[i].offset == reg_instdone.reg)
+                       ee->instdone.instdone = regs[i].value;
+       }
+}
+
 void intel_guc_capture_free_node(struct intel_engine_coredump *ee)
 {
        if (!ee || !ee->guc_capture_node)
@@ -1612,6 +1633,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt,
                        list_del(&n->link);
                        ee->guc_capture_node = n;
                        ee->guc_capture = guc->capture;
+                       guc_capture_find_ecode(ee);
                        return;
                }
        }
index b5855091cf6a92af7f6a14f0896d59f25a6fe8a4..8f8dd05835c5aaf766e0f70ccbba6a3c85904dda 100644 (file)
 
 static bool __guc_rc_supported(struct intel_guc *guc)
 {
-       struct intel_gt *gt = guc_to_gt(guc);
-
-       /*
-        * Wa_14017073508: mtl
-        * Do not enable gucrc to avoid additional interrupts which
-        * may disrupt pcode wa.
-        */
-       if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
-           gt->type == GT_MEDIA)
-               return false;
-
        /* GuC RC is unavailable for pre-Gen12 */
        return guc->submission_supported &&
-               GRAPHICS_VER(gt->i915) >= 12;
+               GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
 }
 
 static bool __guc_rc_selected(struct intel_guc *guc)
index 410905da8e974465cd4b42fb2cef87ff0a4c1ed6..0c103ca160d10de2811b9c78146b5ccd0d3ec071 100644 (file)
@@ -235,6 +235,13 @@ static void delayed_huc_load_fini(struct intel_huc *huc)
        i915_sw_fence_fini(&huc->delayed_load.fence);
 }
 
+int intel_huc_sanitize(struct intel_huc *huc)
+{
+       delayed_huc_load_complete(huc);
+       intel_uc_fw_sanitize(&huc->fw);
+       return 0;
+}
+
 static bool vcs_supported(struct intel_gt *gt)
 {
        intel_engine_mask_t mask = gt->info.engine_mask;
index 52db03620c609ab69302e50f2ba64fc3e42709b6..db555b3c1f56272c424728906f3c3aa3b4d1dfe1 100644 (file)
@@ -41,6 +41,7 @@ struct intel_huc {
        } delayed_load;
 };
 
+int intel_huc_sanitize(struct intel_huc *huc);
 void intel_huc_init_early(struct intel_huc *huc);
 int intel_huc_init(struct intel_huc *huc);
 void intel_huc_fini(struct intel_huc *huc);
@@ -54,12 +55,6 @@ bool intel_huc_is_authenticated(struct intel_huc *huc);
 void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
 void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
 
-static inline int intel_huc_sanitize(struct intel_huc *huc)
-{
-       intel_uc_fw_sanitize(&huc->fw);
-       return 0;
-}
-
 static inline bool intel_huc_is_supported(struct intel_huc *huc)
 {
        return intel_uc_fw_is_supported(&huc->fw);
index 7412abf166a8c366e2711a120ca9b65acc5294e7..8ef93889061a6367e3558137a816efa0e32599da 100644 (file)
@@ -92,8 +92,7 @@ static void debug_active_init(struct i915_active *ref)
 static void debug_active_activate(struct i915_active *ref)
 {
        lockdep_assert_held(&ref->tree_lock);
-       if (!atomic_read(&ref->count)) /* before the first inc */
-               debug_object_activate(ref, &active_debug_desc);
+       debug_object_activate(ref, &active_debug_desc);
 }
 
 static void debug_active_deactivate(struct i915_active *ref)
@@ -422,12 +421,12 @@ replace_barrier(struct i915_active *ref, struct i915_active_fence *active)
         * we can use it to substitute for the pending idle-barrer
         * request that we want to emit on the kernel_context.
         */
-       __active_del_barrier(ref, node_from_active(active));
-       return true;
+       return __active_del_barrier(ref, node_from_active(active));
 }
 
 int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)
 {
+       u64 idx = i915_request_timeline(rq)->fence_context;
        struct dma_fence *fence = &rq->fence;
        struct i915_active_fence *active;
        int err;
@@ -437,16 +436,19 @@ int i915_active_add_request(struct i915_active *ref, struct i915_request *rq)
        if (err)
                return err;
 
-       active = active_instance(ref, i915_request_timeline(rq)->fence_context);
-       if (!active) {
-               err = -ENOMEM;
-               goto out;
-       }
+       do {
+               active = active_instance(ref, idx);
+               if (!active) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+
+               if (replace_barrier(ref, active)) {
+                       RCU_INIT_POINTER(active->fence, NULL);
+                       atomic_dec(&ref->count);
+               }
+       } while (unlikely(is_barrier(active)));
 
-       if (replace_barrier(ref, active)) {
-               RCU_INIT_POINTER(active->fence, NULL);
-               atomic_dec(&ref->count);
-       }
        if (!__i915_active_fence_set(active, fence))
                __i915_active_acquire(ref);
 
index 824a34ec0b83889e6075c4f6371023848f5534ed..0040749363001c0e6ce6edd5dafd004f03d74b84 100644 (file)
@@ -1592,9 +1592,7 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
        /*
         * Wa_16011777198:dg2: Unset the override of GUCRC mode to enable rc6.
         */
-       if (intel_uc_uses_guc_rc(&gt->uc) &&
-           (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_C0) ||
-            IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_B0)))
+       if (stream->override_gucrc)
                drm_WARN_ON(&gt->i915->drm,
                            intel_guc_slpc_unset_gucrc_mode(&gt->uc.guc.slpc));
 
@@ -3305,8 +3303,10 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
                if (ret) {
                        drm_dbg(&stream->perf->i915->drm,
                                "Unable to override gucrc mode\n");
-                       goto err_config;
+                       goto err_gucrc;
                }
+
+               stream->override_gucrc = true;
        }
 
        ret = alloc_oa_buffer(stream);
@@ -3345,11 +3345,15 @@ err_enable:
        free_oa_buffer(stream);
 
 err_oa_buf_alloc:
-       free_oa_configs(stream);
+       if (stream->override_gucrc)
+               intel_guc_slpc_unset_gucrc_mode(&gt->uc.guc.slpc);
 
+err_gucrc:
        intel_uncore_forcewake_put(stream->uncore, FORCEWAKE_ALL);
        intel_engine_pm_put(stream->engine);
 
+       free_oa_configs(stream);
+
 err_config:
        free_noa_wait(stream);
 
@@ -4634,13 +4638,13 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data,
                err = oa_config->id;
                goto sysfs_err;
        }
-
-       mutex_unlock(&perf->metrics_lock);
+       id = oa_config->id;
 
        drm_dbg(&perf->i915->drm,
                "Added config %s id=%i\n", oa_config->uuid, oa_config->id);
+       mutex_unlock(&perf->metrics_lock);
 
-       return oa_config->id;
+       return id;
 
 sysfs_err:
        mutex_unlock(&perf->metrics_lock);
index ca150b7af3f29a5b2c72b017705c3a1f40e6f6af..4d5d8c365d9e2e4629d6b4ddc288acdda34d0f9c 100644 (file)
@@ -316,6 +316,12 @@ struct i915_perf_stream {
         * buffer should be checked for available data.
         */
        u64 poll_oa_period;
+
+       /**
+        * @override_gucrc: GuC RC has been overridden for the perf stream,
+        * and we need to restore the default configuration on release.
+        */
+       bool override_gucrc;
 };
 
 /**
index 52531ab28c5f5530538769a3a7e8febf1025363f..6d422b056f8a8e5a94b697d95a59265939d6d148 100644 (file)
@@ -393,14 +393,12 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
                 * case we assume the system is running at the intended
                 * frequency. Fortunately, the read should rarely fail!
                 */
-               val = intel_rps_read_rpstat_fw(rps);
-               if (val)
-                       val = intel_rps_get_cagf(rps, val);
-               else
-                       val = rps->cur_freq;
+               val = intel_rps_read_actual_frequency_fw(rps);
+               if (!val)
+                       val = intel_gpu_freq(rps, rps->cur_freq);
 
                add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT],
-                               intel_gpu_freq(rps, val), period_ns / 1000);
+                               val, period_ns / 1000);
        }
 
        if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
index 3b2642397b8288f617fcfb291516409a3ae0b9ea..747b53b567a091fa2e8a65d1899d3c167e6167f3 100644 (file)
  * GEN9 clock gating regs
  */
 #define GEN9_CLKGATE_DIS_0             _MMIO(0x46530)
-#define   DARBF_GATING_DIS             (1 << 27)
-#define   PWM2_GATING_DIS              (1 << 14)
-#define   PWM1_GATING_DIS              (1 << 13)
+#define   DARBF_GATING_DIS             REG_BIT(27)
+#define   MTL_PIPEDMC_GATING_DIS_A     REG_BIT(15)
+#define   MTL_PIPEDMC_GATING_DIS_B     REG_BIT(14)
+#define   PWM2_GATING_DIS              REG_BIT(14)
+#define   PWM1_GATING_DIS              REG_BIT(13)
 
 #define GEN9_CLKGATE_DIS_3             _MMIO(0x46538)
 #define   TGL_VRH_GATING_DIS           REG_BIT(31)
 /*   XEHP_PCODE_FREQUENCY_CONFIG param2 */
 #define     PCODE_MBOX_DOMAIN_NONE             0x0
 #define     PCODE_MBOX_DOMAIN_MEDIAFF          0x3
-
-/* Wa_14017210380: mtl */
-#define   PCODE_MBOX_GT_STATE                  0x50
-/* sub-commands (param1) */
-#define     PCODE_MBOX_GT_STATE_MEDIA_BUSY     0x1
-#define     PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY 0x2
-/* param2 */
-#define     PCODE_MBOX_GT_STATE_DOMAIN_MEDIA   0x1
-
 #define GEN6_PCODE_DATA                                _MMIO(0x138128)
 #define   GEN6_PCODE_FREQ_IA_RATIO_SHIFT       8
 #define   GEN6_PCODE_FREQ_RING_RATIO_SHIFT     16
index 79bfe3938d3c6abfd6829f6435ab98167dcdc490..7caf937c3c90d6b7d74456d7f276871ec8527547 100644 (file)
@@ -325,23 +325,23 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
 
        ret = meson_encoder_hdmi_init(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = meson_plane_create(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = meson_overlay_create(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = meson_crtc_create(priv);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        ret = request_irq(priv->vsync_irq, meson_irq, 0, drm->driver->name, drm);
        if (ret)
-               goto exit_afbcd;
+               goto unbind_all;
 
        drm_mode_config_reset(drm);
 
@@ -359,6 +359,9 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
 
 uninstall_irq:
        free_irq(priv->vsync_irq, drm);
+unbind_all:
+       if (has_components)
+               component_unbind_all(drm->dev, drm);
 exit_afbcd:
        if (priv->afbcd.ops)
                priv->afbcd.ops->exit(priv);
index 534621a13a34d28140541e8d881dafb24f64a78a..3d046878ce6cb74f5a3662e795e091be9d7b4b75 100644 (file)
@@ -718,7 +718,7 @@ static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
        dw_plat_data = &meson_dw_hdmi->dw_plat_data;
 
        ret = devm_regulator_get_enable_optional(dev, "hdmi");
-       if (ret < 0)
+       if (ret < 0 && ret != -ENODEV)
                return ret;
 
        meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
index 154837688ab0d17b98f61d81918b99edb3441621..5df1957c8e41f4e438545f91dd9eecb423e53b91 100644 (file)
@@ -100,6 +100,8 @@ void meson_vpp_init(struct meson_drm *priv)
                               priv->io_base + _REG(VPP_DOLBY_CTRL));
                writel_relaxed(0x1020080,
                                priv->io_base + _REG(VPP_DUMMY_DATA1));
+               writel_relaxed(0x42020,
+                               priv->io_base + _REG(VPP_DUMMY_DATA));
        } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
                writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
 
index 051bdbc093cf99657b44671a12a317fcd5fefd96..f38296ad87434eca9aead0f47b47d0c4bcc896cf 100644 (file)
@@ -107,6 +107,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
                bool (*shrink)(struct drm_gem_object *obj);
                bool cond;
                unsigned long freed;
+               unsigned long remaining;
        } stages[] = {
                /* Stages of progressively more aggressive/expensive reclaim: */
                { &priv->lru.dontneed, purge,        true },
@@ -116,14 +117,18 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
        };
        long nr = sc->nr_to_scan;
        unsigned long freed = 0;
+       unsigned long remaining = 0;
 
        for (unsigned i = 0; (nr > 0) && (i < ARRAY_SIZE(stages)); i++) {
                if (!stages[i].cond)
                        continue;
                stages[i].freed =
-                       drm_gem_lru_scan(stages[i].lru, nr, stages[i].shrink);
+                       drm_gem_lru_scan(stages[i].lru, nr,
+                                       &stages[i].remaining,
+                                        stages[i].shrink);
                nr -= stages[i].freed;
                freed += stages[i].freed;
+               remaining += stages[i].remaining;
        }
 
        if (freed) {
@@ -132,7 +137,7 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
                                     stages[3].freed);
        }
 
-       return (freed > 0) ? freed : SHRINK_STOP;
+       return (freed > 0 && remaining > 0) ? freed : SHRINK_STOP;
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -182,10 +187,12 @@ msm_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr)
                NULL,
        };
        unsigned idx, unmapped = 0;
+       unsigned long remaining = 0;
 
        for (idx = 0; lrus[idx] && unmapped < vmap_shrink_limit; idx++) {
                unmapped += drm_gem_lru_scan(lrus[idx],
                                             vmap_shrink_limit - unmapped,
+                                            &remaining,
                                             vmap_shrink);
        }
 
index ed9d374147b8d11614c3c175f1b659b82607b56c..5bb777ff13130853e9742fefb4e58a44f97356a5 100644 (file)
@@ -363,6 +363,35 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
        return 0;
 }
 
+static void
+nv50_outp_atomic_fix_depth(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state)
+{
+       struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+       struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+       struct drm_display_mode *mode = &asyh->state.adjusted_mode;
+       unsigned int max_rate, mode_rate;
+
+       switch (nv_encoder->dcb->type) {
+       case DCB_OUTPUT_DP:
+               max_rate = nv_encoder->dp.link_nr * nv_encoder->dp.link_bw;
+
+               /* we don't support more than 10 anyway */
+               asyh->or.bpc = min_t(u8, asyh->or.bpc, 10);
+
+               /* reduce the bpc until it works out */
+               while (asyh->or.bpc > 6) {
+                       mode_rate = DIV_ROUND_UP(mode->clock * asyh->or.bpc * 3, 8);
+                       if (mode_rate <= max_rate)
+                               break;
+
+                       asyh->or.bpc -= 2;
+               }
+               break;
+       default:
+               break;
+       }
+}
+
 static int
 nv50_outp_atomic_check(struct drm_encoder *encoder,
                       struct drm_crtc_state *crtc_state,
@@ -381,6 +410,9 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
        if (crtc_state->mode_changed || crtc_state->connectors_changed)
                asyh->or.bpc = connector->display_info.bpc;
 
+       /* We might have to reduce the bpc */
+       nv50_outp_atomic_fix_depth(encoder, crtc_state);
+
        return 0;
 }
 
index 40409a29f5b69cb8dad01d136de0f6b85fed11e7..91b5ecc57538083f7be573fbc25ec3a91ce0c9dd 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/apple-gmux.h>
 #include <linux/backlight.h>
 #include <linux/idr.h>
+#include <drm/drm_probe_helper.h>
 
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
@@ -299,8 +300,12 @@ nv50_backlight_init(struct nouveau_backlight *bl,
        struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
        struct nvif_object *device = &drm->client.device.object;
 
+       /*
+        * Note when this runs the connectors have not been probed yet,
+        * so nv_conn->base.status is not set yet.
+        */
        if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)) ||
-           nv_conn->base.status != connector_status_connected)
+           drm_helper_probe_detect(&nv_conn->base, NULL, false) != connector_status_connected)
                return -ENODEV;
 
        if (nv_conn->type == DCB_CONNECTOR_eDP) {
index e00876f92aeea582c13642664b4774cf4c5726c8..d49b4875fc3c934fe4d6cd87c0d3b1b3b997088f 100644 (file)
@@ -263,8 +263,6 @@ nouveau_dp_irq(struct work_struct *work)
 }
 
 /* TODO:
- * - Use the minimum possible BPC here, once we add support for the max bpc
- *   property.
  * - Validate against the DP caps advertised by the GPU (we don't check these
  *   yet)
  */
@@ -276,7 +274,11 @@ nv50_dp_mode_valid(struct drm_connector *connector,
 {
        const unsigned int min_clock = 25000;
        unsigned int max_rate, mode_rate, ds_max_dotclock, clock = mode->clock;
-       const u8 bpp = connector->display_info.bpc * 3;
+       /* Check with the minmum bpc always, so we can advertise better modes.
+        * In particlar not doing this causes modes to be dropped on HDR
+        * displays as we might check with a bpc of 16 even.
+        */
+       const u8 bpp = 6 * 3;
 
        if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace)
                return MODE_NO_INTERLACE;
index f77e44958037e02459940f3d9413a957e391b293..ab9062e5097770be99ff6fefc7f6faddc9085738 100644 (file)
@@ -645,7 +645,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
                                struct drm_nouveau_gem_pushbuf_reloc *reloc,
                                struct drm_nouveau_gem_pushbuf_bo *bo)
 {
-       long ret = 0;
+       int ret = 0;
        unsigned i;
 
        for (i = 0; i < req->nr_relocs; i++) {
@@ -653,6 +653,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
                struct drm_nouveau_gem_pushbuf_bo *b;
                struct nouveau_bo *nvbo;
                uint32_t data;
+               long lret;
 
                if (unlikely(r->bo_index >= req->nr_buffers)) {
                        NV_PRINTK(err, cli, "reloc bo index invalid\n");
@@ -703,13 +704,18 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
                                data |= r->vor;
                }
 
-               ret = dma_resv_wait_timeout(nvbo->bo.base.resv,
-                                           DMA_RESV_USAGE_BOOKKEEP,
-                                           false, 15 * HZ);
-               if (ret == 0)
+               lret = dma_resv_wait_timeout(nvbo->bo.base.resv,
+                                            DMA_RESV_USAGE_BOOKKEEP,
+                                            false, 15 * HZ);
+               if (!lret)
                        ret = -EBUSY;
+               else if (lret > 0)
+                       ret = 0;
+               else
+                       ret = lret;
+
                if (ret) {
-                       NV_PRINTK(err, cli, "reloc wait_idle failed: %ld\n",
+                       NV_PRINTK(err, cli, "reloc wait_idle failed: %d\n",
                                  ret);
                        break;
                }
index 76678dd60f93f9fd7373615776d73266abbe7344..c4c6f67af7ccc817a48e6dd84d3faee7d3c45e05 100644 (file)
@@ -31,6 +31,7 @@ gf108_fb = {
        .init = gf100_fb_init,
        .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
+       .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
        .ram_new = gf108_ram_new,
        .default_bigpage = 17,
 };
index f73442ccb424b491461054cb30abe87aaf6f8520..433fa966ba2319119d1140eb7cba2d7e02cc7483 100644 (file)
@@ -77,6 +77,7 @@ gk104_fb = {
        .init = gf100_fb_init,
        .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
+       .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
        .ram_new = gk104_ram_new,
        .default_bigpage = 17,
        .clkgate_pack = gk104_fb_clkgate_pack,
index 45d6cdffafeedc5f326bc45556357d882531f7d9..4dc283dedf8b5b383446ccdfa560bd15ca558297 100644 (file)
@@ -59,6 +59,7 @@ gk110_fb = {
        .init = gf100_fb_init,
        .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
+       .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
        .ram_new = gk104_ram_new,
        .default_bigpage = 17,
        .clkgate_pack = gk110_fb_clkgate_pack,
index de52462a92bf0ecd2b85a509091800e7b9761444..90bfff616d35bb539efd77d8fc49eab163fee089 100644 (file)
@@ -31,6 +31,7 @@ gm107_fb = {
        .init = gf100_fb_init,
        .init_page = gf100_fb_init_page,
        .intr = gf100_fb_intr,
+       .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
        .ram_new = gm107_ram_new,
        .default_bigpage = 17,
 };
index 4e83a1891f3edc493ac3c5b9bbe1b7eab8b5b52b..e961fa27702ce61f8675f6b63b6ef4dfd1496e05 100644 (file)
@@ -282,7 +282,7 @@ static void panfrost_mmu_flush_range(struct panfrost_device *pfdev,
        if (pm_runtime_active(pfdev->dev))
                mmu_hw_do_operation(pfdev, mmu, iova, size, AS_COMMAND_FLUSH_PT);
 
-       pm_runtime_put_sync_autosuspend(pfdev->dev);
+       pm_runtime_put_autosuspend(pfdev->dev);
 }
 
 static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu,
@@ -504,6 +504,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
                if (IS_ERR(pages[i])) {
                        mutex_unlock(&bo->base.pages_lock);
                        ret = PTR_ERR(pages[i]);
+                       pages[i] = NULL;
                        goto err_pages;
                }
        }
index ba3b817895091fc285c965c518ad3ed614d6ad53..293c228a83f90f65faf3276a6b2eee16f0a9270c 100644 (file)
@@ -839,6 +839,8 @@ static void vop2_enable(struct vop2 *vop2)
                return;
        }
 
+       regcache_sync(vop2->map);
+
        if (vop2->data->soc_id == 3566)
                vop2_writel(vop2, RK3568_OTP_WIN_EN, 1);
 
@@ -867,6 +869,8 @@ static void vop2_disable(struct vop2 *vop2)
 
        pm_runtime_put_sync(vop2->dev);
 
+       regcache_mark_dirty(vop2->map);
+
        clk_disable_unprepare(vop2->aclk);
        clk_disable_unprepare(vop2->hclk);
 }
index 15d04a0ec623469d6bd89c8460a335b9b22cfd8f..e0a8890a62e23a933c853b73ef27b5ee31acbbc2 100644 (file)
@@ -507,12 +507,19 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
 {
        struct drm_sched_entity *entity = sched_job->entity;
        bool first;
+       ktime_t submit_ts;
 
        trace_drm_sched_job(sched_job, entity);
        atomic_inc(entity->rq->sched->score);
        WRITE_ONCE(entity->last_user, current->group_leader);
+
+       /*
+        * After the sched_job is pushed into the entity queue, it may be
+        * completed and freed up at any time. We can no longer access it.
+        * Make sure to set the submit_ts first, to avoid a race.
+        */
+       sched_job->submit_ts = submit_ts = ktime_get();
        first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
-       sched_job->submit_ts = ktime_get();
 
        /* first job wakes up scheduler */
        if (first) {
@@ -529,7 +536,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
                spin_unlock(&entity->rq_lock);
 
                if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
-                       drm_sched_rq_update_fifo(entity, sched_job->submit_ts);
+                       drm_sched_rq_update_fifo(entity, submit_ts);
 
                drm_sched_wakeup(entity->rq->sched);
        }
index 4e6ad6e122bc44943ab73366a653ebbf2bdda51a..1e08cc5a17029e627cea89a314797573657cc8fe 100644 (file)
@@ -308,7 +308,8 @@ static void drm_sched_start_timeout(struct drm_gpu_scheduler *sched)
  */
 void drm_sched_fault(struct drm_gpu_scheduler *sched)
 {
-       mod_delayed_work(sched->timeout_wq, &sched->work_tdr, 0);
+       if (sched->ready)
+               mod_delayed_work(sched->timeout_wq, &sched->work_tdr, 0);
 }
 EXPORT_SYMBOL(drm_sched_fault);
 
@@ -906,12 +907,6 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched)
 
        spin_unlock(&sched->job_list_lock);
 
-       if (job) {
-               job->entity->elapsed_ns += ktime_to_ns(
-                       ktime_sub(job->s_fence->finished.timestamp,
-                                 job->s_fence->scheduled.timestamp));
-       }
-
        return job;
 }
 
index cc94efbbf2d4eede4b9f4f95c15303273d056ced..d6c741716167ae8e2f3ee485b49df4886943bcf9 100644 (file)
@@ -95,12 +95,12 @@ static int sun4i_drv_bind(struct device *dev)
        /* drm_vblank_init calls kcalloc, which can fail */
        ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
        if (ret)
-               goto cleanup_mode_config;
+               goto unbind_all;
 
        /* Remove early framebuffers (ie. simplefb) */
        ret = drm_aperture_remove_framebuffers(false, &sun4i_drv_driver);
        if (ret)
-               goto cleanup_mode_config;
+               goto unbind_all;
 
        sun4i_framebuffer_init(drm);
 
@@ -119,6 +119,8 @@ static int sun4i_drv_bind(struct device *dev)
 
 finish_poll:
        drm_kms_helper_poll_fini(drm);
+unbind_all:
+       component_unbind_all(dev, NULL);
 cleanup_mode_config:
        drm_mode_config_cleanup(drm);
        of_reserved_mem_device_release(dev);
index f8ee714df3967eb2dc93b86885e8fdc3d903210b..09ee6f6af896bd9c36f24b9e08a41f037e764ed8 100644 (file)
@@ -89,7 +89,8 @@ static int check_block(struct kunit *test, struct drm_buddy *mm,
                err = -EINVAL;
        }
 
-       if (!is_power_of_2(block_size)) {
+       /* We can't use is_power_of_2() for a u64 on 32-bit systems. */
+       if (block_size & (block_size - 1)) {
                kunit_err(test, "block size not power of two\n");
                err = -EINVAL;
        }
index 326a3d13a82956846a428ac2e395bab48297a486..c286c6ffe07f691af62cd8f77cf6cdffdce43b71 100644 (file)
@@ -295,8 +295,6 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo,
        if (unlock_resv)
                dma_resv_unlock(bo->base.resv);
 
-       ttm_bo_put(bo);
-
        return 0;
 }
 
index c7a1862f322a1cfadb039d58f52d2fcd30e07dd1..ae2f19dc9f81696894f010a732d5e78fad950276 100644 (file)
@@ -158,7 +158,7 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,
                        struct ttm_buffer_object *bo = res->bo;
                        uint32_t num_pages;
 
-                       if (!bo)
+                       if (!bo || bo->resource != res)
                                continue;
 
                        num_pages = PFN_UP(bo->base.size);
index a04a9b20896dcab4c9baebf509be50a9422f3ba2..1778a2081fd6f72b88a79ffdcd2df879a383a885 100644 (file)
@@ -604,7 +604,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
        bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
 
        if (virtio_gpu_is_shmem(bo) && use_dma_api)
-               dma_sync_sgtable_for_device(&vgdev->vdev->dev,
+               dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
                                            bo->base.sgt, DMA_TO_DEVICE);
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
@@ -1026,7 +1026,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
        bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
 
        if (virtio_gpu_is_shmem(bo) && use_dma_api)
-               dma_sync_sgtable_for_device(&vgdev->vdev->dev,
+               dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
                                            bo->base.sgt, DMA_TO_DEVICE);
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
index 4872d183d86044ed7243e858e93c72deb203048e..aae2efeef503213ccc6695735b6bebf7d4511c16 100644 (file)
@@ -487,7 +487,6 @@ static int host1x_get_resets(struct host1x *host)
 static int host1x_probe(struct platform_device *pdev)
 {
        struct host1x *host;
-       int syncpt_irq;
        int err;
 
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
@@ -517,8 +516,8 @@ static int host1x_probe(struct platform_device *pdev)
        }
 
        host->syncpt_irq = platform_get_irq(pdev, 0);
-       if (syncpt_irq < 0)
-               return syncpt_irq;
+       if (host->syncpt_irq < 0)
+               return host->syncpt_irq;
 
        mutex_init(&host->devices_lock);
        INIT_LIST_HEAD(&host->devices);
index 82f64fb31fdab669bf81ccb415ed230d5734b13e..4ce012f83253ec9f12e3c12b5f95c12142cb4e8c 100644 (file)
@@ -1122,7 +1122,7 @@ config HID_TOPRE
        tristate "Topre REALFORCE keyboards"
        depends on HID
        help
-         Say Y for N-key rollover support on Topre REALFORCE R2 108 key keyboards.
+         Say Y for N-key rollover support on Topre REALFORCE R2 108/87 key keyboards.
 
 config HID_THINGM
        tristate "ThingM blink(1) USB RGB LED"
index 63545cd307e5f8805672301dac5adbfa0025f5f2..c2e9b6d1fd7d3eda054e33cf73a47a3b1f4deea4 100644 (file)
 #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN   0x261A
 #define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN  0x2A1C
 #define I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN     0x279F
+#define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100        0x29F5
+#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1     0x2BED
+#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2     0x2BEE
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
 
 #define USB_VENDOR_ID_TOPRE                    0x0853
 #define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108                   0x0148
+#define USB_DEVICE_ID_TOPRE_REALFORCE_R2_87                    0x0146
 
 #define USB_VENDOR_ID_TOPSEED          0x0766
 #define USB_DEVICE_ID_TOPSEED_CYBERLINK        0x0204
index 7fc967964dd8167de925c977e2207b8cb82b4603..5c65a584b3fa00492112309e8b3454feec66e70e 100644 (file)
@@ -398,6 +398,12 @@ static const struct hid_device_id hid_battery_quirks[] = {
          HID_BATTERY_QUIRK_IGNORE },
        { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100),
+         HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1),
+         HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
index 3e3f89e01d819bb30b2eb30c36adc1d0ba89df42..d85398721659ab6ac90ddb9e48fea4c89fd90e38 100644 (file)
@@ -940,7 +940,7 @@ hid_sensor_register_platform_device(struct platform_device *pdev,
                                    struct hid_sensor_hub_device *hsdev,
                                    const struct hid_sensor_custom_match *match)
 {
-       char real_usage[HID_SENSOR_USAGE_LENGTH];
+       char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
        struct platform_device *custom_pdev;
        const char *dev_name;
        char *c;
index 88a91cdad5f800e951121b6e252fa7780629df22..d1d5ca310eadc0fd7b4d5a44c050efffe7b96e69 100644 (file)
@@ -36,6 +36,8 @@ static __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 static const struct hid_device_id topre_id_table[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE,
                         USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE,
+                        USB_DEVICE_ID_TOPRE_REALFORCE_R2_87) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, topre_id_table);
index 81385ab37fa9a0dc40a703e6a4594501aa12c236..7fc738a223755601e50e51cecbf8f985e6241f01 100644 (file)
@@ -241,8 +241,8 @@ static int ishtp_cl_bus_match(struct device *dev, struct device_driver *drv)
        struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
        struct ishtp_cl_driver *driver = to_ishtp_cl_driver(drv);
 
-       return guid_equal(&driver->id[0].guid,
-                         &device->fw_client->props.protocol_name);
+       return(device->fw_client ? guid_equal(&driver->id[0].guid,
+              &device->fw_client->props.protocol_name) : 0);
 }
 
 /**
index 9dc27e5d367a20c9bce2cb4f6253913724bf02e2..da51b50787dff39ef697b82d4e8f8708c39c9ce0 100644 (file)
@@ -409,6 +409,10 @@ void vmbus_disconnect(void)
  */
 struct vmbus_channel *relid2channel(u32 relid)
 {
+       if (vmbus_connection.channels == NULL) {
+               pr_warn_once("relid2channel: relid=%d: No channels mapped!\n", relid);
+               return NULL;
+       }
        if (WARN_ON(relid >= MAX_CHANNEL_RELIDS))
                return NULL;
        return READ_ONCE(vmbus_connection.channels[relid]);
index c6692fd5ab15581fe0f0c2d3ef0184d26c2d0585..2111e97c3b6389280112cacbab19dc43e3b2375c 100644 (file)
@@ -211,7 +211,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
 
                ring_info->ring_buffer = (struct hv_ring_buffer *)
                        vmap_pfn(pfns_wraparound, page_cnt * 2 - 1,
-                                PAGE_KERNEL);
+                                pgprot_decrypted(PAGE_KERNEL));
                kfree(pfns_wraparound);
 
                if (!ring_info->ring_buffer)
index d24dd65b33d4d334f77d86f662151fd88efc9911..e9e1c4139e0da4feec6cc072c31127983a0cbff5 100644 (file)
@@ -2156,7 +2156,6 @@ void vmbus_device_unregister(struct hv_device *device_obj)
  * VMBUS is an acpi enumerated device. Get the information we
  * need from DSDT.
  */
-#define VTPM_BASE_ADDRESS 0xfed40000
 static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
 {
        resource_size_t start = 0;
index 51b3d16c32233d78a524a9afca79af57dffce362..6e4c92b500b8e383fd99fcc3aca91027e6cfb355 100644 (file)
@@ -488,10 +488,10 @@ static ssize_t temp_store(struct device *dev, struct device_attribute *attr,
                val = (temp - val) / 1000;
 
                if (sattr->index != 1) {
-                       data->temp[HYSTERSIS][sattr->index] &= 0xF0;
+                       data->temp[HYSTERSIS][sattr->index] &= 0x0F;
                        data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4;
                } else {
-                       data->temp[HYSTERSIS][sattr->index] &= 0x0F;
+                       data->temp[HYSTERSIS][sattr->index] &= 0xF0;
                        data->temp[HYSTERSIS][sattr->index] |= (val & 0xF);
                }
 
@@ -556,11 +556,11 @@ static ssize_t temp_st_show(struct device *dev, struct device_attribute *attr,
                val = data->enh_acoustics[0] & 0xf;
                break;
        case 1:
-               val = (data->enh_acoustics[1] >> 4) & 0xf;
+               val = data->enh_acoustics[1] & 0xf;
                break;
        case 2:
        default:
-               val = data->enh_acoustics[1] & 0xf;
+               val = (data->enh_acoustics[1] >> 4) & 0xf;
                break;
        }
 
index 33edb5c02f7d79d4e8ff7a75fe7ae03c84a83579..d193ed3cb35e5b315f104b04e272862922028e17 100644 (file)
@@ -757,6 +757,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
        struct hwmon_device *hwdev;
        const char *label;
        struct device *hdev;
+       struct device *tdev = dev;
        int i, err, id;
 
        /* Complain about invalid characters in hwmon name attribute */
@@ -826,7 +827,9 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
        hwdev->name = name;
        hdev->class = &hwmon_class;
        hdev->parent = dev;
-       hdev->of_node = dev ? dev->of_node : NULL;
+       while (tdev && !tdev->of_node)
+               tdev = tdev->parent;
+       hdev->of_node = tdev ? tdev->of_node : NULL;
        hwdev->chip = chip;
        dev_set_drvdata(hdev, drvdata);
        dev_set_name(hdev, HWMON_ID_FORMAT, id);
@@ -838,7 +841,7 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,
 
        INIT_LIST_HEAD(&hwdev->tzdata);
 
-       if (dev && dev->of_node && chip && chip->ops->read &&
+       if (hdev->of_node && chip && chip->ops->read &&
            chip->info[0]->type == hwmon_chip &&
            (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
                err = hwmon_thermal_register_sensors(hdev);
index e06186986444ee4853248deb4ec8424b616ed726..f3a4c5633b1ea6876336719a06ede4cad9207b30 100644 (file)
@@ -772,7 +772,7 @@ static int ina3221_probe_child_from_dt(struct device *dev,
                return ret;
        } else if (val > INA3221_CHANNEL3) {
                dev_err(dev, "invalid reg %d of %pOFn\n", val, child);
-               return ret;
+               return -EINVAL;
        }
 
        input = &ina->inputs[val];
index 66f7ceaa7c3f5fa6328c905f5ca64b8504f25b3c..e9614eb557d4eb44e16397419d988ef9a9dac1ad 100644 (file)
@@ -515,6 +515,8 @@ static const struct it87_devices it87_devices[] = {
 #define has_six_temp(data)     ((data)->features & FEAT_SIX_TEMP)
 #define has_vin3_5v(data)      ((data)->features & FEAT_VIN3_5V)
 #define has_conf_noexit(data)  ((data)->features & FEAT_CONF_NOEXIT)
+#define has_scaling(data)      ((data)->features & (FEAT_12MV_ADC | \
+                                                    FEAT_10_9MV_ADC))
 
 struct it87_sio_data {
        int sioaddr;
@@ -3134,7 +3136,7 @@ static int it87_probe(struct platform_device *pdev)
                         "Detected broken BIOS defaults, disabling PWM interface\n");
 
        /* Starting with IT8721F, we handle scaling of internal voltages */
-       if (has_12mv_adc(data)) {
+       if (has_scaling(data)) {
                if (sio_data->internal & BIT(0))
                        data->in_scaled |= BIT(3);      /* in3 is AVCC */
                if (sio_data->internal & BIT(1))
index 88514152d9306f98460fd8405ec48ad60c4fa025..69341de397cb93e4c0b741620712b55c42fd2acc 100644 (file)
@@ -323,6 +323,7 @@ static int ltc2992_config_gpio(struct ltc2992_state *st)
        st->gc.label = name;
        st->gc.parent = &st->client->dev;
        st->gc.owner = THIS_MODULE;
+       st->gc.can_sleep = true;
        st->gc.base = -1;
        st->gc.names = st->gpio_names;
        st->gc.ngpio = ARRAY_SIZE(st->gpio_names);
index 30850a479f61fdf96b5ae1cdd985b09802575bdc..87d56f0fc888c23fffac13ac67322639a4bbf409 100644 (file)
@@ -537,6 +537,12 @@ static const struct cpu_info cpu_hsx = {
        .thermal_margin_to_millidegree = &dts_eight_dot_eight_to_millidegree,
 };
 
+static const struct cpu_info cpu_skx = {
+       .reg            = &resolved_cores_reg_hsx,
+       .min_peci_revision = 0x33,
+       .thermal_margin_to_millidegree = &dts_ten_dot_six_to_millidegree,
+};
+
 static const struct cpu_info cpu_icx = {
        .reg            = &resolved_cores_reg_icx,
        .min_peci_revision = 0x40,
@@ -558,7 +564,7 @@ static const struct auxiliary_device_id peci_cputemp_ids[] = {
        },
        {
                .name = "peci_cpu.cputemp.skx",
-               .driver_data = (kernel_ulong_t)&cpu_hsx,
+               .driver_data = (kernel_ulong_t)&cpu_skx,
        },
        {
                .name = "peci_cpu.cputemp.icx",
index ec5f932fc6f0fb6d489418f25beaa1816710759e..1ac2b2f4c5705f5a142579e3085c703675d5b01b 100644 (file)
@@ -301,6 +301,7 @@ static int adm1266_config_gpio(struct adm1266_data *data)
        data->gc.label = name;
        data->gc.parent = &data->client->dev;
        data->gc.owner = THIS_MODULE;
+       data->gc.can_sleep = true;
        data->gc.base = -1;
        data->gc.names = data->gpio_names;
        data->gc.ngpio = ARRAY_SIZE(data->gpio_names);
index 75fc770c9e4035b2b982b34b543b5e51f6dd3378..3daaf22378322f6c2d0074bcad0f96220e227003 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/debugfs.h>
+#include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -16,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/pmbus.h>
 #include <linux/gpio/driver.h>
+#include <linux/timekeeping.h>
 #include "pmbus.h"
 
 enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd90320, ucd9090,
@@ -65,6 +67,7 @@ struct ucd9000_data {
        struct gpio_chip gpio;
 #endif
        struct dentry *debugfs;
+       ktime_t write_time;
 };
 #define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
 
@@ -73,6 +76,73 @@ struct ucd9000_debugfs_entry {
        u8 index;
 };
 
+/*
+ * It has been observed that the UCD90320 randomly fails register access when
+ * doing another access right on the back of a register write. To mitigate this
+ * make sure that there is a minimum delay between a write access and the
+ * following access. The 250us is based on experimental data. At a delay of
+ * 200us the issue seems to go away. Add a bit of extra margin to allow for
+ * system to system differences.
+ */
+#define UCD90320_WAIT_DELAY_US 250
+
+static inline void ucd90320_wait(const struct ucd9000_data *data)
+{
+       s64 delta = ktime_us_delta(ktime_get(), data->write_time);
+
+       if (delta < UCD90320_WAIT_DELAY_US)
+               udelay(UCD90320_WAIT_DELAY_US - delta);
+}
+
+static int ucd90320_read_word_data(struct i2c_client *client, int page,
+                                  int phase, int reg)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct ucd9000_data *data = to_ucd9000_data(info);
+
+       if (reg >= PMBUS_VIRT_BASE)
+               return -ENXIO;
+
+       ucd90320_wait(data);
+       return pmbus_read_word_data(client, page, phase, reg);
+}
+
+static int ucd90320_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct ucd9000_data *data = to_ucd9000_data(info);
+
+       ucd90320_wait(data);
+       return pmbus_read_byte_data(client, page, reg);
+}
+
+static int ucd90320_write_word_data(struct i2c_client *client, int page,
+                                   int reg, u16 word)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct ucd9000_data *data = to_ucd9000_data(info);
+       int ret;
+
+       ucd90320_wait(data);
+       ret = pmbus_write_word_data(client, page, reg, word);
+       data->write_time = ktime_get();
+
+       return ret;
+}
+
+static int ucd90320_write_byte(struct i2c_client *client, int page, u8 value)
+{
+       const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+       struct ucd9000_data *data = to_ucd9000_data(info);
+       int ret;
+
+       ucd90320_wait(data);
+       ret = pmbus_write_byte(client, page, value);
+       data->write_time = ktime_get();
+
+       return ret;
+}
+
 static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
 {
        int fan_config = 0;
@@ -598,6 +668,11 @@ static int ucd9000_probe(struct i2c_client *client)
                info->read_byte_data = ucd9000_read_byte_data;
                info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
                  | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
+       } else if (mid->driver_data == ucd90320) {
+               info->read_byte_data = ucd90320_read_byte_data;
+               info->read_word_data = ucd90320_read_word_data;
+               info->write_byte = ucd90320_write_byte;
+               info->write_word_data = ucd90320_write_word_data;
        }
 
        ucd9000_probe_gpio(client, mid, data);
index 47bbe47e062fd7a20e27f843b625f07e005722ee..7d5f7441aceb1040f8b8bcfedb8695c162c0acf1 100644 (file)
@@ -758,7 +758,7 @@ static int tmp51x_probe(struct i2c_client *client)
 static struct i2c_driver tmp51x_driver = {
        .driver = {
                .name   = "tmp51x",
-               .of_match_table = of_match_ptr(tmp51x_of_match),
+               .of_match_table = tmp51x_of_match,
        },
        .probe_new      = tmp51x_probe,
        .id_table       = tmp51x_id,
index 5cde837bfd094c57a3cf719b0fe0e4c2645dce8e..78d9f52e2a7194f9e0bc8714394ea9311a006379 100644 (file)
@@ -698,14 +698,14 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                ctx->comm_base_addr = pcc_chan->shmem_base_addr;
                if (ctx->comm_base_addr) {
                        if (version == XGENE_HWMON_V2)
-                               ctx->pcc_comm_addr = (void __force *)ioremap(
-                                                       ctx->comm_base_addr,
-                                                       pcc_chan->shmem_size);
+                               ctx->pcc_comm_addr = (void __force *)devm_ioremap(&pdev->dev,
+                                                                 ctx->comm_base_addr,
+                                                                 pcc_chan->shmem_size);
                        else
-                               ctx->pcc_comm_addr = memremap(
-                                                       ctx->comm_base_addr,
-                                                       pcc_chan->shmem_size,
-                                                       MEMREMAP_WB);
+                               ctx->pcc_comm_addr = devm_memremap(&pdev->dev,
+                                                                  ctx->comm_base_addr,
+                                                                  pcc_chan->shmem_size,
+                                                                  MEMREMAP_WB);
                } else {
                        dev_err(&pdev->dev, "Failed to get PCC comm region\n");
                        rc = -ENODEV;
@@ -761,6 +761,7 @@ static int xgene_hwmon_remove(struct platform_device *pdev)
 {
        struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
 
+       cancel_work_sync(&ctx->workq);
        hwmon_device_unregister(ctx->hwmon_dev);
        kfifo_free(&ctx->async_msg_fifo);
        if (acpi_disabled)
index 1ea8f173cca0d9d4561fae5b2e885f581ff6f31c..4c15fae534f3a353c814610647f55e132c4a76a2 100644 (file)
@@ -472,7 +472,7 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
                if (etm4x_sspcicrn_present(drvdata, i))
                        etm4x_relaxed_write32(csa, config->ss_pe_cmp[i], TRCSSPCICRn(i));
        }
-       for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+       for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
                etm4x_relaxed_write64(csa, config->addr_val[i], TRCACVRn(i));
                etm4x_relaxed_write64(csa, config->addr_acc[i], TRCACATRn(i));
        }
@@ -1070,25 +1070,21 @@ static bool etm4_init_iomem_access(struct etmv4_drvdata *drvdata,
                                   struct csdev_access *csa)
 {
        u32 devarch = readl_relaxed(drvdata->base + TRCDEVARCH);
-       u32 idr1 = readl_relaxed(drvdata->base + TRCIDR1);
 
        /*
         * All ETMs must implement TRCDEVARCH to indicate that
-        * the component is an ETMv4. To support any broken
-        * implementations we fall back to TRCIDR1 check, which
-        * is not really reliable.
+        * the component is an ETMv4. Even though TRCIDR1 also
+        * contains the information, it is part of the "Trace"
+        * register and must be accessed with the OSLK cleared,
+        * with MMIO. But we cannot touch the OSLK until we are
+        * sure this is an ETM. So rely only on the TRCDEVARCH.
         */
-       if ((devarch & ETM_DEVARCH_ID_MASK) == ETM_DEVARCH_ETMv4x_ARCH) {
-               drvdata->arch = etm_devarch_to_arch(devarch);
-       } else {
-               pr_warn("CPU%d: ETM4x incompatible TRCDEVARCH: %x, falling back to TRCIDR1\n",
-                       smp_processor_id(), devarch);
-
-               if (ETM_TRCIDR1_ARCH_MAJOR(idr1) != ETM_TRCIDR1_ARCH_ETMv4)
-                       return false;
-               drvdata->arch = etm_trcidr_to_arch(idr1);
+       if ((devarch & ETM_DEVARCH_ID_MASK) != ETM_DEVARCH_ETMv4x_ARCH) {
+               pr_warn_once("TRCDEVARCH doesn't match ETMv4 architecture\n");
+               return false;
        }
 
+       drvdata->arch = etm_devarch_to_arch(devarch);
        *csa = CSDEV_ACCESS_IOMEM(drvdata->base);
        return true;
 }
index 434f4e95ee17bb5de869884f94558a113e1ff511..27c8a99018680c1f321172c0db1fd466b74d652d 100644 (file)
  * TRCDEVARCH  - CoreSight architected register
  *                - Bits[15:12] - Major version
  *                - Bits[19:16] - Minor version
- * TRCIDR1     - ETM architected register
- *                - Bits[11:8] - Major version
- *                - Bits[7:4]  - Minor version
- * We must rely on TRCDEVARCH for the version information,
- * however we don't want to break the support for potential
- * old implementations which might not implement it. Thus
- * we fall back to TRCIDR1 if TRCDEVARCH is not implemented
- * for memory mapped components.
+ *
+ * We must rely only on TRCDEVARCH for the version information. Even though,
+ * TRCIDR1 also provides the architecture version, it is a "Trace" register
+ * and as such must be accessed only with Trace power domain ON. This may
+ * not be available at probe time.
+ *
  * Now to make certain decisions easier based on the version
  * we use an internal representation of the version in the
  * driver, as follows :
@@ -786,12 +784,6 @@ static inline u8 etm_devarch_to_arch(u32 devarch)
                                ETM_DEVARCH_REVISION(devarch));
 }
 
-static inline u8 etm_trcidr_to_arch(u32 trcidr1)
-{
-       return ETM_ARCH_VERSION(ETM_TRCIDR1_ARCH_MAJOR(trcidr1),
-                               ETM_TRCIDR1_ARCH_MINOR(trcidr1));
-}
-
 enum etm_impdef_type {
        ETM4_IMPDEF_HISI_CORE_COMMIT,
        ETM4_IMPDEF_FEATURE_MAX,
index 8c6c7075c765c502e194d222934b294ba966de89..e067671b3ce2eebed4eab2cb51301aaaa3890529 100644 (file)
@@ -316,6 +316,13 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
                    max_write == 0)
                        break;
        }
+
+       /*
+        * Disable the TX_EMPTY interrupt after finishing all the messages to
+        * avoid overwhelming the CPU.
+        */
+       if (ctlr->msg_tx_idx == ctlr->msg_num)
+               hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY);
 }
 
 static irqreturn_t hisi_i2c_irq(int irq, void *context)
@@ -341,7 +348,11 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
                hisi_i2c_read_rx_fifo(ctlr);
 
 out:
-       if (int_stat & HISI_I2C_INT_TRANS_CPLT || ctlr->xfer_err) {
+       /*
+        * Only use TRANS_CPLT to indicate the completion. On error cases we'll
+        * get two interrupts, INT_ERR first then TRANS_CPLT.
+        */
+       if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
                hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
                hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
                complete(ctlr->completion);
index 188f2a36d2fd61bb3ffb943f8d879e8bba6bbe52..a49b14d52a98614bd5745baba5048ec24c43438a 100644 (file)
@@ -463,6 +463,8 @@ static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
                if (num == 1 && msgs[0].len == 0)
                        goto stop;
 
+               lpi2c_imx->rx_buf = NULL;
+               lpi2c_imx->tx_buf = NULL;
                lpi2c_imx->delivered = 0;
                lpi2c_imx->msglen = msgs[i].len;
                init_completion(&lpi2c_imx->complete);
@@ -503,10 +505,14 @@ disable:
 static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
 {
        struct lpi2c_imx_struct *lpi2c_imx = dev_id;
+       unsigned int enabled;
        unsigned int temp;
 
+       enabled = readl(lpi2c_imx->base + LPI2C_MIER);
+
        lpi2c_imx_intctrl(lpi2c_imx, 0);
        temp = readl(lpi2c_imx->base + LPI2C_MSR);
+       temp &= enabled;
 
        if (temp & MSR_RDF)
                lpi2c_imx_read_rxfifo(lpi2c_imx);
index 09af7592114789a924c8bef1cc095df192367151..b21ffd6df9276b34ec14267d6db6fe9cd93c9c66 100644 (file)
@@ -48,9 +48,9 @@
  * SR_HOLD_TIME_XK_TICKS field will indicate the number of ticks of the
  * baud clock required to program 'Hold Time' at X KHz.
  */
-#define SR_HOLD_TIME_100K_TICKS        133
-#define SR_HOLD_TIME_400K_TICKS        20
-#define SR_HOLD_TIME_1000K_TICKS       11
+#define SR_HOLD_TIME_100K_TICKS                150
+#define SR_HOLD_TIME_400K_TICKS                20
+#define SR_HOLD_TIME_1000K_TICKS       12
 
 #define SMB_CORE_COMPLETION_REG_OFF3   (SMBUS_MAST_CORE_ADDR_BASE + 0x23)
 
  * the baud clock required to program 'fair idle delay' at X KHz. Fair idle
  * delay establishes the MCTP T(IDLE_DELAY) period.
  */
-#define FAIR_BUS_IDLE_MIN_100K_TICKS           969
-#define FAIR_BUS_IDLE_MIN_400K_TICKS           157
-#define FAIR_BUS_IDLE_MIN_1000K_TICKS          157
+#define FAIR_BUS_IDLE_MIN_100K_TICKS           992
+#define FAIR_BUS_IDLE_MIN_400K_TICKS           500
+#define FAIR_BUS_IDLE_MIN_1000K_TICKS          500
 
 /*
  * FAIR_IDLE_DELAY_XK_TICKS field will indicate the number of ticks of the
  * baud clock required to satisfy the fairness protocol at X KHz.
  */
-#define FAIR_IDLE_DELAY_100K_TICKS     1000
-#define FAIR_IDLE_DELAY_400K_TICKS     500
-#define FAIR_IDLE_DELAY_1000K_TICKS    500
+#define FAIR_IDLE_DELAY_100K_TICKS     963
+#define FAIR_IDLE_DELAY_400K_TICKS     156
+#define FAIR_IDLE_DELAY_1000K_TICKS    156
 
 #define SMB_IDLE_SCALING_100K          \
        ((FAIR_IDLE_DELAY_100K_TICKS << 16) | FAIR_BUS_IDLE_MIN_100K_TICKS)
  */
 #define BUS_CLK_100K_LOW_PERIOD_TICKS          156
 #define BUS_CLK_400K_LOW_PERIOD_TICKS          41
-#define BUS_CLK_1000K_LOW_PERIOD_TICKS 15
+#define BUS_CLK_1000K_LOW_PERIOD_TICKS         15
 
 /*
  * BUS_CLK_XK_HIGH_PERIOD_TICKS field defines the number of I2C Baud Clock
  */
 #define CLK_SYNC_100K                  4
 #define CLK_SYNC_400K                  4
-#define CLK_SYNC_1000K         4
+#define CLK_SYNC_1000K                 4
 
 #define SMB_CORE_DATA_TIMING_REG_OFF   (SMBUS_MAST_CORE_ADDR_BASE + 0x40)
 
  * determines the SCLK hold time following SDAT driven low during the first
  * START bit in a transfer.
  */
-#define FIRST_START_HOLD_100K_TICKS    22
-#define FIRST_START_HOLD_400K_TICKS    16
-#define FIRST_START_HOLD_1000K_TICKS   6
+#define FIRST_START_HOLD_100K_TICKS    23
+#define FIRST_START_HOLD_400K_TICKS    8
+#define FIRST_START_HOLD_1000K_TICKS   12
 
 /*
  * STOP_SETUP_XK_TICKS will indicate the number of ticks of the baud clock
  * required to program 'STOP_SETUP' timer at X KHz. This timer determines the
  * SDAT setup time from the rising edge of SCLK for a STOP condition.
  */
-#define STOP_SETUP_100K_TICKS          157
+#define STOP_SETUP_100K_TICKS          150
 #define STOP_SETUP_400K_TICKS          20
-#define STOP_SETUP_1000K_TICKS 12
+#define STOP_SETUP_1000K_TICKS         12
 
 /*
  * RESTART_SETUP_XK_TICKS will indicate the number of ticks of the baud clock
  * required to program 'RESTART_SETUP' timer at X KHz. This timer determines the
  * SDAT setup time from the rising edge of SCLK for a repeated START condition.
  */
-#define RESTART_SETUP_100K_TICKS       157
+#define RESTART_SETUP_100K_TICKS       156
 #define RESTART_SETUP_400K_TICKS       20
 #define RESTART_SETUP_1000K_TICKS      12
 
  * required to program 'DATA_HOLD' timer at X KHz. This timer determines the
  * SDAT hold time following SCLK driven low.
  */
-#define DATA_HOLD_100K_TICKS           2
+#define DATA_HOLD_100K_TICKS           12
 #define DATA_HOLD_400K_TICKS           2
 #define DATA_HOLD_1000K_TICKS          2
 
  * Bus Idle Minimum time = BUS_IDLE_MIN[7:0] x Baud_Clock_Period x
  * (BUS_IDLE_MIN_XK_TICKS[7] ? 4,1)
  */
-#define BUS_IDLE_MIN_100K_TICKS                167UL
-#define BUS_IDLE_MIN_400K_TICKS                139UL
-#define BUS_IDLE_MIN_1000K_TICKS               133UL
+#define BUS_IDLE_MIN_100K_TICKS                36UL
+#define BUS_IDLE_MIN_400K_TICKS                10UL
+#define BUS_IDLE_MIN_1000K_TICKS       4UL
 
 /*
  * CTRL_CUM_TIME_OUT_XK_TICKS defines SMBus Controller Cumulative Time-Out.
  * SMBus Controller Cumulative Time-Out duration =
  * CTRL_CUM_TIME_OUT_XK_TICKS[7:0] x Baud_Clock_Period x 2048
  */
-#define CTRL_CUM_TIME_OUT_100K_TICKS           159
-#define CTRL_CUM_TIME_OUT_400K_TICKS           159
-#define CTRL_CUM_TIME_OUT_1000K_TICKS          159
+#define CTRL_CUM_TIME_OUT_100K_TICKS           76
+#define CTRL_CUM_TIME_OUT_400K_TICKS           76
+#define CTRL_CUM_TIME_OUT_1000K_TICKS          76
 
 /*
  * TARGET_CUM_TIME_OUT_XK_TICKS defines SMBus Target Cumulative Time-Out duration.
  * SMBus Target Cumulative Time-Out duration = TARGET_CUM_TIME_OUT_XK_TICKS[7:0] x
  * Baud_Clock_Period x 4096
  */
-#define TARGET_CUM_TIME_OUT_100K_TICKS 199
-#define TARGET_CUM_TIME_OUT_400K_TICKS 199
-#define TARGET_CUM_TIME_OUT_1000K_TICKS        199
+#define TARGET_CUM_TIME_OUT_100K_TICKS 95
+#define TARGET_CUM_TIME_OUT_400K_TICKS 95
+#define TARGET_CUM_TIME_OUT_1000K_TICKS        95
 
 /*
  * CLOCK_HIGH_TIME_OUT_XK defines Clock High time out period.
  * Clock High time out period = CLOCK_HIGH_TIME_OUT_XK[7:0] x Baud_Clock_Period x 8
  */
-#define CLOCK_HIGH_TIME_OUT_100K_TICKS 204
-#define CLOCK_HIGH_TIME_OUT_400K_TICKS 204
-#define CLOCK_HIGH_TIME_OUT_1000K_TICKS        204
+#define CLOCK_HIGH_TIME_OUT_100K_TICKS 97
+#define CLOCK_HIGH_TIME_OUT_400K_TICKS 97
+#define CLOCK_HIGH_TIME_OUT_1000K_TICKS        97
 
 #define TO_SCALING_100K                \
        ((BUS_IDLE_MIN_100K_TICKS << 24) | (CTRL_CUM_TIME_OUT_100K_TICKS << 16) | \
index d113bed7954526e1cb9afff96b8df98be26d1f15..e0f3b3545cfe4984dad9c582c419737ce448b506 100644 (file)
@@ -171,7 +171,7 @@ static void mxs_i2c_dma_irq_callback(void *param)
 }
 
 static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
-                       struct i2c_msg *msg, uint32_t flags)
+                       struct i2c_msg *msg, u8 *buf, uint32_t flags)
 {
        struct dma_async_tx_descriptor *desc;
        struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
@@ -226,7 +226,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                }
 
                /* Queue the DMA data transfer. */
-               sg_init_one(&i2c->sg_io[1], msg->buf, msg->len);
+               sg_init_one(&i2c->sg_io[1], buf, msg->len);
                dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
                                        DMA_DEV_TO_MEM,
@@ -259,7 +259,7 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                /* Queue the DMA data transfer. */
                sg_init_table(i2c->sg_io, 2);
                sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1);
-               sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len);
+               sg_set_buf(&i2c->sg_io[1], buf, msg->len);
                dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
                desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
                                        DMA_MEM_TO_DEV,
@@ -563,6 +563,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
        int ret;
        int flags;
+       u8 *dma_buf;
        int use_pio = 0;
        unsigned long time_left;
 
@@ -588,13 +589,20 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
                if (ret && (ret != -ENXIO))
                        mxs_i2c_reset(i2c);
        } else {
+               dma_buf = i2c_get_dma_safe_msg_buf(msg, 1);
+               if (!dma_buf)
+                       return -ENOMEM;
+
                reinit_completion(&i2c->cmd_complete);
-               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
-               if (ret)
+               ret = mxs_i2c_dma_setup_xfer(adap, msg, dma_buf, flags);
+               if (ret) {
+                       i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
                        return ret;
+               }
 
                time_left = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
+               i2c_put_dma_safe_msg_buf(dma_buf, msg, true);
                if (!time_left)
                        goto timeout;
 
index a0af027db04c11b98fef28be555ceb7804d92eb6..2e575856c5cd5dfa57a7fa28bce0ac17d62bfa30 100644 (file)
@@ -342,18 +342,18 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
  * ocores_isr(), we just add our polling code around it.
  *
  * It can run in atomic context
+ *
+ * Return: 0 on success, -ETIMEDOUT on timeout
  */
-static void ocores_process_polling(struct ocores_i2c *i2c)
+static int ocores_process_polling(struct ocores_i2c *i2c)
 {
-       while (1) {
-               irqreturn_t ret;
-               int err;
+       irqreturn_t ret;
+       int err = 0;
 
+       while (1) {
                err = ocores_poll_wait(i2c);
-               if (err) {
-                       i2c->state = STATE_ERROR;
+               if (err)
                        break; /* timeout */
-               }
 
                ret = ocores_isr(-1, i2c);
                if (ret == IRQ_NONE)
@@ -364,13 +364,15 @@ static void ocores_process_polling(struct ocores_i2c *i2c)
                                        break;
                }
        }
+
+       return err;
 }
 
 static int ocores_xfer_core(struct ocores_i2c *i2c,
                            struct i2c_msg *msgs, int num,
                            bool polling)
 {
-       int ret;
+       int ret = 0;
        u8 ctrl;
 
        ctrl = oc_getreg(i2c, OCI2C_CONTROL);
@@ -388,15 +390,16 @@ static int ocores_xfer_core(struct ocores_i2c *i2c,
        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
 
        if (polling) {
-               ocores_process_polling(i2c);
+               ret = ocores_process_polling(i2c);
        } else {
-               ret = wait_event_timeout(i2c->wait,
-                                        (i2c->state == STATE_ERROR) ||
-                                        (i2c->state == STATE_DONE), HZ);
-               if (ret == 0) {
-                       ocores_process_timeout(i2c);
-                       return -ETIMEDOUT;
-               }
+               if (wait_event_timeout(i2c->wait,
+                                      (i2c->state == STATE_ERROR) ||
+                                      (i2c->state == STATE_DONE), HZ) == 0)
+                       ret = -ETIMEDOUT;
+       }
+       if (ret) {
+               ocores_process_timeout(i2c);
+               return ret;
        }
 
        return (i2c->state == STATE_DONE) ? num : -EIO;
index 63259b3ea5abd7aa43de6b22d0ec7861a47e7489..3538d36368a90b5fcf5f8e18e01826908c2198ec 100644 (file)
@@ -308,6 +308,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip,
        u32 msg[3];
        int rc;
 
+       if (writelen > I2C_SMBUS_BLOCK_MAX)
+               return -EINVAL;
+
        memcpy(ctx->dma_buffer, data, writelen);
        paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
                               DMA_TO_DEVICE);
index bce6b796e04c2ca0523bf1fc83117b13b4bc2c43..545436b7dd5355a5505f1c4348241d58a6157470 100644 (file)
@@ -178,6 +178,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
                        return NOTIFY_OK;
                }
 
+               /*
+                * Clear the flag before adding the device so that fw_devlink
+                * doesn't skip adding consumers to this device.
+                */
+               rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
                client = of_i2c_register_device(adap, rd->dn);
                if (IS_ERR(client)) {
                        dev_err(&adap->dev, "failed to create client for '%pOF'\n",
index f866859855cddc9433a421829b023952808013c8..1c3a72380fb85dd8e7945e2e141996fddf947cca 100644 (file)
@@ -864,7 +864,7 @@ static irqreturn_t kx022a_trigger_handler(int irq, void *p)
        if (ret < 0)
                goto err_read;
 
-       iio_push_to_buffers_with_timestamp(idev, data->buffer, pf->timestamp);
+       iio_push_to_buffers_with_timestamp(idev, data->buffer, data->timestamp);
 err_read:
        iio_trigger_notify_done(idev->trig);
 
index fee8d129a5f0806530a98b8ab9e6681006337797..86effe8501b440fefe53636ab50dfa751200215f 100644 (file)
@@ -253,7 +253,7 @@ static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
        .has_registers = true,
        .addr_shift = 4,
        .read_mask = BIT(3),
-       .irq_flags = IRQF_TRIGGER_LOW,
+       .irq_flags = IRQF_TRIGGER_FALLING,
 };
 
 static int ad7791_read_raw(struct iio_dev *indio_dev,
index 50d02e5fc6fc125177e47805d3487badb8ef67f0..7258912fe17b758f279de776b420c206ed313f4a 100644 (file)
@@ -1409,7 +1409,7 @@ static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
        trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
                                iio_device_id(indio), trigger_name);
        if (!trig)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        trig->dev.parent = indio->dev.parent;
        iio_trigger_set_drvdata(trig, indio);
index 17370c5eb6fe32d7e164358d0d0a6a405b06d26c..ec198c6f13d6bc9a1aaafedb590ff64feca4aa75 100644 (file)
@@ -28,7 +28,6 @@ struct ltc2497_driverdata {
        struct ltc2497core_driverdata common_ddata;
        struct i2c_client *client;
        u32 recv_size;
-       u32 sub_lsb;
        /*
         * DMA (thus cache coherency maintenance) may require the
         * transfer buffers to live in their own cache lines.
@@ -65,10 +64,10 @@ static int ltc2497_result_and_measure(struct ltc2497core_driverdata *ddata,
                 * equivalent to a sign extension.
                 */
                if (st->recv_size == 3) {
-                       *val = (get_unaligned_be24(st->data.d8) >> st->sub_lsb)
+                       *val = (get_unaligned_be24(st->data.d8) >> 6)
                                - BIT(ddata->chip_info->resolution + 1);
                } else {
-                       *val = (be32_to_cpu(st->data.d32) >> st->sub_lsb)
+                       *val = (be32_to_cpu(st->data.d32) >> 6)
                                - BIT(ddata->chip_info->resolution + 1);
                }
 
@@ -122,7 +121,6 @@ static int ltc2497_probe(struct i2c_client *client)
        st->common_ddata.chip_info = chip_info;
 
        resolution = chip_info->resolution;
-       st->sub_lsb = 31 - (resolution + 1);
        st->recv_size = BITS_TO_BYTES(resolution) + 1;
 
        return ltc2497core_probe(dev, indio_dev);
index b74b689ee7de7003e0996c27d49ea2a33e374c41..f6895bc9fc4b6cd6918dfb3ed515c9eb69f49b43 100644 (file)
@@ -414,13 +414,17 @@ static int max11410_sample(struct max11410_state *st, int *sample_raw,
                if (!ret)
                        return -ETIMEDOUT;
        } else {
+               int ret2;
+
                /* Wait for status register Conversion Ready flag */
-               ret = read_poll_timeout(max11410_read_reg, ret,
-                                       ret || (val & MAX11410_STATUS_CONV_READY_BIT),
+               ret = read_poll_timeout(max11410_read_reg, ret2,
+                                       ret2 || (val & MAX11410_STATUS_CONV_READY_BIT),
                                        5000, MAX11410_CONVERSION_TIMEOUT_MS * 1000,
                                        true, st, MAX11410_REG_STATUS, &val);
                if (ret)
                        return ret;
+               if (ret2)
+                       return ret2;
        }
 
        /* Read ADC Data */
@@ -851,17 +855,21 @@ static int max11410_init_vref(struct device *dev,
 
 static int max11410_calibrate(struct max11410_state *st, u32 cal_type)
 {
-       int ret, val;
+       int ret, ret2, val;
 
        ret = max11410_write_reg(st, MAX11410_REG_CAL_START, cal_type);
        if (ret)
                return ret;
 
        /* Wait for status register Calibration Ready flag */
-       return read_poll_timeout(max11410_read_reg, ret,
-                                ret || (val & MAX11410_STATUS_CAL_READY_BIT),
-                                50000, MAX11410_CALIB_TIMEOUT_MS * 1000, true,
-                                st, MAX11410_REG_STATUS, &val);
+       ret = read_poll_timeout(max11410_read_reg, ret2,
+                               ret2 || (val & MAX11410_STATUS_CAL_READY_BIT),
+                               50000, MAX11410_CALIB_TIMEOUT_MS * 1000, true,
+                               st, MAX11410_REG_STATUS, &val);
+       if (ret)
+               return ret;
+
+       return ret2;
 }
 
 static int max11410_self_calibrate(struct max11410_state *st)
index fd000345ec5cff0b1201092453547e0356446876..849a697a467e58689b7ba1ac72a8c650400852af 100644 (file)
@@ -639,7 +639,7 @@ out:
 
 static int palmas_gpadc_remove(struct platform_device *pdev)
 {
-       struct iio_dev *indio_dev = dev_to_iio_dev(&pdev->dev);
+       struct iio_dev *indio_dev = dev_get_drvdata(&pdev->dev);
        struct palmas_gpadc *adc = iio_priv(indio_dev);
 
        if (adc->wakeup1_enable || adc->wakeup2_enable)
index e90c299c913a2aa9d4033cb833872370c23d2655..c2d5e06f137a7e64f66a112b9cc47c5de2e6d309 100644 (file)
@@ -628,12 +628,20 @@ static int adc5_get_fw_channel_data(struct adc5_chip *adc,
                                    struct fwnode_handle *fwnode,
                                    const struct adc5_data *data)
 {
-       const char *name = fwnode_get_name(fwnode), *channel_name;
+       const char *channel_name;
+       char *name;
        u32 chan, value, varr[2];
        u32 sid = 0;
        int ret;
        struct device *dev = adc->dev;
 
+       name = devm_kasprintf(dev, GFP_KERNEL, "%pfwP", fwnode);
+       if (!name)
+               return -ENOMEM;
+
+       /* Cut the address part */
+       name[strchrnul(name, '@') - name] = '\0';
+
        ret = fwnode_property_read_u32(fwnode, "reg", &chan);
        if (ret) {
                dev_err(dev, "invalid channel number %s\n", name);
index 2cc9a9bd9db60f97b857f6d726f3af176556a898..263fc3a1b87e1d97f215e39b489264eefdfa8442 100644 (file)
@@ -634,6 +634,7 @@ static int ti_ads7950_probe(struct spi_device *spi)
        st->chip.label = dev_name(&st->spi->dev);
        st->chip.parent = &st->spi->dev;
        st->chip.owner = THIS_MODULE;
+       st->chip.can_sleep = true;
        st->chip.base = -1;
        st->chip.ngpio = TI_ADS7950_NUM_GPIOS;
        st->chip.get_direction = ti_ads7950_get_direction;
index beadfa938d2da856d4d11e2ed322fac52ec433f2..404865e354602cb077393479b77d5e32d45c6b51 100644 (file)
@@ -802,6 +802,7 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
        return pdata;
 
  error_out:
+       fwnode_handle_put(pp);
        devm_kfree(dev, pdata);
        return NULL;
 }
index 791dd999cf291ec5394ec196f0ca6d2b16e98c45..18a64f72fc188dbb0d47ed84860e7e07ba8e2a78 100644 (file)
@@ -66,8 +66,8 @@ static int cio_dac_write_raw(struct iio_dev *indio_dev,
        if (mask != IIO_CHAN_INFO_RAW)
                return -EINVAL;
 
-       /* DAC can only accept up to a 16-bit value */
-       if ((unsigned int)val > 65535)
+       /* DAC can only accept up to a 12-bit value */
+       if ((unsigned int)val > 4095)
                return -EINVAL;
 
        priv->chan_out_states[chan->channel] = val;
index f1d7d4b5e22243134967418b491fbf2cc5ccda47..c2f97629e9cdb6f726ecd7b9053b9b5e9137f825 100644 (file)
@@ -47,6 +47,7 @@ config ADIS16480
        depends on SPI
        select IIO_ADIS_LIB
        select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
+       select CRC32
        help
          Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
          ADIS16485, ADIS16488 inertial sensors.
index 80c78bd6bbef4970fe39149bddd06b361ad9c74c..a7a080bed1808f1f763bdb6dfff7c939c95a2bc8 100644 (file)
@@ -203,24 +203,27 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
                                break;
                        }
 
+                       if (filp->f_flags & O_NONBLOCK) {
+                               if (!written)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+
                        wait_woken(&wait, TASK_INTERRUPTIBLE,
                                        MAX_SCHEDULE_TIMEOUT);
                        continue;
                }
 
                ret = rb->access->write(rb, n - written, buf + written);
-               if (ret == 0 && (filp->f_flags & O_NONBLOCK))
-                       ret = -EAGAIN;
+               if (ret < 0)
+                       break;
 
-               if (ret > 0) {
-                       written += ret;
-                       if (written != n && !(filp->f_flags & O_NONBLOCK))
-                               continue;
-               }
-       } while (ret == 0);
+               written += ret;
+
+       } while (written != n);
        remove_wait_queue(&rb->pollq, &wait);
 
-       return ret < 0 ? ret : n;
+       return ret < 0 ? ret : written;
 }
 
 /**
index b1674a5bfa368d048b9c3629148e7daec8f0a3f0..d4a34a3bf00d9503fbeff879f1a86278ad159d4e 100644 (file)
@@ -429,6 +429,14 @@ static const struct iio_info cm32181_info = {
        .attrs                  = &cm32181_attribute_group,
 };
 
+static void cm32181_unregister_dummy_client(void *data)
+{
+       struct i2c_client *client = data;
+
+       /* Unregister the dummy client */
+       i2c_unregister_device(client);
+}
+
 static int cm32181_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
@@ -460,6 +468,10 @@ static int cm32181_probe(struct i2c_client *client)
                client = i2c_acpi_new_device(dev, 1, &board_info);
                if (IS_ERR(client))
                        return PTR_ERR(client);
+
+               ret = devm_add_action_or_reset(dev, cm32181_unregister_dummy_client, client);
+               if (ret)
+                       return ret;
        }
 
        cm32181 = iio_priv(indio_dev);
index ad50baa0202cceda80600b8fdd187d478c4351fb..e823c145f6792ee4204697f902d238c0a1b9f440 100644 (file)
@@ -601,6 +601,7 @@ static int tsl2772_read_prox_diodes(struct tsl2772_chip *chip)
                        return -EINVAL;
                }
        }
+       chip->settings.prox_diode = prox_diode_mask;
 
        return 0;
 }
index 6bdfce9747f926088ba9b0f2468e772174c39397..5c44a36ab5b3951896e05c412164d3ead97e4766 100644 (file)
@@ -208,7 +208,6 @@ static int vcnl4000_init(struct vcnl4000_data *data)
 
        data->rev = ret & 0xf;
        data->al_scale = 250000;
-       mutex_init(&data->vcnl4000_lock);
 
        return data->chip_spec->set_power_state(data, true);
 };
@@ -1367,6 +1366,8 @@ static int vcnl4000_probe(struct i2c_client *client)
        data->id = id->driver_data;
        data->chip_spec = &vcnl4000_chip_spec_cfg[data->id];
 
+       mutex_init(&data->vcnl4000_lock);
+
        ret = data->chip_spec->init(data);
        if (ret < 0)
                return ret;
index 3081559377133e4df5f55789435130e48c415d52..6b9563d4f23c94dfab6dbff02a601942a7b315d4 100644 (file)
@@ -624,22 +624,11 @@ static inline unsigned short cma_family(struct rdma_id_private *id_priv)
        return id_priv->id.route.addr.src_addr.ss_family;
 }
 
-static int cma_set_qkey(struct rdma_id_private *id_priv, u32 qkey)
+static int cma_set_default_qkey(struct rdma_id_private *id_priv)
 {
        struct ib_sa_mcmember_rec rec;
        int ret = 0;
 
-       if (id_priv->qkey) {
-               if (qkey && id_priv->qkey != qkey)
-                       return -EINVAL;
-               return 0;
-       }
-
-       if (qkey) {
-               id_priv->qkey = qkey;
-               return 0;
-       }
-
        switch (id_priv->id.ps) {
        case RDMA_PS_UDP:
        case RDMA_PS_IB:
@@ -659,6 +648,16 @@ static int cma_set_qkey(struct rdma_id_private *id_priv, u32 qkey)
        return ret;
 }
 
+static int cma_set_qkey(struct rdma_id_private *id_priv, u32 qkey)
+{
+       if (!qkey ||
+           (id_priv->qkey && (id_priv->qkey != qkey)))
+               return -EINVAL;
+
+       id_priv->qkey = qkey;
+       return 0;
+}
+
 static void cma_translate_ib(struct sockaddr_ib *sib, struct rdma_dev_addr *dev_addr)
 {
        dev_addr->dev_type = ARPHRD_INFINIBAND;
@@ -1229,7 +1228,7 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
        *qp_attr_mask = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT;
 
        if (id_priv->id.qp_type == IB_QPT_UD) {
-               ret = cma_set_qkey(id_priv, 0);
+               ret = cma_set_default_qkey(id_priv);
                if (ret)
                        return ret;
 
@@ -4569,7 +4568,10 @@ static int cma_send_sidr_rep(struct rdma_id_private *id_priv,
        memset(&rep, 0, sizeof rep);
        rep.status = status;
        if (status == IB_SIDR_SUCCESS) {
-               ret = cma_set_qkey(id_priv, qkey);
+               if (qkey)
+                       ret = cma_set_qkey(id_priv, qkey);
+               else
+                       ret = cma_set_default_qkey(id_priv);
                if (ret)
                        return ret;
                rep.qp_num = id_priv->qp_num;
@@ -4774,9 +4776,7 @@ static void cma_make_mc_event(int status, struct rdma_id_private *id_priv,
        enum ib_gid_type gid_type;
        struct net_device *ndev;
 
-       if (!status)
-               status = cma_set_qkey(id_priv, be32_to_cpu(multicast->rec.qkey));
-       else
+       if (status)
                pr_debug_ratelimited("RDMA CM: MULTICAST_ERROR: failed to join multicast. status %d\n",
                                     status);
 
@@ -4804,7 +4804,7 @@ static void cma_make_mc_event(int status, struct rdma_id_private *id_priv,
        }
 
        event->param.ud.qp_num = 0xFFFFFF;
-       event->param.ud.qkey = be32_to_cpu(multicast->rec.qkey);
+       event->param.ud.qkey = id_priv->qkey;
 
 out:
        if (ndev)
@@ -4823,8 +4823,11 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
            READ_ONCE(id_priv->state) == RDMA_CM_DESTROYING)
                goto out;
 
-       cma_make_mc_event(status, id_priv, multicast, &event, mc);
-       ret = cma_cm_event_handler(id_priv, &event);
+       ret = cma_set_qkey(id_priv, be32_to_cpu(multicast->rec.qkey));
+       if (!ret) {
+               cma_make_mc_event(status, id_priv, multicast, &event, mc);
+               ret = cma_cm_event_handler(id_priv, &event);
+       }
        rdma_destroy_ah_attr(&event.param.ud.ah_attr);
        WARN_ON(ret);
 
@@ -4877,9 +4880,11 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
        if (ret)
                return ret;
 
-       ret = cma_set_qkey(id_priv, 0);
-       if (ret)
-               return ret;
+       if (!id_priv->qkey) {
+               ret = cma_set_default_qkey(id_priv);
+               if (ret)
+                       return ret;
+       }
 
        cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
        rec.qkey = cpu_to_be32(id_priv->qkey);
@@ -4956,9 +4961,6 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
        cma_iboe_set_mgid(addr, &ib.rec.mgid, gid_type);
 
        ib.rec.pkey = cpu_to_be16(0xffff);
-       if (id_priv->id.ps == RDMA_PS_UDP)
-               ib.rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
-
        if (dev_addr->bound_dev_if)
                ndev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
        if (!ndev)
@@ -4984,6 +4986,9 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
        if (err || !ib.rec.mtu)
                return err ?: -EINVAL;
 
+       if (!id_priv->qkey)
+               cma_set_default_qkey(id_priv);
+
        rdma_ip2gid((struct sockaddr *)&id_priv->id.route.addr.src_addr,
                    &ib.rec.port_gid);
        INIT_WORK(&mc->iboe_join.work, cma_iboe_join_work_handler);
@@ -5009,6 +5014,9 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
                            READ_ONCE(id_priv->state) != RDMA_CM_ADDR_RESOLVED))
                return -EINVAL;
 
+       if (id_priv->id.qp_type != IB_QPT_UD)
+               return -EINVAL;
+
        mc = kzalloc(sizeof(*mc), GFP_KERNEL);
        if (!mc)
                return -ENOMEM;
index 11b1c1603aeb44e6d0dcbc3904a57a5bf314d03e..b99b3cc283b650b9d001bccbfe0bcfdee6100573 100644 (file)
@@ -532,6 +532,8 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,
        else
                ret = device->ops.create_ah(ah, &init_attr, NULL);
        if (ret) {
+               if (ah->sgid_attr)
+                       rdma_put_gid_attr(ah->sgid_attr);
                kfree(ah);
                return ERR_PTR(ret);
        }
index cabd8678b3558963b3069304ba5372ea0233b3a0..7bc354273d4ec00542efeeca47c384aa7431ad43 100644 (file)
@@ -65,7 +65,7 @@ static const enum ib_wc_opcode wc_mapping_table[ERDMA_NUM_OPCODES] = {
        [ERDMA_OP_LOCAL_INV] = IB_WC_LOCAL_INV,
        [ERDMA_OP_READ_WITH_INV] = IB_WC_RDMA_READ,
        [ERDMA_OP_ATOMIC_CAS] = IB_WC_COMP_SWAP,
-       [ERDMA_OP_ATOMIC_FAD] = IB_WC_FETCH_ADD,
+       [ERDMA_OP_ATOMIC_FAA] = IB_WC_FETCH_ADD,
 };
 
 static const struct {
index 4c38d99c73f1cb1b7044e94d9999da51605fe5d7..37ad1bb1917c4931dd74b1fb3e2ab55784aa8d73 100644 (file)
@@ -441,7 +441,7 @@ struct erdma_reg_mr_sqe {
 };
 
 /* EQ related. */
-#define ERDMA_DEFAULT_EQ_DEPTH 256
+#define ERDMA_DEFAULT_EQ_DEPTH 4096
 
 /* ceqe */
 #define ERDMA_CEQE_HDR_DB_MASK BIT_ULL(63)
@@ -491,7 +491,7 @@ enum erdma_opcode {
        ERDMA_OP_LOCAL_INV = 15,
        ERDMA_OP_READ_WITH_INV = 16,
        ERDMA_OP_ATOMIC_CAS = 17,
-       ERDMA_OP_ATOMIC_FAD = 18,
+       ERDMA_OP_ATOMIC_FAA = 18,
        ERDMA_NUM_OPCODES = 19,
        ERDMA_OP_INVALID = ERDMA_NUM_OPCODES + 1
 };
index 5dc31e5df5cba78ca1025120186fbe891e4551c3..4a29a53a6652eacde0bf5619a3b63850cf9faf2a 100644 (file)
@@ -56,7 +56,7 @@ done:
 static int erdma_enum_and_get_netdev(struct erdma_dev *dev)
 {
        struct net_device *netdev;
-       int ret = -ENODEV;
+       int ret = -EPROBE_DEFER;
 
        /* Already binded to a net_device, so we skip. */
        if (dev->netdev)
index d088d6bef431afa8c6936219dd2f60a6ce46942e..44923c51a01b44d7dc322fd472e0a0988d8dec2b 100644 (file)
@@ -405,7 +405,7 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
                        FIELD_PREP(ERDMA_SQE_MR_MTT_CNT_MASK,
                                   mr->mem.mtt_nents);
 
-               if (mr->mem.mtt_nents < ERDMA_MAX_INLINE_MTT_ENTRIES) {
+               if (mr->mem.mtt_nents <= ERDMA_MAX_INLINE_MTT_ENTRIES) {
                        attrs |= FIELD_PREP(ERDMA_SQE_MR_MTT_TYPE_MASK, 0);
                        /* Copy SGLs to SQE content to accelerate */
                        memcpy(get_queue_entry(qp->kern_qp.sq_buf, idx + 1,
@@ -439,7 +439,7 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
                                cpu_to_le64(atomic_wr(send_wr)->compare_add);
                } else {
                        wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK,
-                                             ERDMA_OP_ATOMIC_FAD);
+                                             ERDMA_OP_ATOMIC_FAA);
                        atomic_sqe->fetchadd_swap_data =
                                cpu_to_le64(atomic_wr(send_wr)->compare_add);
                }
index e0a993bc032a44aaa76e399ead33ccf8f6f0734e..131cf5f409822cb50daa57a8a24b17d4136dd393 100644 (file)
@@ -11,7 +11,7 @@
 
 /* RDMA Capability. */
 #define ERDMA_MAX_PD (128 * 1024)
-#define ERDMA_MAX_SEND_WR 4096
+#define ERDMA_MAX_SEND_WR 8192
 #define ERDMA_MAX_ORD 128
 #define ERDMA_MAX_IRD 128
 #define ERDMA_MAX_SGE_RD 1
index b1d6ca7e970830aef6eedee06f069ad8f5a0984b..f3d6ce45c3974764f3d8956f98e4133b35ef6d22 100644 (file)
@@ -267,6 +267,8 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
 
        if (!HFI1_CAP_IS_KSET(SDMA))
                return -EINVAL;
+       if (!from->user_backed)
+               return -EINVAL;
        idx = srcu_read_lock(&fd->pq_srcu);
        pq = srcu_dereference(fd->pq, &fd->pq_srcu);
        if (!cq || !pq) {
@@ -274,11 +276,6 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
                return -EIO;
        }
 
-       if (!iter_is_iovec(from) || !dim) {
-               srcu_read_unlock(&fd->pq_srcu, idx);
-               return -EINVAL;
-       }
-
        trace_hfi1_sdma_request(fd->dd, fd->uctxt->ctxt, fd->subctxt, dim);
 
        if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) {
@@ -287,11 +284,12 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
        }
 
        while (dim) {
+               const struct iovec *iov = iter_iov(from);
                int ret;
                unsigned long count = 0;
 
                ret = hfi1_user_sdma_process_request(
-                       fd, (struct iovec *)(from->iov + done),
+                       fd, (struct iovec *)(iov + done),
                        dim, &count);
                if (ret) {
                        reqs = ret;
index 195aa9ea18b6ca74c24dc7c45a24d693cedece9b..8817864154af1f079eda127f648085b2d9107999 100644 (file)
@@ -1458,13 +1458,15 @@ static int irdma_send_fin(struct irdma_cm_node *cm_node)
  * irdma_find_listener - find a cm node listening on this addr-port pair
  * @cm_core: cm's core
  * @dst_addr: listener ip addr
+ * @ipv4: flag indicating IPv4 when true
  * @dst_port: listener tcp port num
  * @vlan_id: virtual LAN ID
  * @listener_state: state to match with listen node's
  */
 static struct irdma_cm_listener *
-irdma_find_listener(struct irdma_cm_core *cm_core, u32 *dst_addr, u16 dst_port,
-                   u16 vlan_id, enum irdma_cm_listener_state listener_state)
+irdma_find_listener(struct irdma_cm_core *cm_core, u32 *dst_addr, bool ipv4,
+                   u16 dst_port, u16 vlan_id,
+                   enum irdma_cm_listener_state listener_state)
 {
        struct irdma_cm_listener *listen_node;
        static const u32 ip_zero[4] = { 0, 0, 0, 0 };
@@ -1477,7 +1479,7 @@ irdma_find_listener(struct irdma_cm_core *cm_core, u32 *dst_addr, u16 dst_port,
        list_for_each_entry (listen_node, &cm_core->listen_list, list) {
                memcpy(listen_addr, listen_node->loc_addr, sizeof(listen_addr));
                listen_port = listen_node->loc_port;
-               if (listen_port != dst_port ||
+               if (listen_node->ipv4 != ipv4 || listen_port != dst_port ||
                    !(listener_state & listen_node->listener_state))
                        continue;
                /* compare node pair, return node handle if a match */
@@ -2902,9 +2904,10 @@ irdma_make_listen_node(struct irdma_cm_core *cm_core,
        unsigned long flags;
 
        /* cannot have multiple matching listeners */
-       listener = irdma_find_listener(cm_core, cm_info->loc_addr,
-                                      cm_info->loc_port, cm_info->vlan_id,
-                                      IRDMA_CM_LISTENER_EITHER_STATE);
+       listener =
+               irdma_find_listener(cm_core, cm_info->loc_addr, cm_info->ipv4,
+                                   cm_info->loc_port, cm_info->vlan_id,
+                                   IRDMA_CM_LISTENER_EITHER_STATE);
        if (listener &&
            listener->listener_state == IRDMA_CM_LISTENER_ACTIVE_STATE) {
                refcount_dec(&listener->refcnt);
@@ -3153,6 +3156,7 @@ void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf)
 
                listener = irdma_find_listener(cm_core,
                                               cm_info.loc_addr,
+                                              cm_info.ipv4,
                                               cm_info.loc_port,
                                               cm_info.vlan_id,
                                               IRDMA_CM_LISTENER_ACTIVE_STATE);
index 19c284975fc7c874cc62d1253d4b60664c1a8aa9..7feadb3e1eda343c1fcfc1d6a47ff035317ae94c 100644 (file)
@@ -41,7 +41,7 @@
 #define TCP_OPTIONS_PADDING    3
 
 #define IRDMA_DEFAULT_RETRYS   64
-#define IRDMA_DEFAULT_RETRANS  8
+#define IRDMA_DEFAULT_RETRANS  32
 #define IRDMA_DEFAULT_TTL              0x40
 #define IRDMA_DEFAULT_RTT_VAR          6
 #define IRDMA_DEFAULT_SS_THRESH                0x3fffffff
index 2e1e2bad04011a42e4e025eb46774d2feaf7307b..43dfa4761f0698e5530ae403dcc68a9cff85a9cf 100644 (file)
@@ -41,6 +41,7 @@ static enum irdma_hmc_rsrc_type iw_hmc_obj_types[] = {
        IRDMA_HMC_IW_XFFL,
        IRDMA_HMC_IW_Q1,
        IRDMA_HMC_IW_Q1FL,
+       IRDMA_HMC_IW_PBLE,
        IRDMA_HMC_IW_TIMER,
        IRDMA_HMC_IW_FSIMC,
        IRDMA_HMC_IW_FSIAV,
@@ -827,6 +828,8 @@ static int irdma_create_hmc_objs(struct irdma_pci_f *rf, bool privileged,
        info.entry_type = rf->sd_type;
 
        for (i = 0; i < IW_HMC_OBJ_TYPE_NUM; i++) {
+               if (iw_hmc_obj_types[i] == IRDMA_HMC_IW_PBLE)
+                       continue;
                if (dev->hmc_info->hmc_obj[iw_hmc_obj_types[i]].cnt) {
                        info.rsrc_type = iw_hmc_obj_types[i];
                        info.count = dev->hmc_info->hmc_obj[info.rsrc_type].cnt;
index 445e69e864097ef85adbf351387eccd08150ffcb..7887230c867b1efd784ff5415e9704eff96044c6 100644 (file)
@@ -2595,7 +2595,10 @@ void irdma_generate_flush_completions(struct irdma_qp *iwqp)
                        /* remove the SQ WR by moving SQ tail*/
                        IRDMA_RING_SET_TAIL(*sq_ring,
                                sq_ring->tail + qp->sq_wrtrk_array[sq_ring->tail].quanta);
-
+                       if (cmpl->cpi.op_type == IRDMAQP_OP_NOP) {
+                               kfree(cmpl);
+                               continue;
+                       }
                        ibdev_dbg(iwqp->iwscq->ibcq.device,
                                  "DEV: %s: adding wr_id = 0x%llx SQ Completion to list qp_id=%d\n",
                                  __func__, cmpl->cpi.wr_id, qp->qp_id);
index 5b988db66b8fdb90c8c9303bbe29d4d3ec6f0a54..5d45de223c43a9afed62a70265b9e32d75db4e10 100644 (file)
@@ -442,6 +442,10 @@ static int translate_eth_ext_proto_oper(u32 eth_proto_oper, u16 *active_speed,
                *active_width = IB_WIDTH_2X;
                *active_speed = IB_SPEED_NDR;
                break;
+       case MLX5E_PROT_MASK(MLX5E_400GAUI_8):
+               *active_width = IB_WIDTH_8X;
+               *active_speed = IB_SPEED_HDR;
+               break;
        case MLX5E_PROT_MASK(MLX5E_400GAUI_4_400GBASE_CR4_KR4):
                *active_width = IB_WIDTH_4X;
                *active_speed = IB_SPEED_NDR;
index 80fe92a21f960e341eb85e3c27b6fb2ae89d66cd..815ea72ad4739836eb299ab482c621aaf795e716 100644 (file)
@@ -2245,10 +2245,10 @@ static ssize_t qib_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct qib_ctxtdata *rcd = ctxt_fp(iocb->ki_filp);
        struct qib_user_sdma_queue *pq = fp->pq;
 
-       if (!iter_is_iovec(from) || !from->nr_segs || !pq)
+       if (!from->user_backed || !from->nr_segs || !pq)
                return -EINVAL;
 
-       return qib_user_sdma_writev(rcd, pq, from->iov, from->nr_segs);
+       return qib_user_sdma_writev(rcd, pq, iter_iov(from), from->nr_segs);
 }
 
 static struct class *qib_class;
index 3acab569fbb94aa668b18e1c06c190ce199970f9..9b4c0389d2c006c41ae6967420ed77fa42ca285b 100644 (file)
@@ -97,7 +97,7 @@ static void cacheless_memcpy(void *dst, void *src, size_t n)
         * there are no security issues.  The extra fault recovery machinery
         * is not invoked.
         */
-       __copy_user_nocache(dst, (void __user *)src, n, 0);
+       __copy_user_nocache(dst, (void __user *)src, n);
 }
 
 void rvt_wss_exit(struct rvt_dev_info *rdi)
index f642ec8e92ddd4bacebbf0046256af54ef363348..29131f1a2f067166eef3638d60546304c941e786 100644 (file)
@@ -781,9 +781,6 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
        input_report_key(dev, BTN_C, data[8]);
        input_report_key(dev, BTN_Z, data[9]);
 
-       /* Profile button has a value of 0-3, so it is reported as an axis */
-       if (xpad->mapping & MAP_PROFILE_BUTTON)
-               input_report_abs(dev, ABS_PROFILE, data[34]);
 
        input_sync(dev);
 }
@@ -1061,6 +1058,10 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
                                        (__u16) le16_to_cpup((__le16 *)(data + 8)));
                }
 
+               /* Profile button has a value of 0-3, so it is reported as an axis */
+               if (xpad->mapping & MAP_PROFILE_BUTTON)
+                       input_report_abs(dev, ABS_PROFILE, data[34]);
+
                /* paddle handling */
                /* based on SDL's SDL_hidapi_xboxone.c */
                if (xpad->mapping & MAP_PADDLES) {
index 989228b5a0a44d050fa83f291d7c2bd32b576a1e..e2c11d9f3868f3ea2ec05a4230472070e32d20a4 100644 (file)
@@ -852,8 +852,8 @@ static void alps_process_packet_v6(struct psmouse *psmouse)
                        x = y = z = 0;
 
                /* Divide 4 since trackpoint's speed is too fast */
-               input_report_rel(dev2, REL_X, (char)x / 4);
-               input_report_rel(dev2, REL_Y, -((char)y / 4));
+               input_report_rel(dev2, REL_X, (s8)x / 4);
+               input_report_rel(dev2, REL_Y, -((s8)y / 4));
 
                psmouse_report_standard_buttons(dev2, packet[3]);
 
@@ -1104,8 +1104,8 @@ static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
            ((packet[3] & 0x20) << 1);
        z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
 
-       input_report_rel(dev2, REL_X, (char)x);
-       input_report_rel(dev2, REL_Y, -((char)y));
+       input_report_rel(dev2, REL_X, (s8)x);
+       input_report_rel(dev2, REL_Y, -((s8)y));
        input_report_abs(dev2, ABS_PRESSURE, z);
 
        psmouse_report_standard_buttons(dev2, packet[1]);
@@ -2294,20 +2294,20 @@ static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
        if (reg < 0)
                return reg;
 
-       x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+       x_pitch = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
        x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
 
-       y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
+       y_pitch = (s8)reg >> 4; /* sign extend upper 4 bits */
        y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
 
        reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
        if (reg < 0)
                return reg;
 
-       x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+       x_electrode = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
        x_electrode = 17 + x_electrode;
 
-       y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
+       y_electrode = (s8)reg >> 4; /* sign extend upper 4 bits */
        y_electrode = 13 + y_electrode;
 
        x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
index 6fd5fff0cbfffd752748d995bab8256c12c9e258..c74b99077d16a35637c1d0c015a772cea687c13b 100644 (file)
@@ -202,8 +202,8 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
        state->pressed = packet[0] >> 7;
        finger1 = ((packet[0] >> 4) & 0x7) - 1;
        if (finger1 < FOC_MAX_FINGERS) {
-               state->fingers[finger1].x += (char)packet[1];
-               state->fingers[finger1].y += (char)packet[2];
+               state->fingers[finger1].x += (s8)packet[1];
+               state->fingers[finger1].y += (s8)packet[2];
        } else {
                psmouse_err(psmouse, "First finger in rel packet invalid: %d\n",
                            finger1);
@@ -218,8 +218,8 @@ static void focaltech_process_rel_packet(struct psmouse *psmouse,
         */
        finger2 = ((packet[3] >> 4) & 0x7) - 1;
        if (finger2 < FOC_MAX_FINGERS) {
-               state->fingers[finger2].x += (char)packet[4];
-               state->fingers[finger2].y += (char)packet[5];
+               state->fingers[finger2].x += (s8)packet[4];
+               state->fingers[finger2].y += (s8)packet[5];
        }
 }
 
index efc61736099b9a606951b8274a6deebbd8488fa0..028e45bd050bf3f151cee382b666bfce86775ee7 100644 (file)
@@ -610,6 +610,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
                },
                .driver_data = (void *)(SERIO_QUIRK_NOMUX)
        },
+       {
+               /* Fujitsu Lifebook A574/H */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "FMVA0501PZ"),
+               },
+               .driver_data = (void *)(SERIO_QUIRK_NOMUX)
+       },
        {
                /* Gigabyte M912 */
                .matches = {
@@ -1116,6 +1124,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
                .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
                                        SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
        },
+       {
+               /*
+                * Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes
+                * the keyboard very laggy for ~5 seconds after boot and
+                * sometimes also after resume.
+                * However both are required for the keyboard to not fail
+                * completely sometimes after boot or resume.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "N150CU"),
+               },
+               .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+                                       SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
@@ -1123,6 +1145,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
                .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
                                        SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
        },
+       {
+               /*
+                * Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes
+                * the keyboard very laggy for ~5 seconds after boot and
+                * sometimes also after resume.
+                * However both are required for the keyboard to not fail
+                * completely sometimes after boot or resume.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "NHxxRZQ"),
+               },
+               .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+                                       SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
index d836d3dcc6a2491905535f0c8fcab35d5ae6b541..a68da2988f9cd828942b5a23eed5efd5576cb7f5 100644 (file)
@@ -296,6 +296,12 @@ static int pegasus_probe(struct usb_interface *intf,
        pegasus->intf = intf;
 
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+       /* Sanity check that pipe's type matches endpoint's type */
+       if (usb_pipe_type_check(dev, pipe)) {
+               error = -EINVAL;
+               goto err_free_mem;
+       }
+
        pegasus->data_len = usb_maxpacket(dev, pipe);
 
        pegasus->data = usb_alloc_coherent(dev, pegasus->data_len, GFP_KERNEL,
index 16caffa35dd99ed0cf7944b68298d2b46f5cab1c..30102cb80fac823ae47a27cc64a540a78211e656 100644 (file)
@@ -111,6 +111,7 @@ struct cyttsp5_sensing_conf_data_dev {
        __le16 max_z;
        u8 origin_x;
        u8 origin_y;
+       u8 panel_id;
        u8 btn;
        u8 scan_mode;
        u8 max_num_of_tch_per_refresh_cycle;
index b348172f19c3de1ae79c70b1a1fccfebfacd17db..d77f116680a0a098ffaa06f8c33666dff092fd4a 100644 (file)
@@ -124,10 +124,18 @@ static const unsigned long goodix_irq_flags[] = {
 static const struct dmi_system_id nine_bytes_report[] = {
 #if defined(CONFIG_DMI) && defined(CONFIG_X86)
        {
-               .ident = "Lenovo YogaBook",
-               /* YB1-X91L/F and YB1-X90L/F */
+               /* Lenovo Yoga Book X90F / X90L */
                .matches = {
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9")
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+               }
+       },
+       {
+               /* Lenovo Yoga Book X91F / X91L */
+               .matches = {
+                       /* Non exact match to match F + L versions */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
                }
        },
 #endif
index 0f392f59b1353142188dcc12774b9c53dcb181f0..7a24c1444ace3c50e4727dd757c123c74fc05b17 100644 (file)
@@ -850,6 +850,10 @@ void icc_node_destroy(int id)
 
        mutex_unlock(&icc_lock);
 
+       if (!node)
+               return;
+
+       kfree(node->links);
        kfree(node);
 }
 EXPORT_SYMBOL_GPL(icc_node_destroy);
@@ -1029,54 +1033,68 @@ int icc_nodes_remove(struct icc_provider *provider)
 EXPORT_SYMBOL_GPL(icc_nodes_remove);
 
 /**
- * icc_provider_add() - add a new interconnect provider
- * @provider: the interconnect provider that will be added into topology
+ * icc_provider_init() - initialize a new interconnect provider
+ * @provider: the interconnect provider to initialize
+ *
+ * Must be called before adding nodes to the provider.
+ */
+void icc_provider_init(struct icc_provider *provider)
+{
+       WARN_ON(!provider->set);
+
+       INIT_LIST_HEAD(&provider->nodes);
+}
+EXPORT_SYMBOL_GPL(icc_provider_init);
+
+/**
+ * icc_provider_register() - register a new interconnect provider
+ * @provider: the interconnect provider to register
  *
  * Return: 0 on success, or an error code otherwise
  */
-int icc_provider_add(struct icc_provider *provider)
+int icc_provider_register(struct icc_provider *provider)
 {
-       if (WARN_ON(!provider->set))
-               return -EINVAL;
        if (WARN_ON(!provider->xlate && !provider->xlate_extended))
                return -EINVAL;
 
        mutex_lock(&icc_lock);
-
-       INIT_LIST_HEAD(&provider->nodes);
        list_add_tail(&provider->provider_list, &icc_providers);
-
        mutex_unlock(&icc_lock);
 
-       dev_dbg(provider->dev, "interconnect provider added to topology\n");
+       dev_dbg(provider->dev, "interconnect provider registered\n");
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(icc_provider_add);
+EXPORT_SYMBOL_GPL(icc_provider_register);
 
 /**
- * icc_provider_del() - delete previously added interconnect provider
- * @provider: the interconnect provider that will be removed from topology
+ * icc_provider_deregister() - deregister an interconnect provider
+ * @provider: the interconnect provider to deregister
  */
-void icc_provider_del(struct icc_provider *provider)
+void icc_provider_deregister(struct icc_provider *provider)
 {
        mutex_lock(&icc_lock);
-       if (provider->users) {
-               pr_warn("interconnect provider still has %d users\n",
-                       provider->users);
-               mutex_unlock(&icc_lock);
-               return;
-       }
-
-       if (!list_empty(&provider->nodes)) {
-               pr_warn("interconnect provider still has nodes\n");
-               mutex_unlock(&icc_lock);
-               return;
-       }
+       WARN_ON(provider->users);
 
        list_del(&provider->provider_list);
        mutex_unlock(&icc_lock);
 }
+EXPORT_SYMBOL_GPL(icc_provider_deregister);
+
+int icc_provider_add(struct icc_provider *provider)
+{
+       icc_provider_init(provider);
+
+       return icc_provider_register(provider);
+}
+EXPORT_SYMBOL_GPL(icc_provider_add);
+
+void icc_provider_del(struct icc_provider *provider)
+{
+       WARN_ON(!list_empty(&provider->nodes));
+
+       icc_provider_deregister(provider);
+}
 EXPORT_SYMBOL_GPL(icc_provider_del);
 
 static const struct of_device_id __maybe_unused ignore_list[] = {
index 823d9be9771a1c70a3d3db7d3b844a68c868854c..979ed610f704b576d346547deba78a2ea2b2a4d5 100644 (file)
@@ -295,6 +295,9 @@ int imx_icc_register(struct platform_device *pdev,
        provider->xlate = of_icc_xlate_onecell;
        provider->data = data;
        provider->dev = dev->parent;
+
+       icc_provider_init(provider);
+
        platform_set_drvdata(pdev, imx_provider);
 
        if (settings) {
@@ -306,20 +309,18 @@ int imx_icc_register(struct platform_device *pdev,
                }
        }
 
-       ret = icc_provider_add(provider);
-       if (ret) {
-               dev_err(dev, "error adding interconnect provider: %d\n", ret);
+       ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
+       if (ret)
                return ret;
-       }
 
-       ret = imx_icc_register_nodes(imx_provider, nodes, nodes_count, settings);
+       ret = icc_provider_register(provider);
        if (ret)
-               goto provider_del;
+               goto err_unregister_nodes;
 
        return 0;
 
-provider_del:
-       icc_provider_del(provider);
+err_unregister_nodes:
+       imx_icc_unregister_nodes(&imx_provider->provider);
        return ret;
 }
 EXPORT_SYMBOL_GPL(imx_icc_register);
@@ -328,9 +329,8 @@ void imx_icc_unregister(struct platform_device *pdev)
 {
        struct imx_icc_provider *imx_provider = platform_get_drvdata(pdev);
 
+       icc_provider_deregister(&imx_provider->provider);
        imx_icc_unregister_nodes(&imx_provider->provider);
-
-       icc_provider_del(&imx_provider->provider);
 }
 EXPORT_SYMBOL_GPL(imx_icc_unregister);
 
index df3196f7253687248bbd00fe2099e6d531171f38..4180a06681b2b9aca3134ee1aeb57e2c0ca6df20 100644 (file)
@@ -503,7 +503,6 @@ regmap_done:
        }
 
        provider = &qp->provider;
-       INIT_LIST_HEAD(&provider->nodes);
        provider->dev = dev;
        provider->set = qcom_icc_set;
        provider->pre_aggregate = qcom_icc_pre_bw_aggregate;
@@ -511,12 +510,7 @@ regmap_done:
        provider->xlate_extended = qcom_icc_xlate_extended;
        provider->data = data;
 
-       ret = icc_provider_add(provider);
-       if (ret) {
-               dev_err(dev, "error adding interconnect provider: %d\n", ret);
-               clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-               return ret;
-       }
+       icc_provider_init(provider);
 
        for (i = 0; i < num_nodes; i++) {
                size_t j;
@@ -524,7 +518,7 @@ regmap_done:
                node = icc_node_create(qnodes[i]->id);
                if (IS_ERR(node)) {
                        ret = PTR_ERR(node);
-                       goto err;
+                       goto err_remove_nodes;
                }
 
                node->name = qnodes[i]->name;
@@ -538,17 +532,26 @@ regmap_done:
        }
        data->num_nodes = num_nodes;
 
+       ret = icc_provider_register(provider);
+       if (ret)
+               goto err_remove_nodes;
+
        platform_set_drvdata(pdev, qp);
 
        /* Populate child NoC devices if any */
-       if (of_get_child_count(dev->of_node) > 0)
-               return of_platform_populate(dev->of_node, NULL, NULL, dev);
+       if (of_get_child_count(dev->of_node) > 0) {
+               ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+               if (ret)
+                       goto err_deregister_provider;
+       }
 
        return 0;
-err:
+
+err_deregister_provider:
+       icc_provider_deregister(provider);
+err_remove_nodes:
        icc_nodes_remove(provider);
        clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-       icc_provider_del(provider);
 
        return ret;
 }
@@ -558,9 +561,9 @@ int qnoc_remove(struct platform_device *pdev)
 {
        struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
 
+       icc_provider_deregister(&qp->provider);
        icc_nodes_remove(&qp->provider);
        clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-       icc_provider_del(&qp->provider);
 
        return 0;
 }
index fd17291c61eb96b5b9480669c1f1f090b41c2825..fdb5e58e408b4da8d42f614fad20805cc9c09ca0 100644 (file)
@@ -192,9 +192,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
        provider->pre_aggregate = qcom_icc_pre_aggregate;
        provider->aggregate = qcom_icc_aggregate;
        provider->xlate_extended = qcom_icc_xlate_extended;
-       INIT_LIST_HEAD(&provider->nodes);
        provider->data = data;
 
+       icc_provider_init(provider);
+
        qp->dev = dev;
        qp->bcms = desc->bcms;
        qp->num_bcms = desc->num_bcms;
@@ -203,10 +204,6 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
        if (IS_ERR(qp->voter))
                return PTR_ERR(qp->voter);
 
-       ret = icc_provider_add(provider);
-       if (ret)
-               return ret;
-
        for (i = 0; i < qp->num_bcms; i++)
                qcom_icc_bcm_init(qp->bcms[i], dev);
 
@@ -218,7 +215,7 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
                node = icc_node_create(qn->id);
                if (IS_ERR(node)) {
                        ret = PTR_ERR(node);
-                       goto err;
+                       goto err_remove_nodes;
                }
 
                node->name = qn->name;
@@ -232,16 +229,27 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
        }
 
        data->num_nodes = num_nodes;
+
+       ret = icc_provider_register(provider);
+       if (ret)
+               goto err_remove_nodes;
+
        platform_set_drvdata(pdev, qp);
 
        /* Populate child NoC devices if any */
-       if (of_get_child_count(dev->of_node) > 0)
-               return of_platform_populate(dev->of_node, NULL, NULL, dev);
+       if (of_get_child_count(dev->of_node) > 0) {
+               ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+               if (ret)
+                       goto err_deregister_provider;
+       }
 
        return 0;
-err:
+
+err_deregister_provider:
+       icc_provider_deregister(provider);
+err_remove_nodes:
        icc_nodes_remove(provider);
-       icc_provider_del(provider);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(qcom_icc_rpmh_probe);
@@ -250,8 +258,8 @@ int qcom_icc_rpmh_remove(struct platform_device *pdev)
 {
        struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
 
+       icc_provider_deregister(&qp->provider);
        icc_nodes_remove(&qp->provider);
-       icc_provider_del(&qp->provider);
 
        return 0;
 }
index 5ea192f1141dc42f4cee48fb6c28cc51bcd65430..1828deaca44326249d0e29da7c5cf9456a5b2315 100644 (file)
@@ -692,7 +692,6 @@ static int msm8974_icc_probe(struct platform_device *pdev)
                return ret;
 
        provider = &qp->provider;
-       INIT_LIST_HEAD(&provider->nodes);
        provider->dev = dev;
        provider->set = msm8974_icc_set;
        provider->aggregate = icc_std_aggregate;
@@ -700,11 +699,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        provider->data = data;
        provider->get_bw = msm8974_get_bw;
 
-       ret = icc_provider_add(provider);
-       if (ret) {
-               dev_err(dev, "error adding interconnect provider: %d\n", ret);
-               goto err_disable_clks;
-       }
+       icc_provider_init(provider);
 
        for (i = 0; i < num_nodes; i++) {
                size_t j;
@@ -712,7 +707,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
                node = icc_node_create(qnodes[i]->id);
                if (IS_ERR(node)) {
                        ret = PTR_ERR(node);
-                       goto err_del_icc;
+                       goto err_remove_nodes;
                }
 
                node->name = qnodes[i]->name;
@@ -729,15 +724,16 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        }
        data->num_nodes = num_nodes;
 
+       ret = icc_provider_register(provider);
+       if (ret)
+               goto err_remove_nodes;
+
        platform_set_drvdata(pdev, qp);
 
        return 0;
 
-err_del_icc:
+err_remove_nodes:
        icc_nodes_remove(provider);
-       icc_provider_del(provider);
-
-err_disable_clks:
        clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
 
        return ret;
@@ -747,9 +743,9 @@ static int msm8974_icc_remove(struct platform_device *pdev)
 {
        struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
 
+       icc_provider_deregister(&qp->provider);
        icc_nodes_remove(&qp->provider);
        clk_bulk_disable_unprepare(qp->num_clks, qp->bus_clks);
-       icc_provider_del(&qp->provider);
 
        return 0;
 }
index 5fa1710874258926ac8c31a7b8b70e0880a538d8..1bafb54f1432912a6fdbc4846ca5549390de031c 100644 (file)
@@ -158,8 +158,8 @@ static int qcom_osm_l3_remove(struct platform_device *pdev)
 {
        struct qcom_osm_l3_icc_provider *qp = platform_get_drvdata(pdev);
 
+       icc_provider_deregister(&qp->provider);
        icc_nodes_remove(&qp->provider);
-       icc_provider_del(&qp->provider);
 
        return 0;
 }
@@ -236,7 +236,7 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
        qnodes = desc->nodes;
        num_nodes = desc->num_nodes;
 
-       data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
+       data = devm_kzalloc(&pdev->dev, struct_size(data, nodes, num_nodes), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
@@ -245,14 +245,9 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
        provider->set = qcom_osm_l3_set;
        provider->aggregate = icc_std_aggregate;
        provider->xlate = of_icc_xlate_onecell;
-       INIT_LIST_HEAD(&provider->nodes);
        provider->data = data;
 
-       ret = icc_provider_add(provider);
-       if (ret) {
-               dev_err(&pdev->dev, "error adding interconnect provider\n");
-               return ret;
-       }
+       icc_provider_init(provider);
 
        for (i = 0; i < num_nodes; i++) {
                size_t j;
@@ -275,12 +270,15 @@ static int qcom_osm_l3_probe(struct platform_device *pdev)
        }
        data->num_nodes = num_nodes;
 
+       ret = icc_provider_register(provider);
+       if (ret)
+               goto err;
+
        platform_set_drvdata(pdev, qp);
 
        return 0;
 err:
        icc_nodes_remove(provider);
-       icc_provider_del(provider);
 
        return ret;
 }
index 0da612d6398c54874f6b97f674e50edabc5247a5..a29cdb4fac03faec3c376bd68e0a7a5c86c0404a 100644 (file)
@@ -147,9 +147,9 @@ static struct qcom_icc_node mas_snoc_bimc_nrt = {
        .name = "mas_snoc_bimc_nrt",
        .buswidth = 16,
        .qos.ap_owned = true,
-       .qos.qos_port = 2,
+       .qos.qos_port = 3,
        .qos.qos_mode = NOC_QOS_MODE_BYPASS,
-       .mas_rpm_id = 163,
+       .mas_rpm_id = 164,
        .slv_rpm_id = -1,
        .num_links = ARRAY_SIZE(mas_snoc_bimc_nrt_links),
        .links = mas_snoc_bimc_nrt_links,
index e3a12e3d6e0619275670d3d41a69680f8c61d667..2d7a8e7b85ec29e94684ee7cc172be46109f89ec 100644 (file)
@@ -1844,100 +1844,6 @@ static const struct qcom_icc_desc sm8450_system_noc = {
        .num_bcms = ARRAY_SIZE(system_noc_bcms),
 };
 
-static int qnoc_probe(struct platform_device *pdev)
-{
-       const struct qcom_icc_desc *desc;
-       struct icc_onecell_data *data;
-       struct icc_provider *provider;
-       struct qcom_icc_node * const *qnodes;
-       struct qcom_icc_provider *qp;
-       struct icc_node *node;
-       size_t num_nodes, i;
-       int ret;
-
-       desc = device_get_match_data(&pdev->dev);
-       if (!desc)
-               return -EINVAL;
-
-       qnodes = desc->nodes;
-       num_nodes = desc->num_nodes;
-
-       qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
-       if (!qp)
-               return -ENOMEM;
-
-       data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       provider = &qp->provider;
-       provider->dev = &pdev->dev;
-       provider->set = qcom_icc_set;
-       provider->pre_aggregate = qcom_icc_pre_aggregate;
-       provider->aggregate = qcom_icc_aggregate;
-       provider->xlate_extended = qcom_icc_xlate_extended;
-       INIT_LIST_HEAD(&provider->nodes);
-       provider->data = data;
-
-       qp->dev = &pdev->dev;
-       qp->bcms = desc->bcms;
-       qp->num_bcms = desc->num_bcms;
-
-       qp->voter = of_bcm_voter_get(qp->dev, NULL);
-       if (IS_ERR(qp->voter))
-               return PTR_ERR(qp->voter);
-
-       ret = icc_provider_add(provider);
-       if (ret) {
-               dev_err(&pdev->dev, "error adding interconnect provider\n");
-               return ret;
-       }
-
-       for (i = 0; i < qp->num_bcms; i++)
-               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
-       for (i = 0; i < num_nodes; i++) {
-               size_t j;
-
-               if (!qnodes[i])
-                       continue;
-
-               node = icc_node_create(qnodes[i]->id);
-               if (IS_ERR(node)) {
-                       ret = PTR_ERR(node);
-                       goto err;
-               }
-
-               node->name = qnodes[i]->name;
-               node->data = qnodes[i];
-               icc_node_add(node, provider);
-
-               for (j = 0; j < qnodes[i]->num_links; j++)
-                       icc_link_create(node, qnodes[i]->links[j]);
-
-               data->nodes[i] = node;
-       }
-       data->num_nodes = num_nodes;
-
-       platform_set_drvdata(pdev, qp);
-
-       return 0;
-err:
-       icc_nodes_remove(provider);
-       icc_provider_del(provider);
-       return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
-       struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
-       icc_nodes_remove(&qp->provider);
-       icc_provider_del(&qp->provider);
-
-       return 0;
-}
-
 static const struct of_device_id qnoc_of_match[] = {
        { .compatible = "qcom,sm8450-aggre1-noc",
          .data = &sm8450_aggre1_noc},
@@ -1966,8 +1872,8 @@ static const struct of_device_id qnoc_of_match[] = {
 MODULE_DEVICE_TABLE(of, qnoc_of_match);
 
 static struct platform_driver qnoc_driver = {
-       .probe = qnoc_probe,
-       .remove = qnoc_remove,
+       .probe = qcom_icc_rpmh_probe,
+       .remove = qcom_icc_rpmh_remove,
        .driver = {
                .name = "qnoc-sm8450",
                .of_match_table = qnoc_of_match,
index 54fa027ab961f7c86a1208538f0d1c9c7d052338..d823ba988ef68c75a976de744c0e04750364bc2b 100644 (file)
@@ -2165,101 +2165,6 @@ static const struct qcom_icc_desc sm8550_system_noc = {
        .num_bcms = ARRAY_SIZE(system_noc_bcms),
 };
 
-static int qnoc_probe(struct platform_device *pdev)
-{
-       const struct qcom_icc_desc *desc;
-       struct icc_onecell_data *data;
-       struct icc_provider *provider;
-       struct qcom_icc_node * const *qnodes;
-       struct qcom_icc_provider *qp;
-       struct icc_node *node;
-       size_t num_nodes, i;
-       int ret;
-
-       desc = device_get_match_data(&pdev->dev);
-       if (!desc)
-               return -EINVAL;
-
-       qnodes = desc->nodes;
-       num_nodes = desc->num_nodes;
-
-       qp = devm_kzalloc(&pdev->dev, sizeof(*qp), GFP_KERNEL);
-       if (!qp)
-               return -ENOMEM;
-
-       data = devm_kcalloc(&pdev->dev, num_nodes, sizeof(*node), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       provider = &qp->provider;
-       provider->dev = &pdev->dev;
-       provider->set = qcom_icc_set;
-       provider->pre_aggregate = qcom_icc_pre_aggregate;
-       provider->aggregate = qcom_icc_aggregate;
-       provider->xlate_extended = qcom_icc_xlate_extended;
-       INIT_LIST_HEAD(&provider->nodes);
-       provider->data = data;
-
-       qp->dev = &pdev->dev;
-       qp->bcms = desc->bcms;
-       qp->num_bcms = desc->num_bcms;
-
-       qp->voter = of_bcm_voter_get(qp->dev, NULL);
-       if (IS_ERR(qp->voter))
-               return PTR_ERR(qp->voter);
-
-       ret = icc_provider_add(provider);
-       if (ret) {
-               dev_err_probe(&pdev->dev, ret,
-                             "error adding interconnect provider\n");
-               return ret;
-       }
-
-       for (i = 0; i < qp->num_bcms; i++)
-               qcom_icc_bcm_init(qp->bcms[i], &pdev->dev);
-
-       for (i = 0; i < num_nodes; i++) {
-               size_t j;
-
-               if (!qnodes[i])
-                       continue;
-
-               node = icc_node_create(qnodes[i]->id);
-               if (IS_ERR(node)) {
-                       ret = PTR_ERR(node);
-                       goto err;
-               }
-
-               node->name = qnodes[i]->name;
-               node->data = qnodes[i];
-               icc_node_add(node, provider);
-
-               for (j = 0; j < qnodes[i]->num_links; j++)
-                       icc_link_create(node, qnodes[i]->links[j]);
-
-               data->nodes[i] = node;
-       }
-       data->num_nodes = num_nodes;
-
-       platform_set_drvdata(pdev, qp);
-
-       return 0;
-err:
-       icc_nodes_remove(provider);
-       icc_provider_del(provider);
-       return ret;
-}
-
-static int qnoc_remove(struct platform_device *pdev)
-{
-       struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
-
-       icc_nodes_remove(&qp->provider);
-       icc_provider_del(&qp->provider);
-
-       return 0;
-}
-
 static const struct of_device_id qnoc_of_match[] = {
        { .compatible = "qcom,sm8550-aggre1-noc",
          .data = &sm8550_aggre1_noc},
@@ -2294,8 +2199,8 @@ static const struct of_device_id qnoc_of_match[] = {
 MODULE_DEVICE_TABLE(of, qnoc_of_match);
 
 static struct platform_driver qnoc_driver = {
-       .probe = qnoc_probe,
-       .remove = qnoc_remove,
+       .probe = qcom_icc_rpmh_probe,
+       .remove = qcom_icc_rpmh_remove,
        .driver = {
                .name = "qnoc-sm8550",
                .of_match_table = qnoc_of_match,
index 6559d8cf80687bf8d4034f52ea1f150c33c5f13c..ebf09bbf725bd117195eec5457b5495b12305105 100644 (file)
@@ -96,14 +96,9 @@ static struct icc_node *exynos_generic_icc_xlate(struct of_phandle_args *spec,
 static int exynos_generic_icc_remove(struct platform_device *pdev)
 {
        struct exynos_icc_priv *priv = platform_get_drvdata(pdev);
-       struct icc_node *parent_node, *node = priv->node;
-
-       parent_node = exynos_icc_get_parent(priv->dev->parent->of_node);
-       if (parent_node && !IS_ERR(parent_node))
-               icc_link_destroy(node, parent_node);
 
+       icc_provider_deregister(&priv->provider);
        icc_nodes_remove(&priv->provider);
-       icc_provider_del(&priv->provider);
 
        return 0;
 }
@@ -132,15 +127,11 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
        provider->inter_set = true;
        provider->data = priv;
 
-       ret = icc_provider_add(provider);
-       if (ret < 0)
-               return ret;
+       icc_provider_init(provider);
 
        icc_node = icc_node_create(pdev->id);
-       if (IS_ERR(icc_node)) {
-               ret = PTR_ERR(icc_node);
-               goto err_prov_del;
-       }
+       if (IS_ERR(icc_node))
+               return PTR_ERR(icc_node);
 
        priv->node = icc_node;
        icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn",
@@ -149,6 +140,9 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
                                 &priv->bus_clk_ratio))
                priv->bus_clk_ratio = EXYNOS_ICC_DEFAULT_BUS_CLK_RATIO;
 
+       icc_node->data = priv;
+       icc_node_add(icc_node, provider);
+
        /*
         * Register a PM QoS request for the parent (devfreq) device.
         */
@@ -157,9 +151,6 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
        if (ret < 0)
                goto err_node_del;
 
-       icc_node->data = priv;
-       icc_node_add(icc_node, provider);
-
        icc_parent_node = exynos_icc_get_parent(bus_dev->of_node);
        if (IS_ERR(icc_parent_node)) {
                ret = PTR_ERR(icc_parent_node);
@@ -171,14 +162,17 @@ static int exynos_generic_icc_probe(struct platform_device *pdev)
                        goto err_pmqos_del;
        }
 
+       ret = icc_provider_register(provider);
+       if (ret < 0)
+               goto err_pmqos_del;
+
        return 0;
 
 err_pmqos_del:
        dev_pm_qos_remove_request(&priv->qos_req);
 err_node_del:
        icc_nodes_remove(provider);
-err_prov_del:
-       icc_provider_del(provider);
+
        return ret;
 }
 
index 483aaaeb6daeac685dbead517c6409f54b2db807..1abd187c6075e4bedce585fd6c4c24794f1b0e84 100644 (file)
@@ -1415,23 +1415,26 @@ static struct iommu_device *exynos_iommu_probe_device(struct device *dev)
        return &data->iommu;
 }
 
-static void exynos_iommu_release_device(struct device *dev)
+static void exynos_iommu_set_platform_dma(struct device *dev)
 {
        struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
-       struct sysmmu_drvdata *data;
 
        if (owner->domain) {
                struct iommu_group *group = iommu_group_get(dev);
 
                if (group) {
-#ifndef CONFIG_ARM
-                       WARN_ON(owner->domain !=
-                               iommu_group_default_domain(group));
-#endif
                        exynos_iommu_detach_device(owner->domain, dev);
                        iommu_group_put(group);
                }
        }
+}
+
+static void exynos_iommu_release_device(struct device *dev)
+{
+       struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev);
+       struct sysmmu_drvdata *data;
+
+       exynos_iommu_set_platform_dma(dev);
 
        list_for_each_entry(data, &owner->controllers, owner_node)
                device_link_del(data->link);
@@ -1479,7 +1482,7 @@ static const struct iommu_ops exynos_iommu_ops = {
        .domain_alloc = exynos_iommu_domain_alloc,
        .device_group = generic_device_group,
 #ifdef CONFIG_ARM
-       .set_platform_dma_ops = exynos_iommu_release_device,
+       .set_platform_dma_ops = exynos_iommu_set_platform_dma,
 #endif
        .probe_device = exynos_iommu_probe_device,
        .release_device = exynos_iommu_release_device,
index 6acfe879589cb75f625c8b9715838b193ba44e4b..23828d189c2a609cff3145afd951faae6bdee17c 100644 (file)
@@ -1071,7 +1071,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
        }
 
        err = -EINVAL;
-       if (cap_sagaw(iommu->cap) == 0) {
+       if (!cap_sagaw(iommu->cap) &&
+           (!ecap_smts(iommu->ecap) || ecap_slts(iommu->ecap))) {
                pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
                        iommu->name);
                drhd->ignored = 1;
index d6df3b8658129a39721b4a011c6272b5ca574b38..694ab9b7d3e95a0ff98a750f622279dace3b86d8 100644 (file)
@@ -641,6 +641,8 @@ struct iommu_pmu {
        DECLARE_BITMAP(used_mask, IOMMU_PMU_IDX_MAX);
        struct perf_event       *event_list[IOMMU_PMU_IDX_MAX];
        unsigned char           irq_name[16];
+       struct hlist_node       cpuhp_node;
+       int                     cpu;
 };
 
 #define IOMMU_IRQ_ID_OFFSET_PRQ                (DMAR_UNITS_SUPPORTED)
index 6d01fa078c36fcaea0cf5fcde3bca84a061ffd3b..df9e261af0b564e8a999612f83029cf41ca22cd0 100644 (file)
@@ -311,14 +311,12 @@ static int set_ioapic_sid(struct irte *irte, int apic)
        if (!irte)
                return -1;
 
-       down_read(&dmar_global_lock);
        for (i = 0; i < MAX_IO_APICS; i++) {
                if (ir_ioapic[i].iommu && ir_ioapic[i].id == apic) {
                        sid = (ir_ioapic[i].bus << 8) | ir_ioapic[i].devfn;
                        break;
                }
        }
-       up_read(&dmar_global_lock);
 
        if (sid == 0) {
                pr_warn("Failed to set source-id of IOAPIC (%d)\n", apic);
@@ -338,14 +336,12 @@ static int set_hpet_sid(struct irte *irte, u8 id)
        if (!irte)
                return -1;
 
-       down_read(&dmar_global_lock);
        for (i = 0; i < MAX_HPET_TBS; i++) {
                if (ir_hpet[i].iommu && ir_hpet[i].id == id) {
                        sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
                        break;
                }
        }
-       up_read(&dmar_global_lock);
 
        if (sid == 0) {
                pr_warn("Failed to set source-id of HPET block (%d)\n", id);
@@ -1339,9 +1335,7 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain,
        if (!data)
                goto out_free_parent;
 
-       down_read(&dmar_global_lock);
        index = alloc_irte(iommu, &data->irq_2_iommu, nr_irqs);
-       up_read(&dmar_global_lock);
        if (index < 0) {
                pr_warn("Failed to allocate IRTE\n");
                kfree(data);
index e17d9743a0d8c3abaf805030c070960016ab5512..cf43e798eca49936e79a20ea5397a6b0e9f1cc82 100644 (file)
@@ -773,19 +773,34 @@ static void iommu_pmu_unset_interrupt(struct intel_iommu *iommu)
        iommu->perf_irq = 0;
 }
 
-static int iommu_pmu_cpu_online(unsigned int cpu)
+static int iommu_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
 {
+       struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
+
        if (cpumask_empty(&iommu_pmu_cpu_mask))
                cpumask_set_cpu(cpu, &iommu_pmu_cpu_mask);
 
+       if (cpumask_test_cpu(cpu, &iommu_pmu_cpu_mask))
+               iommu_pmu->cpu = cpu;
+
        return 0;
 }
 
-static int iommu_pmu_cpu_offline(unsigned int cpu)
+static int iommu_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
 {
-       struct dmar_drhd_unit *drhd;
-       struct intel_iommu *iommu;
-       int target;
+       struct iommu_pmu *iommu_pmu = hlist_entry_safe(node, typeof(*iommu_pmu), cpuhp_node);
+       int target = cpumask_first(&iommu_pmu_cpu_mask);
+
+       /*
+        * The iommu_pmu_cpu_mask has been updated when offline the CPU
+        * for the first iommu_pmu. Migrate the other iommu_pmu to the
+        * new target.
+        */
+       if (target < nr_cpu_ids && target != iommu_pmu->cpu) {
+               perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
+               iommu_pmu->cpu = target;
+               return 0;
+       }
 
        if (!cpumask_test_and_clear_cpu(cpu, &iommu_pmu_cpu_mask))
                return 0;
@@ -795,45 +810,50 @@ static int iommu_pmu_cpu_offline(unsigned int cpu)
        if (target < nr_cpu_ids)
                cpumask_set_cpu(target, &iommu_pmu_cpu_mask);
        else
-               target = -1;
+               return 0;
 
-       rcu_read_lock();
-
-       for_each_iommu(iommu, drhd) {
-               if (!iommu->pmu)
-                       continue;
-               perf_pmu_migrate_context(&iommu->pmu->pmu, cpu, target);
-       }
-       rcu_read_unlock();
+       perf_pmu_migrate_context(&iommu_pmu->pmu, cpu, target);
+       iommu_pmu->cpu = target;
 
        return 0;
 }
 
 static int nr_iommu_pmu;
+static enum cpuhp_state iommu_cpuhp_slot;
 
 static int iommu_pmu_cpuhp_setup(struct iommu_pmu *iommu_pmu)
 {
        int ret;
 
-       if (nr_iommu_pmu++)
-               return 0;
+       if (!nr_iommu_pmu) {
+               ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+                                             "driver/iommu/intel/perfmon:online",
+                                             iommu_pmu_cpu_online,
+                                             iommu_pmu_cpu_offline);
+               if (ret < 0)
+                       return ret;
+               iommu_cpuhp_slot = ret;
+       }
 
-       ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
-                               "driver/iommu/intel/perfmon:online",
-                               iommu_pmu_cpu_online,
-                               iommu_pmu_cpu_offline);
-       if (ret)
-               nr_iommu_pmu = 0;
+       ret = cpuhp_state_add_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
+       if (ret) {
+               if (!nr_iommu_pmu)
+                       cpuhp_remove_multi_state(iommu_cpuhp_slot);
+               return ret;
+       }
+       nr_iommu_pmu++;
 
-       return ret;
+       return 0;
 }
 
 static void iommu_pmu_cpuhp_free(struct iommu_pmu *iommu_pmu)
 {
+       cpuhp_state_remove_instance(iommu_cpuhp_slot, &iommu_pmu->cpuhp_node);
+
        if (--nr_iommu_pmu)
                return;
 
-       cpuhp_remove_state(CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE);
+       cpuhp_remove_multi_state(iommu_cpuhp_slot);
 }
 
 void iommu_pmu_register(struct intel_iommu *iommu)
index f8d92c9bb65b603add9596e9040907c587843035..3c47846cc5efe8f49c26b283e10f3ae42c42d641 100644 (file)
@@ -294,9 +294,9 @@ static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns)
                        batch->npfns[batch->end - 1] < keep_pfns);
 
        batch->total_pfns = keep_pfns;
-       batch->npfns[0] = keep_pfns;
        batch->pfns[0] = batch->pfns[batch->end - 1] +
                         (batch->npfns[batch->end - 1] - keep_pfns);
+       batch->npfns[0] = keep_pfns;
        batch->end = 0;
 }
 
@@ -1142,6 +1142,7 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
                                    bool writable)
 {
        struct iopt_pages *pages;
+       unsigned long end;
 
        /*
         * The iommu API uses size_t as the length, and protect the DIV_ROUND_UP
@@ -1150,6 +1151,9 @@ struct iopt_pages *iopt_alloc_pages(void __user *uptr, unsigned long length,
        if (length > SIZE_MAX - PAGE_SIZE || length == 0)
                return ERR_PTR(-EINVAL);
 
+       if (check_add_overflow((unsigned long)uptr, length, &end))
+               return ERR_PTR(-EOVERFLOW);
+
        pages = kzalloc(sizeof(*pages), GFP_KERNEL_ACCOUNT);
        if (!pages)
                return ERR_PTR(-ENOMEM);
@@ -1203,13 +1207,21 @@ iopt_area_unpin_domain(struct pfn_batch *batch, struct iopt_area *area,
                        unsigned long start =
                                max(start_index, *unmapped_end_index);
 
+                       if (IS_ENABLED(CONFIG_IOMMUFD_TEST) &&
+                           batch->total_pfns)
+                               WARN_ON(*unmapped_end_index -
+                                               batch->total_pfns !=
+                                       start_index);
                        batch_from_domain(batch, domain, area, start,
                                          last_index);
-                       batch_last_index = start + batch->total_pfns - 1;
+                       batch_last_index = start_index + batch->total_pfns - 1;
                } else {
                        batch_last_index = last_index;
                }
 
+               if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
+                       WARN_ON(batch_last_index > real_last_index);
+
                /*
                 * unmaps must always 'cut' at a place where the pfns are not
                 * contiguous to pair with the maps that always install
index 7dc990eb2c9baab84e2d66fed99890b808915657..09e422da482ff5f4a7f672453b0f147a3a28b25a 100644 (file)
@@ -7,6 +7,7 @@ config IRQCHIP
 
 config ARM_GIC
        bool
+       depends on OF
        select IRQ_DOMAIN_HIERARCHY
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
 
@@ -35,6 +36,7 @@ config ARM_GIC_V3
        select IRQ_DOMAIN_HIERARCHY
        select PARTITION_PERCPU
        select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP
+       select HAVE_ARM_SMCCC_DISCOVERY
 
 config ARM_GIC_V3_ITS
        bool
@@ -535,6 +537,7 @@ config TI_PRUSS_INTC
 config RISCV_INTC
        bool
        depends on RISCV
+       select IRQ_DOMAIN_HIERARCHY
 
 config SIFIVE_PLIC
        bool
index 6899e37810a8866b77c3e7ae2a62c3baf63862b4..fa113cb2529a4ff795a9af373884e967f21d65c9 100644 (file)
@@ -257,6 +257,9 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
        if (!cpu->map_base)
                return -ENOMEM;
 
+       if (!request_mem_region(res.start, sz, res.name))
+               pr_err("failed to request intc memory");
+
        for (i = 0; i < n_words; i++) {
                cpu->enable_cache[i] = 0;
                __raw_writel(0, cpu->map_base + reg_enable(intc, i));
@@ -335,8 +338,7 @@ static int __init bcm6345_l1_of_init(struct device_node *dn,
        for_each_cpu(idx, &intc->cpumask) {
                struct bcm6345_l1_cpu *cpu = intc->cpus[idx];
 
-               pr_info("  CPU%u at MMIO 0x%p (irq = %d)\n", idx,
-                               cpu->map_base, cpu->parent_irq);
+               pr_info("  CPU%u (irq = %d)\n", idx, cpu->parent_irq);
        }
 
        return 0;
index 42d8a2438ebc2910f79bb852146a1ba338c4cbe9..6710691e4c254d6a7f79f06f4da4b7a9b1764a73 100644 (file)
@@ -68,7 +68,7 @@ static void __init ck_set_gc(struct device_node *node, void __iomem *reg_base,
        gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
        gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
 
-       if (of_find_property(node, "csky,support-pulse-signal", NULL))
+       if (of_property_read_bool(node, "csky,support-pulse-signal"))
                gc->chip_types[0].chip.irq_unmask = irq_ck_mask_set_bit;
 }
 
index f1e75b35a52af14541090993b7177bdbf8b5b669..f2ff4387870d6942776ca6bb01a87baa2abd6079 100644 (file)
@@ -421,7 +421,7 @@ static int __init gicv2m_of_init(struct fwnode_handle *parent_handle,
                u32 spi_start = 0, nr_spis = 0;
                struct resource res;
 
-               if (!of_find_property(child, "msi-controller", NULL))
+               if (!of_property_read_bool(child, "msi-controller"))
                        continue;
 
                ret = of_address_to_resource(child, 0, &res);
index 586271b8aa394d0a91f84f37ee150faeaa972e32..fa4641a5dfd809e25775d3609fdd45058f789467 100644 (file)
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING          (1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375      (1ULL << 1)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_23144      (1ULL << 2)
+#define ITS_FLAGS_FORCE_NON_SHAREABLE          (1ULL << 3)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING    (1 << 0)
 #define RDIST_FLAGS_RD_TABLES_PREALLOCATED     (1 << 1)
+#define RDIST_FLAGS_FORCE_NON_SHAREABLE                (1 << 2)
 
 #define RD_LOCAL_LPI_ENABLED                    BIT(0)
 #define RD_LOCAL_PENDTABLE_PREALLOCATED         BIT(1)
@@ -2359,6 +2361,9 @@ retry_baser:
        its_write_baser(its, baser, val);
        tmp = baser->val;
 
+       if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GITS_BASER_SHAREABILITY_MASK;
+
        if ((val ^ tmp) & GITS_BASER_SHAREABILITY_MASK) {
                /*
                 * Shareability didn't stick. Just use
@@ -3096,6 +3101,9 @@ static void its_cpu_init_lpis(void)
        gicr_write_propbaser(val, rbase + GICR_PROPBASER);
        tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
 
+       if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GICR_PROPBASER_SHAREABILITY_MASK;
+
        if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
                if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
                        /*
@@ -3120,6 +3128,9 @@ static void its_cpu_init_lpis(void)
        gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
        tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
 
+       if (gic_rdists->flags & RDIST_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GICR_PENDBASER_SHAREABILITY_MASK;
+
        if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
                /*
                 * The HW reports non-shareable, we must remove the
@@ -4710,6 +4721,19 @@ static bool __maybe_unused its_enable_quirk_hip07_161600802(void *data)
        return true;
 }
 
+static bool __maybe_unused its_enable_rk3588001(void *data)
+{
+       struct its_node *its = data;
+
+       if (!of_machine_is_compatible("rockchip,rk3588"))
+               return false;
+
+       its->flags |= ITS_FLAGS_FORCE_NON_SHAREABLE;
+       gic_rdists->flags |= RDIST_FLAGS_FORCE_NON_SHAREABLE;
+
+       return true;
+}
+
 static const struct gic_quirk its_quirks[] = {
 #ifdef CONFIG_CAVIUM_ERRATUM_22375
        {
@@ -4755,6 +4779,14 @@ static const struct gic_quirk its_quirks[] = {
                .mask   = 0xffffffff,
                .init   = its_enable_quirk_hip07_161600802,
        },
+#endif
+#ifdef CONFIG_ROCKCHIP_ERRATUM_3588001
+       {
+               .desc   = "ITS: Rockchip erratum RK3588001",
+               .iidr   = 0x0201743b,
+               .mask   = 0xffffffff,
+               .init   = its_enable_rk3588001,
+       },
 #endif
        {
        }
@@ -5096,6 +5128,9 @@ static int __init its_probe_one(struct resource *res,
        gits_write_cbaser(baser, its->base + GITS_CBASER);
        tmp = gits_read_cbaser(its->base + GITS_CBASER);
 
+       if (its->flags & ITS_FLAGS_FORCE_NON_SHAREABLE)
+               tmp &= ~GITS_CBASER_SHAREABILITY_MASK;
+
        if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
                if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
                        /*
index fd134e1f481a294bc3b565930459083335ce7e87..6fcee221f201720929f1481aa64d3367d6395737 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/irqchip/arm-gic-common.h>
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/irqchip/irq-partition-percpu.h>
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/arm-smccc.h>
 
 #include <asm/cputype.h>
 #include <asm/exception.h>
@@ -47,6 +50,7 @@ struct redist_region {
 
 struct gic_chip_data {
        struct fwnode_handle    *fwnode;
+       phys_addr_t             dist_phys_base;
        void __iomem            *dist_base;
        struct redist_region    *redist_regions;
        struct rdists           rdists;
@@ -59,6 +63,10 @@ struct gic_chip_data {
        struct partition_desc   **ppi_descs;
 };
 
+#define T241_CHIPS_MAX         4
+static void __iomem *t241_dist_base_alias[T241_CHIPS_MAX] __read_mostly;
+static DEFINE_STATIC_KEY_FALSE(gic_nvidia_t241_erratum);
+
 static struct gic_chip_data gic_data __read_mostly;
 static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
 
@@ -179,6 +187,39 @@ static inline bool gic_irq_in_rdist(struct irq_data *d)
        }
 }
 
+static inline void __iomem *gic_dist_base_alias(struct irq_data *d)
+{
+       if (static_branch_unlikely(&gic_nvidia_t241_erratum)) {
+               irq_hw_number_t hwirq = irqd_to_hwirq(d);
+               u32 chip;
+
+               /*
+                * For the erratum T241-FABRIC-4, read accesses to GICD_In{E}
+                * registers are directed to the chip that owns the SPI. The
+                * the alias region can also be used for writes to the
+                * GICD_In{E} except GICD_ICENABLERn. Each chip has support
+                * for 320 {E}SPIs. Mappings for all 4 chips:
+                *    Chip0 = 32-351
+                *    Chip1 = 352-671
+                *    Chip2 = 672-991
+                *    Chip3 = 4096-4415
+                */
+               switch (__get_intid_range(hwirq)) {
+               case SPI_RANGE:
+                       chip = (hwirq - 32) / 320;
+                       break;
+               case ESPI_RANGE:
+                       chip = 3;
+                       break;
+               default:
+                       unreachable();
+               }
+               return t241_dist_base_alias[chip];
+       }
+
+       return gic_data.dist_base;
+}
+
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
        switch (get_intid_range(d)) {
@@ -337,7 +378,7 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
        if (gic_irq_in_rdist(d))
                base = gic_data_rdist_sgi_base();
        else
-               base = gic_data.dist_base;
+               base = gic_dist_base_alias(d);
 
        return !!(readl_relaxed(base + offset + (index / 32) * 4) & mask);
 }
@@ -588,7 +629,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
        if (gic_irq_in_rdist(d))
                base = gic_data_rdist_sgi_base();
        else
-               base = gic_data.dist_base;
+               base = gic_dist_base_alias(d);
 
        offset = convert_offset_index(d, GICD_ICFGR, &index);
 
@@ -1708,6 +1749,43 @@ static bool gic_enable_quirk_hip06_07(void *data)
        return false;
 }
 
+#define T241_CHIPN_MASK                GENMASK_ULL(45, 44)
+#define T241_CHIP_GICDA_OFFSET 0x1580000
+#define SMCCC_SOC_ID_T241      0x036b0241
+
+static bool gic_enable_quirk_nvidia_t241(void *data)
+{
+       s32 soc_id = arm_smccc_get_soc_id_version();
+       unsigned long chip_bmask = 0;
+       phys_addr_t phys;
+       u32 i;
+
+       /* Check JEP106 code for NVIDIA T241 chip (036b:0241) */
+       if ((soc_id < 0) || (soc_id != SMCCC_SOC_ID_T241))
+               return false;
+
+       /* Find the chips based on GICR regions PHYS addr */
+       for (i = 0; i < gic_data.nr_redist_regions; i++) {
+               chip_bmask |= BIT(FIELD_GET(T241_CHIPN_MASK,
+                                 (u64)gic_data.redist_regions[i].phys_base));
+       }
+
+       if (hweight32(chip_bmask) < 3)
+               return false;
+
+       /* Setup GICD alias regions */
+       for (i = 0; i < ARRAY_SIZE(t241_dist_base_alias); i++) {
+               if (chip_bmask & BIT(i)) {
+                       phys = gic_data.dist_phys_base + T241_CHIP_GICDA_OFFSET;
+                       phys |= FIELD_PREP(T241_CHIPN_MASK, i);
+                       t241_dist_base_alias[i] = ioremap(phys, SZ_64K);
+                       WARN_ON_ONCE(!t241_dist_base_alias[i]);
+               }
+       }
+       static_branch_enable(&gic_nvidia_t241_erratum);
+       return true;
+}
+
 static const struct gic_quirk gic_quirks[] = {
        {
                .desc   = "GICv3: Qualcomm MSM8996 broken firmware",
@@ -1739,6 +1817,12 @@ static const struct gic_quirk gic_quirks[] = {
                .mask   = 0xe8f00fff,
                .init   = gic_enable_quirk_cavium_38539,
        },
+       {
+               .desc   = "GICv3: NVIDIA erratum T241-FABRIC-4",
+               .iidr   = 0x0402043b,
+               .mask   = 0xffffffff,
+               .init   = gic_enable_quirk_nvidia_t241,
+       },
        {
        }
 };
@@ -1798,7 +1882,8 @@ static void gic_enable_nmi_support(void)
                gic_chip.flags |= IRQCHIP_SUPPORTS_NMI;
 }
 
-static int __init gic_init_bases(void __iomem *dist_base,
+static int __init gic_init_bases(phys_addr_t dist_phys_base,
+                                void __iomem *dist_base,
                                 struct redist_region *rdist_regs,
                                 u32 nr_redist_regions,
                                 u64 redist_stride,
@@ -1814,6 +1899,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
                pr_info("GIC: Using split EOI/Deactivate mode\n");
 
        gic_data.fwnode = handle;
+       gic_data.dist_phys_base = dist_phys_base;
        gic_data.dist_base = dist_base;
        gic_data.redist_regions = rdist_regs;
        gic_data.nr_redist_regions = nr_redist_regions;
@@ -1841,10 +1927,13 @@ static int __init gic_init_bases(void __iomem *dist_base,
        gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
                                                 &gic_data);
        gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
-       gic_data.rdists.has_rvpeid = true;
-       gic_data.rdists.has_vlpis = true;
-       gic_data.rdists.has_direct_lpi = true;
-       gic_data.rdists.has_vpend_valid_dirty = true;
+       if (!static_branch_unlikely(&gic_nvidia_t241_erratum)) {
+               /* Disable GICv4.x features for the erratum T241-FABRIC-4 */
+               gic_data.rdists.has_rvpeid = true;
+               gic_data.rdists.has_vlpis = true;
+               gic_data.rdists.has_direct_lpi = true;
+               gic_data.rdists.has_vpend_valid_dirty = true;
+       }
 
        if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
                err = -ENOMEM;
@@ -2050,6 +2139,7 @@ static void __iomem *gic_of_iomap(struct device_node *node, int idx,
 
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
 {
+       phys_addr_t dist_phys_base;
        void __iomem *dist_base;
        struct redist_region *rdist_regs;
        struct resource res;
@@ -2063,6 +2153,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
                return PTR_ERR(dist_base);
        }
 
+       dist_phys_base = res.start;
+
        err = gic_validate_dist_version(dist_base);
        if (err) {
                pr_err("%pOF: no distributor detected, giving up\n", node);
@@ -2094,8 +2186,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
 
        gic_enable_of_quirks(node, gic_quirks, &gic_data);
 
-       err = gic_init_bases(dist_base, rdist_regs, nr_redist_regions,
-                            redist_stride, &node->fwnode);
+       err = gic_init_bases(dist_phys_base, dist_base, rdist_regs,
+                            nr_redist_regions, redist_stride, &node->fwnode);
        if (err)
                goto out_unmap_rdist;
 
@@ -2411,8 +2503,9 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
                goto out_redist_unmap;
        }
 
-       err = gic_init_bases(acpi_data.dist_base, acpi_data.redist_regs,
-                            acpi_data.nr_redist_regions, 0, gsi_domain_handle);
+       err = gic_init_bases(dist->base_address, acpi_data.dist_base,
+                            acpi_data.redist_regs, acpi_data.nr_redist_regions,
+                            0, gsi_domain_handle);
        if (err)
                goto out_fwhandle_free;
 
index 95e3d2a71db64a998898219cc21e237144c84e0f..412196a7dad587dca5773dcd71e6b2f9d3d95b5f 100644 (file)
@@ -1081,10 +1081,6 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
-static void gic_irq_domain_unmap(struct irq_domain *d, unsigned int irq)
-{
-}
-
 static int gic_irq_domain_translate(struct irq_domain *d,
                                    struct irq_fwspec *fwspec,
                                    unsigned long *hwirq,
@@ -1167,11 +1163,6 @@ static const struct irq_domain_ops gic_irq_domain_hierarchy_ops = {
        .free = irq_domain_free_irqs_top,
 };
 
-static const struct irq_domain_ops gic_irq_domain_ops = {
-       .map = gic_irq_domain_map,
-       .unmap = gic_irq_domain_unmap,
-};
-
 static int gic_init_bases(struct gic_chip_data *gic,
                          struct fwnode_handle *handle)
 {
@@ -1219,30 +1210,9 @@ static int gic_init_bases(struct gic_chip_data *gic,
                gic_irqs = 1020;
        gic->gic_irqs = gic_irqs;
 
-       if (handle) {           /* DT/ACPI */
-               gic->domain = irq_domain_create_linear(handle, gic_irqs,
-                                                      &gic_irq_domain_hierarchy_ops,
-                                                      gic);
-       } else {                /* Legacy support */
-               /*
-                * For primary GICs, skip over SGIs.
-                * No secondary GIC support whatsoever.
-                */
-               int irq_base;
-
-               gic_irqs -= 16; /* calculate # of irqs to allocate */
-
-               irq_base = irq_alloc_descs(16, 16, gic_irqs,
-                                          numa_node_id());
-               if (irq_base < 0) {
-                       WARN(1, "Cannot allocate irq_descs @ IRQ16, assuming pre-allocated\n");
-                       irq_base = 16;
-               }
-
-               gic->domain = irq_domain_add_legacy(NULL, gic_irqs, irq_base,
-                                                   16, &gic_irq_domain_ops, gic);
-       }
-
+       gic->domain = irq_domain_create_linear(handle, gic_irqs,
+                                              &gic_irq_domain_hierarchy_ops,
+                                              gic);
        if (WARN_ON(!gic->domain)) {
                ret = -ENODEV;
                goto error;
@@ -1297,23 +1267,6 @@ static int __init __gic_init_bases(struct gic_chip_data *gic,
        return ret;
 }
 
-void __init gic_init(void __iomem *dist_base, void __iomem *cpu_base)
-{
-       struct gic_chip_data *gic;
-
-       /*
-        * Non-DT/ACPI systems won't run a hypervisor, so let's not
-        * bother with these...
-        */
-       static_branch_disable(&supports_deactivate_key);
-
-       gic = &gic_data[0];
-       gic->raw_dist_base = dist_base;
-       gic->raw_cpu_base = cpu_base;
-
-       __gic_init_bases(gic, NULL);
-}
-
 static void gic_teardown(struct gic_chip_data *gic)
 {
        if (WARN_ON(!gic))
@@ -1325,7 +1278,6 @@ static void gic_teardown(struct gic_chip_data *gic)
                iounmap(gic->raw_cpu_base);
 }
 
-#ifdef CONFIG_OF
 static int gic_cnt __initdata;
 static bool gicv2_force_probe;
 
@@ -1570,12 +1522,6 @@ IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init);
 IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
 IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
 IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init);
-#else
-int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq)
-{
-       return -ENOTSUPP;
-}
-#endif
 
 #ifdef CONFIG_ACPI
 static struct
index d15fd38c17568e213285920350f4adc4bc584960..90181c42840b4e92a8b7a8a59d3da5280532ada3 100644 (file)
@@ -280,9 +280,6 @@ static void acpi_set_vec_parent(int node, struct irq_domain *parent, struct acpi
 {
        int i;
 
-       if (cpu_has_flatmode)
-               node = cpu_to_node(node * CORES_PER_EIO_NODE);
-
        for (i = 0; i < MAX_IO_PICS; i++) {
                if (node == vec_group[i].node) {
                        vec_group[i].parent = parent;
@@ -343,19 +340,27 @@ static int __init pch_pic_parse_madt(union acpi_subtable_headers *header,
        if (parent)
                return pch_pic_acpi_init(parent, pchpic_entry);
 
-       return -EINVAL;
+       return 0;
 }
 
 static int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
                                        const unsigned long end)
 {
+       struct irq_domain *parent;
        struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header;
-       struct irq_domain *parent = acpi_get_vec_parent(eiointc_priv[nr_pics - 1]->node, msi_group);
+       int node;
+
+       if (cpu_has_flatmode)
+               node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE);
+       else
+               node = eiointc_priv[nr_pics - 1]->node;
+
+       parent = acpi_get_vec_parent(node, msi_group);
 
        if (parent)
                return pch_msi_acpi_init(parent, pchmsi_entry);
 
-       return -EINVAL;
+       return 0;
 }
 
 static int __init acpi_cascade_irqdomain_init(void)
@@ -379,6 +384,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
        int i, ret, parent_irq;
        unsigned long node_map;
        struct eiointc_priv *priv;
+       int node;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -416,13 +422,19 @@ int __init eiointc_acpi_init(struct irq_domain *parent,
        parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade);
        irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv);
 
-       register_syscore_ops(&eiointc_syscore_ops);
-       cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
+       if (nr_pics == 1) {
+               register_syscore_ops(&eiointc_syscore_ops);
+               cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING,
                                  "irqchip/loongarch/intc:starting",
                                  eiointc_router_init, NULL);
+       }
 
-       acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group);
-       acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group);
+       if (cpu_has_flatmode)
+               node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE);
+       else
+               node = acpi_eiointc->node;
+       acpi_set_vec_parent(node, priv->eiointc_domain, pch_group);
+       acpi_set_vec_parent(node, priv->eiointc_domain, msi_group);
        ret = acpi_cascade_irqdomain_init();
 
        return ret;
index 437f1af693d015d0ace1c20ce69be33e91646d98..e5fe4d50be056ffe00e2ab8f6c53fc5f1e464169 100644 (file)
@@ -311,7 +311,8 @@ static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
        pch_pic_handle[nr_pics] = domain_handle;
        pch_pic_priv[nr_pics++] = priv;
 
-       register_syscore_ops(&pch_pic_syscore_ops);
+       if (nr_pics == 1)
+               register_syscore_ops(&pch_pic_syscore_ops);
 
        return 0;
 
@@ -403,6 +404,9 @@ int __init pch_pic_acpi_init(struct irq_domain *parent,
        int ret, vec_base;
        struct fwnode_handle *domain_handle;
 
+       if (find_pch_pic(acpi_pchpic->gsi_base) >= 0)
+               return 0;
+
        vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ;
 
        domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address);
index 499e5f81b3fe33f913fc810aa11251c59021d86f..f229e3e66387033605c1e02742de4d878599fb1e 100644 (file)
@@ -26,20 +26,7 @@ static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
        if (unlikely(cause >= BITS_PER_LONG))
                panic("unexpected interrupt cause");
 
-       switch (cause) {
-#ifdef CONFIG_SMP
-       case RV_IRQ_SOFT:
-               /*
-                * We only use software interrupts to pass IPIs, so if a
-                * non-SMP system gets one, then we don't know what to do.
-                */
-               handle_IPI(regs);
-               break;
-#endif
-       default:
-               generic_handle_domain_irq(intc_domain, cause);
-               break;
-       }
+       generic_handle_domain_irq(intc_domain, cause);
 }
 
 /*
@@ -59,22 +46,27 @@ static void riscv_intc_irq_unmask(struct irq_data *d)
        csr_set(CSR_IE, BIT(d->hwirq));
 }
 
-static int riscv_intc_cpu_starting(unsigned int cpu)
-{
-       csr_set(CSR_IE, BIT(RV_IRQ_SOFT));
-       return 0;
-}
-
-static int riscv_intc_cpu_dying(unsigned int cpu)
+static void riscv_intc_irq_eoi(struct irq_data *d)
 {
-       csr_clear(CSR_IE, BIT(RV_IRQ_SOFT));
-       return 0;
+       /*
+        * The RISC-V INTC driver uses handle_percpu_devid_irq() flow
+        * for the per-HART local interrupts and child irqchip drivers
+        * (such as PLIC, SBI IPI, CLINT, APLIC, IMSIC, etc) implement
+        * chained handlers for the per-HART local interrupts.
+        *
+        * In the absence of irq_eoi(), the chained_irq_enter() and
+        * chained_irq_exit() functions (used by child irqchip drivers)
+        * will do unnecessary mask/unmask of per-HART local interrupts
+        * at the time of handling interrupts. To avoid this, we provide
+        * an empty irq_eoi() callback for RISC-V INTC irqchip.
+        */
 }
 
 static struct irq_chip riscv_intc_chip = {
        .name = "RISC-V INTC",
        .irq_mask = riscv_intc_irq_mask,
        .irq_unmask = riscv_intc_irq_unmask,
+       .irq_eoi = riscv_intc_irq_eoi,
 };
 
 static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
@@ -87,11 +79,39 @@ static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
+static int riscv_intc_domain_alloc(struct irq_domain *domain,
+                                  unsigned int virq, unsigned int nr_irqs,
+                                  void *arg)
+{
+       int i, ret;
+       irq_hw_number_t hwirq;
+       unsigned int type = IRQ_TYPE_NONE;
+       struct irq_fwspec *fwspec = arg;
+
+       ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < nr_irqs; i++) {
+               ret = riscv_intc_domain_map(domain, virq + i, hwirq + i);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static const struct irq_domain_ops riscv_intc_domain_ops = {
        .map    = riscv_intc_domain_map,
        .xlate  = irq_domain_xlate_onecell,
+       .alloc  = riscv_intc_domain_alloc
 };
 
+static struct fwnode_handle *riscv_intc_hwnode(void)
+{
+       return intc_domain->fwnode;
+}
+
 static int __init riscv_intc_init(struct device_node *node,
                                  struct device_node *parent)
 {
@@ -126,10 +146,7 @@ static int __init riscv_intc_init(struct device_node *node,
                return rc;
        }
 
-       cpuhp_setup_state(CPUHP_AP_IRQ_RISCV_STARTING,
-                         "irqchip/riscv/intc:starting",
-                         riscv_intc_cpu_starting,
-                         riscv_intc_cpu_dying);
+       riscv_set_intc_hwnode_fn(riscv_intc_hwnode);
 
        pr_info("%d local interrupts mapped\n", BITS_PER_LONG);
 
index ff47bd0dec455fa931bf367e44976ba82d5b9db9..e1484905b7bdbcb92e83ea4c88496c92dfdd199f 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
 #include <asm/smp.h>
 
 /*
@@ -67,6 +68,8 @@ struct plic_priv {
        struct irq_domain *irqdomain;
        void __iomem *regs;
        unsigned long plic_quirks;
+       unsigned int nr_irqs;
+       unsigned long *prio_save;
 };
 
 struct plic_handler {
@@ -78,6 +81,7 @@ struct plic_handler {
         */
        raw_spinlock_t          enable_lock;
        void __iomem            *enable_base;
+       u32                     *enable_save;
        struct plic_priv        *priv;
 };
 static int plic_parent_irq __ro_after_init;
@@ -229,6 +233,71 @@ static int plic_irq_set_type(struct irq_data *d, unsigned int type)
        return IRQ_SET_MASK_OK;
 }
 
+static int plic_irq_suspend(void)
+{
+       unsigned int i, cpu;
+       u32 __iomem *reg;
+       struct plic_priv *priv;
+
+       priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
+
+       for (i = 0; i < priv->nr_irqs; i++)
+               if (readl(priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID))
+                       __set_bit(i, priv->prio_save);
+               else
+                       __clear_bit(i, priv->prio_save);
+
+       for_each_cpu(cpu, cpu_present_mask) {
+               struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
+
+               if (!handler->present)
+                       continue;
+
+               raw_spin_lock(&handler->enable_lock);
+               for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) {
+                       reg = handler->enable_base + i * sizeof(u32);
+                       handler->enable_save[i] = readl(reg);
+               }
+               raw_spin_unlock(&handler->enable_lock);
+       }
+
+       return 0;
+}
+
+static void plic_irq_resume(void)
+{
+       unsigned int i, index, cpu;
+       u32 __iomem *reg;
+       struct plic_priv *priv;
+
+       priv = per_cpu_ptr(&plic_handlers, smp_processor_id())->priv;
+
+       for (i = 0; i < priv->nr_irqs; i++) {
+               index = BIT_WORD(i);
+               writel((priv->prio_save[index] & BIT_MASK(i)) ? 1 : 0,
+                      priv->regs + PRIORITY_BASE + i * PRIORITY_PER_ID);
+       }
+
+       for_each_cpu(cpu, cpu_present_mask) {
+               struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
+
+               if (!handler->present)
+                       continue;
+
+               raw_spin_lock(&handler->enable_lock);
+               for (i = 0; i < DIV_ROUND_UP(priv->nr_irqs, 32); i++) {
+                       reg = handler->enable_base + i * sizeof(u32);
+                       writel(handler->enable_save[i], reg);
+               }
+               raw_spin_unlock(&handler->enable_lock);
+       }
+}
+
+static struct syscore_ops plic_irq_syscore_ops = {
+       .suspend        = plic_irq_suspend,
+       .resume         = plic_irq_resume,
+};
+
 static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
                              irq_hw_number_t hwirq)
 {
@@ -345,6 +414,7 @@ static int __init __plic_init(struct device_node *node,
        u32 nr_irqs;
        struct plic_priv *priv;
        struct plic_handler *handler;
+       unsigned int cpu;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -363,15 +433,21 @@ static int __init __plic_init(struct device_node *node,
        if (WARN_ON(!nr_irqs))
                goto out_iounmap;
 
+       priv->nr_irqs = nr_irqs;
+
+       priv->prio_save = bitmap_alloc(nr_irqs, GFP_KERNEL);
+       if (!priv->prio_save)
+               goto out_free_priority_reg;
+
        nr_contexts = of_irq_count(node);
        if (WARN_ON(!nr_contexts))
-               goto out_iounmap;
+               goto out_free_priority_reg;
 
        error = -ENOMEM;
        priv->irqdomain = irq_domain_add_linear(node, nr_irqs + 1,
                        &plic_irqdomain_ops, priv);
        if (WARN_ON(!priv->irqdomain))
-               goto out_iounmap;
+               goto out_free_priority_reg;
 
        for (i = 0; i < nr_contexts; i++) {
                struct of_phandle_args parent;
@@ -441,6 +517,11 @@ static int __init __plic_init(struct device_node *node,
                handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE +
                        i * CONTEXT_ENABLE_SIZE;
                handler->priv = priv;
+
+               handler->enable_save =  kcalloc(DIV_ROUND_UP(nr_irqs, 32),
+                                               sizeof(*handler->enable_save), GFP_KERNEL);
+               if (!handler->enable_save)
+                       goto out_free_enable_reg;
 done:
                for (hwirq = 1; hwirq <= nr_irqs; hwirq++) {
                        plic_toggle(handler, hwirq, 0);
@@ -461,11 +542,19 @@ done:
                                  plic_starting_cpu, plic_dying_cpu);
                plic_cpuhp_setup_done = true;
        }
+       register_syscore_ops(&plic_irq_syscore_ops);
 
        pr_info("%pOFP: mapped %d interrupts with %d handlers for"
                " %d contexts.\n", node, nr_irqs, nr_handlers, nr_contexts);
        return 0;
 
+out_free_enable_reg:
+       for_each_cpu(cpu, cpu_present_mask) {
+               handler = per_cpu_ptr(&plic_handlers, cpu);
+               kfree(handler->enable_save);
+       }
+out_free_priority_reg:
+       kfree(priv->prio_save);
 out_iounmap:
        iounmap(priv->regs);
 out_free_priv:
index 1b83512b29c62ae5e6bec5daf83faa85f2d358f7..819a12297b587415418d092a256e06ebf41bb612 100644 (file)
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
-#define STIH415_SYSCFG_642             0x0a8
-#define STIH416_SYSCFG_7543            0x87c
 #define STIH407_SYSCFG_5102            0x198
-#define STID127_SYSCFG_734             0x088
 
 #define ST_A9_IRQ_MASK                 0x001FFFFF
 #define ST_A9_IRQ_MAX_CHANS            2
@@ -44,22 +41,10 @@ struct st_irq_syscfg {
 };
 
 static const struct of_device_id st_irq_syscfg_match[] = {
-       {
-               .compatible = "st,stih415-irq-syscfg",
-               .data = (void *)STIH415_SYSCFG_642,
-       },
-       {
-               .compatible = "st,stih416-irq-syscfg",
-               .data = (void *)STIH416_SYSCFG_7543,
-       },
        {
                .compatible = "st,stih407-irq-syscfg",
                .data = (void *)STIH407_SYSCFG_5102,
        },
-       {
-               .compatible = "st,stid127-irq-syscfg",
-               .data = (void *)STID127_SYSCFG_734,
-       },
        {}
 };
 
index 853901acaeec23281fa70c7a1a95968deab52fdc..162df49654fba2e89ad7051cf13482af1e425d0a 100644 (file)
@@ -39,7 +39,7 @@
 #define SCB_CTRL_NOTIFY_MASK BIT(SCB_CTRL_NOTIFY)
 
 #define SCB_CTRL_POS (16)
-#define SCB_CTRL_MASK GENMASK_ULL(SCB_CTRL_POS + SCB_MASK_WIDTH, SCB_CTRL_POS)
+#define SCB_CTRL_MASK GENMASK(SCB_CTRL_POS + SCB_MASK_WIDTH - 1, SCB_CTRL_POS)
 
 /* SCBCTRL service status register */
 
@@ -79,6 +79,27 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
        return status & SCB_STATUS_BUSY_MASK;
 }
 
+static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
+{
+       struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
+       struct mpfs_mss_response *response = mbox->response;
+       u32 val;
+
+       if (mpfs_mbox_busy(mbox))
+               return false;
+
+       /*
+        * The service status is stored in bits 31:16 of the SERVICES_SR
+        * register & is only valid when the system controller is not busy.
+        * Failed services are intended to generated interrupts, but in reality
+        * this does not happen, so the status must be checked here.
+        */
+       val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
+       response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
+
+       return true;
+}
+
 static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
 {
        struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
@@ -118,6 +139,7 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
        }
 
        opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu));
+
        tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK;
        tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK;
        writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
@@ -130,7 +152,7 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
        struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
        struct mpfs_mss_response *response = mbox->response;
        u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
-       u32 i, status;
+       u32 i;
 
        if (!response->resp_msg) {
                dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
@@ -138,8 +160,6 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
        }
 
        /*
-        * The status is stored in bits 31:16 of the SERVICES_SR register.
-        * It is only valid when BUSY == 0.
         * We should *never* get an interrupt while the controller is
         * still in the busy state. If we do, something has gone badly
         * wrong & the content of the mailbox would not be valid.
@@ -150,24 +170,10 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
                return;
        }
 
-       status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
-
-       /*
-        * If the status of the individual servers is non-zero, the service has
-        * failed. The contents of the mailbox at this point are not be valid,
-        * so don't bother reading them. Set the status so that the driver
-        * implementing the service can handle the result.
-        */
-       response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS;
-       if (response->resp_status)
-               return;
-
-       if (!mpfs_mbox_busy(mbox)) {
-               for (i = 0; i < num_words; i++) {
-                       response->resp_msg[i] =
-                               readl_relaxed(mbox->mbox_base
-                                             + mbox->resp_offset + i * 0x4);
-               }
+       for (i = 0; i < num_words; i++) {
+               response->resp_msg[i] =
+                       readl_relaxed(mbox->mbox_base
+                                     + mbox->resp_offset + i * 0x4);
        }
 
        mbox_chan_received_data(chan, response);
@@ -182,7 +188,6 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
 
        mpfs_mbox_rx_data(chan);
 
-       mbox_chan_txdone(chan, 0);
        return IRQ_HANDLED;
 }
 
@@ -212,6 +217,7 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
        .send_data = mpfs_mbox_send_data,
        .startup = mpfs_mbox_startup,
        .shutdown = mpfs_mbox_shutdown,
+       .last_tx_done = mpfs_mbox_last_tx_done,
 };
 
 static int mpfs_mbox_probe(struct platform_device *pdev)
@@ -247,7 +253,8 @@ static int mpfs_mbox_probe(struct platform_device *pdev)
        mbox->controller.num_chans = 1;
        mbox->controller.chans = mbox->chans;
        mbox->controller.ops = &mpfs_mbox_ops;
-       mbox->controller.txdone_irq = true;
+       mbox->controller.txdone_poll = true;
+       mbox->controller.txpoll_period = 10u;
 
        ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
        if (ret) {
index 5f1e2593fad7ec4feb9667a9c790cbb1b35123de..b0a22e99bade37148914492b26ec75d5523088d7 100644 (file)
@@ -15,6 +15,10 @@ if MD
 config BLK_DEV_MD
        tristate "RAID support"
        select BLOCK_HOLDER_DEPRECATED if SYSFS
+       # BLOCK_LEGACY_AUTOLOAD requirement should be removed
+       # after relevant mdadm enhancements - to make "names=yes"
+       # the default - are widely available.
+       select BLOCK_LEGACY_AUTOLOAD
        help
          This driver lets you combine several hard disk partitions into one
          logical block device. This can be used to simply append one
index 40cb1719ae4d526b2fbe40a93f5f36fe7e25ec28..3ba53dc3cc3f627218941a61a9bdd6d948c87f43 100644 (file)
@@ -72,7 +72,9 @@ struct dm_crypt_io {
        struct crypt_config *cc;
        struct bio *base_bio;
        u8 *integrity_metadata;
-       bool integrity_metadata_from_pool;
+       bool integrity_metadata_from_pool:1;
+       bool in_tasklet:1;
+
        struct work_struct work;
        struct tasklet_struct tasklet;
 
@@ -1730,6 +1732,7 @@ static void crypt_io_init(struct dm_crypt_io *io, struct crypt_config *cc,
        io->ctx.r.req = NULL;
        io->integrity_metadata = NULL;
        io->integrity_metadata_from_pool = false;
+       io->in_tasklet = false;
        atomic_set(&io->io_pending, 0);
 }
 
@@ -1776,14 +1779,13 @@ static void crypt_dec_pending(struct dm_crypt_io *io)
         * our tasklet. In this case we need to delay bio_endio()
         * execution to after the tasklet is done and dequeued.
         */
-       if (tasklet_trylock(&io->tasklet)) {
-               tasklet_unlock(&io->tasklet);
-               bio_endio(base_bio);
+       if (io->in_tasklet) {
+               INIT_WORK(&io->work, kcryptd_io_bio_endio);
+               queue_work(cc->io_queue, &io->work);
                return;
        }
 
-       INIT_WORK(&io->work, kcryptd_io_bio_endio);
-       queue_work(cc->io_queue, &io->work);
+       bio_endio(base_bio);
 }
 
 /*
@@ -1936,6 +1938,7 @@ pop_from_list:
                        io = crypt_io_from_node(rb_first(&write_tree));
                        rb_erase(&io->rb_node, &write_tree);
                        kcryptd_io_write(io);
+                       cond_resched();
                } while (!RB_EMPTY_ROOT(&write_tree));
                blk_finish_plug(&plug);
        }
@@ -2230,6 +2233,7 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io)
                 * it is being executed with irqs disabled.
                 */
                if (in_hardirq() || irqs_disabled()) {
+                       io->in_tasklet = true;
                        tasklet_init(&io->tasklet, kcryptd_crypt_tasklet, (unsigned long)&io->work);
                        tasklet_schedule(&io->tasklet);
                        return;
index c21a19ab73f705d791e611101e79b467fe329bf0..db2d997a6c1815ce6f7f72fa0fed51572afae856 100644 (file)
@@ -188,7 +188,7 @@ static int dm_stat_in_flight(struct dm_stat_shared *shared)
               atomic_read(&shared->in_flight[WRITE]);
 }
 
-void dm_stats_init(struct dm_stats *stats)
+int dm_stats_init(struct dm_stats *stats)
 {
        int cpu;
        struct dm_stats_last_position *last;
@@ -197,11 +197,16 @@ void dm_stats_init(struct dm_stats *stats)
        INIT_LIST_HEAD(&stats->list);
        stats->precise_timestamps = false;
        stats->last = alloc_percpu(struct dm_stats_last_position);
+       if (!stats->last)
+               return -ENOMEM;
+
        for_each_possible_cpu(cpu) {
                last = per_cpu_ptr(stats->last, cpu);
                last->last_sector = (sector_t)ULLONG_MAX;
                last->last_rw = UINT_MAX;
        }
+
+       return 0;
 }
 
 void dm_stats_cleanup(struct dm_stats *stats)
index 0bc152c8e4f310282845a30d65a0528d029af254..c6728c8b41594bd1a9cac425be013d8a03f085d3 100644 (file)
@@ -21,7 +21,7 @@ struct dm_stats_aux {
        unsigned long long duration_ns;
 };
 
-void dm_stats_init(struct dm_stats *st);
+int dm_stats_init(struct dm_stats *st);
 void dm_stats_cleanup(struct dm_stats *st);
 
 struct mapped_device;
index 6cd105c1cef35cc51defa05a16684b361ef1ac12..13d4677baafd176065a8e218695910205606245f 100644 (file)
@@ -3369,6 +3369,7 @@ static int pool_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        pt->low_water_blocks = low_water_blocks;
        pt->adjusted_pf = pt->requested_pf = pf;
        ti->num_flush_bios = 1;
+       ti->limit_swap_bios = true;
 
        /*
         * Only need to enable discards if the pool should pass
@@ -4249,6 +4250,7 @@ static int thin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto bad;
 
        ti->num_flush_bios = 1;
+       ti->limit_swap_bios = true;
        ti->flush_supported = true;
        ti->accounts_remapped_io = true;
        ti->per_io_data_size = sizeof(struct dm_thin_endio_hook);
index eace45a18d45611e70e1b4a988d674535925a30a..dfde0088147a1e5bd7be946d330f30b2b4684dcf 100644 (file)
@@ -512,10 +512,10 @@ static void dm_io_acct(struct dm_io *io, bool end)
                sectors = io->sectors;
 
        if (!end)
-               bdev_start_io_acct(bio->bi_bdev, sectors, bio_op(bio),
-                                  start_time);
+               bdev_start_io_acct(bio->bi_bdev, bio_op(bio), start_time);
        else
-               bdev_end_io_acct(bio->bi_bdev, bio_op(bio), start_time);
+               bdev_end_io_acct(bio->bi_bdev, bio_op(bio), sectors,
+                                start_time);
 
        if (static_branch_unlikely(&stats_enabled) &&
            unlikely(dm_stats_used(&md->stats))) {
@@ -1467,7 +1467,8 @@ static void setup_split_accounting(struct clone_info *ci, unsigned int len)
 }
 
 static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
-                               struct dm_target *ti, unsigned int num_bios)
+                               struct dm_target *ti, unsigned int num_bios,
+                               unsigned *len)
 {
        struct bio *bio;
        int try;
@@ -1478,7 +1479,7 @@ static void alloc_multiple_bios(struct bio_list *blist, struct clone_info *ci,
                if (try)
                        mutex_lock(&ci->io->md->table_devices_lock);
                for (bio_nr = 0; bio_nr < num_bios; bio_nr++) {
-                       bio = alloc_tio(ci, ti, bio_nr, NULL,
+                       bio = alloc_tio(ci, ti, bio_nr, len,
                                        try ? GFP_NOIO : GFP_NOWAIT);
                        if (!bio)
                                break;
@@ -1513,8 +1514,10 @@ static int __send_duplicate_bios(struct clone_info *ci, struct dm_target *ti,
                ret = 1;
                break;
        default:
+               if (len)
+                       setup_split_accounting(ci, *len);
                /* dm_accept_partial_bio() is not supported with shared tio->len_ptr */
-               alloc_multiple_bios(&blist, ci, ti, num_bios);
+               alloc_multiple_bios(&blist, ci, ti, num_bios, len);
                while ((clone = bio_list_pop(&blist))) {
                        dm_tio_set_flag(clone_to_tio(clone), DM_TIO_IS_DUPLICATE_BIO);
                        __map_bio(clone);
@@ -2097,7 +2100,9 @@ static struct mapped_device *alloc_dev(int minor)
        if (!md->pending_io)
                goto bad;
 
-       dm_stats_init(&md->stats);
+       r = dm_stats_init(&md->stats);
+       if (r < 0)
+               goto bad;
 
        /* Populate the mapping, nobody knows we exist yet */
        spin_lock(&_minor_lock);
index 927a43db5dfbb98fd0702163e0962201e111fe68..13321dbb5fbcf0fd65b17f88a76b14cfc3b135f9 100644 (file)
@@ -3128,6 +3128,9 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
                err = kstrtouint(buf, 10, (unsigned int *)&slot);
                if (err < 0)
                        return err;
+               if (slot < 0)
+                       /* overflow */
+                       return -ENOSPC;
        }
        if (rdev->mddev->pers && slot == -1) {
                /* Setting 'slot' on an active array requires also
@@ -6256,6 +6259,10 @@ static void __md_stop(struct mddev *mddev)
                mddev->to_remove = &md_redundancy_group;
        module_put(pers->owner);
        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+
+       percpu_ref_exit(&mddev->active_io);
+       bioset_exit(&mddev->bio_set);
+       bioset_exit(&mddev->sync_set);
 }
 
 void md_stop(struct mddev *mddev)
@@ -6266,9 +6273,6 @@ void md_stop(struct mddev *mddev)
        __md_stop_writes(mddev);
        __md_stop(mddev);
        percpu_ref_exit(&mddev->writes_pending);
-       percpu_ref_exit(&mddev->active_io);
-       bioset_exit(&mddev->bio_set);
-       bioset_exit(&mddev->sync_set);
 }
 
 EXPORT_SYMBOL_GPL(md_stop);
@@ -7840,10 +7844,6 @@ static void md_free_disk(struct gendisk *disk)
        struct mddev *mddev = disk->private_data;
 
        percpu_ref_exit(&mddev->writes_pending);
-       percpu_ref_exit(&mddev->active_io);
-       bioset_exit(&mddev->bio_set);
-       bioset_exit(&mddev->sync_set);
-
        mddev_free(mddev);
 }
 
index 49d6c8bdec412ab2beb7f7dbc3e7b43400518900..48ae2e0adf9ea84615f00fa0d50a13a7ccdad860 100644 (file)
@@ -1098,7 +1098,7 @@ static int imx290_runtime_suspend(struct device *dev)
 }
 
 static const struct dev_pm_ops imx290_pm_ops = {
-       SET_RUNTIME_PM_OPS(imx290_runtime_suspend, imx290_runtime_resume, NULL)
+       RUNTIME_PM_OPS(imx290_runtime_suspend, imx290_runtime_resume, NULL)
 };
 
 /* ----------------------------------------------------------------------------
@@ -1362,8 +1362,8 @@ static struct i2c_driver imx290_i2c_driver = {
        .remove = imx290_remove,
        .driver = {
                .name  = "imx290",
-               .pm = &imx290_pm_ops,
-               .of_match_table = of_match_ptr(imx290_of_match),
+               .pm = pm_ptr(&imx290_pm_ops),
+               .of_match_table = imx290_of_match,
        },
 };
 
index 2b01873ba0db51c9c999a2d578591a85c944f0e1..5c2336f318d9a132d18b815f505da78bc033ab92 100644 (file)
@@ -488,7 +488,7 @@ static enum m5mols_restype __find_restype(u32 code)
        do {
                if (code == m5mols_default_ffmt[type].code)
                        return type;
-       } while (type++ != SIZE_DEFAULT_FFMT);
+       } while (++type != SIZE_DEFAULT_FFMT);
 
        return 0;
 }
index 61ff20a7e935e14b88ca8b81db66b64922508474..cfb11c551167ce72f3261a2bdd4c6fd994368977 100644 (file)
@@ -38,8 +38,8 @@ static void venus_reset_cpu(struct venus_core *core)
        writel(fw_size, wrapper_base + WRAPPER_FW_END_ADDR);
        writel(0, wrapper_base + WRAPPER_CPA_START_ADDR);
        writel(fw_size, wrapper_base + WRAPPER_CPA_END_ADDR);
-       writel(0, wrapper_base + WRAPPER_NONPIX_START_ADDR);
-       writel(0, wrapper_base + WRAPPER_NONPIX_END_ADDR);
+       writel(fw_size, wrapper_base + WRAPPER_NONPIX_START_ADDR);
+       writel(fw_size, wrapper_base + WRAPPER_NONPIX_END_ADDR);
 
        if (IS_V6(core)) {
                /* Bring XTSS out of reset */
index fac290e48e0b86b84aa4d1a20e8e6eaec018b7fc..91774e6ee6240e3718c4a657c8ac35471caa56e4 100644 (file)
@@ -228,7 +228,7 @@ config RENESAS_RPCIF
 
 config STM32_FMC2_EBI
        tristate "Support for FMC2 External Bus Interface on STM32MP SoCs"
-       depends on MACH_STM32MP157 || COMPILE_TEST
+       depends on ARCH_STM32 || COMPILE_TEST
        select MFD_SYSCON
        help
          Select this option to enable the STM32 FMC2 External Bus Interface
index e749dcb3ddea93335a6ca5f5dd6e1de0e9a52418..635966d705cbb24502da0092af8ea39a90978830 100644 (file)
@@ -598,7 +598,7 @@ static int atmel_ebi_probe(struct platform_device *pdev)
        reg_cells += val;
 
        for_each_available_child_of_node(np, child) {
-               if (!of_find_property(child, "reg", NULL))
+               if (!of_property_present(child, "reg"))
                        continue;
 
                ret = atmel_ebi_dev_setup(ebi, child, reg_cells);
index 85965fa26e0bbbb50dca26668f4aa25366f0eba1..78bd71b203f2daa511749772f9c4b026faadc51b 100644 (file)
@@ -321,4 +321,3 @@ module_platform_driver(l2_ctl_driver);
 
 MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
 MODULE_DESCRIPTION("Baikal-T1 L2-cache driver");
-MODULE_LICENSE("GPL v2");
index b32005bf269cb426f731bcc12f4db4429452c0bf..0ef8cc878b95c5a3f7e5e59a663715fdf552c605 100644 (file)
@@ -164,4 +164,3 @@ module_platform_driver(da8xx_ddrctl_driver);
 
 MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
 MODULE_DESCRIPTION("TI da8xx DDR2/mDDR controller driver");
-MODULE_LICENSE("GPL v2");
index e83b61c925a4fdd061c89f8901a81bfeb50a7c3a..9e8d8e9c5ad868d0ff55d0063d3406adb7cb373b 100644 (file)
@@ -327,6 +327,5 @@ static int __init fsl_ifc_init(void)
 }
 subsys_initcall(fsl_ifc_init);
 
-MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Freescale Semiconductor");
 MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");
index 5a9754442bc75fa3f883b65c3461a1ca0d8c5f29..6523cb51051827c6f247206986fb27e16ec2a456 100644 (file)
@@ -713,6 +713,11 @@ static const struct mtk_smi_common_plat mtk_smi_sub_common_mt8195 = {
        .has_gals = true,
 };
 
+static const struct mtk_smi_common_plat mtk_smi_common_mt8365 = {
+       .type     = MTK_SMI_GEN2,
+       .bus_sel  = F_MMU1_LARB(2) | F_MMU1_LARB(4),
+};
+
 static const struct of_device_id mtk_smi_common_of_ids[] = {
        {.compatible = "mediatek,mt2701-smi-common", .data = &mtk_smi_common_gen1},
        {.compatible = "mediatek,mt2712-smi-common", .data = &mtk_smi_common_gen2},
@@ -728,6 +733,7 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
        {.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
        {.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
        {.compatible = "mediatek,mt8195-smi-sub-common", .data = &mtk_smi_sub_common_mt8195},
+       {.compatible = "mediatek,mt8365-smi-common", .data = &mtk_smi_common_mt8365},
        {}
 };
 
index efc6c08db2b70a78ae2d6eb902305153fb8cf36e..406fddcdba02a01e35254c4e0d7216607d5350c9 100644 (file)
@@ -341,6 +341,5 @@ static int __init mvebu_devbus_init(void)
 }
 module_init(mvebu_devbus_init);
 
-MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
 MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");
index 592907546ee64a7acc48e65980ecb8e695f24bf4..9082b6c3763dcc16b11dcd418c9b95bd94fa0547 100644 (file)
@@ -794,16 +794,12 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
        mc->provider.aggregate = mc->soc->icc_ops->aggregate;
        mc->provider.xlate_extended = mc->soc->icc_ops->xlate_extended;
 
-       err = icc_provider_add(&mc->provider);
-       if (err)
-               return err;
+       icc_provider_init(&mc->provider);
 
        /* create Memory Controller node */
        node = icc_node_create(TEGRA_ICC_MC);
-       if (IS_ERR(node)) {
-               err = PTR_ERR(node);
-               goto del_provider;
-       }
+       if (IS_ERR(node))
+               return PTR_ERR(node);
 
        node->name = "Memory Controller";
        icc_node_add(node, &mc->provider);
@@ -830,12 +826,14 @@ static int tegra_mc_interconnect_setup(struct tegra_mc *mc)
                        goto remove_nodes;
        }
 
+       err = icc_provider_register(&mc->provider);
+       if (err)
+               goto remove_nodes;
+
        return 0;
 
 remove_nodes:
        icc_nodes_remove(&mc->provider);
-del_provider:
-       icc_provider_del(&mc->provider);
 
        return err;
 }
@@ -985,4 +983,3 @@ arch_initcall(tegra_mc_init);
 
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra Memory Controller driver");
-MODULE_LICENSE("GPL v2");
index 85bc936c02f9401eb71b11e070757345c9b45553..00ed2b6a0d1b27e0466bd2ab14e82b7efc6c1ae0 100644 (file)
@@ -1351,15 +1351,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
        emc->provider.aggregate = soc->icc_ops->aggregate;
        emc->provider.xlate_extended = emc_of_icc_xlate_extended;
 
-       err = icc_provider_add(&emc->provider);
-       if (err)
-               goto err_msg;
+       icc_provider_init(&emc->provider);
 
        /* create External Memory Controller node */
        node = icc_node_create(TEGRA_ICC_EMC);
        if (IS_ERR(node)) {
                err = PTR_ERR(node);
-               goto del_provider;
+               goto err_msg;
        }
 
        node->name = "External Memory Controller";
@@ -1380,12 +1378,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
        node->name = "External Memory (DRAM)";
        icc_node_add(node, &emc->provider);
 
+       err = icc_provider_register(&emc->provider);
+       if (err)
+               goto remove_nodes;
+
        return 0;
 
 remove_nodes:
        icc_nodes_remove(&emc->provider);
-del_provider:
-       icc_provider_del(&emc->provider);
 err_msg:
        dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
 
index 26e763bde92a76278dda84fcda84855c496b0ec1..e935ad4e95b68729bd42e53de80e6a1e41154d3f 100644 (file)
@@ -280,4 +280,3 @@ module_platform_driver(tegra186_emc_driver);
 
 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 MODULE_DESCRIPTION("NVIDIA Tegra186 External Memory Controller driver");
-MODULE_LICENSE("GPL v2");
index bd4e37b6552de5d5a426ac963f0116352ca6590d..fd595c851a27865bb9044818596062e797ed80f6 100644 (file)
@@ -1021,15 +1021,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
        emc->provider.aggregate = soc->icc_ops->aggregate;
        emc->provider.xlate_extended = emc_of_icc_xlate_extended;
 
-       err = icc_provider_add(&emc->provider);
-       if (err)
-               goto err_msg;
+       icc_provider_init(&emc->provider);
 
        /* create External Memory Controller node */
        node = icc_node_create(TEGRA_ICC_EMC);
        if (IS_ERR(node)) {
                err = PTR_ERR(node);
-               goto del_provider;
+               goto err_msg;
        }
 
        node->name = "External Memory Controller";
@@ -1050,12 +1048,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
        node->name = "External Memory (DRAM)";
        icc_node_add(node, &emc->provider);
 
+       err = icc_provider_register(&emc->provider);
+       if (err)
+               goto remove_nodes;
+
        return 0;
 
 remove_nodes:
        icc_nodes_remove(&emc->provider);
-del_provider:
-       icc_provider_del(&emc->provider);
 err_msg:
        dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
 
index cc76adb8d7e8a111b6b1ae1993e59662ee83a795..4cb608c71ead5208cc7da9481cdb30bac2dc4622 100644 (file)
@@ -277,7 +277,7 @@ static u32 update_clock_tree_delay(struct tegra210_emc *emc, int type)
                /*
                 * Dev1 LSB.
                 */
-               value = tegra210_emc_mrr_read(emc, 2, 18);
+               value = tegra210_emc_mrr_read(emc, 1, 18);
 
                for (i = 0; i < emc->num_channels; i++) {
                        temp[i][0] |= (value & 0x00ff) >> 0;
index 3e0598363b873b30534283b78a7028c93edf35b8..34a8785d2861aa80216451f6bb64cbf543894888 100644 (file)
@@ -22,8 +22,6 @@ static int tegra210_emc_table_device_init(struct reserved_mem *rmem,
                return -ENOMEM;
        }
 
-       count = 0;
-
        for (i = 0; i < TEGRA_EMC_MAX_FREQS; i++) {
                if (timings[i].revision == 0)
                        break;
index 77706e9bc5433917712a5c52e68f80134b7fd322..c91e9b7e2e019cf4af40fb0e5253f55455e984c1 100644 (file)
@@ -1533,15 +1533,13 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
        emc->provider.aggregate = soc->icc_ops->aggregate;
        emc->provider.xlate_extended = emc_of_icc_xlate_extended;
 
-       err = icc_provider_add(&emc->provider);
-       if (err)
-               goto err_msg;
+       icc_provider_init(&emc->provider);
 
        /* create External Memory Controller node */
        node = icc_node_create(TEGRA_ICC_EMC);
        if (IS_ERR(node)) {
                err = PTR_ERR(node);
-               goto del_provider;
+               goto err_msg;
        }
 
        node->name = "External Memory Controller";
@@ -1562,12 +1560,14 @@ static int tegra_emc_interconnect_init(struct tegra_emc *emc)
        node->name = "External Memory (DRAM)";
        icc_node_add(node, &emc->provider);
 
+       err = icc_provider_register(&emc->provider);
+       if (err)
+               goto remove_nodes;
+
        return 0;
 
 remove_nodes:
        icc_nodes_remove(&emc->provider);
-del_provider:
-       icc_provider_del(&emc->provider);
 err_msg:
        dev_err(emc->dev, "failed to initialize ICC: %d\n", err);
 
index bf766784545916a6068932ed4ea925e94a240aef..bbfaf6536903d35c704fced42859fb4fb3e54afe 100644 (file)
@@ -410,6 +410,7 @@ static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
        return card;
 err_out:
        host->card = old_card;
+       kfree_const(card->dev.kobj.name);
        kfree(card);
        return NULL;
 }
@@ -468,8 +469,10 @@ static void memstick_check(struct work_struct *work)
                                put_device(&card->dev);
                                host->card = NULL;
                        }
-               } else
+               } else {
+                       kfree_const(card->dev.kobj.name);
                        kfree(card);
+               }
        }
 
 out_power_off:
index a701132638cf2a8439448b88f1469c50e571ed2c..f48466960f1b9c0f9b78ff4c6d0038c7719e124f 100644 (file)
@@ -262,7 +262,7 @@ struct fastrpc_channel_ctx {
        int domain_id;
        int sesscount;
        int vmcount;
-       u32 perms;
+       u64 perms;
        struct qcom_scm_vmperm vmperms[FASTRPC_MAX_VMIDS];
        struct rpmsg_device *rpdev;
        struct fastrpc_session_ctx session[FASTRPC_MAX_SESSIONS];
index 172696abce31b0d7dc3e922028c77666b0b37feb..f22b44827e9295e7628aaf322392758f5f32c057 100644 (file)
@@ -687,7 +687,7 @@ int vmci_ctx_remove_notification(u32 context_id, u32 remote_cid)
        spin_unlock(&context->lock);
 
        if (notifier)
-               kvfree_rcu(notifier);
+               kvfree_rcu_mightsleep(notifier);
 
        vmci_ctx_put(context);
 
index 2100297c94ad02ef18c9e06e0f3bd1938d396536..5d7ac07623c27330d42a37686329293b2761ef67 100644 (file)
@@ -209,7 +209,7 @@ int vmci_event_unsubscribe(u32 sub_id)
        if (!s)
                return VMCI_ERROR_NOT_FOUND;
 
-       kvfree_rcu(s);
+       kvfree_rcu_mightsleep(s);
 
        return VMCI_SUCCESS;
 }
index 40f5969b07a6678cdaae9734931c6e7f1d775e73..dab1508bf83c67ea8cbcf3d07d6f3a207930735a 100644 (file)
@@ -51,7 +51,7 @@ static int dw_mci_starfive_execute_tuning(struct dw_mci_slot *slot,
        struct dw_mci *host = slot->host;
        struct starfive_priv *priv = host->priv;
        int rise_point = -1, fall_point = -1;
-       int err, prev_err;
+       int err, prev_err = 0;
        int i;
        bool found = 0;
        u32 regval;
index 7ef828942df359c53339b59ae6ecda11e6ed2d04..672d37ea98d0f39771f2c90039f8cba75312a2b6 100644 (file)
@@ -351,8 +351,6 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg)
                 */
                case MMC_TIMING_SD_HS:
                case MMC_TIMING_MMC_HS:
-               case MMC_TIMING_UHS_SDR12:
-               case MMC_TIMING_UHS_SDR25:
                        val &= ~SDHCI_CTRL_HISPD;
                }
        }
@@ -369,7 +367,7 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg)
                                        MAX_POWER_ON_TIMEOUT, false, host, val,
                                        reg);
                if (ret)
-                       dev_warn(mmc_dev(host->mmc), "Power on failed\n");
+                       dev_info(mmc_dev(host->mmc), "Power on failed\n");
        }
 }
 
index 1e94e7d10b8be64172d222b3136948133391d1d3..a0a1194dc1d902579f79b7befdad1d61b4a671a4 100644 (file)
@@ -153,7 +153,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
                                mtdblk->cache_state = STATE_EMPTY;
                                ret = mtd_read(mtd, sect_start, sect_size,
                                               &retlen, mtdblk->cache_data);
-                               if (ret)
+                               if (ret && !mtd_is_bitflip(ret))
                                        return ret;
                                if (retlen != sect_size)
                                        return -EIO;
@@ -188,8 +188,12 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
        pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
                        mtd->name, pos, len);
 
-       if (!sect_size)
-               return mtd_read(mtd, pos, len, &retlen, buf);
+       if (!sect_size) {
+               ret = mtd_read(mtd, pos, len, &retlen, buf);
+               if (ret && !mtd_is_bitflip(ret))
+                       return ret;
+               return 0;
+       }
 
        while (len > 0) {
                unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -209,7 +213,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
                        memcpy (buf, mtdblk->cache_data + offset, size);
                } else {
                        ret = mtd_read(mtd, pos, size, &retlen, buf);
-                       if (ret)
+                       if (ret && !mtd_is_bitflip(ret))
                                return ret;
                        if (retlen != size)
                                return -EIO;
index 8afdca731b87496e5b9ef77029668ba24494122c..6b487ffe2f2dc4dd6b0344080cf665ccaab4198b 100644 (file)
@@ -429,6 +429,7 @@ static int mxic_ecc_data_xfer_wait_for_completion(struct mxic_ecc_engine *mxic)
                mxic_ecc_enable_int(mxic);
                ret = wait_for_completion_timeout(&mxic->complete,
                                                  msecs_to_jiffies(1000));
+               ret = ret ? 0 : -ETIMEDOUT;
                mxic_ecc_disable_int(mxic);
        } else {
                ret = readl_poll_timeout(mxic->regs + INTRPT_STS, val,
index 5ee01231ac4cdc5dbb156851a2fdb6c13a402e07..074e14225c06a07e0ceba491d14b5272472860d7 100644 (file)
@@ -176,6 +176,7 @@ struct meson_nfc {
 
        dma_addr_t daddr;
        dma_addr_t iaddr;
+       u32 info_bytes;
 
        unsigned long assigned_cs;
 };
@@ -279,7 +280,7 @@ static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir,
 
        if (raw) {
                len = mtd->writesize + mtd->oobsize;
-               cmd = (len & GENMASK(5, 0)) | scrambler | DMA_DIR(dir);
+               cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir);
                writel(cmd, nfc->reg_base + NFC_REG_CMD);
                return;
        }
@@ -503,6 +504,7 @@ static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, void *databuf,
                                         nfc->daddr, datalen, dir);
                        return ret;
                }
+               nfc->info_bytes = infolen;
                cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr);
                writel(cmd, nfc->reg_base + NFC_REG_CMD);
 
@@ -520,8 +522,10 @@ static void meson_nfc_dma_buffer_release(struct nand_chip *nand,
        struct meson_nfc *nfc = nand_get_controller_data(nand);
 
        dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir);
-       if (infolen)
+       if (infolen) {
                dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir);
+               nfc->info_bytes = 0;
+       }
 }
 
 static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
@@ -540,7 +544,7 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
        if (ret)
                goto out;
 
-       cmd = NFC_CMD_N2M | (len & GENMASK(5, 0));
+       cmd = NFC_CMD_N2M | (len & GENMASK(13, 0));
        writel(cmd, nfc->reg_base + NFC_REG_CMD);
 
        meson_nfc_drain_cmd(nfc);
@@ -564,7 +568,7 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
        if (ret)
                return ret;
 
-       cmd = NFC_CMD_M2N | (len & GENMASK(5, 0));
+       cmd = NFC_CMD_M2N | (len & GENMASK(13, 0));
        writel(cmd, nfc->reg_base + NFC_REG_CMD);
 
        meson_nfc_drain_cmd(nfc);
@@ -710,6 +714,8 @@ static void meson_nfc_check_ecc_pages_valid(struct meson_nfc *nfc,
                usleep_range(10, 15);
                /* info is updated by nfc dma engine*/
                smp_rmb();
+               dma_sync_single_for_cpu(nfc->dev, nfc->iaddr, nfc->info_bytes,
+                                       DMA_FROM_DEVICE);
                ret = *info & ECC_COMPLETE;
        } while (!ret);
 }
@@ -991,7 +997,7 @@ static const struct mtd_ooblayout_ops meson_ooblayout_ops = {
 
 static int meson_nfc_clk_init(struct meson_nfc *nfc)
 {
-       struct clk_parent_data nfc_divider_parent_data[1];
+       struct clk_parent_data nfc_divider_parent_data[1] = {0};
        struct clk_init_data init = {0};
        int ret;
 
index c21abf7489481a5b230fc67b6361456eaa6e07a5..179b28459b4bdd5a158534b69b180dee9cedd5b2 100644 (file)
@@ -2160,8 +2160,23 @@ static int ns_exec_op(struct nand_chip *chip, const struct nand_operation *op,
        const struct nand_op_instr *instr = NULL;
        struct nandsim *ns = nand_get_controller_data(chip);
 
-       if (check_only)
+       if (check_only) {
+               /* The current implementation of nandsim needs to know the
+                * ongoing operation when performing the address cycles. This
+                * means it cannot make the difference between a regular read
+                * and a continuous read. Hence, this hack to manually refuse
+                * supporting sequential cached operations.
+                */
+               for (op_id = 0; op_id < op->ninstrs; op_id++) {
+                       instr = &op->instrs[op_id];
+                       if (instr->type == NAND_OP_CMD_INSTR &&
+                           (instr->ctx.cmd.opcode == NAND_CMD_READCACHEEND ||
+                            instr->ctx.cmd.opcode == NAND_CMD_READCACHESEQ))
+                               return -EOPNOTSUPP;
+               }
+
                return 0;
+       }
 
        ns->lines.ce = 1;
 
index 5d627048c420de5d2516b2135736bb2aec65780b..9e74bcd90aaa2e216a74fee29476bc0b7f209e2c 100644 (file)
@@ -1531,6 +1531,9 @@ static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr,
        if (IS_ERR(sdrt))
                return PTR_ERR(sdrt);
 
+       if (conf->timings.mode > 3)
+               return -EOPNOTSUPP;
+
        if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
                return 0;
 
index 0a78045ca1d94ea184d295bfdb3af8bb1f41894b..522d375aeccff6be0397ce2df10e33261358307e 100644 (file)
@@ -3343,7 +3343,19 @@ static struct spi_mem_driver spi_nor_driver = {
        .remove = spi_nor_remove,
        .shutdown = spi_nor_shutdown,
 };
-module_spi_mem_driver(spi_nor_driver);
+
+static int __init spi_nor_module_init(void)
+{
+       return spi_mem_driver_register(&spi_nor_driver);
+}
+module_init(spi_nor_module_init);
+
+static void __exit spi_nor_module_exit(void)
+{
+       spi_mem_driver_unregister(&spi_nor_driver);
+       spi_nor_debugfs_shutdown();
+}
+module_exit(spi_nor_module_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
index 25423225c29d33f1817a1872106c54e4a00ad5c8..e0cc42a4a0c8410a0148a649b58684ae6eb8940d 100644 (file)
@@ -711,8 +711,10 @@ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 
 #ifdef CONFIG_DEBUG_FS
 void spi_nor_debugfs_register(struct spi_nor *nor);
+void spi_nor_debugfs_shutdown(void);
 #else
 static inline void spi_nor_debugfs_register(struct spi_nor *nor) {}
+static inline void spi_nor_debugfs_shutdown(void) {}
 #endif
 
 #endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
index 845b78c7ecc7a27f6fa18a6afd982adf63a0fea6..fc7ad203df12802b0f5aa5c386a5077b3844143e 100644 (file)
@@ -226,13 +226,13 @@ static void spi_nor_debugfs_unregister(void *data)
        nor->debugfs_root = NULL;
 }
 
+static struct dentry *rootdir;
+
 void spi_nor_debugfs_register(struct spi_nor *nor)
 {
-       struct dentry *rootdir, *d;
+       struct dentry *d;
        int ret;
 
-       /* Create rootdir once. Will never be deleted again. */
-       rootdir = debugfs_lookup(SPI_NOR_DEBUGFS_ROOT, NULL);
        if (!rootdir)
                rootdir = debugfs_create_dir(SPI_NOR_DEBUGFS_ROOT, NULL);
 
@@ -247,3 +247,8 @@ void spi_nor_debugfs_register(struct spi_nor *nor)
        debugfs_create_file("capabilities", 0444, d, nor,
                            &spi_nor_capabilities_fops);
 }
+
+void spi_nor_debugfs_shutdown(void)
+{
+       debugfs_remove(rootdir);
+}
index 0904eb40c95fa133c1cdc4454beb6d4d3d90fc6a..ad025b2ee41773397f7dac35d34dbcba763eb5cf 100644 (file)
@@ -666,12 +666,6 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024)
        ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
        ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
 
-       if (ubi->vid_hdr_offset && ((ubi->vid_hdr_offset + UBI_VID_HDR_SIZE) >
-           ubi->vid_hdr_alsize)) {
-               ubi_err(ubi, "VID header offset %d too large.", ubi->vid_hdr_offset);
-               return -EINVAL;
-       }
-
        dbg_gen("min_io_size      %d", ubi->min_io_size);
        dbg_gen("max_write_size   %d", ubi->max_write_size);
        dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
@@ -689,6 +683,21 @@ static int io_init(struct ubi_device *ubi, int max_beb_per1024)
                                                ubi->vid_hdr_aloffset;
        }
 
+       /*
+        * Memory allocation for VID header is ubi->vid_hdr_alsize
+        * which is described in comments in io.c.
+        * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds
+        * ubi->vid_hdr_alsize, so that all vid header operations
+        * won't access memory out of bounds.
+        */
+       if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) {
+               ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)"
+                       " + VID header size(%zu) > VID header aligned size(%d).",
+                       ubi->vid_hdr_offset, ubi->vid_hdr_shift,
+                       UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize);
+               return -EINVAL;
+       }
+
        /* Similar for the data offset */
        ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
        ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
index 40f39e5d6dfcc068519598452bd8787c7b143c39..26a214f016c18448469c4bb3988ac09af224ab95 100644 (file)
@@ -575,7 +575,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
  * @vol_id: the volume ID that last used this PEB
  * @lnum: the last used logical eraseblock number for the PEB
  * @torture: if the physical eraseblock has to be tortured
- * @nested: denotes whether the work_sem is already held in read mode
+ * @nested: denotes whether the work_sem is already held
  *
  * This function returns zero in case of success and a %-ENOMEM in case of
  * failure.
@@ -1131,7 +1131,7 @@ static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
                int err1;
 
                /* Re-schedule the LEB for erasure */
-               err1 = schedule_erase(ubi, e, vol_id, lnum, 0, false);
+               err1 = schedule_erase(ubi, e, vol_id, lnum, 0, true);
                if (err1) {
                        spin_lock(&ubi->wl_lock);
                        wl_entry_destroy(ubi, e);
index 00646aa315c307f6708f179b5180a9c24813da59..7a7d584f378a5ae441d41ab5c804a31601ec9453 100644 (file)
@@ -1775,6 +1775,20 @@ void bond_lower_state_changed(struct slave *slave)
                slave_err(bond_dev, slave_dev, "Error: %s\n", errmsg);  \
 } while (0)
 
+/* The bonding driver uses ether_setup() to convert a master bond device
+ * to ARPHRD_ETHER, that resets the target netdevice's flags so we always
+ * have to restore the IFF_MASTER flag, and only restore IFF_SLAVE and IFF_UP
+ * if they were set
+ */
+static void bond_ether_setup(struct net_device *bond_dev)
+{
+       unsigned int flags = bond_dev->flags & (IFF_SLAVE | IFF_UP);
+
+       ether_setup(bond_dev);
+       bond_dev->flags |= IFF_MASTER | flags;
+       bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+}
+
 /* enslave device <slave> to bond device <master> */
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
                 struct netlink_ext_ack *extack)
@@ -1866,10 +1880,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 
                        if (slave_dev->type != ARPHRD_ETHER)
                                bond_setup_by_slave(bond_dev, slave_dev);
-                       else {
-                               ether_setup(bond_dev);
-                               bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-                       }
+                       else
+                               bond_ether_setup(bond_dev);
 
                        call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE,
                                                 bond_dev);
@@ -2289,9 +2301,7 @@ err_undo_flags:
                        eth_hw_addr_random(bond_dev);
                if (bond_dev->type != ARPHRD_ETHER) {
                        dev_close(bond_dev);
-                       ether_setup(bond_dev);
-                       bond_dev->flags |= IFF_MASTER;
-                       bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+                       bond_ether_setup(bond_dev);
                }
        }
 
@@ -3260,7 +3270,8 @@ static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond,
 
        combined = skb_header_pointer(skb, 0, sizeof(_combined), &_combined);
        if (!combined || combined->ip6.nexthdr != NEXTHDR_ICMP ||
-           combined->icmp6.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT)
+           (combined->icmp6.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION &&
+            combined->icmp6.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT))
                goto out;
 
        saddr = &combined->ip6.saddr;
@@ -3282,7 +3293,7 @@ static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond,
        else if (curr_active_slave &&
                 time_after(slave_last_rx(bond, curr_active_slave),
                            curr_active_slave->last_link_up))
-               bond_validate_na(bond, slave, saddr, daddr);
+               bond_validate_na(bond, slave, daddr, saddr);
        else if (curr_arp_slave &&
                 bond_time_in_interval(bond, slave_last_tx(curr_arp_slave), 1))
                bond_validate_na(bond, slave, saddr, daddr);
index 8d916e2ee6c252e22a200376787e4f84351c7363..8dcc32e4e30efac4f655cf9f28d856758d97252a 100644 (file)
@@ -93,20 +93,20 @@ static int cc770_get_of_node_data(struct platform_device *pdev,
        if (priv->can.clock.freq > 8000000)
                priv->cpu_interface |= CPUIF_DMC;
 
-       if (of_get_property(np, "bosch,divide-memory-clock", NULL))
+       if (of_property_read_bool(np, "bosch,divide-memory-clock"))
                priv->cpu_interface |= CPUIF_DMC;
-       if (of_get_property(np, "bosch,iso-low-speed-mux", NULL))
+       if (of_property_read_bool(np, "bosch,iso-low-speed-mux"))
                priv->cpu_interface |= CPUIF_MUX;
 
        if (!of_get_property(np, "bosch,no-comperator-bypass", NULL))
                priv->bus_config |= BUSCFG_CBY;
-       if (of_get_property(np, "bosch,disconnect-rx0-input", NULL))
+       if (of_property_read_bool(np, "bosch,disconnect-rx0-input"))
                priv->bus_config |= BUSCFG_DR0;
-       if (of_get_property(np, "bosch,disconnect-rx1-input", NULL))
+       if (of_property_read_bool(np, "bosch,disconnect-rx1-input"))
                priv->bus_config |= BUSCFG_DR1;
-       if (of_get_property(np, "bosch,disconnect-tx1-output", NULL))
+       if (of_property_read_bool(np, "bosch,disconnect-tx1-output"))
                priv->bus_config |= BUSCFG_DT1;
-       if (of_get_property(np, "bosch,polarity-dominant", NULL))
+       if (of_property_read_bool(np, "bosch,polarity-dominant"))
                priv->bus_config |= BUSCFG_POL;
 
        prop = of_get_property(np, "bosch,clock-out-frequency", &prop_size);
index e968322dfbf0b262e23cd55fa482d5eb268fd2dc..d9434ed9450dfe0e3921e890f1ebe7d629690334 100644 (file)
@@ -216,6 +216,18 @@ static int b53_mmap_write64(struct b53_device *dev, u8 page, u8 reg,
        return 0;
 }
 
+static int b53_mmap_phy_read16(struct b53_device *dev, int addr, int reg,
+                              u16 *value)
+{
+       return -EIO;
+}
+
+static int b53_mmap_phy_write16(struct b53_device *dev, int addr, int reg,
+                               u16 value)
+{
+       return -EIO;
+}
+
 static const struct b53_io_ops b53_mmap_ops = {
        .read8 = b53_mmap_read8,
        .read16 = b53_mmap_read16,
@@ -227,6 +239,8 @@ static const struct b53_io_ops b53_mmap_ops = {
        .write32 = b53_mmap_write32,
        .write48 = b53_mmap_write48,
        .write64 = b53_mmap_write64,
+       .phy_read16 = b53_mmap_phy_read16,
+       .phy_write16 = b53_mmap_phy_write16,
 };
 
 static int b53_mmap_probe_of(struct platform_device *pdev,
@@ -263,7 +277,7 @@ static int b53_mmap_probe_of(struct platform_device *pdev,
                if (of_property_read_u32(of_port, "reg", &reg))
                        continue;
 
-               if (reg < B53_CPU_PORT)
+               if (reg < B53_N_PORTS)
                        pdata->enabled_ports |= BIT(reg);
        }
 
index 003b0ac2854c97c5c9f4c8c84ca20c642dab1259..ffcad057d0650c7fbd44aa494bc68896f8b5829a 100644 (file)
@@ -96,7 +96,7 @@ static int ksz8795_change_mtu(struct ksz_device *dev, int frame_size)
 
        if (frame_size > KSZ8_LEGAL_PACKET_SIZE)
                ctrl2 |= SW_LEGAL_PACKET_DISABLE;
-       else if (frame_size > KSZ8863_NORMAL_PACKET_SIZE)
+       if (frame_size > KSZ8863_NORMAL_PACKET_SIZE)
                ctrl1 |= SW_HUGE_PACKET;
 
        ret = ksz_rmw8(dev, REG_SW_CTRL_1, SW_HUGE_PACKET, ctrl1);
@@ -958,15 +958,14 @@ int ksz8_fdb_dump(struct ksz_device *dev, int port,
        u16 entries = 0;
        u8 timestamp = 0;
        u8 fid;
-       u8 member;
-       struct alu_struct alu;
+       u8 src_port;
+       u8 mac[ETH_ALEN];
 
        do {
-               alu.is_static = false;
-               ret = ksz8_r_dyn_mac_table(dev, i, alu.mac, &fid, &member,
+               ret = ksz8_r_dyn_mac_table(dev, i, mac, &fid, &src_port,
                                           &timestamp, &entries);
-               if (!ret && (member & BIT(port))) {
-                       ret = cb(alu.mac, alu.fid, alu.is_static, data);
+               if (!ret && port == src_port) {
+                       ret = cb(mac, fid, false, data);
                        if (ret)
                                break;
                }
index 2f4623f3bd852a81253375175af18efb1ef7e8a3..3698112138b78b33a1205690b3d9a35e5ab6c557 100644 (file)
@@ -82,22 +82,16 @@ static const struct regmap_bus regmap_smi[] = {
        {
                .read = ksz8863_mdio_read,
                .write = ksz8863_mdio_write,
-               .max_raw_read = 1,
-               .max_raw_write = 1,
        },
        {
                .read = ksz8863_mdio_read,
                .write = ksz8863_mdio_write,
                .val_format_endian_default = REGMAP_ENDIAN_BIG,
-               .max_raw_read = 2,
-               .max_raw_write = 2,
        },
        {
                .read = ksz8863_mdio_read,
                .write = ksz8863_mdio_write,
                .val_format_endian_default = REGMAP_ENDIAN_BIG,
-               .max_raw_read = 4,
-               .max_raw_write = 4,
        }
 };
 
@@ -108,7 +102,6 @@ static const struct regmap_config ksz8863_regmap_config[] = {
                .pad_bits = 24,
                .val_bits = 8,
                .cache_type = REGCACHE_NONE,
-               .use_single_read = 1,
                .lock = ksz_regmap_lock,
                .unlock = ksz_regmap_unlock,
        },
@@ -118,7 +111,6 @@ static const struct regmap_config ksz8863_regmap_config[] = {
                .pad_bits = 24,
                .val_bits = 16,
                .cache_type = REGCACHE_NONE,
-               .use_single_read = 1,
                .lock = ksz_regmap_lock,
                .unlock = ksz_regmap_unlock,
        },
@@ -128,7 +120,6 @@ static const struct regmap_config ksz8863_regmap_config[] = {
                .pad_bits = 24,
                .val_bits = 32,
                .cache_type = REGCACHE_NONE,
-               .use_single_read = 1,
                .lock = ksz_regmap_lock,
                .unlock = ksz_regmap_unlock,
        }
index 729b36eeb2c46acacf9312f1af6fd7a68f40455e..74c56d05ab0b9d582eb32c45480b5c6fd8df5ecd 100644 (file)
@@ -319,7 +319,7 @@ static const u16 ksz8795_regs[] = {
        [S_BROADCAST_CTRL]              = 0x06,
        [S_MULTICAST_CTRL]              = 0x04,
        [P_XMII_CTRL_0]                 = 0x06,
-       [P_XMII_CTRL_1]                 = 0x56,
+       [P_XMII_CTRL_1]                 = 0x06,
 };
 
 static const u32 ksz8795_masks[] = {
@@ -404,13 +404,13 @@ static const u32 ksz8863_masks[] = {
        [VLAN_TABLE_VALID]              = BIT(19),
        [STATIC_MAC_TABLE_VALID]        = BIT(19),
        [STATIC_MAC_TABLE_USE_FID]      = BIT(21),
-       [STATIC_MAC_TABLE_FID]          = GENMASK(29, 26),
+       [STATIC_MAC_TABLE_FID]          = GENMASK(25, 22),
        [STATIC_MAC_TABLE_OVERRIDE]     = BIT(20),
        [STATIC_MAC_TABLE_FWD_PORTS]    = GENMASK(18, 16),
-       [DYNAMIC_MAC_TABLE_ENTRIES_H]   = GENMASK(5, 0),
-       [DYNAMIC_MAC_TABLE_MAC_EMPTY]   = BIT(7),
+       [DYNAMIC_MAC_TABLE_ENTRIES_H]   = GENMASK(1, 0),
+       [DYNAMIC_MAC_TABLE_MAC_EMPTY]   = BIT(2),
        [DYNAMIC_MAC_TABLE_NOT_READY]   = BIT(7),
-       [DYNAMIC_MAC_TABLE_ENTRIES]     = GENMASK(31, 28),
+       [DYNAMIC_MAC_TABLE_ENTRIES]     = GENMASK(31, 24),
        [DYNAMIC_MAC_TABLE_FID]         = GENMASK(19, 16),
        [DYNAMIC_MAC_TABLE_SRC_PORT]    = GENMASK(21, 20),
        [DYNAMIC_MAC_TABLE_TIMESTAMP]   = GENMASK(23, 22),
@@ -420,10 +420,10 @@ static u8 ksz8863_shifts[] = {
        [VLAN_TABLE_MEMBERSHIP_S]       = 16,
        [STATIC_MAC_FWD_PORTS]          = 16,
        [STATIC_MAC_FID]                = 22,
-       [DYNAMIC_MAC_ENTRIES_H]         = 3,
+       [DYNAMIC_MAC_ENTRIES_H]         = 8,
        [DYNAMIC_MAC_ENTRIES]           = 24,
        [DYNAMIC_MAC_FID]               = 16,
-       [DYNAMIC_MAC_TIMESTAMP]         = 24,
+       [DYNAMIC_MAC_TIMESTAMP]         = 22,
        [DYNAMIC_MAC_SRC_PORT]          = 20,
 };
 
index a508402c4ecbf60379097106a47a7dc53bb96ac8..02410ac439b76c18c915562ebddd35aec685364a 100644 (file)
@@ -396,6 +396,9 @@ mt7530_fdb_write(struct mt7530_priv *priv, u16 vid,
 /* Set up switch core clock for MT7530 */
 static void mt7530_pll_setup(struct mt7530_priv *priv)
 {
+       /* Disable core clock */
+       core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
+
        /* Disable PLL */
        core_write(priv, CORE_GSWPLL_GRP1, 0);
 
@@ -409,14 +412,19 @@ static void mt7530_pll_setup(struct mt7530_priv *priv)
                   RG_GSWPLL_EN_PRE |
                   RG_GSWPLL_POSDIV_200M(2) |
                   RG_GSWPLL_FBKDIV_200M(32));
+
+       udelay(20);
+
+       /* Enable core clock */
+       core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
 }
 
-/* Setup TX circuit including relevant PAD and driving */
+/* Setup port 6 interface mode and TRGMII TX circuit */
 static int
 mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
 {
        struct mt7530_priv *priv = ds->priv;
-       u32 ncpo1, ssc_delta, trgint, i, xtal;
+       u32 ncpo1, ssc_delta, trgint, xtal;
 
        xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
 
@@ -430,11 +438,13 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
        switch (interface) {
        case PHY_INTERFACE_MODE_RGMII:
                trgint = 0;
-               /* PLL frequency: 125MHz */
-               ncpo1 = 0x0c80;
                break;
        case PHY_INTERFACE_MODE_TRGMII:
                trgint = 1;
+               if (xtal == HWTRAP_XTAL_25MHZ)
+                       ssc_delta = 0x57;
+               else
+                       ssc_delta = 0x87;
                if (priv->id == ID_MT7621) {
                        /* PLL frequency: 150MHz: 1.2GBit */
                        if (xtal == HWTRAP_XTAL_40MHZ)
@@ -454,46 +464,32 @@ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
                return -EINVAL;
        }
 
-       if (xtal == HWTRAP_XTAL_25MHZ)
-               ssc_delta = 0x57;
-       else
-               ssc_delta = 0x87;
-
        mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
                   P6_INTF_MODE(trgint));
 
-       /* Lower Tx Driving for TRGMII path */
-       for (i = 0 ; i < NUM_TRGMII_CTRL ; i++)
-               mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
-                            TD_DM_DRVP(8) | TD_DM_DRVN(8));
+       if (trgint) {
+               /* Disable the MT7530 TRGMII clocks */
+               core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
+
+               /* Setup the MT7530 TRGMII Tx Clock */
+               core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1));
+               core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0));
+               core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta));
+               core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta));
+               core_write(priv, CORE_PLL_GROUP4,
+                          RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN |
+                          RG_SYSPLL_BIAS_LPF_EN);
+               core_write(priv, CORE_PLL_GROUP2,
+                          RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
+                          RG_SYSPLL_POSDIV(1));
+               core_write(priv, CORE_PLL_GROUP7,
+                          RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) |
+                          RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
+
+               /* Enable the MT7530 TRGMII clocks */
+               core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
+       }
 
-       /* Disable MT7530 core and TRGMII Tx clocks */
-       core_clear(priv, CORE_TRGMII_GSW_CLK_CG,
-                  REG_GSWCK_EN | REG_TRGMIICK_EN);
-
-       /* Setup the MT7530 TRGMII Tx Clock */
-       core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1));
-       core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0));
-       core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta));
-       core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta));
-       core_write(priv, CORE_PLL_GROUP4,
-                  RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN |
-                  RG_SYSPLL_BIAS_LPF_EN);
-       core_write(priv, CORE_PLL_GROUP2,
-                  RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
-                  RG_SYSPLL_POSDIV(1));
-       core_write(priv, CORE_PLL_GROUP7,
-                  RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) |
-                  RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
-
-       /* Enable MT7530 core and TRGMII Tx clocks */
-       core_set(priv, CORE_TRGMII_GSW_CLK_CG,
-                REG_GSWCK_EN | REG_TRGMIICK_EN);
-
-       if (!trgint)
-               for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
-                       mt7530_rmw(priv, MT7530_TRGMII_RD(i),
-                                  RD_TAP_MASK, RD_TAP(16));
        return 0;
 }
 
@@ -2201,7 +2197,16 @@ mt7530_setup(struct dsa_switch *ds)
 
        mt7530_pll_setup(priv);
 
-       /* Enable Port 6 only; P5 as GMAC5 which currently is not supported */
+       /* Lower Tx driving for TRGMII path */
+       for (i = 0; i < NUM_TRGMII_CTRL; i++)
+               mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
+                            TD_DM_DRVP(8) | TD_DM_DRVN(8));
+
+       for (i = 0; i < NUM_TRGMII_CTRL; i++)
+               mt7530_rmw(priv, MT7530_TRGMII_RD(i),
+                          RD_TAP_MASK, RD_TAP(16));
+
+       /* Enable port 6 */
        val = mt7530_read(priv, MT7530_MHWTRAP);
        val &= ~MHWTRAP_P6_DIS & ~MHWTRAP_PHY_ACCESS;
        val |= MHWTRAP_MANUAL;
index 0a5d6c7bb128dfd8dab5b200f72d0a1f6c7396b1..7108f745fbf010b78bea87f5155eb61b17651175 100644 (file)
@@ -3354,9 +3354,14 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
         * If this is the upstream port for this switch, enable
         * forwarding of unknown unicasts and multicasts.
         */
-       reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
-               MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
+       reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
                MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
+       /* Forward any IPv4 IGMP or IPv6 MLD frames received
+        * by a USER port to the CPU port to allow snooping.
+        */
+       if (dsa_is_user_port(ds, port))
+               reg |= MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP;
+
        err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
        if (err)
                return err;
@@ -3549,7 +3554,7 @@ static int mv88e6xxx_get_max_mtu(struct dsa_switch *ds, int port)
                return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
        else if (chip->info->ops->set_max_frame_size)
                return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
-       return 1522 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;
+       return ETH_DATA_LEN;
 }
 
 static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
@@ -3557,6 +3562,17 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
        struct mv88e6xxx_chip *chip = ds->priv;
        int ret = 0;
 
+       /* For families where we don't know how to alter the MTU,
+        * just accept any value up to ETH_DATA_LEN
+        */
+       if (!chip->info->ops->port_set_jumbo_size &&
+           !chip->info->ops->set_max_frame_size) {
+               if (new_mtu > ETH_DATA_LEN)
+                       return -EINVAL;
+
+               return 0;
+       }
+
        if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
                new_mtu += EDSA_HLEN;
 
@@ -3565,9 +3581,6 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
                ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu);
        else if (chip->info->ops->set_max_frame_size)
                ret = chip->info->ops->set_max_frame_size(chip, new_mtu);
-       else
-               if (new_mtu > 1522)
-                       ret = -EINVAL;
        mv88e6xxx_reg_unlock(chip);
 
        return ret;
@@ -5588,7 +5601,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
         * .port_set_upstream_port method.
         */
        .set_egress_port = mv88e6393x_set_egress_port,
-       .watchdog_ops = &mv88e6390_watchdog_ops,
+       .watchdog_ops = &mv88e6393x_watchdog_ops,
        .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
        .pot_clear = mv88e6xxx_g2_pot_clear,
        .reset = mv88e6352_g1_reset,
index ed3b2f88e7835d7b7449d4b1f7c8e6ce80f188cd..a7af3cebae97c9a1ce67893fb44c53202cb4af59 100644 (file)
@@ -943,6 +943,26 @@ const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
        .irq_free = mv88e6390_watchdog_free,
 };
 
+static int mv88e6393x_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
+{
+       mv88e6390_watchdog_action(chip, irq);
+
+       /* Fix for clearing the force WD event bit.
+        * Unreleased erratum on mv88e6393x.
+        */
+       mv88e6xxx_g2_write(chip, MV88E6390_G2_WDOG_CTL,
+                          MV88E6390_G2_WDOG_CTL_UPDATE |
+                          MV88E6390_G2_WDOG_CTL_PTR_EVENT);
+
+       return IRQ_HANDLED;
+}
+
+const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops = {
+       .irq_action = mv88e6393x_watchdog_action,
+       .irq_setup = mv88e6390_watchdog_setup,
+       .irq_free = mv88e6390_watchdog_free,
+};
+
 static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
 {
        struct mv88e6xxx_chip *chip = dev_id;
index e973114d689069998c6934787d614d779910db7b..7e091965582b75254b3dd6b0fed781a77f637d75 100644 (file)
@@ -369,6 +369,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
 extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
 extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
 extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
+extern const struct mv88e6xxx_irq_ops mv88e6393x_watchdog_ops;
 
 extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
 extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops;
index 3e54fac5f9027ca1ae3d11f39f3735a102b0d17d..5a8fe707ca25ef7bafa7f1c7448ef8b158018fdf 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/overflow.h>
 #include <linux/regmap.h>
 
 #include "realtek.h"
@@ -152,7 +153,9 @@ static int realtek_mdio_probe(struct mdio_device *mdiodev)
        if (!var)
                return -EINVAL;
 
-       priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
+       priv = devm_kzalloc(&mdiodev->dev,
+                           size_add(sizeof(*priv), var->chip_data_sz),
+                           GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
index 8da79eedc057c2f68dbbe5cd3ff6656934f915b7..1d4f2f4d10f2967fda9d4a1a17f5b7e7b17111f8 100644 (file)
@@ -850,11 +850,20 @@ static int ena_set_channels(struct net_device *netdev,
        struct ena_adapter *adapter = netdev_priv(netdev);
        u32 count = channels->combined_count;
        /* The check for max value is already done in ethtool */
-       if (count < ENA_MIN_NUM_IO_QUEUES ||
-           (ena_xdp_present(adapter) &&
-           !ena_xdp_legal_queue_count(adapter, count)))
+       if (count < ENA_MIN_NUM_IO_QUEUES)
                return -EINVAL;
 
+       if (!ena_xdp_legal_queue_count(adapter, count)) {
+               if (ena_xdp_present(adapter))
+                       return -EINVAL;
+
+               xdp_clear_features_flag(netdev);
+       } else {
+               xdp_set_features_flag(netdev,
+                                     NETDEV_XDP_ACT_BASIC |
+                                     NETDEV_XDP_ACT_REDIRECT);
+       }
+
        return ena_update_queue_count(adapter, count);
 }
 
index d3999db7c6a29d1f6677ca9de4ff197ee28fda4b..cbfe7f977270f7f5134d766b552449a35bd65927 100644 (file)
@@ -4105,8 +4105,6 @@ static void ena_set_conf_feat_params(struct ena_adapter *adapter,
        /* Set offload features */
        ena_set_dev_offloads(feat, netdev);
 
-       netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT;
-
        adapter->max_mtu = feat->dev_attr.max_mtu;
        netdev->max_mtu = adapter->max_mtu;
        netdev->min_mtu = ENA_MIN_MTU;
@@ -4393,6 +4391,10 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        ena_config_debug_area(adapter);
 
+       if (ena_xdp_legal_queue_count(adapter, adapter->num_io_queues))
+               netdev->xdp_features = NETDEV_XDP_ACT_BASIC |
+                                      NETDEV_XDP_ACT_REDIRECT;
+
        memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);
 
        netif_carrier_off(netdev);
index 1e8d902e1c8eaa45df1ad5231299f10247919958..7f933175cbdac9aa643246190a0f6b297af19414 100644 (file)
@@ -412,6 +412,25 @@ int aq_xdp_xmit(struct net_device *dev, int num_frames,
        return num_frames - drop;
 }
 
+static struct sk_buff *aq_xdp_build_skb(struct xdp_buff *xdp,
+                                       struct net_device *dev,
+                                       struct aq_ring_buff_s *buff)
+{
+       struct xdp_frame *xdpf;
+       struct sk_buff *skb;
+
+       xdpf = xdp_convert_buff_to_frame(xdp);
+       if (unlikely(!xdpf))
+               return NULL;
+
+       skb = xdp_build_skb_from_frame(xdpf, dev);
+       if (!skb)
+               return NULL;
+
+       aq_get_rxpages_xdp(buff, xdp);
+       return skb;
+}
+
 static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic,
                                       struct xdp_buff *xdp,
                                       struct aq_ring_s *rx_ring,
@@ -431,7 +450,7 @@ static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic,
 
        prog = READ_ONCE(rx_ring->xdp_prog);
        if (!prog)
-               goto pass;
+               return aq_xdp_build_skb(xdp, aq_nic->ndev, buff);
 
        prefetchw(xdp->data_hard_start); /* xdp_frame write */
 
@@ -442,17 +461,12 @@ static struct sk_buff *aq_xdp_run_prog(struct aq_nic_s *aq_nic,
        act = bpf_prog_run_xdp(prog, xdp);
        switch (act) {
        case XDP_PASS:
-pass:
-               xdpf = xdp_convert_buff_to_frame(xdp);
-               if (unlikely(!xdpf))
-                       goto out_aborted;
-               skb = xdp_build_skb_from_frame(xdpf, aq_nic->ndev);
+               skb = aq_xdp_build_skb(xdp, aq_nic->ndev, buff);
                if (!skb)
                        goto out_aborted;
                u64_stats_update_begin(&rx_ring->stats.rx.syncp);
                ++rx_ring->stats.rx.xdp_pass;
                u64_stats_update_end(&rx_ring->stats.rx.syncp);
-               aq_get_rxpages_xdp(buff, xdp);
                return skb;
        case XDP_TX:
                xdpf = xdp_convert_buff_to_frame(xdp);
index 16c490692f4221aa5fa415fa045e3a67fd2c4d2c..12083b9679b54988bb61643962377f313738256b 100644 (file)
@@ -672,6 +672,18 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        return 0;
 }
 
+static struct sk_buff *
+bnx2x_build_skb(const struct bnx2x_fastpath *fp, void *data)
+{
+       struct sk_buff *skb;
+
+       if (fp->rx_frag_size)
+               skb = build_skb(data, fp->rx_frag_size);
+       else
+               skb = slab_build_skb(data);
+       return skb;
+}
+
 static void bnx2x_frag_free(const struct bnx2x_fastpath *fp, void *data)
 {
        if (fp->rx_frag_size)
@@ -779,7 +791,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
                         fp->rx_buf_size, DMA_FROM_DEVICE);
        if (likely(new_data))
-               skb = build_skb(data, fp->rx_frag_size);
+               skb = bnx2x_build_skb(fp, data);
 
        if (likely(skb)) {
 #ifdef BNX2X_STOP_ON_ERROR
@@ -1046,7 +1058,7 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                                                 dma_unmap_addr(rx_buf, mapping),
                                                 fp->rx_buf_size,
                                                 DMA_FROM_DEVICE);
-                               skb = build_skb(data, fp->rx_frag_size);
+                               skb = bnx2x_build_skb(fp, data);
                                if (unlikely(!skb)) {
                                        bnx2x_frag_free(fp, data);
                                        bnx2x_fp_qstats(bp, fp)->
index 808236dc898b8d15fe41dc7f508fe40e87a13000..651b79ce5d80c628e3c9625de2a56b4253c286a7 100644 (file)
@@ -175,12 +175,12 @@ static const struct pci_device_id bnxt_pci_tbl[] = {
        { PCI_VDEVICE(BROADCOM, 0x1750), .driver_data = BCM57508 },
        { PCI_VDEVICE(BROADCOM, 0x1751), .driver_data = BCM57504 },
        { PCI_VDEVICE(BROADCOM, 0x1752), .driver_data = BCM57502 },
-       { PCI_VDEVICE(BROADCOM, 0x1800), .driver_data = BCM57508_NPAR },
+       { PCI_VDEVICE(BROADCOM, 0x1800), .driver_data = BCM57502_NPAR },
        { PCI_VDEVICE(BROADCOM, 0x1801), .driver_data = BCM57504_NPAR },
-       { PCI_VDEVICE(BROADCOM, 0x1802), .driver_data = BCM57502_NPAR },
-       { PCI_VDEVICE(BROADCOM, 0x1803), .driver_data = BCM57508_NPAR },
+       { PCI_VDEVICE(BROADCOM, 0x1802), .driver_data = BCM57508_NPAR },
+       { PCI_VDEVICE(BROADCOM, 0x1803), .driver_data = BCM57502_NPAR },
        { PCI_VDEVICE(BROADCOM, 0x1804), .driver_data = BCM57504_NPAR },
-       { PCI_VDEVICE(BROADCOM, 0x1805), .driver_data = BCM57502_NPAR },
+       { PCI_VDEVICE(BROADCOM, 0x1805), .driver_data = BCM57508_NPAR },
        { PCI_VDEVICE(BROADCOM, 0xd802), .driver_data = BCM58802 },
        { PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 },
 #ifdef CONFIG_BNXT_SRIOV
@@ -2388,7 +2388,7 @@ static int bnxt_async_event_process(struct bnxt *bp,
        case ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE: {
                switch (BNXT_EVENT_PHC_EVENT_TYPE(data1)) {
                case ASYNC_EVENT_CMPL_PHC_UPDATE_EVENT_DATA1_FLAGS_PHC_RTC_UPDATE:
-                       if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) {
+                       if (BNXT_PTP_USE_RTC(bp)) {
                                struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
                                u64 ns;
 
@@ -6990,11 +6990,9 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
                if (flags & FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED)
                        bp->fw_cap |= BNXT_FW_CAP_DCBX_AGENT;
        }
-       if (BNXT_PF(bp) && (flags & FUNC_QCFG_RESP_FLAGS_MULTI_HOST)) {
+       if (BNXT_PF(bp) && (flags & FUNC_QCFG_RESP_FLAGS_MULTI_HOST))
                bp->flags |= BNXT_FLAG_MULTI_HOST;
-               if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC)
-                       bp->fw_cap &= ~BNXT_FW_CAP_PTP_RTC;
-       }
+
        if (flags & FUNC_QCFG_RESP_FLAGS_RING_MONITOR_ENABLED)
                bp->fw_cap |= BNXT_FW_CAP_RING_MONITOR;
 
@@ -7629,7 +7627,7 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
        u8 flags;
        int rc;
 
-       if (bp->hwrm_spec_code < 0x10801) {
+       if (bp->hwrm_spec_code < 0x10801 || !BNXT_CHIP_P5_THOR(bp)) {
                rc = -ENODEV;
                goto no_ptp;
        }
index dcb09fbe4007814ab9fec7bb03f06c4d0460ebe5..5928430f6f518eef02c19ea950497a178e114731 100644 (file)
@@ -1226,6 +1226,7 @@ struct bnxt_link_info {
 #define BNXT_LINK_SPEED_40GB   PORT_PHY_QCFG_RESP_LINK_SPEED_40GB
 #define BNXT_LINK_SPEED_50GB   PORT_PHY_QCFG_RESP_LINK_SPEED_50GB
 #define BNXT_LINK_SPEED_100GB  PORT_PHY_QCFG_RESP_LINK_SPEED_100GB
+#define BNXT_LINK_SPEED_200GB  PORT_PHY_QCFG_RESP_LINK_SPEED_200GB
        u16                     support_speeds;
        u16                     support_pam4_speeds;
        u16                     auto_link_speeds;       /* fw adv setting */
@@ -2000,6 +2001,8 @@ struct bnxt {
        u32                     fw_dbg_cap;
 
 #define BNXT_NEW_RM(bp)                ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
+#define BNXT_PTP_USE_RTC(bp)   (!BNXT_MH(bp) && \
+                                ((bp)->fw_cap & BNXT_FW_CAP_PTP_RTC))
        u32                     hwrm_spec_code;
        u16                     hwrm_cmd_seq;
        u16                     hwrm_cmd_kong_seq;
index ec573127b70762fd6b26f5108b28a4318f045d92..6bd18eb5137f44c8cf7ac7e41a4d128da10704f7 100644 (file)
@@ -1714,6 +1714,8 @@ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
                return SPEED_50000;
        case BNXT_LINK_SPEED_100GB:
                return SPEED_100000;
+       case BNXT_LINK_SPEED_200GB:
+               return SPEED_200000;
        default:
                return SPEED_UNKNOWN;
        }
@@ -3738,6 +3740,7 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
                bnxt_ulp_stop(bp);
                rc = bnxt_close_nic(bp, true, false);
                if (rc) {
+                       etest->flags |= ETH_TEST_FL_FAILED;
                        bnxt_ulp_start(bp, rc);
                        return;
                }
index 4ec8bba18cdd2c8abd58fc4649d1516f2507669a..a3a3978a4d1c257d343b425b1350dbef66c318ae 100644 (file)
@@ -63,7 +63,7 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
                                                ptp_info);
        u64 ns = timespec64_to_ns(ts);
 
-       if (ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC)
+       if (BNXT_PTP_USE_RTC(ptp->bp))
                return bnxt_ptp_cfg_settime(ptp->bp, ns);
 
        spin_lock_bh(&ptp->ptp_lock);
@@ -196,7 +196,7 @@ static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
        struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
                                                ptp_info);
 
-       if (ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC)
+       if (BNXT_PTP_USE_RTC(ptp->bp))
                return bnxt_ptp_adjphc(ptp, delta);
 
        spin_lock_bh(&ptp->ptp_lock);
@@ -205,34 +205,39 @@ static int bnxt_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta)
        return 0;
 }
 
+static int bnxt_ptp_adjfine_rtc(struct bnxt *bp, long scaled_ppm)
+{
+       s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+       struct hwrm_port_mac_cfg_input *req;
+       int rc;
+
+       rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG);
+       if (rc)
+               return rc;
+
+       req->ptp_freq_adj_ppb = cpu_to_le32(ppb);
+       req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB);
+       rc = hwrm_req_send(bp, req);
+       if (rc)
+               netdev_err(bp->dev,
+                          "ptp adjfine failed. rc = %d\n", rc);
+       return rc;
+}
+
 static int bnxt_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm)
 {
        struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
                                                ptp_info);
-       struct hwrm_port_mac_cfg_input *req;
        struct bnxt *bp = ptp->bp;
-       int rc = 0;
 
-       if (!(ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC)) {
-               spin_lock_bh(&ptp->ptp_lock);
-               timecounter_read(&ptp->tc);
-               ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm);
-               spin_unlock_bh(&ptp->ptp_lock);
-       } else {
-               s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
-
-               rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_CFG);
-               if (rc)
-                       return rc;
+       if (BNXT_PTP_USE_RTC(bp))
+               return bnxt_ptp_adjfine_rtc(bp, scaled_ppm);
 
-               req->ptp_freq_adj_ppb = cpu_to_le32(ppb);
-               req->enables = cpu_to_le32(PORT_MAC_CFG_REQ_ENABLES_PTP_FREQ_ADJ_PPB);
-               rc = hwrm_req_send(ptp->bp, req);
-               if (rc)
-                       netdev_err(ptp->bp->dev,
-                                  "ptp adjfine failed. rc = %d\n", rc);
-       }
-       return rc;
+       spin_lock_bh(&ptp->ptp_lock);
+       timecounter_read(&ptp->tc);
+       ptp->cc.mult = adjust_by_scaled_ppm(ptp->cmult, scaled_ppm);
+       spin_unlock_bh(&ptp->ptp_lock);
+       return 0;
 }
 
 void bnxt_ptp_pps_event(struct bnxt *bp, u32 data1, u32 data2)
@@ -879,7 +884,7 @@ int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg)
        u64 ns;
        int rc;
 
-       if (!bp->ptp_cfg || !(bp->fw_cap & BNXT_FW_CAP_PTP_RTC))
+       if (!bp->ptp_cfg || !BNXT_PTP_USE_RTC(bp))
                return -ENODEV;
 
        if (!phc_cfg) {
@@ -932,13 +937,14 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
        atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS);
        spin_lock_init(&ptp->ptp_lock);
 
-       if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) {
+       if (BNXT_PTP_USE_RTC(bp)) {
                bnxt_ptp_timecounter_init(bp, false);
                rc = bnxt_ptp_init_rtc(bp, phc_cfg);
                if (rc)
                        goto out;
        } else {
                bnxt_ptp_timecounter_init(bp, true);
+               bnxt_ptp_adjfine_rtc(bp, 0);
        }
 
        ptp->ptp_info = bnxt_ptp_caps;
index e7b5e28ee29f185eebf92662dc37f5881f1f186d..852eb449ccae222c74e147de17e1aeec63b90ca7 100644 (file)
@@ -304,7 +304,7 @@ void bnxt_rdma_aux_device_uninit(struct bnxt *bp)
        struct auxiliary_device *adev;
 
        /* Skip if no auxiliary device init was done. */
-       if (!(bp->flags & BNXT_FLAG_ROCE_CAP))
+       if (!bp->aux_priv)
                return;
 
        aux_priv = bp->aux_priv;
@@ -324,6 +324,7 @@ static void bnxt_aux_dev_release(struct device *dev)
        bp->edev = NULL;
        kfree(aux_priv->edev);
        kfree(aux_priv);
+       bp->aux_priv = NULL;
 }
 
 static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
@@ -359,19 +360,18 @@ void bnxt_rdma_aux_device_init(struct bnxt *bp)
        if (!(bp->flags & BNXT_FLAG_ROCE_CAP))
                return;
 
-       bp->aux_priv = kzalloc(sizeof(*bp->aux_priv), GFP_KERNEL);
-       if (!bp->aux_priv)
+       aux_priv = kzalloc(sizeof(*bp->aux_priv), GFP_KERNEL);
+       if (!aux_priv)
                goto exit;
 
-       bp->aux_priv->id = ida_alloc(&bnxt_aux_dev_ids, GFP_KERNEL);
-       if (bp->aux_priv->id < 0) {
+       aux_priv->id = ida_alloc(&bnxt_aux_dev_ids, GFP_KERNEL);
+       if (aux_priv->id < 0) {
                netdev_warn(bp->dev,
                            "ida alloc failed for ROCE auxiliary device\n");
-               kfree(bp->aux_priv);
+               kfree(aux_priv);
                goto exit;
        }
 
-       aux_priv = bp->aux_priv;
        aux_dev = &aux_priv->aux_dev;
        aux_dev->id = aux_priv->id;
        aux_dev->name = "rdma";
@@ -380,10 +380,11 @@ void bnxt_rdma_aux_device_init(struct bnxt *bp)
 
        rc = auxiliary_device_init(aux_dev);
        if (rc) {
-               ida_free(&bnxt_aux_dev_ids, bp->aux_priv->id);
-               kfree(bp->aux_priv);
+               ida_free(&bnxt_aux_dev_ids, aux_priv->id);
+               kfree(aux_priv);
                goto exit;
        }
+       bp->aux_priv = aux_priv;
 
        /* From this point, all cleanup will happen via the .release callback &
         * any error unwinding will need to include a call to
index 6e141a8bbf43cbcc36d6bd9eee78eb9d32d599d8..e43d99ec50ba2c9c547bdfa1daed5b894fee2992 100644 (file)
@@ -1064,6 +1064,10 @@ static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
        }
 #endif
        addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
+#ifdef CONFIG_MACB_USE_HWSTAMP
+       if (bp->hw_dma_cap & HW_DMA_CAP_PTP)
+               addr &= ~GEM_BIT(DMA_RXVALID);
+#endif
        return addr;
 }
 
@@ -4990,7 +4994,7 @@ static int macb_probe(struct platform_device *pdev)
                bp->jumbo_max_len = macb_config->jumbo_max_len;
 
        bp->wol = 0;
-       if (of_get_property(np, "magic-packet", NULL))
+       if (of_property_read_bool(np, "magic-packet"))
                bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
        device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
index e5c71f90785237348ab57924037dea3e85f04f09..d8d71bf97983b859c68c95899f65fc90dc66bb69 100644 (file)
@@ -735,12 +735,17 @@ static int nicvf_set_channels(struct net_device *dev,
        if (channel->tx_count > nic->max_queues)
                return -EINVAL;
 
-       if (nic->xdp_prog &&
-           ((channel->tx_count + channel->rx_count) > nic->max_queues)) {
-               netdev_err(nic->netdev,
-                          "XDP mode, RXQs + TXQs > Max %d\n",
-                          nic->max_queues);
-               return -EINVAL;
+       if (channel->tx_count + channel->rx_count > nic->max_queues) {
+               if (nic->xdp_prog) {
+                       netdev_err(nic->netdev,
+                                  "XDP mode, RXQs + TXQs > Max %d\n",
+                                  nic->max_queues);
+                       return -EINVAL;
+               }
+
+               xdp_clear_features_flag(nic->netdev);
+       } else if (!pass1_silicon(nic->pdev)) {
+               xdp_set_features_flag(dev, NETDEV_XDP_ACT_BASIC);
        }
 
        if (if_up)
index 8b25313c7f6b8fa28d58cbfb50ff46515880c1f0..eff350e0bc2a8ec7d1f3584028d21762afecfe3d 100644 (file)
@@ -2218,7 +2218,9 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        netdev->netdev_ops = &nicvf_netdev_ops;
        netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
 
-       netdev->xdp_features = NETDEV_XDP_ACT_BASIC;
+       if (!pass1_silicon(nic->pdev) &&
+           nic->rx_queues + nic->tx_queues <= nic->max_queues)
+               netdev->xdp_features = NETDEV_XDP_ACT_BASIC;
 
        /* MTU range: 64 - 9200 */
        netdev->min_mtu = NIC_HW_MIN_FRS;
index dd9be229819a594701b52e039b6afd7ffb466b8a..d3541159487dd04ca9978e8270fad8c7eacf37b9 100644 (file)
@@ -1135,7 +1135,7 @@ void cxgb4_cleanup_tc_flower(struct adapter *adap)
                return;
 
        if (adap->flower_stats_timer.function)
-               del_timer_sync(&adap->flower_stats_timer);
+               timer_shutdown_sync(&adap->flower_stats_timer);
        cancel_work_sync(&adap->flower_stats_work);
        rhashtable_destroy(&adap->flower_tbl);
        adap->tc_flower_initialized = false;
index b21e56de61671a90ef3906a03f98ff7c879a988d..05a89ab6766c4161d48ec9af79997bba1bc31f14 100644 (file)
@@ -1393,9 +1393,9 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
        if (!pdata)
                return ERR_PTR(-ENOMEM);
 
-       if (of_find_property(np, "davicom,ext-phy", NULL))
+       if (of_property_read_bool(np, "davicom,ext-phy"))
                pdata->flags |= DM9000_PLATF_EXT_PHY;
-       if (of_find_property(np, "davicom,no-eeprom", NULL))
+       if (of_property_read_bool(np, "davicom,no-eeprom"))
                pdata->flags |= DM9000_PLATF_NO_EEPROM;
 
        ret = of_get_mac_address(np, pdata->dev_addr);
index bca68edfbe9cd53c8128d91d1de9ac0fde2e1570..838750a03cf68a3d4da7d6c3be7cc45fc3c1a708 100644 (file)
@@ -370,8 +370,7 @@ static const struct ethtool_rmon_hist_range enetc_rmon_ranges[] = {
 };
 
 static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
-                            struct ethtool_rmon_stats *s,
-                            const struct ethtool_rmon_hist_range **ranges)
+                            struct ethtool_rmon_stats *s)
 {
        s->undersize_pkts = enetc_port_rd(hw, ENETC_PM_RUND(mac));
        s->oversize_pkts = enetc_port_rd(hw, ENETC_PM_ROVR(mac));
@@ -393,8 +392,6 @@ static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
        s->hist_tx[4] = enetc_port_rd(hw, ENETC_PM_T1023(mac));
        s->hist_tx[5] = enetc_port_rd(hw, ENETC_PM_T1522(mac));
        s->hist_tx[6] = enetc_port_rd(hw, ENETC_PM_T1523X(mac));
-
-       *ranges = enetc_rmon_ranges;
 }
 
 static void enetc_get_eth_mac_stats(struct net_device *ndev,
@@ -447,13 +444,15 @@ static void enetc_get_rmon_stats(struct net_device *ndev,
        struct enetc_hw *hw = &priv->si->hw;
        struct enetc_si *si = priv->si;
 
+       *ranges = enetc_rmon_ranges;
+
        switch (rmon_stats->src) {
        case ETHTOOL_MAC_STATS_SRC_EMAC:
-               enetc_rmon_stats(hw, 0, rmon_stats, ranges);
+               enetc_rmon_stats(hw, 0, rmon_stats);
                break;
        case ETHTOOL_MAC_STATS_SRC_PMAC:
                if (si->hw_features & ENETC_SI_F_QBU)
-                       enetc_rmon_stats(hw, 1, rmon_stats, ranges);
+                       enetc_rmon_stats(hw, 1, rmon_stats);
                break;
        case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
                ethtool_aggregate_rmon_stats(ndev, rmon_stats);
@@ -990,6 +989,20 @@ static int enetc_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
        return 0;
 }
 
+/* FIXME: Workaround for the link partner's verification failing if ENETC
+ * priorly received too much express traffic. The documentation doesn't
+ * suggest this is needed.
+ */
+static void enetc_restart_emac_rx(struct enetc_si *si)
+{
+       u32 val = enetc_port_rd(&si->hw, ENETC_PM0_CMD_CFG);
+
+       enetc_port_wr(&si->hw, ENETC_PM0_CMD_CFG, val & ~ENETC_PM0_RX_EN);
+
+       if (val & ENETC_PM0_RX_EN)
+               enetc_port_wr(&si->hw, ENETC_PM0_CMD_CFG, val);
+}
+
 static int enetc_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
                        struct netlink_ext_ack *extack)
 {
@@ -1041,6 +1054,8 @@ static int enetc_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
 
        enetc_port_wr(hw, ENETC_MMCSR, val);
 
+       enetc_restart_emac_rx(priv->si);
+
        mutex_unlock(&priv->mm_lock);
 
        return 0;
index 5ba1e0d71c687892bb7578d9aea42a344c9fc2fc..9939ccafb556609f8b6931ef42bb49f267aadea8 100644 (file)
@@ -507,6 +507,11 @@ struct bufdesc_ex {
 /* i.MX6Q adds pm_qos support */
 #define FEC_QUIRK_HAS_PMQOS                    BIT(23)
 
+/* Not all FEC hardware block MDIOs support accesses in C45 mode.
+ * Older blocks in the ColdFire parts do not support it.
+ */
+#define FEC_QUIRK_HAS_MDIO_C45         BIT(24)
+
 struct bufdesc_prop {
        int qid;
        /* Address of Rx and Tx buffers */
index c73e25f8995eb9b0a95ba118a1ce007110e6f8ff..160c1b3525f5bd4d9001626f27be1308fc6ba385 100644 (file)
@@ -100,18 +100,19 @@ struct fec_devinfo {
 
 static const struct fec_devinfo fec_imx25_info = {
        .quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
-                 FEC_QUIRK_HAS_FRREG,
+                 FEC_QUIRK_HAS_FRREG | FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx27_info = {
-       .quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+       .quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG |
+                 FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx28_info = {
        .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
                  FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
                  FEC_QUIRK_HAS_FRREG | FEC_QUIRK_CLEAR_SETUP_MII |
-                 FEC_QUIRK_NO_HARD_RESET,
+                 FEC_QUIRK_NO_HARD_RESET | FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx6q_info = {
@@ -119,11 +120,12 @@ static const struct fec_devinfo fec_imx6q_info = {
                  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
                  FEC_QUIRK_HAS_RACC | FEC_QUIRK_CLEAR_SETUP_MII |
-                 FEC_QUIRK_HAS_PMQOS,
+                 FEC_QUIRK_HAS_PMQOS | FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_mvf600_info = {
-       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+       .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC |
+                 FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx6x_info = {
@@ -132,7 +134,8 @@ static const struct fec_devinfo fec_imx6x_info = {
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
                  FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
                  FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
-                 FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES,
+                 FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
+                 FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx6ul_info = {
@@ -140,7 +143,8 @@ static const struct fec_devinfo fec_imx6ul_info = {
                  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
                  FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
-                 FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_CLEAR_SETUP_MII,
+                 FEC_QUIRK_HAS_COALESCE | FEC_QUIRK_CLEAR_SETUP_MII |
+                 FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx8mq_info = {
@@ -150,7 +154,8 @@ static const struct fec_devinfo fec_imx8mq_info = {
                  FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
                  FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
                  FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
-                 FEC_QUIRK_HAS_EEE | FEC_QUIRK_WAKEUP_FROM_INT2,
+                 FEC_QUIRK_HAS_EEE | FEC_QUIRK_WAKEUP_FROM_INT2 |
+                 FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_imx8qm_info = {
@@ -160,14 +165,15 @@ static const struct fec_devinfo fec_imx8qm_info = {
                  FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
                  FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE |
                  FEC_QUIRK_CLEAR_SETUP_MII | FEC_QUIRK_HAS_MULTI_QUEUES |
-                 FEC_QUIRK_DELAYED_CLKS_SUPPORT,
+                 FEC_QUIRK_DELAYED_CLKS_SUPPORT | FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static const struct fec_devinfo fec_s32v234_info = {
        .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
                  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
                  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
-                 FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE,
+                 FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
+                 FEC_QUIRK_HAS_MDIO_C45,
 };
 
 static struct platform_device_id fec_devtype[] = {
@@ -2434,8 +2440,10 @@ static int fec_enet_mii_init(struct platform_device *pdev)
        fep->mii_bus->name = "fec_enet_mii_bus";
        fep->mii_bus->read = fec_enet_mdio_read_c22;
        fep->mii_bus->write = fec_enet_mdio_write_c22;
-       fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
-       fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
+       if (fep->quirks & FEC_QUIRK_HAS_MDIO_C45) {
+               fep->mii_bus->read_c45 = fec_enet_mdio_read_c45;
+               fep->mii_bus->write_c45 = fec_enet_mdio_write_c45;
+       }
        snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
                pdev->name, fep->dev_id + 1);
        fep->mii_bus->priv = fep;
@@ -4251,7 +4259,7 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_ipc_init;
 
-       if (of_get_property(np, "fsl,magic-packet", NULL))
+       if (of_property_read_bool(np, "fsl,magic-packet"))
                fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
 
        ret = fec_enet_init_stop_mode(fep, np);
index a7f4c3c29f3e41965609aed79e1a145478755b20..b88816b71ddff3dca52753d24d90817014d9924b 100644 (file)
@@ -937,7 +937,7 @@ static int mpc52xx_fec_probe(struct platform_device *op)
        priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
 
        /* the 7-wire property means don't use MII mode */
-       if (of_find_property(np, "fsl,7-wire-mode", NULL)) {
+       if (of_property_read_bool(np, "fsl,7-wire-mode")) {
                priv->seven_wire_mode = 1;
                dev_info(&ndev->dev, "using 7-wire PHY mode\n");
        }
index b2def295523ab5ce23b547fae1a21b7662c25f17..38d5013c6fedf5a654cf67eadbdae8eed5fb8ac1 100644 (file)
@@ -787,10 +787,10 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
        else
                priv->interface = gfar_get_interface(dev);
 
-       if (of_find_property(np, "fsl,magic-packet", NULL))
+       if (of_property_read_bool(np, "fsl,magic-packet"))
                priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
 
-       if (of_get_property(np, "fsl,wake-on-filer", NULL))
+       if (of_property_read_bool(np, "fsl,wake-on-filer"))
                priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER;
 
        priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
index 64eb0442c82fd3ce485d4a326403940c79d29df7..005cb9dfe078bc588acc6d15e0c47a7c903d9da9 100644 (file)
@@ -47,6 +47,8 @@
 
 #define GVE_RX_BUFFER_SIZE_DQO 2048
 
+#define GVE_GQ_TX_MIN_PKT_DESC_BYTES 182
+
 /* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
 struct gve_rx_desc_queue {
        struct gve_rx_desc *desc_ring; /* the descriptor ring */
index ce574d097e280f9dbf52663661ebeffa4f7b8ba9..5f81470843b49658b882658eea8f75e109e9e5bc 100644 (file)
@@ -537,7 +537,10 @@ static int gve_get_link_ksettings(struct net_device *netdev,
                                  struct ethtool_link_ksettings *cmd)
 {
        struct gve_priv *priv = netdev_priv(netdev);
-       int err = gve_adminq_report_link_speed(priv);
+       int err = 0;
+
+       if (priv->link_speed == 0)
+               err = gve_adminq_report_link_speed(priv);
 
        cmd->base.speed = priv->link_speed;
        return err;
index 4888bf05fbedb5b84aa18648547e5c878359e991..5e11b823675454ab4f3c63951c80e3da4f45cec5 100644 (file)
@@ -284,8 +284,8 @@ static inline int gve_skb_fifo_bytes_required(struct gve_tx_ring *tx,
        int bytes;
        int hlen;
 
-       hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) +
-                                tcp_hdrlen(skb) : skb_headlen(skb);
+       hlen = skb_is_gso(skb) ? skb_checksum_start_offset(skb) + tcp_hdrlen(skb) :
+                                min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
 
        pad_bytes = gve_tx_fifo_pad_alloc_one_frag(&tx->tx_fifo,
                                                   hlen);
@@ -454,13 +454,11 @@ static int gve_tx_add_skb_copy(struct gve_priv *priv, struct gve_tx_ring *tx, st
        pkt_desc = &tx->desc[idx];
 
        l4_hdr_offset = skb_checksum_start_offset(skb);
-       /* If the skb is gso, then we want the tcp header in the first segment
-        * otherwise we want the linear portion of the skb (which will contain
-        * the checksum because skb->csum_start and skb->csum_offset are given
-        * relative to skb->head) in the first segment.
+       /* If the skb is gso, then we want the tcp header alone in the first segment
+        * otherwise we want the minimum required by the gVNIC spec.
         */
        hlen = is_gso ? l4_hdr_offset + tcp_hdrlen(skb) :
-                       skb_headlen(skb);
+                       min_t(int, GVE_GQ_TX_MIN_PKT_DESC_BYTES, skb->len);
 
        info->skb =  skb;
        /* We don't want to split the header, so if necessary, pad to the end
index daec9ce04531be2531a24d5b44bc83ad5dae3a2c..54bb4d9a0d1ea4230d8269dfc0184a0f7df93ff0 100644 (file)
@@ -78,6 +78,7 @@ static int sni_82596_probe(struct platform_device *dev)
        void __iomem *mpu_addr;
        void __iomem *ca_addr;
        u8 __iomem *eth_addr;
+       u8 mac[ETH_ALEN];
 
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
        ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
@@ -109,12 +110,13 @@ static int sni_82596_probe(struct platform_device *dev)
                goto probe_failed;
 
        /* someone seems to like messed up stuff */
-       netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
-       netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
-       netdevice->dev_addr[2] = readb(eth_addr + 0x09);
-       netdevice->dev_addr[3] = readb(eth_addr + 0x08);
-       netdevice->dev_addr[4] = readb(eth_addr + 0x07);
-       netdevice->dev_addr[5] = readb(eth_addr + 0x06);
+       mac[0] = readb(eth_addr + 0x0b);
+       mac[1] = readb(eth_addr + 0x0a);
+       mac[2] = readb(eth_addr + 0x09);
+       mac[3] = readb(eth_addr + 0x08);
+       mac[4] = readb(eth_addr + 0x07);
+       mac[5] = readb(eth_addr + 0x06);
+       eth_hw_addr_set(netdevice, mac);
        iounmap(eth_addr);
 
        if (netdevice->irq < 0) {
index 9b08e41ccc294dae821d17a438b0f82b6d15182b..c97095abd26abcd88c6ac40cb9307a9ac90a3a94 100644 (file)
@@ -2939,9 +2939,9 @@ static int emac_init_config(struct emac_instance *dev)
        }
 
        /* Fixup some feature bits based on the device tree */
-       if (of_get_property(np, "has-inverted-stacr-oc", NULL))
+       if (of_property_read_bool(np, "has-inverted-stacr-oc"))
                dev->features |= EMAC_FTR_STACR_OC_INVERT;
-       if (of_get_property(np, "has-new-stacr-staopc", NULL))
+       if (of_property_read_bool(np, "has-new-stacr-staopc"))
                dev->features |= EMAC_FTR_HAS_NEW_STACR;
 
        /* CAB lacks the appropriate properties */
@@ -3042,7 +3042,7 @@ static int emac_probe(struct platform_device *ofdev)
         * property here for now, but new flat device trees should set a
         * status property to "disabled" instead.
         */
-       if (of_get_property(np, "unused", NULL) || !of_device_is_available(np))
+       if (of_property_read_bool(np, "unused") || !of_device_is_available(np))
                return -ENODEV;
 
        /* Find ourselves in the bootlist if we are there */
@@ -3333,7 +3333,7 @@ static void __init emac_make_bootlist(void)
 
                if (of_match_node(emac_match, np) == NULL)
                        continue;
-               if (of_get_property(np, "unused", NULL))
+               if (of_property_read_bool(np, "unused"))
                        continue;
                idx = of_get_property(np, "cell-index", NULL);
                if (idx == NULL)
index 242ef976fd15e6bf7a9ed9ffd4b87a2d4ccee694..50358cf0013068c45749b3cd905d71cc8cd92ba1 100644 (file)
@@ -242,7 +242,7 @@ static int rgmii_probe(struct platform_device *ofdev)
        }
 
        /* Check for RGMII flags */
-       if (of_get_property(ofdev->dev.of_node, "has-mdio", NULL))
+       if (of_property_read_bool(ofdev->dev.of_node, "has-mdio"))
                dev->flags |= EMAC_RGMII_FLAG_HAS_MDIO;
 
        /* CAB lacks the right properties, fix this up */
index e1eb1de88bf928b98ad8a6b4bad8d8ff47e9c9aa..e14d1e45318f824180979043b269694c47c84d36 100644 (file)
@@ -5288,31 +5288,6 @@ static void e1000_watchdog_task(struct work_struct *work)
                                ew32(TARC(0), tarc0);
                        }
 
-                       /* disable TSO for pcie and 10/100 speeds, to avoid
-                        * some hardware issues
-                        */
-                       if (!(adapter->flags & FLAG_TSO_FORCE)) {
-                               switch (adapter->link_speed) {
-                               case SPEED_10:
-                               case SPEED_100:
-                                       e_info("10/100 speed: disabling TSO\n");
-                                       netdev->features &= ~NETIF_F_TSO;
-                                       netdev->features &= ~NETIF_F_TSO6;
-                                       break;
-                               case SPEED_1000:
-                                       netdev->features |= NETIF_F_TSO;
-                                       netdev->features |= NETIF_F_TSO6;
-                                       break;
-                               default:
-                                       /* oops */
-                                       break;
-                               }
-                               if (hw->mac.type == e1000_pch_spt) {
-                                       netdev->features &= ~NETIF_F_TSO;
-                                       netdev->features &= ~NETIF_F_TSO6;
-                               }
-                       }
-
                        /* enable transmits in the hardware, need to do this
                         * after setting TARC(0)
                         */
@@ -7526,6 +7501,32 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                            NETIF_F_RXCSUM |
                            NETIF_F_HW_CSUM);
 
+       /* disable TSO for pcie and 10/100 speeds to avoid
+        * some hardware issues and for i219 to fix transfer
+        * speed being capped at 60%
+        */
+       if (!(adapter->flags & FLAG_TSO_FORCE)) {
+               switch (adapter->link_speed) {
+               case SPEED_10:
+               case SPEED_100:
+                       e_info("10/100 speed: disabling TSO\n");
+                       netdev->features &= ~NETIF_F_TSO;
+                       netdev->features &= ~NETIF_F_TSO6;
+                       break;
+               case SPEED_1000:
+                       netdev->features |= NETIF_F_TSO;
+                       netdev->features |= NETIF_F_TSO6;
+                       break;
+               default:
+                       /* oops */
+                       break;
+               }
+               if (hw->mac.type == e1000_pch_spt) {
+                       netdev->features &= ~NETIF_F_TSO;
+                       netdev->features &= ~NETIF_F_TSO6;
+               }
+       }
+
        /* Set user-changeable features (subset of all device features) */
        netdev->hw_features = netdev->features;
        netdev->hw_features |= NETIF_F_RXFCS;
index 5b3519c6e362ebacab5c4c6b426cc30f03901b7b..97fe1787a8f4aa4f1388cce893e47932fe23333a 100644 (file)
@@ -44,7 +44,7 @@ static int i40e_diag_reg_pattern_test(struct i40e_hw *hw,
        return 0;
 }
 
-struct i40e_diag_reg_test_info i40e_reg_list[] = {
+const struct i40e_diag_reg_test_info i40e_reg_list[] = {
        /* offset               mask         elements   stride */
        {I40E_QTX_CTL(0),       0x0000FFBF, 1,
                I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
@@ -78,27 +78,28 @@ int i40e_diag_reg_test(struct i40e_hw *hw)
 {
        int ret_code = 0;
        u32 reg, mask;
+       u32 elements;
        u32 i, j;
 
        for (i = 0; i40e_reg_list[i].offset != 0 &&
                                             !ret_code; i++) {
 
+               elements = i40e_reg_list[i].elements;
                /* set actual reg range for dynamically allocated resources */
                if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&
                    hw->func_caps.num_tx_qp != 0)
-                       i40e_reg_list[i].elements = hw->func_caps.num_tx_qp;
+                       elements = hw->func_caps.num_tx_qp;
                if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||
                     i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||
                     i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||
                     i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||
                     i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&
                    hw->func_caps.num_msix_vectors != 0)
-                       i40e_reg_list[i].elements =
-                               hw->func_caps.num_msix_vectors - 1;
+                       elements = hw->func_caps.num_msix_vectors - 1;
 
                /* test register access */
                mask = i40e_reg_list[i].mask;
-               for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) {
+               for (j = 0; j < elements && !ret_code; j++) {
                        reg = i40e_reg_list[i].offset +
                              (j * i40e_reg_list[i].stride);
                        ret_code = i40e_diag_reg_pattern_test(hw, reg, mask);
index e641035c7297dcc12dfb5fcf6937ffdfb5f82deb..c3ce5f35211f03220b1cc6169a31a8e3c7000fdb 100644 (file)
@@ -20,7 +20,7 @@ struct i40e_diag_reg_test_info {
        u32 stride;     /* bytes between each element */
 };
 
-extern struct i40e_diag_reg_test_info i40e_reg_list[];
+extern const struct i40e_diag_reg_test_info i40e_reg_list[];
 
 int i40e_diag_reg_test(struct i40e_hw *hw);
 int i40e_diag_eeprom_test(struct i40e_hw *hw);
index 467001db5070ed568a9d4be4f5e3c6d957c526cb..7c30abd0dfc22720415f8f649ae732de73a099b3 100644 (file)
@@ -11059,8 +11059,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
                                             pf->hw.aq.asq_last_status));
        }
        /* reinit the misc interrupt */
-       if (pf->flags & I40E_FLAG_MSIX_ENABLED)
+       if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
                ret = i40e_setup_misc_vector(pf);
+               if (ret)
+                       goto end_unlock;
+       }
 
        /* Add a filter to drop all Flow control frames from any VSI from being
         * transmitted. By doing so we stop a malicious VF from sending out
@@ -14133,15 +14136,15 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
                vsi->id = ctxt.vsi_number;
        }
 
-       vsi->active_filters = 0;
-       clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
        spin_lock_bh(&vsi->mac_filter_hash_lock);
+       vsi->active_filters = 0;
        /* If macvlan filters already exist, force them to get loaded */
        hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
                f->state = I40E_FILTER_NEW;
                f_count++;
        }
        spin_unlock_bh(&vsi->mac_filter_hash_lock);
+       clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
 
        if (f_count) {
                vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -15525,6 +15528,7 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw)
        int err;
        int v_idx;
 
+       pci_set_drvdata(pf->pdev, pf);
        pci_save_state(pf->pdev);
 
        /* set up periodic task facility */
index 924f972b91faf2f69ce78ff5c8bd1f208a048da0..72b091f2509d8b0330d2f26e311b3acbce4e3547 100644 (file)
@@ -171,10 +171,10 @@ static char *i40e_create_dummy_packet(u8 *dummy_packet, bool ipv4, u8 l4proto,
                                      struct i40e_fdir_filter *data)
 {
        bool is_vlan = !!data->vlan_tag;
-       struct vlan_hdr vlan;
-       struct ipv6hdr ipv6;
-       struct ethhdr eth;
-       struct iphdr ip;
+       struct vlan_hdr vlan = {};
+       struct ipv6hdr ipv6 = {};
+       struct ethhdr eth = {};
+       struct iphdr ip = {};
        u8 *tmp;
 
        if (ipv4) {
index 232bc61d9eee9ce6c2eb7a6a3c758ac22cfe20b3..746ff76f2fb1e648882b9a393415823be12d0c9c 100644 (file)
@@ -59,8 +59,6 @@ enum iavf_vsi_state_t {
 struct iavf_vsi {
        struct iavf_adapter *back;
        struct net_device *netdev;
-       unsigned long active_cvlans[BITS_TO_LONGS(VLAN_N_VID)];
-       unsigned long active_svlans[BITS_TO_LONGS(VLAN_N_VID)];
        u16 seid;
        u16 id;
        DECLARE_BITMAP(state, __IAVF_VSI_STATE_SIZE__);
@@ -158,15 +156,20 @@ struct iavf_vlan {
        u16 tpid;
 };
 
+enum iavf_vlan_state_t {
+       IAVF_VLAN_INVALID,
+       IAVF_VLAN_ADD,          /* filter needs to be added */
+       IAVF_VLAN_IS_NEW,       /* filter is new, wait for PF answer */
+       IAVF_VLAN_ACTIVE,       /* filter is accepted by PF */
+       IAVF_VLAN_DISABLE,      /* filter needs to be deleted by PF, then marked INACTIVE */
+       IAVF_VLAN_INACTIVE,     /* filter is inactive, we are in IFF_DOWN */
+       IAVF_VLAN_REMOVE,       /* filter needs to be removed from list */
+};
+
 struct iavf_vlan_filter {
        struct list_head list;
        struct iavf_vlan vlan;
-       struct {
-               u8 is_new_vlan:1;       /* filter is new, wait for PF answer */
-               u8 remove:1;            /* filter needs to be removed */
-               u8 add:1;               /* filter needs to be added */
-               u8 padding:5;
-       };
+       enum iavf_vlan_state_t state;
 };
 
 #define IAVF_MAX_TRAFFIC_CLASS 4
@@ -258,6 +261,7 @@ struct iavf_adapter {
        wait_queue_head_t vc_waitqueue;
        struct iavf_q_vector *q_vectors;
        struct list_head vlan_filter_list;
+       int num_vlan_filters;
        struct list_head mac_filter_list;
        struct mutex crit_lock;
        struct mutex client_lock;
index 16c490965b61a58843ddaeeaef0601524ab6a7e3..dd11dbbd5551a2c1d9f8a431d972655d9cabe79c 100644 (file)
@@ -661,7 +661,7 @@ struct iavf_rx_ptype_decoded iavf_ptype_lookup[BIT(8)] = {
        /* Non Tunneled IPv6 */
        IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
        IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
-       IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY3),
+       IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY4),
        IAVF_PTT_UNUSED_ENTRY(91),
        IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP,  PAY4),
        IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
index 3273aeb8fa67631421def6a71bab6faaef0e5d91..2de4baff4c20501baab55b7ffddb84b6f8e20aee 100644 (file)
@@ -791,7 +791,8 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,
                f->vlan = vlan;
 
                list_add_tail(&f->list, &adapter->vlan_filter_list);
-               f->add = true;
+               f->state = IAVF_VLAN_ADD;
+               adapter->num_vlan_filters++;
                adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
        }
 
@@ -813,7 +814,7 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)
 
        f = iavf_find_vlan(adapter, vlan);
        if (f) {
-               f->remove = true;
+               f->state = IAVF_VLAN_REMOVE;
                adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER;
        }
 
@@ -828,14 +829,18 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)
  **/
 static void iavf_restore_filters(struct iavf_adapter *adapter)
 {
-       u16 vid;
+       struct iavf_vlan_filter *f;
 
        /* re-add all VLAN filters */
-       for_each_set_bit(vid, adapter->vsi.active_cvlans, VLAN_N_VID)
-               iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021Q));
+       spin_lock_bh(&adapter->mac_vlan_list_lock);
+
+       list_for_each_entry(f, &adapter->vlan_filter_list, list) {
+               if (f->state == IAVF_VLAN_INACTIVE)
+                       f->state = IAVF_VLAN_ADD;
+       }
 
-       for_each_set_bit(vid, adapter->vsi.active_svlans, VLAN_N_VID)
-               iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021AD));
+       spin_unlock_bh(&adapter->mac_vlan_list_lock);
+       adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
 }
 
 /**
@@ -844,8 +849,7 @@ static void iavf_restore_filters(struct iavf_adapter *adapter)
  */
 u16 iavf_get_num_vlans_added(struct iavf_adapter *adapter)
 {
-       return bitmap_weight(adapter->vsi.active_cvlans, VLAN_N_VID) +
-               bitmap_weight(adapter->vsi.active_svlans, VLAN_N_VID);
+       return adapter->num_vlan_filters;
 }
 
 /**
@@ -893,6 +897,10 @@ static int iavf_vlan_rx_add_vid(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
+       /* Do not track VLAN 0 filter, always added by the PF on VF init */
+       if (!vid)
+               return 0;
+
        if (!VLAN_FILTERING_ALLOWED(adapter))
                return -EIO;
 
@@ -919,12 +927,11 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
-       iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto)));
-       if (proto == cpu_to_be16(ETH_P_8021Q))
-               clear_bit(vid, adapter->vsi.active_cvlans);
-       else
-               clear_bit(vid, adapter->vsi.active_svlans);
+       /* We do not track VLAN 0 filter */
+       if (!vid)
+               return 0;
 
+       iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto)));
        return 0;
 }
 
@@ -1285,16 +1292,11 @@ static void iavf_clear_mac_vlan_filters(struct iavf_adapter *adapter)
                }
        }
 
-       /* remove all VLAN filters */
+       /* disable all VLAN filters */
        list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list,
-                                list) {
-               if (vlf->add) {
-                       list_del(&vlf->list);
-                       kfree(vlf);
-               } else {
-                       vlf->remove = true;
-               }
-       }
+                                list)
+               vlf->state = IAVF_VLAN_DISABLE;
+
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
 }
 
@@ -2906,6 +2908,7 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
                list_del(&fv->list);
                kfree(fv);
        }
+       adapter->num_vlan_filters = 0;
 
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
 
@@ -3123,9 +3126,6 @@ continue_reset:
        adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER;
        iavf_misc_irq_enable(adapter);
 
-       bitmap_clear(adapter->vsi.active_cvlans, 0, VLAN_N_VID);
-       bitmap_clear(adapter->vsi.active_svlans, 0, VLAN_N_VID);
-
        mod_delayed_work(adapter->wq, &adapter->watchdog_task, 2);
 
        /* We were running when the reset started, so we need to restore some
@@ -5066,6 +5066,11 @@ static void iavf_remove(struct pci_dev *pdev)
                        mutex_unlock(&adapter->crit_lock);
                        break;
                }
+               /* Simply return if we already went through iavf_shutdown */
+               if (adapter->state == __IAVF_REMOVE) {
+                       mutex_unlock(&adapter->crit_lock);
+                       return;
+               }
 
                mutex_unlock(&adapter->crit_lock);
                usleep_range(500, 1000);
index 18b6a702a1d6dff9e9aeac001526444a6ca38736..e989feda133c1e63447f005437f09ba248084fdb 100644 (file)
@@ -1096,7 +1096,7 @@ static inline void iavf_rx_hash(struct iavf_ring *ring,
                cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<
                            IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT);
 
-       if (ring->netdev->features & NETIF_F_RXHASH)
+       if (!(ring->netdev->features & NETIF_F_RXHASH))
                return;
 
        if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
index 6d23338604bb33e07f2df55f3656296ed4db24b0..9afbbdac35903f1ae018c00fe28213ece3227d3f 100644 (file)
@@ -642,16 +642,10 @@ static void iavf_vlan_add_reject(struct iavf_adapter *adapter)
 
        spin_lock_bh(&adapter->mac_vlan_list_lock);
        list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
-               if (f->is_new_vlan) {
-                       if (f->vlan.tpid == ETH_P_8021Q)
-                               clear_bit(f->vlan.vid,
-                                         adapter->vsi.active_cvlans);
-                       else
-                               clear_bit(f->vlan.vid,
-                                         adapter->vsi.active_svlans);
-
+               if (f->state == IAVF_VLAN_IS_NEW) {
                        list_del(&f->list);
                        kfree(f);
+                       adapter->num_vlan_filters--;
                }
        }
        spin_unlock_bh(&adapter->mac_vlan_list_lock);
@@ -679,7 +673,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
        spin_lock_bh(&adapter->mac_vlan_list_lock);
 
        list_for_each_entry(f, &adapter->vlan_filter_list, list) {
-               if (f->add)
+               if (f->state == IAVF_VLAN_ADD)
                        count++;
        }
        if (!count || !VLAN_FILTERING_ALLOWED(adapter)) {
@@ -710,11 +704,10 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
                vvfl->vsi_id = adapter->vsi_res->vsi_id;
                vvfl->num_elements = count;
                list_for_each_entry(f, &adapter->vlan_filter_list, list) {
-                       if (f->add) {
+                       if (f->state == IAVF_VLAN_ADD) {
                                vvfl->vlan_id[i] = f->vlan.vid;
                                i++;
-                               f->add = false;
-                               f->is_new_vlan = true;
+                               f->state = IAVF_VLAN_IS_NEW;
                                if (i == count)
                                        break;
                        }
@@ -760,7 +753,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
                vvfl_v2->vport_id = adapter->vsi_res->vsi_id;
                vvfl_v2->num_elements = count;
                list_for_each_entry(f, &adapter->vlan_filter_list, list) {
-                       if (f->add) {
+                       if (f->state == IAVF_VLAN_ADD) {
                                struct virtchnl_vlan_supported_caps *filtering_support =
                                        &adapter->vlan_v2_caps.filtering.filtering_support;
                                struct virtchnl_vlan *vlan;
@@ -778,8 +771,7 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
                                vlan->tpid = f->vlan.tpid;
 
                                i++;
-                               f->add = false;
-                               f->is_new_vlan = true;
+                               f->state = IAVF_VLAN_IS_NEW;
                        }
                }
 
@@ -822,10 +814,16 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
                 * filters marked for removal to enable bailing out before
                 * sending a virtchnl message
                 */
-               if (f->remove && !VLAN_FILTERING_ALLOWED(adapter)) {
+               if (f->state == IAVF_VLAN_REMOVE &&
+                   !VLAN_FILTERING_ALLOWED(adapter)) {
                        list_del(&f->list);
                        kfree(f);
-               } else if (f->remove) {
+                       adapter->num_vlan_filters--;
+               } else if (f->state == IAVF_VLAN_DISABLE &&
+                   !VLAN_FILTERING_ALLOWED(adapter)) {
+                       f->state = IAVF_VLAN_INACTIVE;
+               } else if (f->state == IAVF_VLAN_REMOVE ||
+                          f->state == IAVF_VLAN_DISABLE) {
                        count++;
                }
        }
@@ -857,11 +855,18 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
                vvfl->vsi_id = adapter->vsi_res->vsi_id;
                vvfl->num_elements = count;
                list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
-                       if (f->remove) {
+                       if (f->state == IAVF_VLAN_DISABLE) {
                                vvfl->vlan_id[i] = f->vlan.vid;
+                               f->state = IAVF_VLAN_INACTIVE;
                                i++;
+                               if (i == count)
+                                       break;
+                       } else if (f->state == IAVF_VLAN_REMOVE) {
+                               vvfl->vlan_id[i] = f->vlan.vid;
                                list_del(&f->list);
                                kfree(f);
+                               adapter->num_vlan_filters--;
+                               i++;
                                if (i == count)
                                        break;
                        }
@@ -901,7 +906,8 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
                vvfl_v2->vport_id = adapter->vsi_res->vsi_id;
                vvfl_v2->num_elements = count;
                list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
-                       if (f->remove) {
+                       if (f->state == IAVF_VLAN_DISABLE ||
+                           f->state == IAVF_VLAN_REMOVE) {
                                struct virtchnl_vlan_supported_caps *filtering_support =
                                        &adapter->vlan_v2_caps.filtering.filtering_support;
                                struct virtchnl_vlan *vlan;
@@ -915,8 +921,13 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
                                vlan->tci = f->vlan.vid;
                                vlan->tpid = f->vlan.tpid;
 
-                               list_del(&f->list);
-                               kfree(f);
+                               if (f->state == IAVF_VLAN_DISABLE) {
+                                       f->state = IAVF_VLAN_INACTIVE;
+                               } else {
+                                       list_del(&f->list);
+                                       kfree(f);
+                                       adapter->num_vlan_filters--;
+                               }
                                i++;
                                if (i == count)
                                        break;
@@ -2192,7 +2203,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                                list_for_each_entry(vlf,
                                                    &adapter->vlan_filter_list,
                                                    list)
-                                       vlf->add = true;
+                                       vlf->state = IAVF_VLAN_ADD;
 
                                adapter->aq_required |=
                                        IAVF_FLAG_AQ_ADD_VLAN_FILTER;
@@ -2260,7 +2271,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                                list_for_each_entry(vlf,
                                                    &adapter->vlan_filter_list,
                                                    list)
-                                       vlf->add = true;
+                                       vlf->state = IAVF_VLAN_ADD;
 
                                aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
                        }
@@ -2444,17 +2455,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
 
                spin_lock_bh(&adapter->mac_vlan_list_lock);
                list_for_each_entry(f, &adapter->vlan_filter_list, list) {
-                       if (f->is_new_vlan) {
-                               f->is_new_vlan = false;
-                               if (!f->vlan.vid)
-                                       continue;
-                               if (f->vlan.tpid == ETH_P_8021Q)
-                                       set_bit(f->vlan.vid,
-                                               adapter->vsi.active_cvlans);
-                               else
-                                       set_bit(f->vlan.vid,
-                                               adapter->vsi.active_svlans);
-                       }
+                       if (f->state == IAVF_VLAN_IS_NEW)
+                               f->state = IAVF_VLAN_ACTIVE;
                }
                spin_unlock_bh(&adapter->mac_vlan_list_lock);
                }
index b0e29e34240185b3b4aa1d6bc32c74f95adedc4b..e809249500e18b15b4a339289bf7a8fca0bc323c 100644 (file)
@@ -509,6 +509,7 @@ enum ice_pf_flags {
        ICE_FLAG_VF_VLAN_PRUNING,
        ICE_FLAG_LINK_LENIENT_MODE_ENA,
        ICE_FLAG_PLUG_AUX_DEV,
+       ICE_FLAG_UNPLUG_AUX_DEV,
        ICE_FLAG_MTU_CHANGED,
        ICE_FLAG_GNSS,                  /* GNSS successfully initialized */
        ICE_PF_FLAGS_NBITS              /* must be last */
@@ -955,16 +956,11 @@ static inline void ice_set_rdma_cap(struct ice_pf *pf)
  */
 static inline void ice_clear_rdma_cap(struct ice_pf *pf)
 {
-       /* We can directly unplug aux device here only if the flag bit
-        * ICE_FLAG_PLUG_AUX_DEV is not set because ice_unplug_aux_dev()
-        * could race with ice_plug_aux_dev() called from
-        * ice_service_task(). In this case we only clear that bit now and
-        * aux device will be unplugged later once ice_plug_aux_device()
-        * called from ice_service_task() finishes (see ice_service_task()).
+       /* defer unplug to service task to avoid RTNL lock and
+        * clear PLUG bit so that pending plugs don't interfere
         */
-       if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
-               ice_unplug_aux_dev(pf);
-
+       clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags);
+       set_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags);
        clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
 }
 #endif /* _ICE_H_ */
index 0f52ea38b6f3a2a49fdf5420a2b395cc1b27a16e..450317dfcca7360cb1acdfca470bd4295d11e3db 100644 (file)
@@ -291,6 +291,7 @@ static void ice_vsi_delete_from_hw(struct ice_vsi *vsi)
        struct ice_vsi_ctx *ctxt;
        int status;
 
+       ice_fltr_remove_all(vsi);
        ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
        if (!ctxt)
                return;
@@ -2892,7 +2893,6 @@ void ice_vsi_decfg(struct ice_vsi *vsi)
            !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
                ice_cfg_sw_lldp(vsi, false, false);
 
-       ice_fltr_remove_all(vsi);
        ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
        err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
        if (err)
index 567694bf098ba52684899ad593e6df448653a68b..0d8b8c6f9bd35184467df4680f9f5bc42e14760e 100644 (file)
@@ -2316,18 +2316,15 @@ static void ice_service_task(struct work_struct *work)
                }
        }
 
-       if (test_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags)) {
-               /* Plug aux device per request */
-               ice_plug_aux_dev(pf);
+       /* unplug aux dev per request, if an unplug request came in
+        * while processing a plug request, this will handle it
+        */
+       if (test_and_clear_bit(ICE_FLAG_UNPLUG_AUX_DEV, pf->flags))
+               ice_unplug_aux_dev(pf);
 
-               /* Mark plugging as done but check whether unplug was
-                * requested during ice_plug_aux_dev() call
-                * (e.g. from ice_clear_rdma_cap()) and if so then
-                * plug aux device.
-                */
-               if (!test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
-                       ice_unplug_aux_dev(pf);
-       }
+       /* Plug aux device per request */
+       if (test_and_clear_bit(ICE_FLAG_PLUG_AUX_DEV, pf->flags))
+               ice_plug_aux_dev(pf);
 
        if (test_and_clear_bit(ICE_FLAG_MTU_CHANGED, pf->flags)) {
                struct iidc_event *event;
@@ -4644,6 +4641,12 @@ static int ice_start_eth(struct ice_vsi *vsi)
        return err;
 }
 
+static void ice_stop_eth(struct ice_vsi *vsi)
+{
+       ice_fltr_remove_all(vsi);
+       ice_vsi_close(vsi);
+}
+
 static int ice_init_eth(struct ice_pf *pf)
 {
        struct ice_vsi *vsi = ice_get_main_vsi(pf);
@@ -5132,7 +5135,7 @@ void ice_unload(struct ice_pf *pf)
 {
        ice_deinit_features(pf);
        ice_deinit_rdma(pf);
-       ice_vsi_close(ice_get_main_vsi(pf));
+       ice_stop_eth(ice_get_main_vsi(pf));
        ice_vsi_decfg(ice_get_main_vsi(pf));
        ice_deinit_dev(pf);
 }
index 4eca8d195ef04391422120aafcac1277881eda10..b7682de0ae0578c19ac16b9bb373d8d4004f9d9e 100644 (file)
@@ -2788,7 +2788,7 @@ static int
 ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
                           u16 vsi_handle, unsigned long *tc_bitmap)
 {
-       struct ice_sched_agg_vsi_info *agg_vsi_info, *old_agg_vsi_info = NULL;
+       struct ice_sched_agg_vsi_info *agg_vsi_info, *iter, *old_agg_vsi_info = NULL;
        struct ice_sched_agg_info *agg_info, *old_agg_info;
        struct ice_hw *hw = pi->hw;
        int status = 0;
@@ -2806,11 +2806,13 @@ ice_sched_assoc_vsi_to_agg(struct ice_port_info *pi, u32 agg_id,
        if (old_agg_info && old_agg_info != agg_info) {
                struct ice_sched_agg_vsi_info *vtmp;
 
-               list_for_each_entry_safe(old_agg_vsi_info, vtmp,
+               list_for_each_entry_safe(iter, vtmp,
                                         &old_agg_info->agg_vsi_list,
                                         list_entry)
-                       if (old_agg_vsi_info->vsi_handle == vsi_handle)
+                       if (iter->vsi_handle == vsi_handle) {
+                               old_agg_vsi_info = iter;
                                break;
+                       }
        }
 
        /* check if entry already exist */
index 96a64c25e2ef7f7d796c55bbd46e6a68bc84fd74..0cc05e54a78154307bf7d9ed32f8ce6e4c31be35 100644 (file)
@@ -1341,15 +1341,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
        struct ice_vf *vf;
        int ret;
 
+       vf = ice_get_vf_by_id(pf, vf_id);
+       if (!vf)
+               return -EINVAL;
+
        if (ice_is_eswitch_mode_switchdev(pf)) {
                dev_info(ice_pf_to_dev(pf), "Trusted VF is forbidden in switchdev mode\n");
                return -EOPNOTSUPP;
        }
 
-       vf = ice_get_vf_by_id(pf, vf_id);
-       if (!vf)
-               return -EINVAL;
-
        ret = ice_check_vf_ready_for_cfg(vf);
        if (ret)
                goto out_put_vf;
index 61f844d2251235f9f81a0dfd358ae5e944210f06..46b36851af460e2f39e0685f3d7043cda0eec351 100644 (file)
@@ -1780,18 +1780,36 @@ ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
 int
 ice_cfg_rdma_fltr(struct ice_hw *hw, u16 vsi_handle, bool enable)
 {
-       struct ice_vsi_ctx *ctx;
+       struct ice_vsi_ctx *ctx, *cached_ctx;
+       int status;
+
+       cached_ctx = ice_get_vsi_ctx(hw, vsi_handle);
+       if (!cached_ctx)
+               return -ENOENT;
 
-       ctx = ice_get_vsi_ctx(hw, vsi_handle);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
-               return -EIO;
+               return -ENOMEM;
+
+       ctx->info.q_opt_rss = cached_ctx->info.q_opt_rss;
+       ctx->info.q_opt_tc = cached_ctx->info.q_opt_tc;
+       ctx->info.q_opt_flags = cached_ctx->info.q_opt_flags;
+
+       ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
 
        if (enable)
                ctx->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
        else
                ctx->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
 
-       return ice_update_vsi(hw, vsi_handle, ctx, NULL);
+       status = ice_update_vsi(hw, vsi_handle, ctx, NULL);
+       if (!status) {
+               cached_ctx->info.q_opt_flags = ctx->info.q_opt_flags;
+               cached_ctx->info.valid_sections |= ctx->info.valid_sections;
+       }
+
+       kfree(ctx);
+       return status;
 }
 
 /**
index dfd22862e926ba28a163c765a6f287ffb9b5e611..4fcf2d07eb853b10be4b5b483b33e0f95db9446a 100644 (file)
@@ -938,6 +938,7 @@ ice_reuse_rx_page(struct ice_rx_ring *rx_ring, struct ice_rx_buf *old_buf)
  * ice_get_rx_buf - Fetch Rx buffer and synchronize data for use
  * @rx_ring: Rx descriptor ring to transact packets on
  * @size: size of buffer to add to skb
+ * @ntc: index of next to clean element
  *
  * This function will pull an Rx buffer from the ring and synchronize it
  * for use by the CPU.
@@ -1026,7 +1027,6 @@ ice_build_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
 /**
  * ice_construct_skb - Allocate skb and populate it
  * @rx_ring: Rx descriptor ring to transact packets on
- * @rx_buf: Rx buffer to pull data from
  * @xdp: xdp_buff pointing to the data
  *
  * This function allocates an skb. It then populates it with the page
@@ -1210,6 +1210,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
                                ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc);
                        if (++ntc == cnt)
                                ntc = 0;
+                       rx_ring->first_desc = ntc;
                        continue;
                }
 
index 7bc5aa340c7df746d89e1462716a868e989695df..c8322fb6f2b37f710e3da7119c70d60ef61365e1 100644 (file)
@@ -438,6 +438,7 @@ busy:
  * ice_finalize_xdp_rx - Bump XDP Tx tail and/or flush redirect map
  * @xdp_ring: XDP ring
  * @xdp_res: Result of the receive batch
+ * @first_idx: index to write from caller
  *
  * This function bumps XDP Tx tail and/or flush redirect map, and
  * should be called when a batch of packets has been processed in the
index e6ef6b303222d17a5b15101ec6034738ef4bcb85..daa6a1e894cfc2c2ad056e5f3e24f1133381f97c 100644 (file)
@@ -541,6 +541,87 @@ static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)
        }
 }
 
+/**
+ * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR
+ * @fdir: pointer to the VF FDIR structure
+ */
+static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir)
+{
+       enum ice_fltr_ptype flow;
+
+       for (flow = ICE_FLTR_PTYPE_NONF_NONE;
+            flow < ICE_FLTR_PTYPE_MAX; flow++) {
+               fdir->fdir_fltr_cnt[flow][0] = 0;
+               fdir->fdir_fltr_cnt[flow][1] = 0;
+       }
+}
+
+/**
+ * ice_vc_fdir_has_prof_conflict
+ * @vf: pointer to the VF structure
+ * @conf: FDIR configuration for each filter
+ *
+ * Check if @conf has conflicting profile with existing profiles
+ *
+ * Return: true on success, and false on error.
+ */
+static bool
+ice_vc_fdir_has_prof_conflict(struct ice_vf *vf,
+                             struct virtchnl_fdir_fltr_conf *conf)
+{
+       struct ice_fdir_fltr *desc;
+
+       list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) {
+               struct virtchnl_fdir_fltr_conf *existing_conf;
+               enum ice_fltr_ptype flow_type_a, flow_type_b;
+               struct ice_fdir_fltr *a, *b;
+
+               existing_conf = to_fltr_conf_from_desc(desc);
+               a = &existing_conf->input;
+               b = &conf->input;
+               flow_type_a = a->flow_type;
+               flow_type_b = b->flow_type;
+
+               /* No need to compare two rules with different tunnel types or
+                * with the same protocol type.
+                */
+               if (existing_conf->ttype != conf->ttype ||
+                   flow_type_a == flow_type_b)
+                       continue;
+
+               switch (flow_type_a) {
+               case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
+               case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
+               case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
+                       if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
+                               return true;
+                       break;
+               case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
+                       if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
+                           flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
+                           flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_SCTP)
+                               return true;
+                       break;
+               case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
+               case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
+               case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
+                       if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_OTHER)
+                               return true;
+                       break;
+               case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
+                       if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
+                           flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
+                           flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_SCTP)
+                               return true;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return false;
+}
+
 /**
  * ice_vc_fdir_write_flow_prof
  * @vf: pointer to the VF structure
@@ -677,6 +758,13 @@ ice_vc_fdir_config_input_set(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,
        enum ice_fltr_ptype flow;
        int ret;
 
+       ret = ice_vc_fdir_has_prof_conflict(vf, conf);
+       if (ret) {
+               dev_dbg(dev, "Found flow profile conflict for VF %d\n",
+                       vf->vf_id);
+               return ret;
+       }
+
        flow = input->flow_type;
        ret = ice_vc_fdir_alloc_prof(vf, flow);
        if (ret) {
@@ -1798,7 +1886,7 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
                v_ret = VIRTCHNL_STATUS_SUCCESS;
                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
                dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
-               goto err_free_conf;
+               goto err_rem_entry;
        }
 
        ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);
@@ -1807,15 +1895,16 @@ int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
                dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
                        vf->vf_id, ret);
-               goto err_rem_entry;
+               goto err_clr_irq;
        }
 
 exit:
        kfree(stat);
        return ret;
 
-err_rem_entry:
+err_clr_irq:
        ice_vc_fdir_clear_irq_ctx(vf);
+err_rem_entry:
        ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
 err_free_conf:
        devm_kfree(dev, conf);
@@ -1924,6 +2013,7 @@ void ice_vf_fdir_init(struct ice_vf *vf)
        spin_lock_init(&fdir->ctx_lock);
        fdir->ctx_irq.flags = 0;
        fdir->ctx_done.flags = 0;
+       ice_vc_fdir_reset_cnt_all(fdir);
 }
 
 /**
index 31565bbafa224f9cf2035f8c6439ed58f7bcd65a..d1e489da7363f26ecfb723fcc75423a8faa1efdd 100644 (file)
@@ -184,8 +184,6 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
        }
        netif_tx_stop_queue(netdev_get_tx_queue(vsi->netdev, q_idx));
 
-       ice_qvec_dis_irq(vsi, rx_ring, q_vector);
-
        ice_fill_txq_meta(vsi, tx_ring, &txq_meta);
        err = ice_vsi_stop_tx_ring(vsi, ICE_NO_RESET, 0, tx_ring, &txq_meta);
        if (err)
@@ -200,10 +198,11 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
                if (err)
                        return err;
        }
+       ice_qvec_dis_irq(vsi, rx_ring, q_vector);
+
        err = ice_vsi_ctrl_one_rx_ring(vsi, false, q_idx, true);
        if (err)
                return err;
-       ice_clean_rx_ring(rx_ring);
 
        ice_qvec_toggle_napi(vsi, q_vector, false);
        ice_qp_clean_rings(vsi, q_idx);
index 03bc1e8af575f72a6fd3a97cad6b15c2cf5dad09..274c781b554739fce9a98a551f9dfe4776515c29 100644 (file)
@@ -109,6 +109,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *);
 static void igb_setup_mrqc(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
 static void igb_remove(struct pci_dev *pdev);
+static void igb_init_queue_configuration(struct igb_adapter *adapter);
 static int igb_sw_init(struct igb_adapter *);
 int igb_open(struct net_device *);
 int igb_close(struct net_device *);
@@ -175,9 +176,7 @@ static void igb_nfc_filter_restore(struct igb_adapter *adapter);
 
 #ifdef CONFIG_PCI_IOV
 static int igb_vf_configure(struct igb_adapter *adapter, int vf);
-static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs);
-static int igb_disable_sriov(struct pci_dev *dev);
-static int igb_pci_disable_sriov(struct pci_dev *dev);
+static int igb_disable_sriov(struct pci_dev *dev, bool reinit);
 #endif
 
 static int igb_suspend(struct device *);
@@ -3665,7 +3664,7 @@ err_sw_init:
        kfree(adapter->shadow_vfta);
        igb_clear_interrupt_scheme(adapter);
 #ifdef CONFIG_PCI_IOV
-       igb_disable_sriov(pdev);
+       igb_disable_sriov(pdev, false);
 #endif
        pci_iounmap(pdev, adapter->io_addr);
 err_ioremap:
@@ -3679,7 +3678,38 @@ err_dma:
 }
 
 #ifdef CONFIG_PCI_IOV
-static int igb_disable_sriov(struct pci_dev *pdev)
+static int igb_sriov_reinit(struct pci_dev *dev)
+{
+       struct net_device *netdev = pci_get_drvdata(dev);
+       struct igb_adapter *adapter = netdev_priv(netdev);
+       struct pci_dev *pdev = adapter->pdev;
+
+       rtnl_lock();
+
+       if (netif_running(netdev))
+               igb_close(netdev);
+       else
+               igb_reset(adapter);
+
+       igb_clear_interrupt_scheme(adapter);
+
+       igb_init_queue_configuration(adapter);
+
+       if (igb_init_interrupt_scheme(adapter, true)) {
+               rtnl_unlock();
+               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
+               return -ENOMEM;
+       }
+
+       if (netif_running(netdev))
+               igb_open(netdev);
+
+       rtnl_unlock();
+
+       return 0;
+}
+
+static int igb_disable_sriov(struct pci_dev *pdev, bool reinit)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct igb_adapter *adapter = netdev_priv(netdev);
@@ -3713,10 +3743,10 @@ static int igb_disable_sriov(struct pci_dev *pdev)
                adapter->flags |= IGB_FLAG_DMAC;
        }
 
-       return 0;
+       return reinit ? igb_sriov_reinit(pdev) : 0;
 }
 
-static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
+static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs, bool reinit)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct igb_adapter *adapter = netdev_priv(netdev);
@@ -3781,12 +3811,6 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
                        "Unable to allocate memory for VF MAC filter list\n");
        }
 
-       /* only call pci_enable_sriov() if no VFs are allocated already */
-       if (!old_vfs) {
-               err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
-               if (err)
-                       goto err_out;
-       }
        dev_info(&pdev->dev, "%d VFs allocated\n",
                 adapter->vfs_allocated_count);
        for (i = 0; i < adapter->vfs_allocated_count; i++)
@@ -3794,6 +3818,17 @@ static int igb_enable_sriov(struct pci_dev *pdev, int num_vfs)
 
        /* DMA Coalescing is not supported in IOV mode. */
        adapter->flags &= ~IGB_FLAG_DMAC;
+
+       if (reinit) {
+               err = igb_sriov_reinit(pdev);
+               if (err)
+                       goto err_out;
+       }
+
+       /* only call pci_enable_sriov() if no VFs are allocated already */
+       if (!old_vfs)
+               err = pci_enable_sriov(pdev, adapter->vfs_allocated_count);
+
        goto out;
 
 err_out:
@@ -3863,9 +3898,7 @@ static void igb_remove(struct pci_dev *pdev)
        igb_release_hw_control(adapter);
 
 #ifdef CONFIG_PCI_IOV
-       rtnl_lock();
-       igb_disable_sriov(pdev);
-       rtnl_unlock();
+       igb_disable_sriov(pdev, false);
 #endif
 
        unregister_netdev(netdev);
@@ -3911,7 +3944,7 @@ static void igb_probe_vfs(struct igb_adapter *adapter)
        igb_reset_interrupt_capability(adapter);
 
        pci_sriov_set_totalvfs(pdev, 7);
-       igb_enable_sriov(pdev, max_vfs);
+       igb_enable_sriov(pdev, max_vfs, false);
 
 #endif /* CONFIG_PCI_IOV */
 }
@@ -9520,71 +9553,17 @@ static void igb_shutdown(struct pci_dev *pdev)
        }
 }
 
-#ifdef CONFIG_PCI_IOV
-static int igb_sriov_reinit(struct pci_dev *dev)
-{
-       struct net_device *netdev = pci_get_drvdata(dev);
-       struct igb_adapter *adapter = netdev_priv(netdev);
-       struct pci_dev *pdev = adapter->pdev;
-
-       rtnl_lock();
-
-       if (netif_running(netdev))
-               igb_close(netdev);
-       else
-               igb_reset(adapter);
-
-       igb_clear_interrupt_scheme(adapter);
-
-       igb_init_queue_configuration(adapter);
-
-       if (igb_init_interrupt_scheme(adapter, true)) {
-               rtnl_unlock();
-               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-               return -ENOMEM;
-       }
-
-       if (netif_running(netdev))
-               igb_open(netdev);
-
-       rtnl_unlock();
-
-       return 0;
-}
-
-static int igb_pci_disable_sriov(struct pci_dev *dev)
-{
-       int err = igb_disable_sriov(dev);
-
-       if (!err)
-               err = igb_sriov_reinit(dev);
-
-       return err;
-}
-
-static int igb_pci_enable_sriov(struct pci_dev *dev, int num_vfs)
-{
-       int err = igb_enable_sriov(dev, num_vfs);
-
-       if (err)
-               goto out;
-
-       err = igb_sriov_reinit(dev);
-       if (!err)
-               return num_vfs;
-
-out:
-       return err;
-}
-
-#endif
 static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
 {
 #ifdef CONFIG_PCI_IOV
-       if (num_vfs == 0)
-               return igb_pci_disable_sriov(dev);
-       else
-               return igb_pci_enable_sriov(dev, num_vfs);
+       int err;
+
+       if (num_vfs == 0) {
+               return igb_disable_sriov(dev, true);
+       } else {
+               err = igb_enable_sriov(dev, num_vfs, true);
+               return err ? err : num_vfs;
+       }
 #endif
        return 0;
 }
index 3a32809510fc6b771c2a350e5bed9aa3a5bb1a48..72cb1b56e9f2400b5408d4a722171ffcb363e4b9 100644 (file)
@@ -1074,7 +1074,7 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
                          igbvf_intr_msix_rx, 0, adapter->rx_ring->name,
                          netdev);
        if (err)
-               goto out;
+               goto free_irq_tx;
 
        adapter->rx_ring->itr_register = E1000_EITR(vector);
        adapter->rx_ring->itr_val = adapter->current_itr;
@@ -1083,10 +1083,14 @@ static int igbvf_request_msix(struct igbvf_adapter *adapter)
        err = request_irq(adapter->msix_entries[vector].vector,
                          igbvf_msix_other, 0, netdev->name, netdev);
        if (err)
-               goto out;
+               goto free_irq_rx;
 
        igbvf_configure_msix(adapter);
        return 0;
+free_irq_rx:
+       free_irq(adapter->msix_entries[--vector].vector, netdev);
+free_irq_tx:
+       free_irq(adapter->msix_entries[--vector].vector, netdev);
 out:
        return err;
 }
index b8ba3f94c363229b230d3c8dbe1a882149e6e265..a47a2e3e548cf3f2e5241ca3180e816f7ebb626a 100644 (file)
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright(c) 2009 - 2018 Intel Corporation. */
 
+#include <linux/etherdevice.h>
+
 #include "vf.h"
 
 static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
@@ -131,11 +133,16 @@ static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
                /* set our "perm_addr" based on info provided by PF */
                ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
                if (!ret_val) {
-                       if (msgbuf[0] == (E1000_VF_RESET |
-                                         E1000_VT_MSGTYPE_ACK))
+                       switch (msgbuf[0]) {
+                       case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
                                memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
-                       else
+                               break;
+                       case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
+                               eth_zero_addr(hw->mac.perm_addr);
+                               break;
+                       default:
                                ret_val = -E1000_ERR_MAC_INIT;
+                       }
                }
        }
 
index 2928a6c73692871a225cab659a0c0c5adf99af8b..25fc6c65209bf948887311ab10ae65d02a2b0ae9 100644 (file)
@@ -6010,18 +6010,18 @@ static bool validate_schedule(struct igc_adapter *adapter,
                if (e->command != TC_TAPRIO_CMD_SET_GATES)
                        return false;
 
-               for (i = 0; i < adapter->num_tx_queues; i++) {
-                       if (e->gate_mask & BIT(i))
+               for (i = 0; i < adapter->num_tx_queues; i++)
+                       if (e->gate_mask & BIT(i)) {
                                queue_uses[i]++;
 
-                       /* There are limitations: A single queue cannot be
-                        * opened and closed multiple times per cycle unless the
-                        * gate stays open. Check for it.
-                        */
-                       if (queue_uses[i] > 1 &&
-                           !(prev->gate_mask & BIT(i)))
-                               return false;
-               }
+                               /* There are limitations: A single queue cannot
+                                * be opened and closed multiple times per cycle
+                                * unless the gate stays open. Check for it.
+                                */
+                               if (queue_uses[i] > 1 &&
+                                   !(prev->gate_mask & BIT(i)))
+                                       return false;
+                       }
        }
 
        return true;
index 0e39d199ff06158f3aac6ca1665f25d5304942bc..2cad76d0a50ef6fab802bb929948f1136451084d 100644 (file)
@@ -3549,6 +3549,8 @@ static void mvneta_txq_sw_deinit(struct mvneta_port *pp,
 
        netdev_tx_reset_queue(nq);
 
+       txq->buf               = NULL;
+       txq->tso_hdrs          = NULL;
        txq->descs             = NULL;
        txq->last_desc         = 0;
        txq->next_desc_to_proc = 0;
index 41d935d1aaf6ff075e51b13e065d565a2ced4ae7..40aeaa7bd739fa722ea059968810380a690619ea 100644 (file)
@@ -62,35 +62,38 @@ static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
        MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
                       MVPP22_CLS_HEK_IP4_2T,
                       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
-                      MVPP2_PRS_RI_L4_TCP,
+                      MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
                       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
                       MVPP22_CLS_HEK_IP4_2T,
                       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
-                      MVPP2_PRS_RI_L4_TCP,
+                      MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
                       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
                       MVPP22_CLS_HEK_IP4_2T,
                       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
-                      MVPP2_PRS_RI_L4_TCP,
+                      MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
                       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
 
        /* TCP over IPv4 flows, fragmented, with vlan tag */
        MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
                       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
-                      MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP,
+                      MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_IP_FRAG_TRUE |
+                          MVPP2_PRS_RI_L4_TCP,
                       MVPP2_PRS_IP_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
                       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
-                      MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP,
+                      MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_IP_FRAG_TRUE |
+                          MVPP2_PRS_RI_L4_TCP,
                       MVPP2_PRS_IP_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
                       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
-                      MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP,
+                      MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_IP_FRAG_TRUE |
+                          MVPP2_PRS_RI_L4_TCP,
                       MVPP2_PRS_IP_MASK),
 
        /* UDP over IPv4 flows, Not fragmented, no vlan tag */
@@ -132,35 +135,38 @@ static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
        MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
                       MVPP22_CLS_HEK_IP4_2T,
                       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
-                      MVPP2_PRS_RI_L4_UDP,
+                      MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
                       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
                       MVPP22_CLS_HEK_IP4_2T,
                       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
-                      MVPP2_PRS_RI_L4_UDP,
+                      MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
                       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
                       MVPP22_CLS_HEK_IP4_2T,
                       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
-                      MVPP2_PRS_RI_L4_UDP,
+                      MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
                       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
 
        /* UDP over IPv4 flows, fragmented, with vlan tag */
        MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
                       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
-                      MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP,
+                      MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_IP_FRAG_TRUE |
+                          MVPP2_PRS_RI_L4_UDP,
                       MVPP2_PRS_IP_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
                       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
-                      MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP,
+                      MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_IP_FRAG_TRUE |
+                          MVPP2_PRS_RI_L4_UDP,
                       MVPP2_PRS_IP_MASK),
 
        MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
                       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
-                      MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP,
+                      MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_IP_FRAG_TRUE |
+                          MVPP2_PRS_RI_L4_UDP,
                       MVPP2_PRS_IP_MASK),
 
        /* TCP over IPv6 flows, not fragmented, no vlan tag */
index 9b4ecbe4f36d41b3855b70243de9e4a4994b0ea7..3ea00bc9b91caf1fcf293e11448281f48fe3edee 100644 (file)
@@ -4996,6 +4996,14 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu)
 
        for (i = 0; i < priv->port_count; i++) {
                port = priv->port_list[i];
+               if (percpu && port->ntxqs >= num_possible_cpus() * 2)
+                       xdp_set_features_flag(port->dev,
+                                             NETDEV_XDP_ACT_BASIC |
+                                             NETDEV_XDP_ACT_REDIRECT |
+                                             NETDEV_XDP_ACT_NDO_XMIT);
+               else
+                       xdp_clear_features_flag(port->dev);
+
                mvpp2_swf_bm_pool_init(port);
                if (status[i])
                        mvpp2_open(port->dev);
@@ -6863,13 +6871,14 @@ static int mvpp2_port_probe(struct platform_device *pdev,
 
        if (!port->priv->percpu_pools)
                mvpp2_set_hw_csum(port, port->pool_long->id);
+       else if (port->ntxqs >= num_possible_cpus() * 2)
+               dev->xdp_features = NETDEV_XDP_ACT_BASIC |
+                                   NETDEV_XDP_ACT_REDIRECT |
+                                   NETDEV_XDP_ACT_NDO_XMIT;
 
        dev->vlan_features |= features;
        netif_set_tso_max_segs(dev, MVPP2_MAX_TSO_SEGS);
 
-       dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                           NETDEV_XDP_ACT_NDO_XMIT;
-
        dev->priv_flags |= IFF_UNICAST_FLT;
 
        /* MTU range: 68 - 9704 */
index 75ba57bd1d46d85f163c3568f45b0f3708474d7f..9af22f497a40f50ea275af75d165a1635a14f65c 100644 (file)
@@ -1539,8 +1539,8 @@ static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv)
        if (!priv->prs_double_vlans)
                return -ENOMEM;
 
-       /* Double VLAN: 0x8100, 0x88A8 */
-       err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021Q, ETH_P_8021AD,
+       /* Double VLAN: 0x88A8, 0x8100 */
+       err = mvpp2_prs_double_vlan_add(priv, ETH_P_8021AD, ETH_P_8021Q,
                                        MVPP2_PRS_PORT_MASK);
        if (err)
                return err;
@@ -1607,59 +1607,45 @@ static int mvpp2_prs_vlan_init(struct platform_device *pdev, struct mvpp2 *priv)
 static int mvpp2_prs_pppoe_init(struct mvpp2 *priv)
 {
        struct mvpp2_prs_entry pe;
-       int tid;
-
-       /* IPv4 over PPPoE with options */
-       tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
-                                       MVPP2_PE_LAST_FREE_TID);
-       if (tid < 0)
-               return tid;
-
-       memset(&pe, 0, sizeof(pe));
-       mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
-       pe.index = tid;
-
-       mvpp2_prs_match_etype(&pe, 0, PPP_IP);
-
-       mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
-       mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4_OPT,
-                                MVPP2_PRS_RI_L3_PROTO_MASK);
-       /* goto ipv4 dest-address (skip eth_type + IP-header-size - 4) */
-       mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN +
-                                sizeof(struct iphdr) - 4,
-                                MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
-       /* Set L3 offset */
-       mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
-                                 MVPP2_ETH_TYPE_LEN,
-                                 MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
-
-       /* Update shadow table and hw entry */
-       mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
-       mvpp2_prs_hw_write(priv, &pe);
+       int tid, ihl;
 
-       /* IPv4 over PPPoE without options */
-       tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
-                                       MVPP2_PE_LAST_FREE_TID);
-       if (tid < 0)
-               return tid;
+       /* IPv4 over PPPoE with header length >= 5 */
+       for (ihl = MVPP2_PRS_IPV4_IHL_MIN; ihl <= MVPP2_PRS_IPV4_IHL_MAX; ihl++) {
+               tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
+                                               MVPP2_PE_LAST_FREE_TID);
+               if (tid < 0)
+                       return tid;
 
-       pe.index = tid;
+               memset(&pe, 0, sizeof(pe));
+               mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_PPPOE);
+               pe.index = tid;
 
-       mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
-                                    MVPP2_PRS_IPV4_HEAD |
-                                    MVPP2_PRS_IPV4_IHL_MIN,
-                                    MVPP2_PRS_IPV4_HEAD_MASK |
-                                    MVPP2_PRS_IPV4_IHL_MASK);
+               mvpp2_prs_match_etype(&pe, 0, PPP_IP);
+               mvpp2_prs_tcam_data_byte_set(&pe, MVPP2_ETH_TYPE_LEN,
+                                            MVPP2_PRS_IPV4_HEAD | ihl,
+                                            MVPP2_PRS_IPV4_HEAD_MASK |
+                                            MVPP2_PRS_IPV4_IHL_MASK);
 
-       /* Clear ri before updating */
-       pe.sram[MVPP2_PRS_SRAM_RI_WORD] = 0x0;
-       pe.sram[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
-       mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
-                                MVPP2_PRS_RI_L3_PROTO_MASK);
+               mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP4);
+               mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP4,
+                                        MVPP2_PRS_RI_L3_PROTO_MASK);
+               /* goto ipv4 dst-address (skip eth_type + IP-header-size - 4) */
+               mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN +
+                                        sizeof(struct iphdr) - 4,
+                                        MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
+               /* Set L3 offset */
+               mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
+                                         MVPP2_ETH_TYPE_LEN,
+                                         MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
+               /* Set L4 offset */
+               mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L4,
+                                         MVPP2_ETH_TYPE_LEN + (ihl * 4),
+                                         MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
 
-       /* Update shadow table and hw entry */
-       mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
-       mvpp2_prs_hw_write(priv, &pe);
+               /* Update shadow table and hw entry */
+               mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_PPPOE);
+               mvpp2_prs_hw_write(priv, &pe);
+       }
 
        /* IPv6 over PPPoE */
        tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
index 7f8ffbf79cf742905b2d6e5cfbd426a18b8f7bd8..ab126f8706c7491b1aee2e22c366ee1cb63ed1a2 100644 (file)
@@ -709,6 +709,7 @@ err_unreg_netdev:
 err_ptp_destroy:
        otx2_ptp_destroy(vf);
 err_detach_rsrc:
+       free_percpu(vf->hw.lmt_info);
        if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
                qmem_free(vf->dev, vf->dync_lmt);
        otx2_detach_resources(&vf->mbox);
@@ -762,6 +763,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
        otx2_shutdown_tc(vf);
        otx2vf_disable_mbox_intr(vf);
        otx2_detach_resources(&vf->mbox);
+       free_percpu(vf->hw.lmt_info);
        if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
                qmem_free(vf->dev, vf->dync_lmt);
        otx2vf_vfaf_mbox_destroy(vf);
index 3cb43623d3dbe9d2677bee3fd067c4ced5c07585..e14050e178624752c8c15f1f8e3a0347f40d4092 100644 (file)
@@ -753,6 +753,7 @@ static void mtk_mac_link_up(struct phylink_config *config,
                 MAC_MCR_FORCE_RX_FC);
 
        /* Configure speed */
+       mac->speed = speed;
        switch (speed) {
        case SPEED_2500:
        case SPEED_1000:
@@ -763,8 +764,6 @@ static void mtk_mac_link_up(struct phylink_config *config,
                break;
        }
 
-       mtk_set_queue_speed(mac->hw, mac->id, speed);
-
        /* Configure duplex */
        if (duplex == DUPLEX_FULL)
                mcr |= MAC_MCR_FORCE_DPX;
@@ -2059,9 +2058,6 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
                        skb_checksum_none_assert(skb);
                skb->protocol = eth_type_trans(skb, netdev);
 
-               if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
-                       mtk_ppe_check_skb(eth->ppe[0], skb, hash);
-
                if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
                        if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
                                if (trxd.rxd3 & RX_DMA_VTAG_V2) {
@@ -2089,6 +2085,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
                        __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vlan_tci);
                }
 
+               if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
+                       mtk_ppe_check_skb(eth->ppe[0], skb, hash);
+
                skb_record_rx_queue(skb, 0);
                napi_gro_receive(napi, skb);
 
@@ -3237,6 +3236,9 @@ found:
        if (dp->index >= MTK_QDMA_NUM_QUEUES)
                return NOTIFY_DONE;
 
+       if (mac->speed > 0 && mac->speed <= s.base.speed)
+               s.base.speed = 0;
+
        mtk_set_queue_speed(eth, dp->index + 3, s.base.speed);
 
        return NOTIFY_DONE;
index b65de174c3d9b1c2a9d6d410a4db07762cb880e6..084a6badef6d9b4973a7413f474c6f9b68e31fb3 100644 (file)
 #define SGMII_SEND_AN_ERROR_EN         BIT(11)
 #define SGMII_IF_MODE_MASK             GENMASK(5, 1)
 
+/* Register to reset SGMII design */
+#define SGMII_RESERVED_0       0x34
+#define SGMII_SW_RESET         BIT(0)
+
 /* Register to set SGMII speed, ANA RG_ Control Signals III*/
 #define SGMSYS_ANA_RG_CS3      0x2028
 #define RG_PHY_SPEED_MASK      (BIT(2) | BIT(3))
index 6883eb34cd8b437864b3e00575dad2afbc2972b5..fd07d6e142733445d9c5e398af2f258796a91e53 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/platform_device.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
+#include <net/dst_metadata.h>
 #include <net/dsa.h>
 #include "mtk_eth_soc.h"
 #include "mtk_ppe.h"
@@ -458,6 +459,7 @@ __mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
                hwe->ib1 &= ~MTK_FOE_IB1_STATE;
                hwe->ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID);
                dma_wmb();
+               mtk_ppe_cache_clear(ppe);
        }
        entry->hash = 0xffff;
 
@@ -699,7 +701,9 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
                    skb->dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK)
                        goto out;
 
-               tag += 4;
+               if (!skb_metadata_dst(skb))
+                       tag += 4;
+
                if (get_unaligned_be16(tag) != ETH_P_8021Q)
                        break;
 
index 81afd5ee3fbf171fde7b76310ae7126f9f8d3daa..161751bb36c9c5736a7f4c1bc4883d780f6b04e8 100644 (file)
@@ -576,6 +576,7 @@ mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
                if (IS_ERR(block_cb))
                        return PTR_ERR(block_cb);
 
+               flow_block_cb_incref(block_cb);
                flow_block_cb_add(block_cb, f);
                list_add_tail(&block_cb->driver_list, &block_cb_list);
                return 0;
@@ -584,7 +585,7 @@ mtk_eth_setup_tc_block(struct net_device *dev, struct flow_block_offload *f)
                if (!block_cb)
                        return -ENOENT;
 
-               if (flow_block_cb_decref(block_cb)) {
+               if (!flow_block_cb_decref(block_cb)) {
                        flow_block_cb_remove(block_cb, f);
                        list_del(&block_cb->driver_list);
                }
index bb00de1003ac4355808b6805b3221270a7bfb909..83976dc86887589488e9769a4e7fc1f582523609 100644 (file)
@@ -38,20 +38,16 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
                          const unsigned long *advertising,
                          bool permit_pause_to_mac)
 {
+       bool mode_changed = false, changed, use_an;
        struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
        unsigned int rgc3, sgm_mode, bmcr;
        int advertise, link_timer;
-       bool changed, use_an;
 
        advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
                                                             advertising);
        if (advertise < 0)
                return advertise;
 
-       link_timer = phylink_get_link_timer_ns(interface);
-       if (link_timer < 0)
-               return link_timer;
-
        /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
         * we assume that fixes it's speed at bitrate = line rate (in
         * other words, 1000Mbps or 2500Mbps).
@@ -77,17 +73,24 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
        }
 
        if (use_an) {
-               /* FIXME: Do we need to set AN_RESTART here? */
-               bmcr = SGMII_AN_RESTART | SGMII_AN_ENABLE;
+               bmcr = SGMII_AN_ENABLE;
        } else {
                bmcr = 0;
        }
 
        if (mpcs->interface != interface) {
+               link_timer = phylink_get_link_timer_ns(interface);
+               if (link_timer < 0)
+                       return link_timer;
+
                /* PHYA power down */
                regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
                                   SGMII_PHYA_PWD, SGMII_PHYA_PWD);
 
+               /* Reset SGMII PCS state */
+               regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
+                                  SGMII_SW_RESET, SGMII_SW_RESET);
+
                if (interface == PHY_INTERFACE_MODE_2500BASEX)
                        rgc3 = RG_PHY_SPEED_3_125G;
                else
@@ -97,16 +100,17 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
                regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
                                   RG_PHY_SPEED_3_125G, rgc3);
 
+               /* Setup the link timer */
+               regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
+
                mpcs->interface = interface;
+               mode_changed = true;
        }
 
        /* Update the advertisement, noting whether it has changed */
        regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
                                 SGMII_ADVERTISE, advertise, &changed);
 
-       /* Setup the link timer and QPHY power up inside SGMIISYS */
-       regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER, link_timer / 2 / 8);
-
        /* Update the sgmsys mode register */
        regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
                           SGMII_REMOTE_FAULT_DIS | SGMII_SPEED_DUPLEX_AN |
@@ -114,7 +118,7 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
 
        /* Update the BMCR */
        regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
-                          SGMII_AN_RESTART | SGMII_AN_ENABLE, bmcr);
+                          SGMII_AN_ENABLE, bmcr);
 
        /* Release PHYA power down state
         * Only removing bit SGMII_PHYA_PWD isn't enough.
@@ -128,7 +132,7 @@ static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
        usleep_range(50, 100);
        regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
 
-       return changed;
+       return changed || mode_changed;
 }
 
 static void mtk_pcs_restart_an(struct phylink_pcs *pcs)
index 0869d4fff17b1aa49dff0d4a6b21a8868afbd30d..332472fe49902e3f5ee17faf8ca4b5bcd2ac4cf7 100644 (file)
@@ -674,21 +674,39 @@ int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
 
        if (unlikely(_ctx->ring->hwtstamp_rx_filter != HWTSTAMP_FILTER_ALL))
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *timestamp = mlx4_en_get_hwtstamp(_ctx->mdev,
                                          mlx4_en_get_cqe_ts(_ctx->cqe));
        return 0;
 }
 
-int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
+int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                       enum xdp_rss_hash_type *rss_type)
 {
        struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
+       struct mlx4_cqe *cqe = _ctx->cqe;
+       enum xdp_rss_hash_type xht = 0;
+       __be16 status;
 
        if (unlikely(!(_ctx->dev->features & NETIF_F_RXHASH)))
-               return -EOPNOTSUPP;
+               return -ENODATA;
+
+       *hash = be32_to_cpu(cqe->immed_rss_invalid);
+       status = cqe->status;
+       if (status & cpu_to_be16(MLX4_CQE_STATUS_TCP))
+               xht = XDP_RSS_L4_TCP;
+       if (status & cpu_to_be16(MLX4_CQE_STATUS_UDP))
+               xht = XDP_RSS_L4_UDP;
+       if (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 | MLX4_CQE_STATUS_IPV4F))
+               xht |= XDP_RSS_L3_IPV4;
+       if (status & cpu_to_be16(MLX4_CQE_STATUS_IPV6)) {
+               xht |= XDP_RSS_L3_IPV6;
+               if (cqe->ipv6_ext_mask)
+                       xht |= XDP_RSS_L3_DYNHDR;
+       }
+       *rss_type = xht;
 
-       *hash = be32_to_cpu(_ctx->cqe->immed_rss_invalid);
        return 0;
 }
 
index 544e09b97483cb4a09ff8957f12e35001c802d77..4ac4d883047b1c7b12317c62e705382c7e4d2d12 100644 (file)
@@ -798,7 +798,8 @@ int mlx4_en_netdev_event(struct notifier_block *this,
 
 struct xdp_md;
 int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp);
-int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash);
+int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                       enum xdp_rss_hash_type *rss_type);
 
 /*
  * Functions for time stamping
index 445fe30c3d0bc5aa149f366408cea2bd9fc23497..2e7806001fdc5fad2a86987877863eb35d479dad 100644 (file)
@@ -59,9 +59,6 @@ bool mlx5_eth_supported(struct mlx5_core_dev *dev)
        if (!IS_ENABLED(CONFIG_MLX5_CORE_EN))
                return false;
 
-       if (mlx5_core_is_management_pf(dev))
-               return false;
-
        if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
                return false;
 
@@ -201,9 +198,6 @@ bool mlx5_rdma_supported(struct mlx5_core_dev *dev)
        if (!IS_ENABLED(CONFIG_MLX5_INFINIBAND))
                return false;
 
-       if (mlx5_core_is_management_pf(dev))
-               return false;
-
        if (dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_IB_ADEV)
                return false;
 
index 7c9c4e40c019b027e094091a1dff19830747873e..d000236ddbac5a0a4384bd4b8b1149db449f1da1 100644 (file)
@@ -75,10 +75,6 @@ int mlx5_ec_init(struct mlx5_core_dev *dev)
        if (!mlx5_core_is_ecpf(dev))
                return 0;
 
-       /* Management PF don't have a peer PF */
-       if (mlx5_core_is_management_pf(dev))
-               return 0;
-
        return mlx5_host_pf_init(dev);
 }
 
@@ -89,10 +85,6 @@ void mlx5_ec_cleanup(struct mlx5_core_dev *dev)
        if (!mlx5_core_is_ecpf(dev))
                return;
 
-       /* Management PF don't have a peer PF */
-       if (mlx5_core_is_management_pf(dev))
-               return;
-
        mlx5_host_pf_cleanup(dev);
 
        err = mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_HOST_PF]);
index 88460b7796e5574176a1e4f229cd0541050ac02d..4a19ef4a9811066988897c632e19e37e45d38b2e 100644 (file)
@@ -313,7 +313,6 @@ struct mlx5e_params {
                } channel;
        } mqprio;
        bool rx_cqe_compress_def;
-       bool tunneled_offload_en;
        struct dim_cq_moder rx_cq_moderation;
        struct dim_cq_moder tx_cq_moderation;
        struct mlx5e_packet_merge_param packet_merge;
@@ -1243,6 +1242,7 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
 void mlx5e_rx_dim_work(struct work_struct *work);
 void mlx5e_tx_dim_work(struct work_struct *work);
 
+void mlx5e_set_xdp_feature(struct net_device *netdev);
 netdev_features_t mlx5e_features_check(struct sk_buff *skb,
                                       struct net_device *netdev,
                                       netdev_features_t features);
index c4378afdec09e43c02813e3a2f88ccc93170e56e..1bd1c94fb977669ee01600feff6091247fcafbc7 100644 (file)
@@ -178,7 +178,6 @@ tc_act_police_stats(struct mlx5e_priv *priv,
        meter = mlx5e_tc_meter_get(priv->mdev, &params);
        if (IS_ERR(meter)) {
                NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
-               mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
                return PTR_ERR(meter);
        }
 
index 626cb7470fa572bb540ff1d83b300b6fccc3e950..07c1895a2b23414f2a9b5bf5e1454757951624c3 100644 (file)
@@ -64,6 +64,7 @@ mlx5e_tc_act_stats_add(struct mlx5e_tc_act_stats_handle *handle,
 {
        struct mlx5e_tc_act_stats *act_stats, *old_act_stats;
        struct rhashtable *ht = &handle->ht;
+       u64 lastused;
        int err = 0;
 
        act_stats = kvzalloc(sizeof(*act_stats), GFP_KERNEL);
@@ -73,6 +74,10 @@ mlx5e_tc_act_stats_add(struct mlx5e_tc_act_stats_handle *handle,
        act_stats->tc_act_cookie = act_cookie;
        act_stats->counter = counter;
 
+       mlx5_fc_query_cached_raw(counter,
+                                &act_stats->lastbytes,
+                                &act_stats->lastpackets, &lastused);
+
        rcu_read_lock();
        old_act_stats = rhashtable_lookup_get_insert_fast(ht,
                                                          &act_stats->hash,
index ca834bbcb44f1953b42c9a1e6db21856aa2d5aa5..8afcec0c5d3cafda3f00bbc5b7a99d815c58a9b4 100644 (file)
@@ -242,7 +242,7 @@ mlx5e_int_port_remove(struct mlx5e_tc_int_port_priv *priv,
                mlx5_del_flow_rules(int_port->rx_rule);
        mapping_remove(ctx, int_port->mapping);
        mlx5e_int_port_metadata_free(priv, int_port->match_metadata);
-       kfree_rcu(int_port);
+       kfree_rcu_mightsleep(int_port);
        priv->num_ports--;
 }
 
index bcd6370de440f2d3c9f22509750c51c3899c382b..d9d3b9e1f15aa7e31a63df3226cb66b65062d2e3 100644 (file)
@@ -34,6 +34,7 @@
 #include <net/xdp_sock_drv.h>
 #include "en/xdp.h"
 #include "en/params.h"
+#include <linux/bitfield.h>
 
 int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk)
 {
@@ -162,21 +163,79 @@ static int mlx5e_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
 
        if (unlikely(!mlx5e_rx_hw_stamp(_ctx->rq->tstamp)))
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *timestamp =  mlx5e_cqe_ts_to_ns(_ctx->rq->ptp_cyc2time,
                                         _ctx->rq->clock, get_cqe_ts(_ctx->cqe));
        return 0;
 }
 
-static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
+/* Mapping HW RSS Type bits CQE_RSS_HTYPE_IP + CQE_RSS_HTYPE_L4 into 4-bits*/
+#define RSS_TYPE_MAX_TABLE     16 /* 4-bits max 16 entries */
+#define RSS_L4         GENMASK(1, 0)
+#define RSS_L3         GENMASK(3, 2) /* Same as CQE_RSS_HTYPE_IP */
+
+/* Valid combinations of CQE_RSS_HTYPE_IP + CQE_RSS_HTYPE_L4 sorted numerical */
+enum mlx5_rss_hash_type {
+       RSS_TYPE_NO_HASH        = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IP_NONE) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_NONE)),
+       RSS_TYPE_L3_IPV4        = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV4) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_NONE)),
+       RSS_TYPE_L4_IPV4_TCP    = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV4) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_TCP)),
+       RSS_TYPE_L4_IPV4_UDP    = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV4) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_UDP)),
+       RSS_TYPE_L4_IPV4_IPSEC  = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV4) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_IPSEC)),
+       RSS_TYPE_L3_IPV6        = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV6) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_NONE)),
+       RSS_TYPE_L4_IPV6_TCP    = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV6) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_TCP)),
+       RSS_TYPE_L4_IPV6_UDP    = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV6) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_UDP)),
+       RSS_TYPE_L4_IPV6_IPSEC  = (FIELD_PREP_CONST(RSS_L3, CQE_RSS_IPV6) |
+                                  FIELD_PREP_CONST(RSS_L4, CQE_RSS_L4_IPSEC)),
+};
+
+/* Invalid combinations will simply return zero, allows no boundary checks */
+static const enum xdp_rss_hash_type mlx5_xdp_rss_type[RSS_TYPE_MAX_TABLE] = {
+       [RSS_TYPE_NO_HASH]       = XDP_RSS_TYPE_NONE,
+       [1]                      = XDP_RSS_TYPE_NONE, /* Implicit zero */
+       [2]                      = XDP_RSS_TYPE_NONE, /* Implicit zero */
+       [3]                      = XDP_RSS_TYPE_NONE, /* Implicit zero */
+       [RSS_TYPE_L3_IPV4]       = XDP_RSS_TYPE_L3_IPV4,
+       [RSS_TYPE_L4_IPV4_TCP]   = XDP_RSS_TYPE_L4_IPV4_TCP,
+       [RSS_TYPE_L4_IPV4_UDP]   = XDP_RSS_TYPE_L4_IPV4_UDP,
+       [RSS_TYPE_L4_IPV4_IPSEC] = XDP_RSS_TYPE_L4_IPV4_IPSEC,
+       [RSS_TYPE_L3_IPV6]       = XDP_RSS_TYPE_L3_IPV6,
+       [RSS_TYPE_L4_IPV6_TCP]   = XDP_RSS_TYPE_L4_IPV6_TCP,
+       [RSS_TYPE_L4_IPV6_UDP]   = XDP_RSS_TYPE_L4_IPV6_UDP,
+       [RSS_TYPE_L4_IPV6_IPSEC] = XDP_RSS_TYPE_L4_IPV6_IPSEC,
+       [12]                     = XDP_RSS_TYPE_NONE, /* Implicit zero */
+       [13]                     = XDP_RSS_TYPE_NONE, /* Implicit zero */
+       [14]                     = XDP_RSS_TYPE_NONE, /* Implicit zero */
+       [15]                     = XDP_RSS_TYPE_NONE, /* Implicit zero */
+};
+
+static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                            enum xdp_rss_hash_type *rss_type)
 {
        const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
+       const struct mlx5_cqe64 *cqe = _ctx->cqe;
+       u32 hash_type, l4_type, ip_type, lookup;
 
        if (unlikely(!(_ctx->xdp.rxq->dev->features & NETIF_F_RXHASH)))
-               return -EOPNOTSUPP;
+               return -ENODATA;
+
+       *hash = be32_to_cpu(cqe->rss_hash_result);
+
+       hash_type = cqe->rss_hash_type;
+       BUILD_BUG_ON(CQE_RSS_HTYPE_IP != RSS_L3); /* same mask */
+       ip_type = hash_type & CQE_RSS_HTYPE_IP;
+       l4_type = FIELD_GET(CQE_RSS_HTYPE_L4, hash_type);
+       lookup = ip_type | l4_type;
+       *rss_type = mlx5_xdp_rss_type[lookup];
 
-       *hash = be32_to_cpu(_ctx->cqe->rss_hash_result);
        return 0;
 }
 
index 4be770443b0cd2a22df63c07c34ebbec4847678a..9b597cb2459851aa9a3dd46f4757e94ba87c7f70 100644 (file)
@@ -621,15 +621,6 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk,
        if (unlikely(!priv_rx))
                return -ENOMEM;
 
-       dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info);
-       if (IS_ERR(dek)) {
-               err = PTR_ERR(dek);
-               goto err_create_key;
-       }
-       priv_rx->dek = dek;
-
-       INIT_LIST_HEAD(&priv_rx->list);
-       spin_lock_init(&priv_rx->lock);
        switch (crypto_info->cipher_type) {
        case TLS_CIPHER_AES_GCM_128:
                priv_rx->crypto_info.crypto_info_128 =
@@ -642,9 +633,20 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk,
        default:
                WARN_ONCE(1, "Unsupported cipher type %u\n",
                          crypto_info->cipher_type);
-               return -EOPNOTSUPP;
+               err = -EOPNOTSUPP;
+               goto err_cipher_type;
        }
 
+       dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info);
+       if (IS_ERR(dek)) {
+               err = PTR_ERR(dek);
+               goto err_cipher_type;
+       }
+       priv_rx->dek = dek;
+
+       INIT_LIST_HEAD(&priv_rx->list);
+       spin_lock_init(&priv_rx->lock);
+
        rxq = mlx5e_ktls_sk_get_rxq(sk);
        priv_rx->rxq = rxq;
        priv_rx->sk = sk;
@@ -677,7 +679,7 @@ err_post_wqes:
        mlx5e_tir_destroy(&priv_rx->tir);
 err_create_tir:
        mlx5_ktls_destroy_key(priv->tls->dek_pool, priv_rx->dek);
-err_create_key:
+err_cipher_type:
        kfree(priv_rx);
        return err;
 }
index 60b3e08a10286e2285262a6435dacb0ea5265d07..0e4c0a093293a7e8872a7c751bfd8d5373f80935 100644 (file)
@@ -469,14 +469,6 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk,
        if (IS_ERR(priv_tx))
                return PTR_ERR(priv_tx);
 
-       dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info);
-       if (IS_ERR(dek)) {
-               err = PTR_ERR(dek);
-               goto err_create_key;
-       }
-       priv_tx->dek = dek;
-
-       priv_tx->expected_seq = start_offload_tcp_sn;
        switch (crypto_info->cipher_type) {
        case TLS_CIPHER_AES_GCM_128:
                priv_tx->crypto_info.crypto_info_128 =
@@ -489,8 +481,18 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk,
        default:
                WARN_ONCE(1, "Unsupported cipher type %u\n",
                          crypto_info->cipher_type);
-               return -EOPNOTSUPP;
+               err = -EOPNOTSUPP;
+               goto err_pool_push;
        }
+
+       dek = mlx5_ktls_create_key(priv->tls->dek_pool, crypto_info);
+       if (IS_ERR(dek)) {
+               err = PTR_ERR(dek);
+               goto err_pool_push;
+       }
+
+       priv_tx->dek = dek;
+       priv_tx->expected_seq = start_offload_tcp_sn;
        priv_tx->tx_ctx = tls_offload_ctx_tx(tls_ctx);
 
        mlx5e_set_ktls_tx_priv_ctx(tls_ctx, priv_tx);
@@ -500,7 +502,7 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk,
 
        return 0;
 
-err_create_key:
+err_pool_push:
        pool_push(pool, priv_tx);
        return err;
 }
index 08d0929e82603679709d4d425d50a8ff3a95bdc9..51f1cd8364c241585360f8ad1976f0535b8dd4a8 100644 (file)
@@ -89,8 +89,8 @@ struct mlx5e_macsec_rx_sc {
 };
 
 struct mlx5e_macsec_umr {
+       u8 __aligned(64) ctx[MLX5_ST_SZ_BYTES(macsec_aso)];
        dma_addr_t dma_addr;
-       u8 ctx[MLX5_ST_SZ_BYTES(macsec_aso)];
        u32 mkey;
 };
 
@@ -670,7 +670,7 @@ static int mlx5e_macsec_del_txsa(struct macsec_context *ctx)
 
        mlx5e_macsec_cleanup_sa(macsec, tx_sa, true);
        mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id);
-       kfree_rcu(tx_sa);
+       kfree_rcu_mightsleep(tx_sa);
        macsec_device->tx_sa[assoc_num] = NULL;
 
 out:
@@ -849,7 +849,7 @@ static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec
        xa_erase(&macsec->sc_xarray, rx_sc->sc_xarray_element->fs_id);
        metadata_dst_free(rx_sc->md_dst);
        kfree(rx_sc->sc_xarray_element);
-       kfree_rcu(rx_sc);
+       kfree_rcu_mightsleep(rx_sc);
 }
 
 static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
@@ -1412,6 +1412,7 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac
        struct mlx5e_macsec_aso *aso;
        struct mlx5_aso_wqe *aso_wqe;
        struct mlx5_aso *maso;
+       unsigned long expires;
        int err;
 
        aso = &macsec->aso;
@@ -1425,7 +1426,13 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *mac
        macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL);
 
        mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
-       err = mlx5_aso_poll_cq(maso, false);
+       expires = jiffies + msecs_to_jiffies(10);
+       do {
+               err = mlx5_aso_poll_cq(maso, false);
+               if (err)
+                       usleep_range(2, 10);
+       } while (err && time_is_after_jiffies(expires));
+
        if (err)
                goto err_out;
 
index 2449731b7d79a715c3d07a923bb4719cf299bd25..89de92d0648363a899793f1aa5ea4fb324a9ddc8 100644 (file)
@@ -117,12 +117,14 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
        if (!MLX5_CAP_GEN(priv->mdev, ets))
                return -EOPNOTSUPP;
 
-       ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
-       for (i = 0; i < ets->ets_cap; i++) {
+       for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
                err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
                if (err)
                        return err;
+       }
 
+       ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+       for (i = 0; i < ets->ets_cap; i++) {
                err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
                if (err)
                        return err;
index 7708acc9b2ab3a274f444e63bdfbb7278ded6ed5..79fd21ecb9cbc70c7ff47d54e7433265b608439e 100644 (file)
@@ -1985,6 +1985,7 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable)
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5e_params new_params;
+       int err;
 
        if (enable) {
                /* Checking the regular RQ here; mlx5e_validate_xsk_param called
@@ -2005,7 +2006,14 @@ static int set_pflag_rx_striding_rq(struct net_device *netdev, bool enable)
        MLX5E_SET_PFLAG(&new_params, MLX5E_PFLAG_RX_STRIDING_RQ, enable);
        mlx5e_set_rq_type(mdev, &new_params);
 
-       return mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
+       err = mlx5e_safe_switch_params(priv, &new_params, NULL, NULL, true);
+       if (err)
+               return err;
+
+       /* update XDP supported features */
+       mlx5e_set_xdp_feature(netdev);
+
+       return 0;
 }
 
 static int set_pflag_rx_no_csum_complete(struct net_device *netdev, bool enable)
index 76a9c5194a7046a6867414d9240ae9dbc97db68f..7ca7e9b57607fdfa2484cf374d5b2cfa7f731bf3 100644 (file)
@@ -4004,6 +4004,25 @@ static int mlx5e_handle_feature(struct net_device *netdev,
        return 0;
 }
 
+void mlx5e_set_xdp_feature(struct net_device *netdev)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_params *params = &priv->channels.params;
+       xdp_features_t val;
+
+       if (params->packet_merge.type != MLX5E_PACKET_MERGE_NONE) {
+               xdp_clear_features_flag(netdev);
+               return;
+       }
+
+       val = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+             NETDEV_XDP_ACT_XSK_ZEROCOPY |
+             NETDEV_XDP_ACT_NDO_XMIT;
+       if (params->rq_wq_type == MLX5_WQ_TYPE_CYCLIC)
+               val |= NETDEV_XDP_ACT_RX_SG;
+       xdp_set_features_flag(netdev, val);
+}
+
 int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
 {
        netdev_features_t oper_features = features;
@@ -4030,6 +4049,9 @@ int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
                return -EINVAL;
        }
 
+       /* update XDP supported features */
+       mlx5e_set_xdp_feature(netdev);
+
        return 0;
 }
 
@@ -4128,8 +4150,12 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
                }
        }
 
-       if (mlx5e_is_uplink_rep(priv))
+       if (mlx5e_is_uplink_rep(priv)) {
                features = mlx5e_fix_uplink_rep_features(netdev, features);
+               features |= NETIF_F_NETNS_LOCAL;
+       } else {
+               features &= ~NETIF_F_NETNS_LOCAL;
+       }
 
        mutex_unlock(&priv->state_lock);
 
@@ -4147,13 +4173,17 @@ static bool mlx5e_xsk_validate_mtu(struct net_device *netdev,
                struct xsk_buff_pool *xsk_pool =
                        mlx5e_xsk_get_pool(&chs->params, chs->params.xsk, ix);
                struct mlx5e_xsk_param xsk;
+               int max_xdp_mtu;
 
                if (!xsk_pool)
                        continue;
 
                mlx5e_build_xsk_param(xsk_pool, &xsk);
+               max_xdp_mtu = mlx5e_xdp_max_mtu(new_params, &xsk);
 
-               if (!mlx5e_validate_xsk_param(new_params, &xsk, mdev)) {
+               /* Validate XSK params and XDP MTU in advance */
+               if (!mlx5e_validate_xsk_param(new_params, &xsk, mdev) ||
+                   new_params->sw_mtu > max_xdp_mtu) {
                        u32 hr = mlx5e_get_linear_rq_headroom(new_params, &xsk);
                        int max_mtu_frame, max_mtu_page, max_mtu;
 
@@ -4163,9 +4193,9 @@ static bool mlx5e_xsk_validate_mtu(struct net_device *netdev,
                         */
                        max_mtu_frame = MLX5E_HW2SW_MTU(new_params, xsk.chunk_size - hr);
                        max_mtu_page = MLX5E_HW2SW_MTU(new_params, SKB_MAX_HEAD(0));
-                       max_mtu = min(max_mtu_frame, max_mtu_page);
+                       max_mtu = min3(max_mtu_frame, max_mtu_page, max_xdp_mtu);
 
-                       netdev_err(netdev, "MTU %d is too big for an XSK running on channel %u. Try MTU <= %d\n",
+                       netdev_err(netdev, "MTU %d is too big for an XSK running on channel %u or its redirection XDP program. Try MTU <= %d\n",
                                   new_params->sw_mtu, ix, max_mtu);
                        return false;
                }
@@ -4761,13 +4791,6 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
        if (old_prog)
                bpf_prog_put(old_prog);
 
-       if (reset) {
-               if (prog)
-                       xdp_features_set_redirect_target(netdev, true);
-               else
-                       xdp_features_clear_redirect_target(netdev);
-       }
-
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state) || reset)
                goto unlock;
 
@@ -4964,8 +4987,6 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
        /* TX inline */
        mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
 
-       params->tunneled_offload_en = mlx5_tunnel_inner_ft_supported(mdev);
-
        /* AF_XDP */
        params->xsk = xsk;
 
@@ -5163,13 +5184,10 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
        netdev->features         |= NETIF_F_HIGHDMA;
        netdev->features         |= NETIF_F_HW_VLAN_STAG_FILTER;
 
-       netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                              NETDEV_XDP_ACT_XSK_ZEROCOPY |
-                              NETDEV_XDP_ACT_RX_SG;
-
        netdev->priv_flags       |= IFF_UNICAST_FLT;
 
        netif_set_tso_max_size(netdev, GSO_MAX_SIZE);
+       mlx5e_set_xdp_feature(netdev);
        mlx5e_set_netdev_dev_addr(netdev);
        mlx5e_macsec_build_netdev(priv);
        mlx5e_ipsec_build_netdev(priv);
@@ -5241,6 +5259,9 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev,
                mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
 
        mlx5e_health_create_reporters(priv);
+       /* update XDP supported features */
+       mlx5e_set_xdp_feature(netdev);
+
        return 0;
 }
 
@@ -5270,7 +5291,7 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
        }
 
        features = MLX5E_RX_RES_FEATURE_PTP;
-       if (priv->channels.params.tunneled_offload_en)
+       if (mlx5_tunnel_inner_ft_supported(mdev))
                features |= MLX5E_RX_RES_FEATURE_INNER_FT;
        err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, features,
                                priv->max_nch, priv->drop_rq.rqn,
index 9b92034430854759bc1d50c002c1b3810c99a542..8ff654b4e9e14101a5e0e65e0e6a32e22c48431a 100644 (file)
@@ -747,12 +747,14 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
        /* RQ */
        mlx5e_build_rq_params(mdev, params);
 
+       /* update XDP supported features */
+       mlx5e_set_xdp_feature(netdev);
+
        /* CQ moderation params */
        params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
        mlx5e_set_rx_cq_mode_params(params, cq_period_mode);
 
        params->mqprio.num_tc       = 1;
-       params->tunneled_offload_en = false;
        if (rep->vport != MLX5_VPORT_UPLINK)
                params->vlan_strip_disable = true;
 
index 70b8d2dfa751f92267ebd5b7e094f95d181ca93a..87a2850b32d09baa5d0dc945825f1178118ba975 100644 (file)
@@ -1103,8 +1103,8 @@ static void
 mlx5e_hairpin_params_init(struct mlx5e_hairpin_params *hairpin_params,
                          struct mlx5_core_dev *mdev)
 {
+       u32 link_speed = 0;
        u64 link_speed64;
-       u32 link_speed;
 
        hairpin_params->mdev = mdev;
        /* set hairpin pair per each 50Gbs share of the link */
@@ -3752,7 +3752,7 @@ mlx5e_clone_flow_attr_for_post_act(struct mlx5_flow_attr *attr,
        parse_attr->filter_dev = attr->parse_attr->filter_dev;
        attr2->action = 0;
        attr2->counter = NULL;
-       attr->tc_act_cookies_count = 0;
+       attr2->tc_act_cookies_count = 0;
        attr2->flags = 0;
        attr2->parse_attr = parse_attr;
        attr2->dest_chain = 0;
@@ -4304,6 +4304,7 @@ int mlx5e_set_fwd_to_int_port_actions(struct mlx5e_priv *priv,
 
        esw_attr->dest_int_port = dest_int_port;
        esw_attr->dests[out_index].flags |= MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE;
+       esw_attr->split_count = out_index;
 
        /* Forward to root fdb for matching against the new source vport */
        attr->dest_chain = 0;
@@ -5304,8 +5305,10 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
        mlx5e_tc_debugfs_init(tc, mlx5e_fs_get_debugfs_root(priv->fs));
 
        tc->action_stats_handle = mlx5e_tc_act_stats_create();
-       if (IS_ERR(tc->action_stats_handle))
+       if (IS_ERR(tc->action_stats_handle)) {
+               err = PTR_ERR(tc->action_stats_handle);
                goto err_act_stats;
+       }
 
        return 0;
 
@@ -5440,8 +5443,10 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv)
        }
 
        uplink_priv->action_stats_handle = mlx5e_tc_act_stats_create();
-       if (IS_ERR(uplink_priv->action_stats_handle))
+       if (IS_ERR(uplink_priv->action_stats_handle)) {
+               err = PTR_ERR(uplink_priv->action_stats_handle);
                goto err_action_counter;
+       }
 
        return 0;
 
@@ -5463,6 +5468,16 @@ err_tun_mapping:
 
 void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv)
 {
+       struct mlx5e_rep_priv *rpriv;
+       struct mlx5_eswitch *esw;
+       struct mlx5e_priv *priv;
+
+       rpriv = container_of(uplink_priv, struct mlx5e_rep_priv, uplink_priv);
+       priv = netdev_priv(rpriv->netdev);
+       esw = priv->mdev->priv.eswitch;
+
+       mlx5e_tc_clean_fdb_peer_flows(esw);
+
        mlx5e_tc_tun_cleanup(uplink_priv->encap);
 
        mapping_destroy(uplink_priv->tunnel_enc_opts_mapping);
index d55775627a473a698638b2b2fff4e0c7e55a195b..50d2ea32397982884bb6618d1b1da53bf7ca53d5 100644 (file)
@@ -364,8 +364,7 @@ int mlx5_esw_acl_ingress_vport_metadata_update(struct mlx5_eswitch *esw, u16 vpo
 
        if (WARN_ON_ONCE(IS_ERR(vport))) {
                esw_warn(esw->dev, "vport(%d) invalid!\n", vport_num);
-               err = PTR_ERR(vport);
-               goto out;
+               return PTR_ERR(vport);
        }
 
        esw_acl_ingress_ofld_rules_destroy(esw, vport);
index 0f052513fefa104d882355dece4fdbb264d8277d..19fed514fc1734fb2fb44d4000c782b6cbe55879 100644 (file)
@@ -959,6 +959,7 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num)
         */
        esw_vport_change_handle_locked(vport);
        vport->enabled_events = 0;
+       esw_apply_vport_rx_mode(esw, vport, false, false);
        esw_vport_cleanup(esw, vport);
        esw->enabled_vports--;
 
@@ -1487,7 +1488,7 @@ int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *
        void *hca_caps;
        int err;
 
-       if (!mlx5_core_is_ecpf(dev) || mlx5_core_is_management_pf(dev)) {
+       if (!mlx5_core_is_ecpf(dev)) {
                *max_sfs = 0;
                return 0;
        }
index d766a64b18234ea810e1e268991fedfb2d5cbbe3..25a8076a77bff081900591d1748773983018594d 100644 (file)
@@ -723,11 +723,11 @@ mlx5_eswitch_add_fwd_rule(struct mlx5_eswitch *esw,
 
        flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
        for (i = 0; i < esw_attr->split_count; i++) {
-               if (esw_is_indir_table(esw, attr))
-                       err = esw_setup_indir_table(dest, &flow_act, esw, attr, false, &i);
-               else if (esw_is_chain_src_port_rewrite(esw, esw_attr))
-                       err = esw_setup_chain_src_port_rewrite(dest, &flow_act, esw, chains, attr,
-                                                              &i);
+               if (esw_attr->dests[i].flags & MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)
+                       /* Source port rewrite (forward to ovs internal port or statck device) isn't
+                        * supported in the rule of split action.
+                        */
+                       err = -EOPNOTSUPP;
                else
                        esw_setup_vport_dest(dest, &flow_act, esw, esw_attr, i, i, false);
 
@@ -3405,6 +3405,18 @@ static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
        return 0;
 }
 
+static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink)
+{
+       struct net *devl_net, *netdev_net;
+       struct mlx5_eswitch *esw;
+
+       esw = mlx5_devlink_eswitch_get(devlink);
+       netdev_net = dev_net(esw->dev->mlx5e_res.uplink_netdev);
+       devl_net = devlink_net(devlink);
+
+       return net_eq(devl_net, netdev_net);
+}
+
 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
                                  struct netlink_ext_ack *extack)
 {
@@ -3419,6 +3431,13 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
        if (esw_mode_from_devlink(mode, &mlx5_mode))
                return -EINVAL;
 
+       if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV &&
+           !esw_offloads_devlink_ns_eq_netdev_ns(devlink)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Can't change E-Switch mode to switchdev when netdev net namespace has diverged from the devlink's.");
+               return -EPERM;
+       }
+
        mlx5_lag_disable_change(esw->dev);
        err = mlx5_esw_try_lock(esw);
        if (err < 0) {
index c2a4f86bc8909526703840ff8566e2d7a74a0971..baa7ef812313996be093323cb1465af85ef8a5f1 100644 (file)
@@ -70,7 +70,6 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev,
 
        params->packet_merge.type = MLX5E_PACKET_MERGE_NONE;
        params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN;
-       params->tunneled_offload_en = false;
 
        /* CQE compression is not supported for IPoIB */
        params->rx_cqe_compress_def = false;
index 540840e80493b083e9d784caa40ef78df4b4f731..f1de152a61135844f291af44a69d04df60a96bb6 100644 (file)
@@ -1364,8 +1364,8 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
 {
        mlx5_devlink_traps_unregister(priv_to_devlink(dev));
        mlx5_sf_dev_table_destroy(dev);
-       mlx5_sriov_detach(dev);
        mlx5_eswitch_disable(dev->priv.eswitch);
+       mlx5_sriov_detach(dev);
        mlx5_lag_remove_mdev(dev);
        mlx5_ec_cleanup(dev);
        mlx5_sf_hw_table_destroy(dev);
@@ -1789,11 +1789,11 @@ static void remove_one(struct pci_dev *pdev)
        struct mlx5_core_dev *dev  = pci_get_drvdata(pdev);
        struct devlink *devlink = priv_to_devlink(dev);
 
+       set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
        /* mlx5_drain_fw_reset() is using devlink APIs. Hence, we must drain
         * fw_reset before unregistering the devlink.
         */
        mlx5_drain_fw_reset(dev);
-       set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
        devlink_unregister(devlink);
        mlx5_sriov_disable(pdev);
        mlx5_crdump_disable(dev);
index 64d4e7125e9bb5e1da1246a8af27a2bab1bb0f4b..95dc67fb300157aa8071d40ce667d0e43dd1b7af 100644 (file)
@@ -82,6 +82,16 @@ static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_funct
        return func_id <= mlx5_core_max_vfs(dev) ?  MLX5_VF : MLX5_SF;
 }
 
+static u32 mlx5_get_ec_function(u32 function)
+{
+       return function >> 16;
+}
+
+static u32 mlx5_get_func_id(u32 function)
+{
+       return function & 0xffff;
+}
+
 static struct rb_root *page_root_per_function(struct mlx5_core_dev *dev, u32 function)
 {
        struct rb_root *root;
@@ -665,20 +675,22 @@ static int optimal_reclaimed_pages(void)
 }
 
 static int mlx5_reclaim_root_pages(struct mlx5_core_dev *dev,
-                                  struct rb_root *root, u16 func_id)
+                                  struct rb_root *root, u32 function)
 {
        u64 recl_pages_to_jiffies = msecs_to_jiffies(mlx5_tout_ms(dev, RECLAIM_PAGES));
        unsigned long end = jiffies + recl_pages_to_jiffies;
 
        while (!RB_EMPTY_ROOT(root)) {
+               u32 ec_function = mlx5_get_ec_function(function);
+               u32 function_id = mlx5_get_func_id(function);
                int nclaimed;
                int err;
 
-               err = reclaim_pages(dev, func_id, optimal_reclaimed_pages(),
-                                   &nclaimed, false, mlx5_core_is_ecpf(dev));
+               err = reclaim_pages(dev, function_id, optimal_reclaimed_pages(),
+                                   &nclaimed, false, ec_function);
                if (err) {
-                       mlx5_core_warn(dev, "failed reclaiming pages (%d) for func id 0x%x\n",
-                                      err, func_id);
+                       mlx5_core_warn(dev, "reclaim_pages err (%d) func_id=0x%x ec_func=0x%x\n",
+                                      err, function_id, ec_function);
                        return err;
                }
 
index 017d68f1e1232c394aa4b2ac209300256fbbab51..972c571b41587a14518b71d8bacce2172f82a081 100644 (file)
@@ -31,6 +31,8 @@ mlxfw_mfa2_tlv_next(const struct mlxfw_mfa2_file *mfa2_file,
 
        if (tlv->type == MLXFW_MFA2_TLV_MULTI_PART) {
                multi = mlxfw_mfa2_tlv_multi_get(mfa2_file, tlv);
+               if (!multi)
+                       return NULL;
                tlv_len = NLA_ALIGN(tlv_len + be16_to_cpu(multi->total_len));
        }
 
index c5240d38c9dbd83ca87f4b8802144cb7ed4a2018..09ed6e5fa6c34e6db76d160d36cb5df28b67ac8d 100644 (file)
@@ -105,7 +105,6 @@ struct mlxsw_thermal {
        struct thermal_zone_device *tzdev;
        int polling_delay;
        struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
-       u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1];
        struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
        struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS];
        struct mlxsw_thermal_area line_cards[];
@@ -468,7 +467,7 @@ static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
                return idx;
 
        /* Normalize the state to the valid speed range. */
-       state = thermal->cooling_levels[state];
+       state = max_t(unsigned long, MLXSW_THERMAL_MIN_STATE, state);
        mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
        err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
        if (err) {
@@ -859,10 +858,6 @@ int mlxsw_thermal_init(struct mlxsw_core *core,
                }
        }
 
-       /* Initialize cooling levels per PWM state. */
-       for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
-               thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
-
        thermal->polling_delay = bus_info->low_frequency ?
                                 MLXSW_THERMAL_SLOW_POLL_INT :
                                 MLXSW_THERMAL_POLL_INT;
index 48dbfea0a2a1d5db3fea9050fe55f5ade0efce69..7cdf0ce24f288cf0fc867d463ee924007f0242ba 100644 (file)
@@ -26,7 +26,7 @@
 #define MLXSW_PCI_CIR_TIMEOUT_MSECS            1000
 
 #define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       900000
-#define MLXSW_PCI_SW_RESET_WAIT_MSECS          200
+#define MLXSW_PCI_SW_RESET_WAIT_MSECS          400
 #define MLXSW_PCI_FW_READY                     0xA1844
 #define MLXSW_PCI_FW_READY_MASK                        0xFFFF
 #define MLXSW_PCI_FW_READY_MAGIC               0x5E
index a8f94b7544eeab04c8c53d74337245f7e6ebaf17..02a327744a61b6c84319b7d79804966e612e7dcc 100644 (file)
@@ -2937,6 +2937,7 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
 
 static void mlxsw_sp_parsing_init(struct mlxsw_sp *mlxsw_sp)
 {
+       refcount_set(&mlxsw_sp->parsing.parsing_depth_ref, 0);
        mlxsw_sp->parsing.parsing_depth = MLXSW_SP_DEFAULT_PARSING_DEPTH;
        mlxsw_sp->parsing.vxlan_udp_dport = MLXSW_SP_DEFAULT_VXLAN_UDP_DPORT;
        mutex_init(&mlxsw_sp->parsing.lock);
@@ -2945,6 +2946,7 @@ static void mlxsw_sp_parsing_init(struct mlxsw_sp *mlxsw_sp)
 static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp)
 {
        mutex_destroy(&mlxsw_sp->parsing.lock);
+       WARN_ON_ONCE(refcount_read(&mlxsw_sp->parsing.parsing_depth_ref));
 }
 
 struct mlxsw_sp_ipv6_addr_node {
index 045a24cacfa517e5ef79add5528876e2da93a8dd..b6ee2d658b0c43970a921e8cb73519fc9d046b16 100644 (file)
@@ -1354,7 +1354,7 @@ static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid,
                                           u16 vid)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       u8 local_port = mlxsw_sp_port->local_port;
+       u16 local_port = mlxsw_sp_port->local_port;
        int err;
 
        /* In case there are no {Port, VID} => FID mappings on the port,
@@ -1391,7 +1391,7 @@ mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid,
                                  struct mlxsw_sp_port *mlxsw_sp_port, u16 vid)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-       u8 local_port = mlxsw_sp_port->local_port;
+       u16 local_port = mlxsw_sp_port->local_port;
 
        mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
        mlxsw_sp_fid_evid_map(fid, local_port, vid, false);
index 09e32778b012d18c4a15de40b025dbbd901abf8c..4a73e2fe95ef90422ea4bf7efaf7fd05942bd1ac 100644 (file)
@@ -10381,11 +10381,23 @@ err_reg_write:
                                              old_inc_parsing_depth);
        return err;
 }
+
+static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp)
+{
+       bool old_inc_parsing_depth = mlxsw_sp->router->inc_parsing_depth;
+
+       mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp, old_inc_parsing_depth,
+                                             false);
+}
 #else
 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
 {
        return 0;
 }
+
+static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp)
+{
+}
 #endif
 
 static int mlxsw_sp_dscp_init(struct mlxsw_sp *mlxsw_sp)
@@ -10615,6 +10627,7 @@ err_register_inet6addr_notifier:
 err_register_inetaddr_notifier:
        mlxsw_core_flush_owq();
 err_dscp_init:
+       mlxsw_sp_mp_hash_fini(mlxsw_sp);
 err_mp_hash_init:
        mlxsw_sp_neigh_fini(mlxsw_sp);
 err_neigh_init:
@@ -10655,6 +10668,7 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
        unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb);
        unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb);
        mlxsw_core_flush_owq();
+       mlxsw_sp_mp_hash_fini(mlxsw_sp);
        mlxsw_sp_neigh_fini(mlxsw_sp);
        mlxsw_sp_lb_rif_fini(mlxsw_sp);
        mlxsw_sp_vrs_fini(mlxsw_sp);
index bdb893476832bd6da6032f23742be033fa741f52..d0e6cd8dbe5c94c666823be41f670bd8bc02c827 100644 (file)
@@ -258,6 +258,7 @@ struct ocelot_stat_layout {
 struct ocelot_stats_region {
        struct list_head node;
        u32 base;
+       enum ocelot_stat first_stat;
        int count;
        u32 *buf;
 };
@@ -273,6 +274,7 @@ static const struct ocelot_stat_layout ocelot_mm_stats_layout[OCELOT_NUM_STATS]
        OCELOT_STAT(RX_ASSEMBLY_OK),
        OCELOT_STAT(RX_MERGE_FRAGMENTS),
        OCELOT_STAT(TX_MERGE_FRAGMENTS),
+       OCELOT_STAT(TX_MM_HOLD),
        OCELOT_STAT(RX_PMAC_OCTETS),
        OCELOT_STAT(RX_PMAC_UNICAST),
        OCELOT_STAT(RX_PMAC_MULTICAST),
@@ -341,11 +343,12 @@ static int ocelot_port_update_stats(struct ocelot *ocelot, int port)
  */
 static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
 {
-       unsigned int idx = port * OCELOT_NUM_STATS;
        struct ocelot_stats_region *region;
        int j;
 
        list_for_each_entry(region, &ocelot->stats_regions, node) {
+               unsigned int idx = port * OCELOT_NUM_STATS + region->first_stat;
+
                for (j = 0; j < region->count; j++) {
                        u64 *stat = &ocelot->stats[idx + j];
                        u64 val = region->buf[j];
@@ -355,8 +358,6 @@ static void ocelot_port_transfer_stats(struct ocelot *ocelot, int port)
 
                        *stat = (*stat & ~(u64)U32_MAX) + val;
                }
-
-               idx += region->count;
        }
 }
 
@@ -899,7 +900,8 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
                if (!layout[i].reg)
                        continue;
 
-               if (region && layout[i].reg == last + 4) {
+               if (region && ocelot->map[SYS][layout[i].reg & REG_MASK] ==
+                   ocelot->map[SYS][last & REG_MASK] + 4) {
                        region->count++;
                } else {
                        region = devm_kzalloc(ocelot->dev, sizeof(*region),
@@ -914,6 +916,7 @@ static int ocelot_prepare_stats_regions(struct ocelot *ocelot)
                        WARN_ON(last >= layout[i].reg);
 
                        region->base = layout[i].reg;
+                       region->first_stat = i;
                        region->count = 1;
                        list_add_tail(&region->node, &ocelot->stats_regions);
                }
index d17d1b4f2585fed3e16ab0208a441a3aaf5bc025..825356ee3492ec62375f85255009bb51a04317ce 100644 (file)
@@ -292,7 +292,7 @@ static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
         */
 
        laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
-       if (!laddr) {
+       if (dma_mapping_error(lp->device, laddr)) {
                pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
@@ -509,7 +509,7 @@ static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp,
 
        *new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE),
                                   SONIC_RBSIZE, DMA_FROM_DEVICE);
-       if (!*new_addr) {
+       if (dma_mapping_error(lp->device, *new_addr)) {
                dev_kfree_skb(*new_skb);
                *new_skb = NULL;
                return false;
index d61cd32ec3b6575d15b399de16d222314f794c55..86a93cac26470d9ae9feff3cf70006123892ea1e 100644 (file)
@@ -5083,6 +5083,11 @@ static int qed_init_wfq_param(struct qed_hwfn *p_hwfn,
 
        num_vports = p_hwfn->qm_info.num_vports;
 
+       if (num_vports < 2) {
+               DP_NOTICE(p_hwfn, "Unexpected num_vports: %d\n", num_vports);
+               return -EINVAL;
+       }
+
        /* Accounting for the vports which are configured for WFQ explicitly */
        for (i = 0; i < num_vports; i++) {
                u32 tmp_speed;
index 6190adf965bcab448a81a474d4faec0f6bb4eaa5..f55eed092f25d293a6ed567a3c93ad7da1af3429 100644 (file)
@@ -422,7 +422,7 @@ qed_mfw_get_tlv_time_value(struct qed_mfw_tlv_time *p_time,
        if (p_time->hour > 23)
                p_time->hour = 0;
        if (p_time->min > 59)
-               p_time->hour = 0;
+               p_time->min = 0;
        if (p_time->msec > 999)
                p_time->msec = 0;
        if (p_time->usec > 999)
index 2bf18748581d3d155775a0bc23c0ec2fd32c6f98..fa167b1aa01909a84719d3fe126d49648566a225 100644 (file)
@@ -4404,6 +4404,9 @@ qed_iov_configure_min_tx_rate(struct qed_dev *cdev, int vfid, u32 rate)
        }
 
        vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true);
+       if (!vf)
+               return -EINVAL;
+
        vport_id = vf->vport_id;
 
        return qed_configure_vport_wfq(cdev, vport_id, rate);
@@ -5152,7 +5155,7 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
 
                /* Validate that the VF has a configured vport */
                vf = qed_iov_get_vf_info(hwfn, i, true);
-               if (!vf->vport_instance)
+               if (!vf || !vf->vport_instance)
                        continue;
 
                memset(&params, 0, sizeof(params));
index 87f76bac2e463af4162eefb6eec6c39ac4add088..eb827b86ecae8130a0565cd75db3a729991c3a42 100644 (file)
@@ -628,7 +628,13 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
        int i, err, ring;
 
        if (dev->flags & QLCNIC_NEED_FLR) {
-               pci_reset_function(dev->pdev);
+               err = pci_reset_function(dev->pdev);
+               if (err) {
+                       dev_err(&dev->pdev->dev,
+                               "Adapter reset failed (%d). Please reboot\n",
+                               err);
+                       return err;
+               }
                dev->flags &= ~QLCNIC_NEED_FLR;
        }
 
index 3115b2c128980db23bf85851fa9724a5359f0509..eaa50050aa0b798a4ab1cfa201a388d32f88b527 100644 (file)
@@ -724,9 +724,15 @@ static int emac_remove(struct platform_device *pdev)
        struct net_device *netdev = dev_get_drvdata(&pdev->dev);
        struct emac_adapter *adpt = netdev_priv(netdev);
 
+       netif_carrier_off(netdev);
+       netif_tx_disable(netdev);
+
        unregister_netdev(netdev);
        netif_napi_del(&adpt->rx_q.napi);
 
+       free_irq(adpt->irq.irq, &adpt->irq);
+       cancel_work_sync(&adpt->work_thread);
+
        emac_clks_teardown(adpt);
 
        put_device(&adpt->phydev->mdio.dev);
index 930496cd34ed00c61d4b37d11b9008d777fe0609..b50f16786c246abbe25553103ae699f7e5f10592 100644 (file)
@@ -826,6 +826,9 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp,
        /* disable phy pfm mode */
        phy_modify_paged(phydev, 0x0a44, 0x11, BIT(7), 0);
 
+       /* disable 10m pll off */
+       phy_modify_paged(phydev, 0x0a43, 0x10, BIT(0), 0);
+
        rtl8168g_disable_aldps(phydev);
        rtl8168g_config_eee_phy(phydev);
 }
index 0f54849a38235fe7e564f7fe870d501201f6fbc5..894e2690c64372a2beb3ab13907722e823b3ffef 100644 (file)
@@ -1455,8 +1455,6 @@ static int ravb_phy_init(struct net_device *ndev)
                phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
        }
 
-       /* Indicate that the MAC is responsible for managing PHY PM */
-       phydev->mac_managed_pm = true;
        phy_attached_info(phydev);
 
        return 0;
@@ -2379,6 +2377,8 @@ static int ravb_mdio_init(struct ravb_private *priv)
 {
        struct platform_device *pdev = priv->pdev;
        struct device *dev = &pdev->dev;
+       struct phy_device *phydev;
+       struct device_node *pn;
        int error;
 
        /* Bitbang init */
@@ -2400,6 +2400,14 @@ static int ravb_mdio_init(struct ravb_private *priv)
        if (error)
                goto out_free_bus;
 
+       pn = of_parse_phandle(dev->of_node, "phy-handle", 0);
+       phydev = of_phy_find_device(pn);
+       if (phydev) {
+               phydev->mac_managed_pm = true;
+               put_device(&phydev->mdio.dev);
+       }
+       of_node_put(pn);
+
        return 0;
 
 out_free_bus:
index 853394e5bb8b9834959003ec23e014d960930f84..c4f93d24c6a4231589ed390dcaf862fb22314eba 100644 (file)
@@ -702,13 +702,14 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
        u16 pkt_len;
        u32 get_ts;
 
+       if (*quota <= 0)
+               return true;
+
        boguscnt = min_t(int, gq->ring_size, *quota);
        limit = boguscnt;
 
        desc = &gq->rx_ring[gq->cur];
        while ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY) {
-               if (--boguscnt < 0)
-                       break;
                dma_rmb();
                pkt_len = le16_to_cpu(desc->desc.info_ds) & RX_DS;
                skb = gq->skbs[gq->cur];
@@ -734,6 +735,9 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
 
                gq->cur = rswitch_next_queue_index(gq, true, 1);
                desc = &gq->rx_ring[gq->cur];
+
+               if (--boguscnt <= 0)
+                       break;
        }
 
        num = rswitch_get_num_cur_queues(gq);
@@ -745,7 +749,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota)
                goto err;
        gq->dirty = rswitch_next_queue_index(gq, false, num);
 
-       *quota -= limit - (++boguscnt);
+       *quota -= limit - boguscnt;
 
        return boguscnt <= 0;
 
@@ -1437,7 +1441,10 @@ static int rswitch_open(struct net_device *ndev)
        rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, true);
        rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, true);
 
-       iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
+       if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
+               iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
+
+       bitmap_set(rdev->priv->opened_ports, rdev->port, 1);
 
        return 0;
 };
@@ -1448,8 +1455,10 @@ static int rswitch_stop(struct net_device *ndev)
        struct rswitch_gwca_ts_info *ts_info, *ts_info2;
 
        netif_tx_stop_all_queues(ndev);
+       bitmap_clear(rdev->priv->opened_ports, rdev->port, 1);
 
-       iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
+       if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
+               iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
 
        list_for_each_entry_safe(ts_info, ts_info2, &rdev->priv->gwca.ts_info_list, list) {
                if (ts_info->port != rdev->port)
index 27d3d38c055f0643897e2756d5fb4ca6618bd6b6..b3e0411b408ef887b72c2ad0f343273a1f085178 100644 (file)
@@ -998,6 +998,7 @@ struct rswitch_private {
        struct rcar_gen4_ptp_private *ptp_priv;
 
        struct rswitch_device *rdev[RSWITCH_NUM_PORTS];
+       DECLARE_BITMAP(opened_ports, RSWITCH_NUM_PORTS);
 
        struct rswitch_gwca gwca;
        struct rswitch_etha etha[RSWITCH_NUM_PORTS];
index ed17163d781144f7d41aca9a356f66e4f6ca3879..d8ec729825be44fe5735eb0333100ef0eebab260 100644 (file)
@@ -2029,8 +2029,6 @@ static int sh_eth_phy_init(struct net_device *ndev)
        if (mdp->cd->register_type != SH_ETH_REG_GIGABIT)
                phy_set_max_speed(phydev, SPEED_100);
 
-       /* Indicate that the MAC is responsible for managing PHY PM */
-       phydev->mac_managed_pm = true;
        phy_attached_info(phydev);
 
        return 0;
@@ -3097,6 +3095,8 @@ static int sh_mdio_init(struct sh_eth_private *mdp,
        struct bb_info *bitbang;
        struct platform_device *pdev = mdp->pdev;
        struct device *dev = &mdp->pdev->dev;
+       struct phy_device *phydev;
+       struct device_node *pn;
 
        /* create bit control struct for PHY */
        bitbang = devm_kzalloc(dev, sizeof(struct bb_info), GFP_KERNEL);
@@ -3133,6 +3133,14 @@ static int sh_mdio_init(struct sh_eth_private *mdp,
        if (ret)
                goto out_free_bus;
 
+       pn = of_parse_phandle(dev->of_node, "phy-handle", 0);
+       phydev = of_phy_find_device(pn);
+       if (phydev) {
+               phydev->mac_managed_pm = true;
+               put_device(&phydev->mdio.dev);
+       }
+       of_node_put(pn);
+
        return 0;
 
 out_free_bus:
index 7022fb2005a2f6214ea07c6fecf83efdc7697c6f..d30459dbfe8f838e7677d26038824484353f5eff 100644 (file)
@@ -1304,7 +1304,8 @@ static void efx_ef10_fini_nic(struct efx_nic *efx)
 static int efx_ef10_init_nic(struct efx_nic *efx)
 {
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
-       netdev_features_t hw_enc_features = 0;
+       struct net_device *net_dev = efx->net_dev;
+       netdev_features_t tun_feats, tso_feats;
        int rc;
 
        if (nic_data->must_check_datapath_caps) {
@@ -1349,20 +1350,30 @@ static int efx_ef10_init_nic(struct efx_nic *efx)
                nic_data->must_restore_piobufs = false;
        }
 
-       /* add encapsulated checksum offload features */
+       /* encap features might change during reset if fw variant changed */
        if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
-               hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
-       /* add encapsulated TSO features */
-       if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) {
-               netdev_features_t encap_tso_features;
+               net_dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+       else
+               net_dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
 
-               encap_tso_features = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
-                       NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM;
+       tun_feats = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
+                   NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM;
+       tso_feats = NETIF_F_TSO | NETIF_F_TSO6;
 
-               hw_enc_features |= encap_tso_features | NETIF_F_TSO;
-               efx->net_dev->features |= encap_tso_features;
+       if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) {
+               /* If this is first nic_init, or if it is a reset and a new fw
+                * variant has added new features, enable them by default.
+                * If the features are not new, maintain their current value.
+                */
+               if (!(net_dev->hw_features & tun_feats))
+                       net_dev->features |= tun_feats;
+               net_dev->hw_enc_features |= tun_feats | tso_feats;
+               net_dev->hw_features |= tun_feats;
+       } else {
+               net_dev->hw_enc_features &= ~(tun_feats | tso_feats);
+               net_dev->hw_features &= ~tun_feats;
+               net_dev->features &= ~tun_feats;
        }
-       efx->net_dev->hw_enc_features = hw_enc_features;
 
        /* don't fail init if RSS setup doesn't work */
        rc = efx->type->rx_push_rss_config(efx, false,
@@ -4021,7 +4032,10 @@ static unsigned int efx_ef10_recycle_ring_size(const struct efx_nic *efx)
         NETIF_F_HW_VLAN_CTAG_FILTER |  \
         NETIF_F_IPV6_CSUM |            \
         NETIF_F_RXHASH |               \
-        NETIF_F_NTUPLE)
+        NETIF_F_NTUPLE |               \
+        NETIF_F_SG |                   \
+        NETIF_F_RXCSUM |               \
+        NETIF_F_RXALL)
 
 const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
        .is_vf = true,
index 02c2adeb0a12007d2cbf4f5b2349c1051ea578f1..1eceffa02b557a4f271697a7ae36d5a20afc2450 100644 (file)
@@ -541,7 +541,6 @@ int efx_net_open(struct net_device *net_dev)
        else
                efx->state = STATE_NET_UP;
 
-       efx_selftest_async_start(efx);
        return 0;
 }
 
@@ -1001,21 +1000,18 @@ static int efx_pci_probe_post_io(struct efx_nic *efx)
        }
 
        /* Determine netdevice features */
-       net_dev->features |= (efx->type->offload_features | NETIF_F_SG |
-                             NETIF_F_TSO | NETIF_F_RXCSUM | NETIF_F_RXALL);
-       if (efx->type->offload_features & (NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM)) {
-               net_dev->features |= NETIF_F_TSO6;
-               if (efx_has_cap(efx, TX_TSO_V2_ENCAP))
-                       net_dev->hw_enc_features |= NETIF_F_TSO6;
-       }
-       /* Check whether device supports TSO */
-       if (!efx->type->tso_versions || !efx->type->tso_versions(efx))
-               net_dev->features &= ~NETIF_F_ALL_TSO;
+       net_dev->features |= efx->type->offload_features;
+
+       /* Add TSO features */
+       if (efx->type->tso_versions && efx->type->tso_versions(efx))
+               net_dev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+
        /* Mask for features that also apply to VLAN devices */
        net_dev->vlan_features |= (NETIF_F_HW_CSUM | NETIF_F_SG |
                                   NETIF_F_HIGHDMA | NETIF_F_ALL_TSO |
                                   NETIF_F_RXCSUM);
 
+       /* Determine user configurable features */
        net_dev->hw_features |= net_dev->features & ~efx->fixed_features;
 
        /* Disable receiving frames with bad FCS, by default. */
index cc30524c2fe45c9f49857ac6af7d5629166992e2..361687de308dceedce7b68105e32173840d6f9d4 100644 (file)
@@ -544,6 +544,8 @@ void efx_start_all(struct efx_nic *efx)
        /* Start the hardware monitor if there is one */
        efx_start_monitor(efx);
 
+       efx_selftest_async_start(efx);
+
        /* Link state detection is normally event-driven; we have
         * to poll now because we could have missed a change
         */
index a2e511912e6a9f0d1476170f4adbfff5b6a9a07d..a690d139e1770f8b796c1fb72c3fae61639f5ac8 100644 (file)
@@ -1037,8 +1037,6 @@ static int smsc911x_mii_probe(struct net_device *dev)
                return ret;
        }
 
-       /* Indicate that the MAC is responsible for managing PHY PM */
-       phydev->mac_managed_pm = true;
        phy_attached_info(phydev);
 
        phy_set_max_speed(phydev, SPEED_100);
@@ -1066,6 +1064,7 @@ static int smsc911x_mii_init(struct platform_device *pdev,
                             struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
+       struct phy_device *phydev;
        int err = -ENXIO;
 
        pdata->mii_bus = mdiobus_alloc();
@@ -1108,6 +1107,10 @@ static int smsc911x_mii_init(struct platform_device *pdev,
                goto err_out_free_bus_2;
        }
 
+       phydev = phy_find_first(pdata->mii_bus);
+       if (phydev)
+               phydev->mac_managed_pm = true;
+
        return 0;
 
 err_out_free_bus_2:
index 6b5d96bced475f5aac8eab8130988c7451bf6b72..54bb072aeb2d3c39950b96aca0203dc0b367cf95 100644 (file)
@@ -418,6 +418,7 @@ struct dma_features {
        unsigned int frpbs;
        unsigned int frpes;
        unsigned int addr64;
+       unsigned int host_dma_width;
        unsigned int rssen;
        unsigned int vlhash;
        unsigned int sphen;
@@ -531,7 +532,6 @@ struct mac_device_info {
        unsigned int xlgmac;
        unsigned int num_vlan;
        u32 vlan_filter[32];
-       unsigned int promisc;
        bool vlan_fail_q_en;
        u8 vlan_fail_q;
 };
index ac8580f501e2ef07d2db27f5185e8ace9d5cdb3d..2a2be65d65a03c37d1ba182fe42e9efd125b4087 100644 (file)
@@ -213,8 +213,7 @@ imx_dwmac_parse_dt(struct imx_priv_data *dwmac, struct device *dev)
        struct device_node *np = dev->of_node;
        int err = 0;
 
-       if (of_get_property(np, "snps,rmii_refclk_ext", NULL))
-               dwmac->rmii_refclk_ext = true;
+       dwmac->rmii_refclk_ext = of_property_read_bool(np, "snps,rmii_refclk_ext");
 
        dwmac->clk_tx = devm_clk_get(dev, "tx");
        if (IS_ERR(dwmac->clk_tx)) {
@@ -289,7 +288,7 @@ static int imx_dwmac_probe(struct platform_device *pdev)
                goto err_parse_dt;
        }
 
-       plat_dat->addr64 = dwmac->ops->addr_width;
+       plat_dat->host_dma_width = dwmac->ops->addr_width;
        plat_dat->init = imx_dwmac_init;
        plat_dat->exit = imx_dwmac_exit;
        plat_dat->clks_config = imx_dwmac_clks_config;
index 7deb1f817dacc564fb9c4453a4fba3a6fb6c51bd..ab9f876b6df7e901076968187c47919c13e2feb8 100644 (file)
@@ -251,7 +251,6 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
                priv->plat->mdio_bus_data->xpcs_an_inband = false;
        } else {
                priv->plat->max_speed = 1000;
-               priv->plat->mdio_bus_data->xpcs_an_inband = true;
        }
 }
 
@@ -684,7 +683,7 @@ static int ehl_pse0_common_data(struct pci_dev *pdev,
 
        intel_priv->is_pse = true;
        plat->bus_id = 2;
-       plat->addr64 = 32;
+       plat->host_dma_width = 32;
 
        plat->clk_ptp_rate = 200000000;
 
@@ -725,7 +724,7 @@ static int ehl_pse1_common_data(struct pci_dev *pdev,
 
        intel_priv->is_pse = true;
        plat->bus_id = 3;
-       plat->addr64 = 32;
+       plat->host_dma_width = 32;
 
        plat->clk_ptp_rate = 200000000;
 
index 2f7d8e4561d920cf8e2dc7524c6eed9b9dbcbb00..9ae31e3dc82187c8abd6fe3fcaa959d36c84f207 100644 (file)
@@ -591,7 +591,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
        plat->use_phy_wol = priv_plat->mac_wol ? 0 : 1;
        plat->riwt_off = 1;
        plat->maxmtu = ETH_DATA_LEN;
-       plat->addr64 = priv_plat->variant->dma_bit_mask;
+       plat->host_dma_width = priv_plat->variant->dma_bit_mask;
        plat->bsp_priv = priv_plat;
        plat->init = mediatek_dwmac_init;
        plat->clks_config = mediatek_dwmac_clks_config;
index 8c7a0b7c99520ac593285b6a22b669313a4068da..36251ec2589c99d117c78e73129e8c17a99be844 100644 (file)
@@ -472,12 +472,6 @@ static int dwmac4_add_hw_vlan_rx_fltr(struct net_device *dev,
        if (vid > 4095)
                return -EINVAL;
 
-       if (hw->promisc) {
-               netdev_err(dev,
-                          "Adding VLAN in promisc mode not supported\n");
-               return -EPERM;
-       }
-
        /* Single Rx VLAN Filter */
        if (hw->num_vlan == 1) {
                /* For single VLAN filter, VID 0 means VLAN promiscuous */
@@ -527,12 +521,6 @@ static int dwmac4_del_hw_vlan_rx_fltr(struct net_device *dev,
 {
        int i, ret = 0;
 
-       if (hw->promisc) {
-               netdev_err(dev,
-                          "Deleting VLAN in promisc mode not supported\n");
-               return -EPERM;
-       }
-
        /* Single Rx VLAN Filter */
        if (hw->num_vlan == 1) {
                if ((hw->vlan_filter[0] & GMAC_VLAN_TAG_VID) == vid) {
@@ -557,39 +545,6 @@ static int dwmac4_del_hw_vlan_rx_fltr(struct net_device *dev,
        return ret;
 }
 
-static void dwmac4_vlan_promisc_enable(struct net_device *dev,
-                                      struct mac_device_info *hw)
-{
-       void __iomem *ioaddr = hw->pcsr;
-       u32 value;
-       u32 hash;
-       u32 val;
-       int i;
-
-       /* Single Rx VLAN Filter */
-       if (hw->num_vlan == 1) {
-               dwmac4_write_single_vlan(dev, 0);
-               return;
-       }
-
-       /* Extended Rx VLAN Filter Enable */
-       for (i = 0; i < hw->num_vlan; i++) {
-               if (hw->vlan_filter[i] & GMAC_VLAN_TAG_DATA_VEN) {
-                       val = hw->vlan_filter[i] & ~GMAC_VLAN_TAG_DATA_VEN;
-                       dwmac4_write_vlan_filter(dev, hw, i, val);
-               }
-       }
-
-       hash = readl(ioaddr + GMAC_VLAN_HASH_TABLE);
-       if (hash & GMAC_VLAN_VLHT) {
-               value = readl(ioaddr + GMAC_VLAN_TAG);
-               if (value & GMAC_VLAN_VTHM) {
-                       value &= ~GMAC_VLAN_VTHM;
-                       writel(value, ioaddr + GMAC_VLAN_TAG);
-               }
-       }
-}
-
 static void dwmac4_restore_hw_vlan_rx_fltr(struct net_device *dev,
                                           struct mac_device_info *hw)
 {
@@ -709,22 +664,12 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
        }
 
        /* VLAN filtering */
-       if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
+       if (dev->flags & IFF_PROMISC && !hw->vlan_fail_q_en)
+               value &= ~GMAC_PACKET_FILTER_VTFE;
+       else if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
                value |= GMAC_PACKET_FILTER_VTFE;
 
        writel(value, ioaddr + GMAC_PACKET_FILTER);
-
-       if (dev->flags & IFF_PROMISC && !hw->vlan_fail_q_en) {
-               if (!hw->promisc) {
-                       hw->promisc = 1;
-                       dwmac4_vlan_promisc_enable(dev, hw);
-               }
-       } else {
-               if (hw->promisc) {
-                       hw->promisc = 0;
-                       dwmac4_restore_hw_vlan_rx_fltr(dev, hw);
-               }
-       }
 }
 
 static void dwmac4_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
index 8f543c3ab5c564257fa3cca3327383323fd48c24..d7fcab0570322382599f3627e7a26041cfaf311f 100644 (file)
@@ -1134,20 +1134,26 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
 static int stmmac_init_phy(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
+       struct fwnode_handle *phy_fwnode;
        struct fwnode_handle *fwnode;
        int ret;
 
+       if (!phylink_expects_phy(priv->phylink))
+               return 0;
+
        fwnode = of_fwnode_handle(priv->plat->phylink_node);
        if (!fwnode)
                fwnode = dev_fwnode(priv->device);
 
        if (fwnode)
-               ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
+               phy_fwnode = fwnode_get_phy_node(fwnode);
+       else
+               phy_fwnode = NULL;
 
        /* Some DT bindings do not set-up the PHY handle. Let's try to
         * manually parse it
         */
-       if (!fwnode || ret) {
+       if (!phy_fwnode || IS_ERR(phy_fwnode)) {
                int addr = priv->plat->phy_addr;
                struct phy_device *phydev;
 
@@ -1163,6 +1169,9 @@ static int stmmac_init_phy(struct net_device *dev)
                }
 
                ret = phylink_connect_phy(priv->phylink, phydev);
+       } else {
+               fwnode_handle_put(phy_fwnode);
+               ret = phylink_fwnode_phy_connect(priv->phylink, fwnode, 0);
        }
 
        if (!priv->plat->pmt) {
@@ -1431,7 +1440,7 @@ static int stmmac_init_rx_buffers(struct stmmac_priv *priv,
        struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
        gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
 
-       if (priv->dma_cap.addr64 <= 32)
+       if (priv->dma_cap.host_dma_width <= 32)
                gfp |= GFP_DMA32;
 
        if (!buf->page) {
@@ -4587,7 +4596,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
        unsigned int entry = rx_q->dirty_rx;
        gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
 
-       if (priv->dma_cap.addr64 <= 32)
+       if (priv->dma_cap.host_dma_width <= 32)
                gfp |= GFP_DMA32;
 
        while (dirty-- > 0) {
@@ -6205,7 +6214,7 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
        seq_printf(seq, "\tFlexible RX Parser: %s\n",
                   priv->dma_cap.frpsel ? "Y" : "N");
        seq_printf(seq, "\tEnhanced Addressing: %d\n",
-                  priv->dma_cap.addr64);
+                  priv->dma_cap.host_dma_width);
        seq_printf(seq, "\tReceive Side Scaling: %s\n",
                   priv->dma_cap.rssen ? "Y" : "N");
        seq_printf(seq, "\tVLAN Hash Filtering: %s\n",
@@ -6622,6 +6631,8 @@ int stmmac_xdp_open(struct net_device *dev)
                goto init_error;
        }
 
+       stmmac_reset_queues_param(priv);
+
        /* DMA CSR Channel configuration */
        for (chan = 0; chan < dma_csr_ch; chan++) {
                stmmac_init_chan(priv, priv->ioaddr, priv->plat->dma_cfg, chan);
@@ -6948,7 +6959,7 @@ static void stmmac_napi_del(struct net_device *dev)
 int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
-       int ret = 0;
+       int ret = 0, i;
 
        if (netif_running(dev))
                stmmac_release(dev);
@@ -6957,6 +6968,10 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
 
        priv->plat->rx_queues_to_use = rx_cnt;
        priv->plat->tx_queues_to_use = tx_cnt;
+       if (!netif_is_rxfh_configured(dev))
+               for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++)
+                       priv->rss.table[i] = ethtool_rxfh_indir_default(i,
+                                                                       rx_cnt);
 
        stmmac_napi_add(dev);
 
@@ -7178,20 +7193,22 @@ int stmmac_dvr_probe(struct device *device,
                dev_info(priv->device, "SPH feature enabled\n");
        }
 
-       /* The current IP register MAC_HW_Feature1[ADDR64] only define
-        * 32/40/64 bit width, but some SOC support others like i.MX8MP
-        * support 34 bits but it map to 40 bits width in MAC_HW_Feature1[ADDR64].
-        * So overwrite dma_cap.addr64 according to HW real design.
+       /* Ideally our host DMA address width is the same as for the
+        * device. However, it may differ and then we have to use our
+        * host DMA width for allocation and the device DMA width for
+        * register handling.
         */
-       if (priv->plat->addr64)
-               priv->dma_cap.addr64 = priv->plat->addr64;
+       if (priv->plat->host_dma_width)
+               priv->dma_cap.host_dma_width = priv->plat->host_dma_width;
+       else
+               priv->dma_cap.host_dma_width = priv->dma_cap.addr64;
 
-       if (priv->dma_cap.addr64) {
+       if (priv->dma_cap.host_dma_width) {
                ret = dma_set_mask_and_coherent(device,
-                               DMA_BIT_MASK(priv->dma_cap.addr64));
+                               DMA_BIT_MASK(priv->dma_cap.host_dma_width));
                if (!ret) {
-                       dev_info(priv->device, "Using %d bits DMA width\n",
-                                priv->dma_cap.addr64);
+                       dev_info(priv->device, "Using %d/%d bits DMA host/device width\n",
+                                priv->dma_cap.host_dma_width, priv->dma_cap.addr64);
 
                        /*
                         * If more than 32 bits can be addressed, make sure to
@@ -7206,7 +7223,7 @@ int stmmac_dvr_probe(struct device *device,
                                goto error_hw_init;
                        }
 
-                       priv->dma_cap.addr64 = 32;
+                       priv->dma_cap.host_dma_width = 32;
                }
        }
 
index 8addee6d04bd803636c0e14577220332371632c2..734a817d3c945ed5e6c5ff349760508ff6c5c670 100644 (file)
@@ -287,6 +287,9 @@ static int vsw_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 
        hp = mdesc_grab();
 
+       if (!hp)
+               return -ENODEV;
+
        rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
        err = -ENODEV;
        if (!rmac) {
index e6144d963eaaadb3343906fac020b38f1734533f..7a2e767762974cf9dc63d03c17a822630f8783ca 100644 (file)
@@ -4522,7 +4522,7 @@ static int niu_alloc_channels(struct niu *np)
 
                err = niu_rbr_fill(np, rp, GFP_KERNEL);
                if (err)
-                       return err;
+                       goto out_err;
        }
 
        tx_rings = kcalloc(num_tx_rings, sizeof(struct tx_ring_info),
@@ -9271,7 +9271,7 @@ static int niu_get_of_props(struct niu *np)
        if (model)
                strcpy(np->vpd.model, model);
 
-       if (of_find_property(dp, "hot-swappable-phy", NULL)) {
+       if (of_property_read_bool(dp, "hot-swappable-phy")) {
                np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
                        NIU_FLAGS_HOTPLUG_PHY);
        }
index fe86fbd585861c6069533d50c9e8d7f9f0b3a814..e220620d0ffc9070cf07c063a09ccbe1ced18a37 100644 (file)
@@ -433,6 +433,9 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 
        hp = mdesc_grab();
 
+       if (!hp)
+               return -ENODEV;
+
        vp = vnet_find_parent(hp, vdev->mp, vdev);
        if (IS_ERR(vp)) {
                pr_err("Cannot find port parent vnet\n");
index 4e3861c47708c9e2af4d5912a3dc2c7c8e9feb99..bcea87b7151c0b1245fd9c60eccbcf7885852449 100644 (file)
@@ -2926,7 +2926,8 @@ err_free_phylink:
        am65_cpsw_nuss_phylink_cleanup(common);
        am65_cpts_release(common->cpts);
 err_of_clear:
-       of_platform_device_destroy(common->mdio_dev, NULL);
+       if (common->mdio_dev)
+               of_platform_device_destroy(common->mdio_dev, NULL);
 err_pm_clear:
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
@@ -2956,7 +2957,8 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
        am65_cpts_release(common->cpts);
        am65_cpsw_disable_serdes_phy(common);
 
-       of_platform_device_destroy(common->mdio_dev, NULL);
+       if (common->mdio_dev)
+               of_platform_device_destroy(common->mdio_dev, NULL);
 
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
index 16ee9c29cb35a5c77bfc186d7903a70519060b7b..8caf85acbb6af1221a6b4a9d35bb99ac3c0645d5 100644 (file)
@@ -636,6 +636,10 @@ static void am65_cpts_perout_enable_hw(struct am65_cpts *cpts,
                val = lower_32_bits(cycles);
                am65_cpts_write32(cpts, val, genf[req->index].length);
 
+               am65_cpts_write32(cpts, 0, genf[req->index].control);
+               am65_cpts_write32(cpts, 0, genf[req->index].ppm_hi);
+               am65_cpts_write32(cpts, 0, genf[req->index].ppm_low);
+
                cpts->genf_enable |= BIT(req->index);
        } else {
                am65_cpts_write32(cpts, 0, genf[req->index].length);
index e8f38e3f7706eb69e11bf4b82cbba9afbb938b09..25e707d7b87ce320e7b3f68328890ec610d39b6b 100644 (file)
@@ -226,8 +226,7 @@ static int cpsw_phy_sel_probe(struct platform_device *pdev)
        if (IS_ERR(priv->gmii_sel))
                return PTR_ERR(priv->gmii_sel);
 
-       if (of_find_property(pdev->dev.of_node, "rmii-clock-ext", NULL))
-               priv->rmii_clock_external = true;
+       priv->rmii_clock_external = of_property_read_bool(pdev->dev.of_node, "rmii-clock-ext");
 
        dev_set_drvdata(&pdev->dev, priv);
 
index 37f0b62ec5d6a3bc99914fcee1681d9e3ff1bfdb..f9cd566d1c9b588e5cd547ca4109567dc50114e4 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/of.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/if_vlan.h>
 #include <linux/kmemleak.h>
 #include <linux/sys_soc.h>
index 35128dd45ffceb27a6dafea19a2c9d342feb95c1..c61e4e44a78f06ddbd28e94ce65e2af410291fe7 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/platform_device.h>
 #include <linux/timer.h>
 #include <linux/module.h>
 #include <linux/irqreturn.h>
@@ -23,7 +24,7 @@
 #include <linux/of.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
-#include <linux/of_device.h>
+#include <linux/of_platform.h>
 #include <linux/if_vlan.h>
 #include <linux/kmemleak.h>
 #include <linux/sys_soc.h>
index 751fb0bc65c501cb7b4df87c44a453bc10e05c5d..2adf82a32bf6a6b90e4461325c2964fe52eacd0d 100644 (file)
@@ -3583,13 +3583,11 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
        /* init the hw stats lock */
        spin_lock_init(&gbe_dev->hw_stats_lock);
 
-       if (of_find_property(node, "enable-ale", NULL)) {
-               gbe_dev->enable_ale = true;
+       gbe_dev->enable_ale = of_property_read_bool(node, "enable-ale");
+       if (gbe_dev->enable_ale)
                dev_info(dev, "ALE enabled\n");
-       } else {
-               gbe_dev->enable_ale = false;
+       else
                dev_dbg(dev, "ALE bypass enabled*\n");
-       }
 
        ret = of_property_read_u32(node, "tx-queue",
                                   &gbe_dev->tx_queue_id);
index cf8de8a7a8a1eb0ef0c79ebd69daeb6305783ffc..9d535ae5962662106654894dca8bd81b4455e3b5 100644 (file)
@@ -317,15 +317,17 @@ static int gelic_card_init_chain(struct gelic_card *card,
 
        /* set up the hardware pointers in each descriptor */
        for (i = 0; i < no; i++, descr++) {
+               dma_addr_t cpu_addr;
+
                gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE);
-               descr->bus_addr =
-                       dma_map_single(ctodev(card), descr,
-                                      GELIC_DESCR_SIZE,
-                                      DMA_BIDIRECTIONAL);
 
-               if (!descr->bus_addr)
+               cpu_addr = dma_map_single(ctodev(card), descr,
+                                         GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL);
+
+               if (dma_mapping_error(ctodev(card), cpu_addr))
                        goto iommu_error;
 
+               descr->bus_addr = cpu_to_be32(cpu_addr);
                descr->next = descr + 1;
                descr->prev = descr - 1;
        }
@@ -365,26 +367,28 @@ iommu_error:
  *
  * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
  * Activate the descriptor state-wise
+ *
+ * Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length
+ * must be a multiple of GELIC_NET_RXBUF_ALIGN.
  */
 static int gelic_descr_prepare_rx(struct gelic_card *card,
                                  struct gelic_descr *descr)
 {
+       static const unsigned int rx_skb_size =
+               ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) +
+               GELIC_NET_RXBUF_ALIGN - 1;
+       dma_addr_t cpu_addr;
        int offset;
-       unsigned int bufsize;
 
        if (gelic_descr_get_status(descr) !=  GELIC_DESCR_DMA_NOT_IN_USE)
                dev_info(ctodev(card), "%s: ERROR status\n", __func__);
-       /* we need to round up the buffer size to a multiple of 128 */
-       bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
 
-       /* and we need to have it 128 byte aligned, therefore we allocate a
-        * bit more */
-       descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+       descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size);
        if (!descr->skb) {
                descr->buf_addr = 0; /* tell DMAC don't touch memory */
                return -ENOMEM;
        }
-       descr->buf_size = cpu_to_be32(bufsize);
+       descr->buf_size = cpu_to_be32(rx_skb_size);
        descr->dmac_cmd_status = 0;
        descr->result_size = 0;
        descr->valid_size = 0;
@@ -395,11 +399,10 @@ static int gelic_descr_prepare_rx(struct gelic_card *card,
        if (offset)
                skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
        /* io-mmu-map the skb */
-       descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card),
-                                                    descr->skb->data,
-                                                    GELIC_NET_MAX_MTU,
-                                                    DMA_FROM_DEVICE));
-       if (!descr->buf_addr) {
+       cpu_addr = dma_map_single(ctodev(card), descr->skb->data,
+                                 GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE);
+       descr->buf_addr = cpu_to_be32(cpu_addr);
+       if (dma_mapping_error(ctodev(card), cpu_addr)) {
                dev_kfree_skb_any(descr->skb);
                descr->skb = NULL;
                dev_info(ctodev(card),
@@ -779,7 +782,7 @@ static int gelic_descr_prepare_tx(struct gelic_card *card,
 
        buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE);
 
-       if (!buf) {
+       if (dma_mapping_error(ctodev(card), buf)) {
                dev_err(ctodev(card),
                        "dma map 2 failed (%p, %i). Dropping packet\n",
                        skb->data, skb->len);
@@ -915,7 +918,7 @@ static void gelic_net_pass_skb_up(struct gelic_descr *descr,
        data_error = be32_to_cpu(descr->data_error);
        /* unmap skb buffer */
        dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr),
-                        GELIC_NET_MAX_MTU,
+                        GELIC_NET_MAX_FRAME,
                         DMA_FROM_DEVICE);
 
        skb_put(skb, be32_to_cpu(descr->valid_size)?
index 68f324ed4eaf0841072efd46c999455c6c11a8e6..0d98defb011ed7976c88be928f656c634ef3c23f 100644 (file)
@@ -19,8 +19,9 @@
 #define GELIC_NET_RX_DESCRIPTORS        128 /* num of descriptors */
 #define GELIC_NET_TX_DESCRIPTORS        128 /* num of descriptors */
 
-#define GELIC_NET_MAX_MTU               VLAN_ETH_FRAME_LEN
-#define GELIC_NET_MIN_MTU               VLAN_ETH_ZLEN
+#define GELIC_NET_MAX_FRAME             2312
+#define GELIC_NET_MAX_MTU               2294
+#define GELIC_NET_MIN_MTU               64
 #define GELIC_NET_RXBUF_ALIGN           128
 #define GELIC_CARD_RX_CSUM_DEFAULT      1 /* hw chksum */
 #define GELIC_NET_WATCHDOG_TIMEOUT      5*HZ
index a502812ac418a6e26aab5d03a4ead85a0ce38900..86f7843b4591c6a8e48e6225059bd68d76b91da7 100644 (file)
@@ -2709,8 +2709,7 @@ static int velocity_get_platform_info(struct velocity_info *vptr)
        struct resource res;
        int ret;
 
-       if (of_get_property(vptr->dev->of_node, "no-eeprom", NULL))
-               vptr->no_eeprom = 1;
+       vptr->no_eeprom = of_property_read_bool(vptr->dev->of_node, "no-eeprom");
 
        ret = of_address_to_resource(vptr->dev->of_node, 0, &res);
        if (ret) {
index ffdac6fac05499d993debc1fec9f125960b04253..f64ed39b93d8312a5711515243c1408aa2944e46 100644 (file)
@@ -1383,7 +1383,7 @@ struct velocity_info {
        struct device *dev;
        struct pci_dev *pdev;
        struct net_device *netdev;
-       int no_eeprom;
+       bool no_eeprom;
 
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
        u8 ip_addr[4];
index 77d8d7f1707e9678e04869109a728388f221b620..97e2c1e13b8067864f5a6800bca146b1e977b3f1 100644 (file)
 #define WX_PX_INTA                   0x110
 #define WX_PX_GPIE                   0x118
 #define WX_PX_GPIE_MODEL             BIT(0)
-#define WX_PX_IC                     0x120
+#define WX_PX_IC(_i)                 (0x120 + (_i) * 4)
 #define WX_PX_IMS(_i)                (0x140 + (_i) * 4)
 #define WX_PX_IMC(_i)                (0x150 + (_i) * 4)
 #define WX_PX_ISB_ADDR_L             0x160
index 5b564d348c091a9f91346fb4e49c566b922ec4d0..17412e5282dedd094dea634d7a3de0fc1329facf 100644 (file)
@@ -352,7 +352,7 @@ static void ngbe_up(struct wx *wx)
        netif_tx_start_all_queues(wx->netdev);
 
        /* clear any pending interrupts, may auto mask */
-       rd32(wx, WX_PX_IC);
+       rd32(wx, WX_PX_IC(0));
        rd32(wx, WX_PX_MISC_IC);
        ngbe_irq_enable(wx, true);
        if (wx->gpio_ctrl)
index 6c0a982305576997459682b19f4c62936005be70..a58ce5463686a34f37b2b47c1641ea420b55ff58 100644 (file)
@@ -229,7 +229,8 @@ static void txgbe_up_complete(struct wx *wx)
        wx_napi_enable_all(wx);
 
        /* clear any pending interrupts, may auto mask */
-       rd32(wx, WX_PX_IC);
+       rd32(wx, WX_PX_IC(0));
+       rd32(wx, WX_PX_IC(1));
        rd32(wx, WX_PX_MISC_IC);
        txgbe_irq_enable(wx, true);
 
index 1066420d6a83aa55ff6689329b44c0b57ffa37a4..e0ac1bcd9925c2ebfe122ff1faf9a40479a0afdb 100644 (file)
@@ -1455,12 +1455,11 @@ static int temac_probe(struct platform_device *pdev)
         * endianness mode.  Default for OF devices is big-endian.
         */
        little_endian = false;
-       if (temac_np) {
-               if (of_get_property(temac_np, "little-endian", NULL))
-                       little_endian = true;
-       } else if (pdata) {
+       if (temac_np)
+               little_endian = of_property_read_bool(temac_np, "little-endian");
+       else if (pdata)
                little_endian = pdata->reg_little_endian;
-       }
+
        if (little_endian) {
                lp->temac_ior = _temac_ior_le;
                lp->temac_iow = _temac_iow_le;
index 894e92ef415b98b761af99fa917838b0f640e8fb..9f505cf02d9651d63e3c393ad954690f41a595ee 100644 (file)
@@ -503,6 +503,11 @@ static void
 xirc2ps_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
+    struct local_info *local = netdev_priv(dev);
+
+    netif_carrier_off(dev);
+    netif_tx_disable(dev);
+    cancel_work_sync(&local->tx_timeout_task);
 
     dev_dbg(&link->dev, "detach\n");
 
index a9c44f08199d0c5ac160c24c0411cedbfe1926ed..a94c7bd5db2ea3143ca800eff3275d91f76526ac 100644 (file)
@@ -47,7 +47,7 @@ config BPQETHER
 
 config SCC
        tristate "Z8530 SCC driver"
-       depends on ISA && AX25 && ISA_DMA_API
+       depends on ISA && AX25
        help
          These cards are used to connect your Linux box to an amateur radio
          in order to communicate with other computers. If you want to use
index 0b0c6c0764fe9cfab3247917f16a6cb6be93f06e..d0b5129439ed6c02b61f21773ed0bf9e65ea422a 100644 (file)
@@ -1902,10 +1902,9 @@ static int ca8210_skb_tx(
        struct ca8210_priv  *priv
 )
 {
-       int status;
        struct ieee802154_hdr header = { };
        struct secspec secspec;
-       unsigned int mac_len;
+       int mac_len, status;
 
        dev_dbg(&priv->spi->dev, "%s called\n", __func__);
 
index 1412b67304c8e9a12671d84a51c428b2a39660cb..1651fbad4bd54afa42301ba08f5d1bb0c4e01f15 100644 (file)
@@ -15,6 +15,14 @@ static bool gsi_reg_id_valid(struct gsi *gsi, enum gsi_reg_id reg_id)
        switch (reg_id) {
        case INTER_EE_SRC_CH_IRQ_MSK:
        case INTER_EE_SRC_EV_CH_IRQ_MSK:
+               return gsi->version >= IPA_VERSION_3_5;
+
+       case HW_PARAM_2:
+               return gsi->version >= IPA_VERSION_3_5_1;
+
+       case HW_PARAM_4:
+               return gsi->version >= IPA_VERSION_5_0;
+
        case CH_C_CNTXT_0:
        case CH_C_CNTXT_1:
        case CH_C_CNTXT_2:
@@ -43,7 +51,6 @@ static bool gsi_reg_id_valid(struct gsi *gsi, enum gsi_reg_id reg_id)
        case CH_CMD:
        case EV_CH_CMD:
        case GENERIC_CMD:
-       case HW_PARAM_2:
        case CNTXT_TYPE_IRQ:
        case CNTXT_TYPE_IRQ_MSK:
        case CNTXT_SRC_CH_IRQ:
index f62f0a5c653d1a6689f898bf6c67124147e8ac7d..48fde65fa2e8a59d8ed82e3535f0d7cff4677380 100644 (file)
 
 #include <linux/bits.h>
 
+struct platform_device;
+
+struct gsi;
+
 /**
  * DOC: GSI Registers
  *
index 0f52c068c46d635954e78c1796b1c63041cdd36b..ee6fb00b71eb620178cca6a5045580944db13aaf 100644 (file)
@@ -156,7 +156,7 @@ int gsi_trans_pool_init_dma(struct device *dev, struct gsi_trans_pool *pool,
         * gsi_trans_pool_exit_dma() can assume the total allocated
         * size is exactly (count * size).
         */
-       total_size = get_order(total_size) << PAGE_SHIFT;
+       total_size = PAGE_SIZE << get_order(total_size);
 
        virt = dma_alloc_coherent(dev, total_size, &addr, GFP_KERNEL);
        if (!virt)
index 735fa659160979316feaeb3ffd3e89d41e48a2f5..3f475428ddddb467fe287be3b11d77423b99af0d 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
- * Copyright (C) 2019-2022 Linaro Ltd.
+ * Copyright (C) 2019-2023 Linaro Ltd.
  */
 
 #include <linux/io.h>
@@ -15,6 +15,17 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
        enum ipa_version version = ipa->version;
 
        switch (reg_id) {
+       case FILT_ROUT_HASH_EN:
+               return version == IPA_VERSION_4_2;
+
+       case FILT_ROUT_HASH_FLUSH:
+               return version < IPA_VERSION_5_0 && version != IPA_VERSION_4_2;
+
+       case FILT_ROUT_CACHE_FLUSH:
+       case ENDP_FILTER_CACHE_CFG:
+       case ENDP_ROUTER_CACHE_CFG:
+               return version >= IPA_VERSION_5_0;
+
        case IPA_BCR:
        case COUNTER_CFG:
                return version < IPA_VERSION_4_5;
@@ -32,14 +43,17 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
        case SRC_RSRC_GRP_45_RSRC_TYPE:
        case DST_RSRC_GRP_45_RSRC_TYPE:
                return version <= IPA_VERSION_3_1 ||
-                      version == IPA_VERSION_4_5;
+                      version == IPA_VERSION_4_5 ||
+                      version == IPA_VERSION_5_0;
 
        case SRC_RSRC_GRP_67_RSRC_TYPE:
        case DST_RSRC_GRP_67_RSRC_TYPE:
-               return version <= IPA_VERSION_3_1;
+               return version <= IPA_VERSION_3_1 ||
+                      version == IPA_VERSION_5_0;
 
        case ENDP_FILTER_ROUTER_HSH_CFG:
-               return version != IPA_VERSION_4_2;
+               return version < IPA_VERSION_5_0 &&
+                       version != IPA_VERSION_4_2;
 
        case IRQ_SUSPEND_EN:
        case IRQ_SUSPEND_CLR:
@@ -51,10 +65,6 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
        case SHARED_MEM_SIZE:
        case QSB_MAX_WRITES:
        case QSB_MAX_READS:
-       case FILT_ROUT_HASH_EN:
-       case FILT_ROUT_CACHE_CFG:
-       case FILT_ROUT_HASH_FLUSH:
-       case FILT_ROUT_CACHE_FLUSH:
        case STATE_AGGR_ACTIVE:
        case LOCAL_PKT_PROC_CNTXT:
        case AGGR_FORCE_CLOSE:
@@ -76,8 +86,6 @@ static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
        case ENDP_INIT_RSRC_GRP:
        case ENDP_INIT_SEQ:
        case ENDP_STATUS:
-       case ENDP_FILTER_CACHE_CFG:
-       case ENDP_ROUTER_CACHE_CFG:
        case IPA_IRQ_STTS:
        case IPA_IRQ_EN:
        case IPA_IRQ_CLR:
index 28aa1351dd4880e4f9e0ac6bb43ccb785cd83b66..7dd65d39333ddaefb0e3cff1e22421f41bed8eec 100644 (file)
@@ -60,9 +60,8 @@ enum ipa_reg_id {
        SHARED_MEM_SIZE,
        QSB_MAX_WRITES,
        QSB_MAX_READS,
-       FILT_ROUT_HASH_EN,                              /* Not IPA v5.0+ */
-       FILT_ROUT_CACHE_CFG,                            /* IPA v5.0+ */
-       FILT_ROUT_HASH_FLUSH,                           /* Not IPA v5.0+ */
+       FILT_ROUT_HASH_EN,                              /* IPA v4.2 */
+       FILT_ROUT_HASH_FLUSH,                   /* Not IPA v4.2 nor IPA v5.0+ */
        FILT_ROUT_CACHE_FLUSH,                          /* IPA v5.0+ */
        STATE_AGGR_ACTIVE,
        IPA_BCR,                                        /* Not IPA v4.5+ */
@@ -77,12 +76,12 @@ enum ipa_reg_id {
        TIMERS_PULSE_GRAN_CFG,                          /* IPA v4.5+ */
        SRC_RSRC_GRP_01_RSRC_TYPE,
        SRC_RSRC_GRP_23_RSRC_TYPE,
-       SRC_RSRC_GRP_45_RSRC_TYPE,              /* Not IPA v3.5+, IPA v4.5 */
-       SRC_RSRC_GRP_67_RSRC_TYPE,                      /* Not IPA v3.5+ */
+       SRC_RSRC_GRP_45_RSRC_TYPE,      /* Not IPA v3.5+; IPA v4.5, IPA v5.0 */
+       SRC_RSRC_GRP_67_RSRC_TYPE,              /* Not IPA v3.5+; IPA v5.0 */
        DST_RSRC_GRP_01_RSRC_TYPE,
        DST_RSRC_GRP_23_RSRC_TYPE,
-       DST_RSRC_GRP_45_RSRC_TYPE,              /* Not IPA v3.5+, IPA v4.5 */
-       DST_RSRC_GRP_67_RSRC_TYPE,                      /* Not IPA v3.5+ */
+       DST_RSRC_GRP_45_RSRC_TYPE,      /* Not IPA v3.5+; IPA v4.5, IPA v5.0 */
+       DST_RSRC_GRP_67_RSRC_TYPE,              /* Not IPA v3.5+; IPA v5.0 */
        ENDP_INIT_CTRL,         /* Not IPA v4.2+ for TX, not IPA v4.0+ for RX */
        ENDP_INIT_CFG,
        ENDP_INIT_NAT,                  /* TX only */
@@ -206,14 +205,6 @@ enum ipa_reg_qsb_max_reads_field_id {
        GEN_QMB_1_MAX_READS_BEATS,                      /* IPA v4.0+ */
 };
 
-/* FILT_ROUT_CACHE_CFG register */
-enum ipa_reg_filt_rout_cache_cfg_field_id {
-       ROUTER_CACHE_EN,
-       FILTER_CACHE_EN,
-       LOW_PRI_HASH_HIT_DISABLE,
-       LRU_EVICTION_THRESHOLD,
-};
-
 /* FILT_ROUT_HASH_EN and FILT_ROUT_HASH_FLUSH registers */
 enum ipa_reg_filt_rout_hash_field_id {
        IPV6_ROUTER_HASH,
index 57b457f39b6e2b24c309d0849ce119ecfee838ea..2ee07eebca6774fc9fe60e9b2c51efb0a2f37101 100644 (file)
@@ -6,7 +6,8 @@
 #define _REG_H_
 
 #include <linux/types.h>
-#include <linux/bits.h>
+#include <linux/log2.h>
+#include <linux/bug.h>
 
 /**
  * struct reg - A register descriptor
index 648b51b88d4e862335f2a9db6f9fd1e135d1895f..2900e5c3ff88833574d92cbea552c0ba57759536 100644 (file)
@@ -137,17 +137,17 @@ REG_STRIDE(EV_CH_E_SCRATCH_1, ev_ch_e_scratch_1,
           0x0001004c + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(CH_C_DOORBELL_0, ch_c_doorbell_0,
-          0x0001e000 + 0x4000 * GSI_EE_AP, 0x08);
+          0x00011000 + 0x4000 * GSI_EE_AP, 0x08);
 
 REG_STRIDE(EV_CH_E_DOORBELL_0, ev_ch_e_doorbell_0,
-          0x0001e100 + 0x4000 * GSI_EE_AP, 0x08);
+          0x00011100 + 0x4000 * GSI_EE_AP, 0x08);
 
 static const u32 reg_gsi_status_fmask[] = {
        [ENABLED]                                       = BIT(0),
                                                /* Bits 1-31 reserved */
 };
 
-REG_FIELDS(GSI_STATUS, gsi_status, 0x0001f000 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(GSI_STATUS, gsi_status, 0x00012000 + 0x4000 * GSI_EE_AP);
 
 static const u32 reg_ch_cmd_fmask[] = {
        [CH_CHID]                                       = GENMASK(7, 0),
@@ -155,7 +155,7 @@ static const u32 reg_ch_cmd_fmask[] = {
        [CH_OPCODE]                                     = GENMASK(31, 24),
 };
 
-REG_FIELDS(CH_CMD, ch_cmd, 0x0001f008 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(CH_CMD, ch_cmd, 0x00012008 + 0x4000 * GSI_EE_AP);
 
 static const u32 reg_ev_ch_cmd_fmask[] = {
        [EV_CHID]                                       = GENMASK(7, 0),
@@ -163,7 +163,7 @@ static const u32 reg_ev_ch_cmd_fmask[] = {
        [EV_OPCODE]                                     = GENMASK(31, 24),
 };
 
-REG_FIELDS(EV_CH_CMD, ev_ch_cmd, 0x0001f010 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(EV_CH_CMD, ev_ch_cmd, 0x00012010 + 0x4000 * GSI_EE_AP);
 
 static const u32 reg_generic_cmd_fmask[] = {
        [GENERIC_OPCODE]                                = GENMASK(4, 0),
@@ -172,7 +172,7 @@ static const u32 reg_generic_cmd_fmask[] = {
                                                /* Bits 14-31 reserved */
 };
 
-REG_FIELDS(GENERIC_CMD, generic_cmd, 0x0001f018 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(GENERIC_CMD, generic_cmd, 0x00012018 + 0x4000 * GSI_EE_AP);
 
 static const u32 reg_hw_param_2_fmask[] = {
        [IRAM_SIZE]                                     = GENMASK(2, 0),
@@ -188,58 +188,58 @@ static const u32 reg_hw_param_2_fmask[] = {
        [GSI_USE_INTER_EE]                              = BIT(31),
 };
 
-REG_FIELDS(HW_PARAM_2, hw_param_2, 0x0001f040 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(HW_PARAM_2, hw_param_2, 0x00012040 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_TYPE_IRQ, cntxt_type_irq, 0x0001f080 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_TYPE_IRQ, cntxt_type_irq, 0x00012080 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_TYPE_IRQ_MSK, cntxt_type_irq_msk, 0x0001f088 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_TYPE_IRQ_MSK, cntxt_type_irq_msk, 0x00012088 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_SRC_CH_IRQ, cntxt_src_ch_irq, 0x0001f090 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_SRC_CH_IRQ, cntxt_src_ch_irq, 0x00012090 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_SRC_EV_CH_IRQ, cntxt_src_ev_ch_irq, 0x0001f094 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_SRC_EV_CH_IRQ, cntxt_src_ev_ch_irq, 0x00012094 + 0x4000 * GSI_EE_AP);
 
 REG(CNTXT_SRC_CH_IRQ_MSK, cntxt_src_ch_irq_msk,
-    0x0001f098 + 0x4000 * GSI_EE_AP);
+    0x00012098 + 0x4000 * GSI_EE_AP);
 
 REG(CNTXT_SRC_EV_CH_IRQ_MSK, cntxt_src_ev_ch_irq_msk,
-    0x0001f09c + 0x4000 * GSI_EE_AP);
+    0x0001209c + 0x4000 * GSI_EE_AP);
 
 REG(CNTXT_SRC_CH_IRQ_CLR, cntxt_src_ch_irq_clr,
-    0x0001f0a0 + 0x4000 * GSI_EE_AP);
+    0x000120a0 + 0x4000 * GSI_EE_AP);
 
 REG(CNTXT_SRC_EV_CH_IRQ_CLR, cntxt_src_ev_ch_irq_clr,
-    0x0001f0a4 + 0x4000 * GSI_EE_AP);
+    0x000120a4 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_SRC_IEOB_IRQ, cntxt_src_ieob_irq, 0x0001f0b0 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_SRC_IEOB_IRQ, cntxt_src_ieob_irq, 0x000120b0 + 0x4000 * GSI_EE_AP);
 
 REG(CNTXT_SRC_IEOB_IRQ_MSK, cntxt_src_ieob_irq_msk,
-    0x0001f0b8 + 0x4000 * GSI_EE_AP);
+    0x000120b8 + 0x4000 * GSI_EE_AP);
 
 REG(CNTXT_SRC_IEOB_IRQ_CLR, cntxt_src_ieob_irq_clr,
-    0x0001f0c0 + 0x4000 * GSI_EE_AP);
+    0x000120c0 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_GLOB_IRQ_STTS, cntxt_glob_irq_stts, 0x0001f100 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_GLOB_IRQ_STTS, cntxt_glob_irq_stts, 0x00012100 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_GLOB_IRQ_EN, cntxt_glob_irq_en, 0x0001f108 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_GLOB_IRQ_EN, cntxt_glob_irq_en, 0x00012108 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_GLOB_IRQ_CLR, cntxt_glob_irq_clr, 0x0001f110 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_GLOB_IRQ_CLR, cntxt_glob_irq_clr, 0x00012110 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_GSI_IRQ_STTS, cntxt_gsi_irq_stts, 0x0001f118 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_GSI_IRQ_STTS, cntxt_gsi_irq_stts, 0x00012118 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_GSI_IRQ_EN, cntxt_gsi_irq_en, 0x0001f120 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_GSI_IRQ_EN, cntxt_gsi_irq_en, 0x00012120 + 0x4000 * GSI_EE_AP);
 
-REG(CNTXT_GSI_IRQ_CLR, cntxt_gsi_irq_clr, 0x0001f128 + 0x4000 * GSI_EE_AP);
+REG(CNTXT_GSI_IRQ_CLR, cntxt_gsi_irq_clr, 0x00012128 + 0x4000 * GSI_EE_AP);
 
 static const u32 reg_cntxt_intset_fmask[] = {
        [INTYPE]                                        = BIT(0)
                                                /* Bits 1-31 reserved */
 };
 
-REG_FIELDS(CNTXT_INTSET, cntxt_intset, 0x0001f180 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(CNTXT_INTSET, cntxt_intset, 0x00012180 + 0x4000 * GSI_EE_AP);
 
-REG_FIELDS(ERROR_LOG, error_log, 0x0001f200 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(ERROR_LOG, error_log, 0x00012200 + 0x4000 * GSI_EE_AP);
 
-REG(ERROR_LOG_CLR, error_log_clr, 0x0001f210 + 0x4000 * GSI_EE_AP);
+REG(ERROR_LOG_CLR, error_log_clr, 0x00012210 + 0x4000 * GSI_EE_AP);
 
 static const u32 reg_cntxt_scratch_0_fmask[] = {
        [INTER_EE_RESULT]                               = GENMASK(2, 0),
@@ -248,7 +248,7 @@ static const u32 reg_cntxt_scratch_0_fmask[] = {
                                                /* Bits 8-31 reserved */
 };
 
-REG_FIELDS(CNTXT_SCRATCH_0, cntxt_scratch_0, 0x0001f400 + 0x4000 * GSI_EE_AP);
+REG_FIELDS(CNTXT_SCRATCH_0, cntxt_scratch_0, 0x00012400 + 0x4000 * GSI_EE_AP);
 
 static const struct reg *reg_array[] = {
        [INTER_EE_SRC_CH_IRQ_MSK]       = &reg_inter_ee_src_ch_irq_msk,
index 4bf45d264d6b914133bf13148fb3a154727be7f5..8b5d95425a766c97f97f3d2646fe1bc104d7412b 100644 (file)
@@ -27,7 +27,7 @@ static const u32 reg_ch_c_cntxt_0_fmask[] = {
 };
 
 REG_STRIDE_FIELDS(CH_C_CNTXT_0, ch_c_cntxt_0,
-                 0x0001c000 + 0x4000 * GSI_EE_AP, 0x80);
+                 0x0000f000 + 0x4000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_ch_c_cntxt_1_fmask[] = {
        [CH_R_LENGTH]                                   = GENMASK(19, 0),
@@ -35,11 +35,11 @@ static const u32 reg_ch_c_cntxt_1_fmask[] = {
 };
 
 REG_STRIDE_FIELDS(CH_C_CNTXT_1, ch_c_cntxt_1,
-                 0x0001c004 + 0x4000 * GSI_EE_AP, 0x80);
+                 0x0000f004 + 0x4000 * GSI_EE_AP, 0x80);
 
-REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0001c008 + 0x4000 * GSI_EE_AP, 0x80);
+REG_STRIDE(CH_C_CNTXT_2, ch_c_cntxt_2, 0x0000f008 + 0x4000 * GSI_EE_AP, 0x80);
 
-REG_STRIDE(CH_C_CNTXT_3, ch_c_cntxt_3, 0x0001c00c + 0x4000 * GSI_EE_AP, 0x80);
+REG_STRIDE(CH_C_CNTXT_3, ch_c_cntxt_3, 0x0000f00c + 0x4000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_ch_c_qos_fmask[] = {
        [WRR_WEIGHT]                                    = GENMASK(3, 0),
@@ -53,7 +53,7 @@ static const u32 reg_ch_c_qos_fmask[] = {
                                                /* Bits 25-31 reserved */
 };
 
-REG_STRIDE_FIELDS(CH_C_QOS, ch_c_qos, 0x0001c05c + 0x4000 * GSI_EE_AP, 0x80);
+REG_STRIDE_FIELDS(CH_C_QOS, ch_c_qos, 0x0000f05c + 0x4000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_error_log_fmask[] = {
        [ERR_ARG3]                                      = GENMASK(3, 0),
@@ -67,16 +67,16 @@ static const u32 reg_error_log_fmask[] = {
 };
 
 REG_STRIDE(CH_C_SCRATCH_0, ch_c_scratch_0,
-          0x0001c060 + 0x4000 * GSI_EE_AP, 0x80);
+          0x0000f060 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(CH_C_SCRATCH_1, ch_c_scratch_1,
-          0x0001c064 + 0x4000 * GSI_EE_AP, 0x80);
+          0x0000f064 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(CH_C_SCRATCH_2, ch_c_scratch_2,
-          0x0001c068 + 0x4000 * GSI_EE_AP, 0x80);
+          0x0000f068 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(CH_C_SCRATCH_3, ch_c_scratch_3,
-          0x0001c06c + 0x4000 * GSI_EE_AP, 0x80);
+          0x0000f06c + 0x4000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_ev_ch_e_cntxt_0_fmask[] = {
        [EV_CHTYPE]                                     = GENMASK(3, 0),
@@ -89,23 +89,23 @@ static const u32 reg_ev_ch_e_cntxt_0_fmask[] = {
 };
 
 REG_STRIDE_FIELDS(EV_CH_E_CNTXT_0, ev_ch_e_cntxt_0,
-                 0x0001d000 + 0x4000 * GSI_EE_AP, 0x80);
+                 0x00010000 + 0x4000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_ev_ch_e_cntxt_1_fmask[] = {
        [R_LENGTH]                                      = GENMASK(15, 0),
 };
 
 REG_STRIDE_FIELDS(EV_CH_E_CNTXT_1, ev_ch_e_cntxt_1,
-                 0x0001d004 + 0x4000 * GSI_EE_AP, 0x80);
+                 0x00010004 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_2, ev_ch_e_cntxt_2,
-          0x0001d008 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010008 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_3, ev_ch_e_cntxt_3,
-          0x0001d00c + 0x4000 * GSI_EE_AP, 0x80);
+          0x0001000c + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_4, ev_ch_e_cntxt_4,
-          0x0001d010 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010010 + 0x4000 * GSI_EE_AP, 0x80);
 
 static const u32 reg_ev_ch_e_cntxt_8_fmask[] = {
        [EV_MODT]                                       = GENMASK(15, 0),
@@ -114,28 +114,28 @@ static const u32 reg_ev_ch_e_cntxt_8_fmask[] = {
 };
 
 REG_STRIDE_FIELDS(EV_CH_E_CNTXT_8, ev_ch_e_cntxt_8,
-                 0x0001d020 + 0x4000 * GSI_EE_AP, 0x80);
+                 0x00010020 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_9, ev_ch_e_cntxt_9,
-          0x0001d024 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010024 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_10, ev_ch_e_cntxt_10,
-          0x0001d028 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010028 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_11, ev_ch_e_cntxt_11,
-          0x0001d02c + 0x4000 * GSI_EE_AP, 0x80);
+          0x0001002c + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_12, ev_ch_e_cntxt_12,
-          0x0001d030 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010030 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_CNTXT_13, ev_ch_e_cntxt_13,
-          0x0001d034 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010034 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_SCRATCH_0, ev_ch_e_scratch_0,
-          0x0001d048 + 0x4000 * GSI_EE_AP, 0x80);
+          0x00010048 + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(EV_CH_E_SCRATCH_1, ev_ch_e_scratch_1,
-          0x0001d04c + 0x4000 * GSI_EE_AP, 0x80);
+          0x0001004c + 0x4000 * GSI_EE_AP, 0x80);
 
 REG_STRIDE(CH_C_DOORBELL_0, ch_c_doorbell_0,
           0x00011000 + 0x4000 * GSI_EE_AP, 0x08);
index 943d26cbf39f5d8d14ed247f4918d51b5104f31f..71712ea25403dd71322f36297bb54f782d789f2c 100644 (file)
@@ -101,6 +101,7 @@ static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
                goto out;
 
        skb->dev = addr->master->dev;
+       skb->skb_iif = skb->dev->ifindex;
        len = skb->len + ETH_HLEN;
        ipvlan_count_rx(addr->master, len, true, false);
 out:
index d77c987fda9cd1270022a657b37aa61ec870b249..4630dde019749a7a4de81c27b9f6af902bad1c2f 100644 (file)
@@ -18,16 +18,18 @@ MODULE_AUTHOR("Calvin Johnson <calvin.johnson@oss.nxp.com>");
 MODULE_LICENSE("GPL");
 
 /**
- * acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
+ * __acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
  * @mdio: pointer to mii_bus structure
  * @fwnode: pointer to fwnode of MDIO bus. This fwnode is expected to represent
+ * @owner: module owning this @mdio object.
  * an ACPI device object corresponding to the MDIO bus and its children are
  * expected to correspond to the PHY devices on that bus.
  *
  * This function registers the mii_bus structure and registers a phy_device
  * for each child node of @fwnode.
  */
-int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
+int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode,
+                           struct module *owner)
 {
        struct fwnode_handle *child;
        u32 addr;
@@ -35,7 +37,7 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
 
        /* Mask out all PHYs from auto probing. */
        mdio->phy_mask = GENMASK(31, 0);
-       ret = mdiobus_register(mdio);
+       ret = __mdiobus_register(mdio, owner);
        if (ret)
                return ret;
 
@@ -55,4 +57,4 @@ int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
        }
        return 0;
 }
-EXPORT_SYMBOL(acpi_mdiobus_register);
+EXPORT_SYMBOL(__acpi_mdiobus_register);
index 3847ee92c1096c1569442acea2120c279ad2dc60..6067d96b2b7bf030a09a67bfad7490fea60d219f 100644 (file)
@@ -106,6 +106,7 @@ static int thunder_mdiobus_pci_probe(struct pci_dev *pdev,
                if (i >= ARRAY_SIZE(nexus->buses))
                        break;
        }
+       fwnode_handle_put(fwn);
        return 0;
 
 err_release_regions:
index 510822d6d0d90ce4fe012388e71733846c57c115..1e46e39f5f46a0857570682a86e23d876ef77704 100644 (file)
@@ -139,21 +139,23 @@ bool of_mdiobus_child_is_phy(struct device_node *child)
 EXPORT_SYMBOL(of_mdiobus_child_is_phy);
 
 /**
- * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
+ * __of_mdiobus_register - Register mii_bus and create PHYs from the device tree
  * @mdio: pointer to mii_bus structure
  * @np: pointer to device_node of MDIO bus.
+ * @owner: module owning the @mdio object.
  *
  * This function registers the mii_bus structure and registers a phy_device
  * for each child node of @np.
  */
-int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
+int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
+                         struct module *owner)
 {
        struct device_node *child;
        bool scanphys = false;
        int addr, rc;
 
        if (!np)
-               return mdiobus_register(mdio);
+               return __mdiobus_register(mdio, owner);
 
        /* Do not continue if the node is disabled */
        if (!of_device_is_available(np))
@@ -172,7 +174,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
        of_property_read_u32(np, "reset-post-delay-us", &mdio->reset_post_delay_us);
 
        /* Register the MDIO bus */
-       rc = mdiobus_register(mdio);
+       rc = __mdiobus_register(mdio, owner);
        if (rc)
                return rc;
 
@@ -236,7 +238,7 @@ unregister:
        mdiobus_unregister(mdio);
        return rc;
 }
-EXPORT_SYMBOL(of_mdiobus_register);
+EXPORT_SYMBOL(__of_mdiobus_register);
 
 /**
  * of_mdio_find_device - Given a device tree node, find the mdio_device
index 7a28e082436e4a3a5a9e11a3711b666e5735c406..d0c916a53d7ce4689e51eeffdfdaa5dd997ae529 100644 (file)
@@ -130,14 +130,10 @@ static u16 net_failover_select_queue(struct net_device *dev,
                        txq = ops->ndo_select_queue(primary_dev, skb, sb_dev);
                else
                        txq = netdev_pick_tx(primary_dev, skb, NULL);
-
-               qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
-
-               return txq;
+       } else {
+               txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
        }
 
-       txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
-
        /* Save the original txq to restore before passing to the driver */
        qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
 
index b4ff9c5073a3c485e6bba87284eb386152bdf09b..9ab5eff502b71640b1022baf1d6b7567a65c240f 100644 (file)
@@ -588,15 +588,13 @@ static int dp83869_of_init(struct phy_device *phydev)
                                                       &dp83869_internal_delay[0],
                                                       delay_size, true);
        if (dp83869->rx_int_delay < 0)
-               dp83869->rx_int_delay =
-                               dp83869_internal_delay[DP83869_CLK_DELAY_DEF];
+               dp83869->rx_int_delay = DP83869_CLK_DELAY_DEF;
 
        dp83869->tx_int_delay = phy_get_internal_delay(phydev, dev,
                                                       &dp83869_internal_delay[0],
                                                       delay_size, false);
        if (dp83869->tx_int_delay < 0)
-               dp83869->tx_int_delay =
-                               dp83869_internal_delay[DP83869_CLK_DELAY_DEF];
+               dp83869->tx_int_delay = DP83869_CLK_DELAY_DEF;
 
        return ret;
 }
index b560e99695dfd3f4ca3db7a8f9080a1629a26408..69b829e6ab35b84a07f0063f3a6f7b48ea1a6de1 100644 (file)
@@ -98,13 +98,14 @@ EXPORT_SYMBOL(__devm_mdiobus_register);
 
 #if IS_ENABLED(CONFIG_OF_MDIO)
 /**
- * devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
+ * __devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
  * @dev:       Device to register mii_bus for
  * @mdio:      MII bus structure to register
  * @np:                Device node to parse
+ * @owner:     Owning module
  */
-int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
-                            struct device_node *np)
+int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
+                              struct device_node *np, struct module *owner)
 {
        struct mdiobus_devres *dr;
        int ret;
@@ -117,7 +118,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
        if (!dr)
                return -ENOMEM;
 
-       ret = of_mdiobus_register(mdio, np);
+       ret = __of_mdiobus_register(mdio, np, owner);
        if (ret) {
                devres_free(dr);
                return ret;
@@ -127,7 +128,7 @@ int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
        devres_add(dev, dr);
        return 0;
 }
-EXPORT_SYMBOL(devm_of_mdiobus_register);
+EXPORT_SYMBOL(__devm_of_mdiobus_register);
 #endif /* CONFIG_OF_MDIO */
 
 MODULE_LICENSE("GPL");
index 2c84fccef4f644585ac4ec25d23c833e67726430..4e884e4ba0ead7c72efccbb7b079196f8a50ab1e 100644 (file)
@@ -4151,6 +4151,7 @@ static struct phy_driver ksphy_driver[] = {
        .resume         = kszphy_resume,
        .cable_test_start       = ksz9x31_cable_test_start,
        .cable_test_get_status  = ksz9x31_cable_test_get_status,
+       .get_features   = ksz9477_get_features,
 }, {
        .phy_id         = PHY_ID_KSZ8873MLL,
        .phy_id_mask    = MICREL_PHY_ID_MASK,
index 8a13b1ad9a330b599742fc40a5d540ec3dcc0c3f..62bf99e45af16d86ff80428af812e34183888715 100644 (file)
@@ -280,12 +280,9 @@ static int vsc85xx_wol_set(struct phy_device *phydev,
        u16 pwd[3] = {0, 0, 0};
        struct ethtool_wolinfo *wol_conf = wol;
 
-       mutex_lock(&phydev->lock);
        rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
-       if (rc < 0) {
-               rc = phy_restore_page(phydev, rc, rc);
-               goto out_unlock;
-       }
+       if (rc < 0)
+               return phy_restore_page(phydev, rc, rc);
 
        if (wol->wolopts & WAKE_MAGIC) {
                /* Store the device address for the magic packet */
@@ -323,7 +320,7 @@ static int vsc85xx_wol_set(struct phy_device *phydev,
 
        rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
        if (rc < 0)
-               goto out_unlock;
+               return rc;
 
        if (wol->wolopts & WAKE_MAGIC) {
                /* Enable the WOL interrupt */
@@ -331,22 +328,19 @@ static int vsc85xx_wol_set(struct phy_device *phydev,
                reg_val |= MII_VSC85XX_INT_MASK_WOL;
                rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
                if (rc)
-                       goto out_unlock;
+                       return rc;
        } else {
                /* Disable the WOL interrupt */
                reg_val = phy_read(phydev, MII_VSC85XX_INT_MASK);
                reg_val &= (~MII_VSC85XX_INT_MASK_WOL);
                rc = phy_write(phydev, MII_VSC85XX_INT_MASK, reg_val);
                if (rc)
-                       goto out_unlock;
+                       return rc;
        }
        /* Clear WOL iterrupt status */
        reg_val = phy_read(phydev, MII_VSC85XX_INT_STATUS);
 
-out_unlock:
-       mutex_unlock(&phydev->lock);
-
-       return rc;
+       return 0;
 }
 
 static void vsc85xx_wol_get(struct phy_device *phydev,
@@ -358,10 +352,9 @@ static void vsc85xx_wol_get(struct phy_device *phydev,
        u16 pwd[3] = {0, 0, 0};
        struct ethtool_wolinfo *wol_conf = wol;
 
-       mutex_lock(&phydev->lock);
        rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
        if (rc < 0)
-               goto out_unlock;
+               goto out_restore_page;
 
        reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
        if (reg_val & SECURE_ON_ENABLE)
@@ -377,9 +370,8 @@ static void vsc85xx_wol_get(struct phy_device *phydev,
                }
        }
 
-out_unlock:
+out_restore_page:
        phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
-       mutex_unlock(&phydev->lock);
 }
 
 #if IS_ENABLED(CONFIG_OF_MDIO)
index 047c581457e34510236133a6ff4ff292a6c06385..029875a59ff89083e82e9f2b735b9585a25cea26 100644 (file)
@@ -79,7 +79,7 @@
 #define SGMII_ABILITY                  BIT(0)
 
 #define VEND1_MII_BASIC_CONFIG         0xAFC6
-#define MII_BASIC_CONFIG_REV           BIT(8)
+#define MII_BASIC_CONFIG_REV           BIT(4)
 #define MII_BASIC_CONFIG_SGMII         0x9
 #define MII_BASIC_CONFIG_RGMII         0x7
 #define MII_BASIC_CONFIG_RMII          0x5
 #define MAX_ID_PS                      2260U
 #define DEFAULT_ID_PS                  2000U
 
-#define PPM_TO_SUBNS_INC(ppb)  div_u64(GENMASK(31, 0) * (ppb) * \
+#define PPM_TO_SUBNS_INC(ppb)  div_u64(GENMASK_ULL(31, 0) * (ppb) * \
                                        PTP_CLK_PERIOD_100BT1, NSEC_PER_SEC)
 
 #define NXP_C45_SKB_CB(skb)    ((struct nxp_c45_skb_cb *)(skb)->cb)
@@ -1337,6 +1337,17 @@ no_ptp_support:
        return ret;
 }
 
+static void nxp_c45_remove(struct phy_device *phydev)
+{
+       struct nxp_c45_phy *priv = phydev->priv;
+
+       if (priv->ptp_clock)
+               ptp_clock_unregister(priv->ptp_clock);
+
+       skb_queue_purge(&priv->tx_queue);
+       skb_queue_purge(&priv->rx_queue);
+}
+
 static struct phy_driver nxp_c45_driver[] = {
        {
                PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
@@ -1359,6 +1370,7 @@ static struct phy_driver nxp_c45_driver[] = {
                .set_loopback           = genphy_c45_loopback,
                .get_sqi                = nxp_c45_get_sqi,
                .get_sqi_max            = nxp_c45_get_sqi_max,
+               .remove                 = nxp_c45_remove,
        },
 };
 
index b33e55a7364e6e697088cf97de5c110c2a2c20af..99a07eb54c441cec6c4ea7e24b3e89ec3618f516 100644 (file)
@@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st)
        return NULL;
 }
 
+static void phy_process_state_change(struct phy_device *phydev,
+                                    enum phy_state old_state)
+{
+       if (old_state != phydev->state) {
+               phydev_dbg(phydev, "PHY state change %s -> %s\n",
+                          phy_state_to_str(old_state),
+                          phy_state_to_str(phydev->state));
+               if (phydev->drv && phydev->drv->link_change_notify)
+                       phydev->drv->link_change_notify(phydev);
+       }
+}
+
 static void phy_link_up(struct phy_device *phydev)
 {
        phydev->phy_link_change(phydev, true);
@@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
 void phy_stop(struct phy_device *phydev)
 {
        struct net_device *dev = phydev->attached_dev;
+       enum phy_state old_state;
 
        if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
                WARN(1, "called from state %s\n",
@@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev)
        }
 
        mutex_lock(&phydev->lock);
+       old_state = phydev->state;
 
        if (phydev->state == PHY_CABLETEST) {
                phy_abort_cable_test(phydev);
@@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev)
                sfp_upstream_stop(phydev->sfp_bus);
 
        phydev->state = PHY_HALTED;
+       phy_process_state_change(phydev, old_state);
 
        mutex_unlock(&phydev->lock);
 
@@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work)
        if (err < 0)
                phy_error(phydev);
 
-       if (old_state != phydev->state) {
-               phydev_dbg(phydev, "PHY state change %s -> %s\n",
-                          phy_state_to_str(old_state),
-                          phy_state_to_str(phydev->state));
-               if (phydev->drv && phydev->drv->link_change_notify)
-                       phydev->drv->link_change_notify(phydev);
-       }
+       phy_process_state_change(phydev, old_state);
 
        /* Only re-schedule a PHY state machine change if we are polling the
         * PHY, if PHY_MAC_INTERRUPT is set, then we will be moving
index 1785f1cead97103bf58357eb04a34327336229a2..1de3e339b31a5215dc0598a8175454a34632fca5 100644 (file)
@@ -3057,7 +3057,7 @@ EXPORT_SYMBOL_GPL(device_phy_find_device);
  * and "phy-device" are not supported in ACPI. DT supports all the three
  * named references to the phy node.
  */
-struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode)
 {
        struct fwnode_handle *phy_node;
 
index 1a2f074685fa9f386f30b87a5b3fe750009b8696..30c166b334686723bbe2fae46211639bdebf9174 100644 (file)
@@ -1586,6 +1586,25 @@ void phylink_destroy(struct phylink *pl)
 }
 EXPORT_SYMBOL_GPL(phylink_destroy);
 
+/**
+ * phylink_expects_phy() - Determine if phylink expects a phy to be attached
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * When using fixed-link mode, or in-band mode with 1000base-X or 2500base-X,
+ * no PHY is needed.
+ *
+ * Returns true if phylink will be expecting a PHY.
+ */
+bool phylink_expects_phy(struct phylink *pl)
+{
+       if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+           (pl->cfg_link_an_mode == MLO_AN_INBAND &&
+            phy_interface_mode_is_8023z(pl->link_config.interface)))
+               return false;
+       return true;
+}
+EXPORT_SYMBOL_GPL(phylink_expects_phy);
+
 static void phylink_phy_change(struct phy_device *phydev, bool up)
 {
        struct phylink *pl = phydev->phylink;
index daac293e8edece7e594ca35582ff2483a817b6a3..9fc50fcc8fc99263330b7b84df839b82223d56d8 100644 (file)
@@ -17,7 +17,7 @@ struct sfp_bus {
        /* private: */
        struct kref kref;
        struct list_head node;
-       struct fwnode_handle *fwnode;
+       const struct fwnode_handle *fwnode;
 
        const struct sfp_socket_ops *socket_ops;
        struct device *sfp_dev;
@@ -390,7 +390,7 @@ static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus)
        return bus->registered ? bus->upstream_ops : NULL;
 }
 
-static struct sfp_bus *sfp_bus_get(struct fwnode_handle *fwnode)
+static struct sfp_bus *sfp_bus_get(const struct fwnode_handle *fwnode)
 {
        struct sfp_bus *sfp, *new, *found = NULL;
 
@@ -593,7 +593,7 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
  *     - %-ENOMEM if we failed to allocate the bus.
  *     - an error from the upstream's connect_phy() method.
  */
-struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
+struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode)
 {
        struct fwnode_reference_args ref;
        struct sfp_bus *bus;
index c02cad6478a816f3a9c9818fd2af9ff3eec783e7..bf345032d450c9ae3949d1a4485c1b76bfd30f1f 100644 (file)
@@ -210,6 +210,12 @@ static const enum gpiod_flags gpio_flags[] = {
 #define SFP_PHY_ADDR           22
 #define SFP_PHY_ADDR_ROLLBALL  17
 
+/* SFP_EEPROM_BLOCK_SIZE is the size of data chunk to read the EEPROM
+ * at a time. Some SFP modules and also some Linux I2C drivers do not like
+ * reads longer than 16 bytes.
+ */
+#define SFP_EEPROM_BLOCK_SIZE  16
+
 struct sff_data {
        unsigned int gpios;
        bool (*module_supported)(const struct sfp_eeprom_id *id);
@@ -387,6 +393,10 @@ static const struct sfp_quirk sfp_quirks[] = {
 
        SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp),
 
+       // HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports
+       // 2600MBd in their EERPOM
+       SFP_QUIRK_M("HG GENUINE", "MXPD-483II", sfp_quirk_2500basex),
+
        // Huawei MA5671A can operate at 2500base-X, but report 1.2GBd NRZ in
        // their EEPROM
        SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
@@ -1925,11 +1935,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
        u8 check;
        int ret;
 
-       /* Some SFP modules and also some Linux I2C drivers do not like reads
-        * longer than 16 bytes, so read the EEPROM in chunks of 16 bytes at
-        * a time.
-        */
-       sfp->i2c_block_size = 16;
+       sfp->i2c_block_size = SFP_EEPROM_BLOCK_SIZE;
 
        ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base));
        if (ret < 0) {
@@ -2190,6 +2196,11 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
                        break;
                }
 
+               /* Force a poll to re-read the hardware signal state after
+                * sfp_sm_mod_probe() changed state_hw_mask.
+                */
+               mod_delayed_work(system_wq, &sfp->poll, 1);
+
                err = sfp_hwmon_insert(sfp);
                if (err)
                        dev_warn(sfp->dev, "hwmon probe failed: %pe\n",
@@ -2476,6 +2487,9 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee,
        unsigned int first, last, len;
        int ret;
 
+       if (!(sfp->state & SFP_F_PRESENT))
+               return -ENODEV;
+
        if (ee->len == 0)
                return -EINVAL;
 
@@ -2508,6 +2522,9 @@ static int sfp_module_eeprom_by_page(struct sfp *sfp,
                                     const struct ethtool_module_eeprom *page,
                                     struct netlink_ext_ack *extack)
 {
+       if (!(sfp->state & SFP_F_PRESENT))
+               return -ENODEV;
+
        if (page->bank) {
                NL_SET_ERR_MSG(extack, "Banks not supported");
                return -EOPNOTSUPP;
@@ -2612,6 +2629,7 @@ static struct sfp *sfp_alloc(struct device *dev)
                return ERR_PTR(-ENOMEM);
 
        sfp->dev = dev;
+       sfp->i2c_block_size = SFP_EEPROM_BLOCK_SIZE;
 
        mutex_init(&sfp->sm_mutex);
        mutex_init(&sfp->st_mutex);
index 00d9eff91dcfaf34c4fae700e6d7dbcbc97f22cd..df2c5435c5c49ee828d625c36e39f4e2d2af0216 100644 (file)
@@ -199,8 +199,11 @@ static int lan95xx_config_aneg_ext(struct phy_device *phydev)
 static int lan87xx_read_status(struct phy_device *phydev)
 {
        struct smsc_phy_priv *priv = phydev->priv;
+       int err;
 
-       int err = genphy_read_status(phydev);
+       err = genphy_read_status(phydev);
+       if (err)
+               return err;
 
        if (!phydev->link && priv->energy_enable && phydev->irq == PHY_POLL) {
                /* Disable EDPD to wake up PHY */
index ad653b32b2f0043d9264c7b22d7275f95630b0a3..5df1eba7b30a3f675e5521c8fa2e36affb75b195 100644 (file)
@@ -1486,7 +1486,8 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
        skb->truesize += skb->data_len;
 
        for (i = 1; i < it->nr_segs; i++) {
-               size_t fragsz = it->iov[i].iov_len;
+               const struct iovec *iov = iter_iov(it);
+               size_t fragsz = iov->iov_len;
                struct page *page;
                void *frag;
 
index 743cbf5d662c99c9d5ea390478d9516c2f4a871d..f7cff58fe0449313748237d53ff69191b85e5e5e 100644 (file)
@@ -666,8 +666,9 @@ static int asix_resume(struct usb_interface *intf)
 static int ax88772_init_mdio(struct usbnet *dev)
 {
        struct asix_common_private *priv = dev->driver_priv;
+       int ret;
 
-       priv->mdio = devm_mdiobus_alloc(&dev->udev->dev);
+       priv->mdio = mdiobus_alloc();
        if (!priv->mdio)
                return -ENOMEM;
 
@@ -679,7 +680,20 @@ static int ax88772_init_mdio(struct usbnet *dev)
        snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
                 dev->udev->bus->busnum, dev->udev->devnum);
 
-       return devm_mdiobus_register(&dev->udev->dev, priv->mdio);
+       ret = mdiobus_register(priv->mdio);
+       if (ret) {
+               netdev_err(dev->net, "Could not register MDIO bus (err %d)\n", ret);
+               mdiobus_free(priv->mdio);
+               priv->mdio = NULL;
+       }
+
+       return ret;
+}
+
+static void ax88772_mdio_unregister(struct asix_common_private *priv)
+{
+       mdiobus_unregister(priv->mdio);
+       mdiobus_free(priv->mdio);
 }
 
 static int ax88772_init_phy(struct usbnet *dev)
@@ -896,16 +910,23 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 
        ret = ax88772_init_mdio(dev);
        if (ret)
-               return ret;
+               goto mdio_err;
 
        ret = ax88772_phylink_setup(dev);
        if (ret)
-               return ret;
+               goto phylink_err;
 
        ret = ax88772_init_phy(dev);
        if (ret)
-               phylink_destroy(priv->phylink);
+               goto initphy_err;
 
+       return 0;
+
+initphy_err:
+       phylink_destroy(priv->phylink);
+phylink_err:
+       ax88772_mdio_unregister(priv);
+mdio_err:
        return ret;
 }
 
@@ -926,6 +947,7 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
        phylink_disconnect_phy(priv->phylink);
        rtnl_unlock();
        phylink_destroy(priv->phylink);
+       ax88772_mdio_unregister(priv);
        asix_rx_fixup_common_free(dev->driver_priv);
 }
 
index 068488890d57be2f4a1c31ae72ecef518775f110..c458c030fadf6cbaa7a55a4e35344bf2a01122a4 100644 (file)
@@ -3579,13 +3579,29 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb,
                size = (rx_cmd_a & RX_CMD_A_LEN_MASK_);
                align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
 
+               if (unlikely(size > skb->len)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "size err rx_cmd_a=0x%08x\n",
+                                 rx_cmd_a);
+                       return 0;
+               }
+
                if (unlikely(rx_cmd_a & RX_CMD_A_RED_)) {
                        netif_dbg(dev, rx_err, dev->net,
                                  "Error rx_cmd_a=0x%08x", rx_cmd_a);
                } else {
-                       u32 frame_len = size - ETH_FCS_LEN;
+                       u32 frame_len;
                        struct sk_buff *skb2;
 
+                       if (unlikely(size < ETH_FCS_LEN)) {
+                               netif_dbg(dev, rx_err, dev->net,
+                                         "size err rx_cmd_a=0x%08x\n",
+                                         rx_cmd_a);
+                               return 0;
+                       }
+
+                       frame_len = size - ETH_FCS_LEN;
+
                        skb2 = napi_alloc_skb(&dev->napi, frame_len);
                        if (!skb2)
                                return 0;
index 7a2b0094de51f53dd2161fce0ff04193a1f85654..2894114858a295aaea4f04666db198cff5e6b3cb 100644 (file)
@@ -61,12 +61,6 @@ pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
                                val, index, NULL, 0);
 }
 
-static inline int
-pl_clear_QuickLink_features(struct usbnet *dev, int val)
-{
-       return pl_vendor_req(dev, 1, (u8) val, 0);
-}
-
 static inline int
 pl_set_QuickLink_features(struct usbnet *dev, int val)
 {
index decb5ba56a25941d1b5f58495d26e8320607bf43..0fc4b959edc18e6bdd156ff1ec642a7dce8c343e 100644 (file)
@@ -1943,7 +1943,7 @@ static struct rx_agg *alloc_rx_agg(struct r8152 *tp, gfp_t mflags)
        if (!rx_agg)
                return NULL;
 
-       rx_agg->page = alloc_pages(mflags | __GFP_COMP, order);
+       rx_agg->page = alloc_pages(mflags | __GFP_COMP | __GFP_NOWARN, order);
        if (!rx_agg->page)
                goto free_rx;
 
index 95de452ff4dad58f05e571b1e569a4d46a9129e2..5d6454fedb3f17707f7cd8a3b963da08e67c76c9 100644 (file)
@@ -2200,6 +2200,13 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING;
                align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
 
+               if (unlikely(size > skb->len)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "size err rx_cmd_a=0x%08x\n",
+                                 rx_cmd_a);
+                       return 0;
+               }
+
                if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
                        netif_dbg(dev, rx_err, dev->net,
                                  "Error rx_cmd_a=0x%08x\n", rx_cmd_a);
index 32d2c60d334dc75abb495cca3b752b2aa64aad9a..563ecd27b93ea56441daf150aecfa2f51219e6cc 100644 (file)
@@ -1833,6 +1833,12 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                size = (u16)((header & RX_STS_FL_) >> 16);
                align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
 
+               if (unlikely(size > skb->len)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "size err header=0x%08x\n", header);
+                       return 0;
+               }
+
                if (unlikely(header & RX_STS_ES_)) {
                        netif_dbg(dev, rx_err, dev->net,
                                  "Error header=0x%08x\n", header);
index 1bb54de7124d95e4974c158017ac6611a370c4d8..4b3c6647edc669413ccd0bccb70e406a43e9320c 100644 (file)
@@ -708,7 +708,8 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
        u32 frame_sz;
 
        if (skb_shared(skb) || skb_head_is_locked(skb) ||
-           skb_shinfo(skb)->nr_frags) {
+           skb_shinfo(skb)->nr_frags ||
+           skb_headroom(skb) < XDP_PACKET_HEADROOM) {
                u32 size, len, max_head_size, off;
                struct sk_buff *nskb;
                struct page *page;
@@ -773,9 +774,6 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
 
                consume_skb(skb);
                skb = nskb;
-       } else if (skb_headroom(skb) < XDP_PACKET_HEADROOM &&
-                  pskb_expand_head(skb, VETH_XDP_HEADROOM, 0, GFP_ATOMIC)) {
-               goto drop;
        }
 
        /* SKB "head" area always have tailroom for skb_shared_info */
@@ -1257,6 +1255,27 @@ static int veth_enable_range_safe(struct net_device *dev, int start, int end)
        return 0;
 }
 
+static void veth_set_xdp_features(struct net_device *dev)
+{
+       struct veth_priv *priv = netdev_priv(dev);
+       struct net_device *peer;
+
+       peer = rtnl_dereference(priv->peer);
+       if (peer && peer->real_num_tx_queues <= dev->real_num_rx_queues) {
+               struct veth_priv *priv_peer = netdev_priv(peer);
+               xdp_features_t val = NETDEV_XDP_ACT_BASIC |
+                                    NETDEV_XDP_ACT_REDIRECT |
+                                    NETDEV_XDP_ACT_RX_SG;
+
+               if (priv_peer->_xdp_prog || veth_gro_requested(peer))
+                       val |= NETDEV_XDP_ACT_NDO_XMIT |
+                              NETDEV_XDP_ACT_NDO_XMIT_SG;
+               xdp_set_features_flag(dev, val);
+       } else {
+               xdp_clear_features_flag(dev);
+       }
+}
+
 static int veth_set_channels(struct net_device *dev,
                             struct ethtool_channels *ch)
 {
@@ -1323,6 +1342,12 @@ out:
                if (peer)
                        netif_carrier_on(peer);
        }
+
+       /* update XDP supported features */
+       veth_set_xdp_features(dev);
+       if (peer)
+               veth_set_xdp_features(peer);
+
        return err;
 
 revert:
@@ -1480,16 +1505,23 @@ static int veth_set_features(struct net_device *dev,
 {
        netdev_features_t changed = features ^ dev->features;
        struct veth_priv *priv = netdev_priv(dev);
+       struct net_device *peer;
        int err;
 
        if (!(changed & NETIF_F_GRO) || !(dev->flags & IFF_UP) || priv->_xdp_prog)
                return 0;
 
+       peer = rtnl_dereference(priv->peer);
        if (features & NETIF_F_GRO) {
                err = veth_napi_enable(dev);
                if (err)
                        return err;
+
+               if (peer)
+                       xdp_features_set_redirect_target(peer, true);
        } else {
+               if (peer)
+                       xdp_features_clear_redirect_target(peer);
                veth_napi_del(dev);
        }
        return 0;
@@ -1570,10 +1602,15 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                        peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
                        peer->max_mtu = max_mtu;
                }
+
+               xdp_features_set_redirect_target(peer, true);
        }
 
        if (old_prog) {
                if (!prog) {
+                       if (peer && !veth_gro_requested(dev))
+                               xdp_features_clear_redirect_target(peer);
+
                        if (dev->flags & IFF_UP)
                                veth_disable_xdp(dev);
 
@@ -1610,20 +1647,24 @@ static int veth_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        struct veth_xdp_buff *_ctx = (void *)ctx;
 
        if (!_ctx->skb)
-               return -EOPNOTSUPP;
+               return -ENODATA;
 
        *timestamp = skb_hwtstamps(_ctx->skb)->hwtstamp;
        return 0;
 }
 
-static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
+static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                           enum xdp_rss_hash_type *rss_type)
 {
        struct veth_xdp_buff *_ctx = (void *)ctx;
+       struct sk_buff *skb = _ctx->skb;
 
-       if (!_ctx->skb)
-               return -EOPNOTSUPP;
+       if (!skb)
+               return -ENODATA;
+
+       *hash = skb_get_hash(skb);
+       *rss_type = skb->l4_hash ? XDP_RSS_TYPE_L4_ANY : XDP_RSS_TYPE_NONE;
 
-       *hash = skb_get_hash(_ctx->skb);
        return 0;
 }
 
@@ -1686,10 +1727,6 @@ static void veth_setup(struct net_device *dev)
        dev->hw_enc_features = VETH_FEATURES;
        dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;
        netif_set_tso_max_size(dev, GSO_MAX_SIZE);
-
-       dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                           NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-                           NETDEV_XDP_ACT_NDO_XMIT_SG;
 }
 
 /*
@@ -1857,6 +1894,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
                goto err_queues;
 
        veth_disable_gro(dev);
+       /* update XDP supported features */
+       veth_set_xdp_features(dev);
+       veth_set_xdp_features(peer);
+
        return 0;
 
 err_queues:
index fb5e68ed3ec27c1895f96108e35ee7b4832595b6..ea1bd4bb326d1690c2b01ee0ef3179dc7674a411 100644 (file)
@@ -446,7 +446,8 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx)
 static struct sk_buff *page_to_skb(struct virtnet_info *vi,
                                   struct receive_queue *rq,
                                   struct page *page, unsigned int offset,
-                                  unsigned int len, unsigned int truesize)
+                                  unsigned int len, unsigned int truesize,
+                                  unsigned int headroom)
 {
        struct sk_buff *skb;
        struct virtio_net_hdr_mrg_rxbuf *hdr;
@@ -464,11 +465,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
        else
                hdr_padded_len = sizeof(struct padded_vnet_hdr);
 
-       buf = p;
+       buf = p - headroom;
        len -= hdr_len;
        offset += hdr_padded_len;
        p += hdr_padded_len;
-       tailroom = truesize - hdr_padded_len - len;
+       tailroom = truesize - headroom  - hdr_padded_len - len;
 
        shinfo_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
@@ -545,6 +546,87 @@ ok:
        return skb;
 }
 
+static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
+{
+       unsigned int len;
+       unsigned int packets = 0;
+       unsigned int bytes = 0;
+       void *ptr;
+
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(!is_xdp_frame(ptr))) {
+                       struct sk_buff *skb = ptr;
+
+                       pr_debug("Sent skb %p\n", skb);
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, in_napi);
+               } else {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
+
+                       bytes += xdp_get_frame_len(frame);
+                       xdp_return_frame(frame);
+               }
+               packets++;
+       }
+
+       /* Avoid overhead when no packets have been processed
+        * happens when called speculatively from start_xmit.
+        */
+       if (!packets)
+               return;
+
+       u64_stats_update_begin(&sq->stats.syncp);
+       sq->stats.bytes += bytes;
+       sq->stats.packets += packets;
+       u64_stats_update_end(&sq->stats.syncp);
+}
+
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+{
+       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+               return false;
+       else if (q < vi->curr_queue_pairs)
+               return true;
+       else
+               return false;
+}
+
+static void check_sq_full_and_disable(struct virtnet_info *vi,
+                                     struct net_device *dev,
+                                     struct send_queue *sq)
+{
+       bool use_napi = sq->napi.weight;
+       int qnum;
+
+       qnum = sq - vi->sq;
+
+       /* If running out of space, stop queue to avoid getting packets that we
+        * are then unable to transmit.
+        * An alternative would be to force queuing layer to requeue the skb by
+        * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be
+        * returned in a normal path of operation: it means that driver is not
+        * maintaining the TX queue stop/start state properly, and causes
+        * the stack to do a non-trivial amount of useless work.
+        * Since most packets only take 1 or 2 ring slots, stopping the queue
+        * early means 16 slots are typically wasted.
+        */
+       if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
+               netif_stop_subqueue(dev, qnum);
+               if (use_napi) {
+                       if (unlikely(!virtqueue_enable_cb_delayed(sq->vq)))
+                               virtqueue_napi_schedule(&sq->napi, sq->vq);
+               } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
+                       /* More just got used, free them then recheck. */
+                       free_old_xmit_skbs(sq, false);
+                       if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
+                               netif_start_subqueue(dev, qnum);
+                               virtqueue_disable_cb(sq->vq);
+                       }
+               }
+       }
+}
+
 static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
                                   struct send_queue *sq,
                                   struct xdp_frame *xdpf)
@@ -686,6 +768,9 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        }
        ret = nxmit;
 
+       if (!is_xdp_raw_buffer_queue(vi, sq - vi->sq))
+               check_sq_full_and_disable(vi, dev, sq);
+
        if (flags & XDP_XMIT_FLUSH) {
                if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq))
                        kicks = 1;
@@ -729,8 +814,13 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
                                       int page_off,
                                       unsigned int *len)
 {
-       struct page *page = alloc_page(GFP_ATOMIC);
+       int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+       struct page *page;
+
+       if (page_off + *len + tailroom > PAGE_SIZE)
+               return NULL;
 
+       page = alloc_page(GFP_ATOMIC);
        if (!page)
                return NULL;
 
@@ -738,7 +828,6 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
        page_off += *len;
 
        while (--*num_buf) {
-               int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
                unsigned int buflen;
                void *buf;
                int off;
@@ -925,7 +1014,7 @@ static struct sk_buff *receive_big(struct net_device *dev,
 {
        struct page *page = buf;
        struct sk_buff *skb =
-               page_to_skb(vi, rq, page, 0, len, PAGE_SIZE);
+               page_to_skb(vi, rq, page, 0, len, PAGE_SIZE, 0);
 
        stats->bytes += len - vi->hdr_len;
        if (unlikely(!skb))
@@ -1188,9 +1277,12 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
 
                switch (act) {
                case XDP_PASS:
+                       head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
+                       if (unlikely(!head_skb))
+                               goto err_xdp_frags;
+
                        if (unlikely(xdp_page != page))
                                put_page(page);
-                       head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
                        rcu_read_unlock();
                        return head_skb;
                case XDP_TX:
@@ -1248,7 +1340,7 @@ err_xdp_frags:
        rcu_read_unlock();
 
 skip_xdp:
-       head_skb = page_to_skb(vi, rq, page, offset, len, truesize);
+       head_skb = page_to_skb(vi, rq, page, offset, len, truesize, headroom);
        curr_skb = head_skb;
 
        if (unlikely(!curr_skb))
@@ -1714,52 +1806,6 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
        return stats.packets;
 }
 
-static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
-{
-       unsigned int len;
-       unsigned int packets = 0;
-       unsigned int bytes = 0;
-       void *ptr;
-
-       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-               if (likely(!is_xdp_frame(ptr))) {
-                       struct sk_buff *skb = ptr;
-
-                       pr_debug("Sent skb %p\n", skb);
-
-                       bytes += skb->len;
-                       napi_consume_skb(skb, in_napi);
-               } else {
-                       struct xdp_frame *frame = ptr_to_xdp(ptr);
-
-                       bytes += xdp_get_frame_len(frame);
-                       xdp_return_frame(frame);
-               }
-               packets++;
-       }
-
-       /* Avoid overhead when no packets have been processed
-        * happens when called speculatively from start_xmit.
-        */
-       if (!packets)
-               return;
-
-       u64_stats_update_begin(&sq->stats.syncp);
-       sq->stats.bytes += bytes;
-       sq->stats.packets += packets;
-       u64_stats_update_end(&sq->stats.syncp);
-}
-
-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
-{
-       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
-               return false;
-       else if (q < vi->curr_queue_pairs)
-               return true;
-       else
-               return false;
-}
-
 static void virtnet_poll_cleantx(struct receive_queue *rq)
 {
        struct virtnet_info *vi = rq->vq->vdev->priv;
@@ -1989,30 +2035,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
                nf_reset_ct(skb);
        }
 
-       /* If running out of space, stop queue to avoid getting packets that we
-        * are then unable to transmit.
-        * An alternative would be to force queuing layer to requeue the skb by
-        * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be
-        * returned in a normal path of operation: it means that driver is not
-        * maintaining the TX queue stop/start state properly, and causes
-        * the stack to do a non-trivial amount of useless work.
-        * Since most packets only take 1 or 2 ring slots, stopping the queue
-        * early means 16 slots are typically wasted.
-        */
-       if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
-               netif_stop_subqueue(dev, qnum);
-               if (use_napi) {
-                       if (unlikely(!virtqueue_enable_cb_delayed(sq->vq)))
-                               virtqueue_napi_schedule(&sq->napi, sq->vq);
-               } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
-                       /* More just got used, free them then recheck. */
-                       free_old_xmit_skbs(sq, false);
-                       if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
-                               netif_start_subqueue(dev, qnum);
-                               virtqueue_disable_cb(sq->vq);
-                       }
-               }
-       }
+       check_sq_full_and_disable(vi, dev, sq);
 
        if (kick || netif_xmit_stopped(txq)) {
                if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) {
index 682987040ea821e74d2d732a77d93d546f803006..f2b76ee866a4a80154591bab17a4483d9897fcb8 100644 (file)
@@ -1504,7 +1504,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                                goto rcd_done;
                        }
 
-                       if (rxDataRingUsed) {
+                       if (rxDataRingUsed && adapter->rxdataring_enabled) {
                                size_t sz;
 
                                BUG_ON(rcd->len > rq->data_ring.desc_size);
@@ -1688,7 +1688,9 @@ not_lro:
                        if (unlikely(rcd->ts))
                                __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), rcd->tci);
 
-                       if (adapter->netdev->features & NETIF_F_LRO)
+                       /* Use GRO callback if UPT is enabled */
+                       if ((adapter->netdev->features & NETIF_F_LRO) &&
+                           !rq->shared->updateRxProd)
                                netif_receive_skb(skb);
                        else
                                napi_gro_receive(&rq->napi, skb);
index 1c53b5546927052a336bcefabd6876c999f6f1c2..47c2ad7a3e429ae03fc732024728b113fe77d87e 100644 (file)
@@ -1177,14 +1177,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
        uhdlc_priv->dev = &pdev->dev;
        uhdlc_priv->ut_info = ut_info;
 
-       if (of_get_property(np, "fsl,tdm-interface", NULL))
-               uhdlc_priv->tsa = 1;
-
-       if (of_get_property(np, "fsl,ucc-internal-loopback", NULL))
-               uhdlc_priv->loopback = 1;
-
-       if (of_get_property(np, "fsl,hdlc-bus", NULL))
-               uhdlc_priv->hdlc_bus = 1;
+       uhdlc_priv->tsa = of_property_read_bool(np, "fsl,tdm-interface");
+       uhdlc_priv->loopback = of_property_read_bool(np, "fsl,ucc-internal-loopback");
+       uhdlc_priv->hdlc_bus = of_property_read_bool(np, "fsl,hdlc-bus");
 
        if (uhdlc_priv->tsa == 1) {
                utdm = kzalloc(sizeof(*utdm), GFP_KERNEL);
index 90f457b8e1feb8df6a9718fd411054bfc55f3e21..038c5903c0dc15789ae9d192ee308b74c5d796a5 100644 (file)
@@ -33,7 +33,7 @@ static int ath10k_qmi_map_msa_permission(struct ath10k_qmi *qmi,
 {
        struct qcom_scm_vmperm dst_perms[3];
        struct ath10k *ar = qmi->ar;
-       unsigned int src_perms;
+       u64 src_perms;
        u32 perm_count;
        int ret;
 
@@ -65,7 +65,7 @@ static int ath10k_qmi_unmap_msa_permission(struct ath10k_qmi *qmi,
 {
        struct qcom_scm_vmperm dst_perms;
        struct ath10k *ar = qmi->ar;
-       unsigned int src_perms;
+       u64 src_perms;
        int ret;
 
        src_perms = BIT(QCOM_SCM_VMID_MSS_MSA) | BIT(QCOM_SCM_VMID_WLAN);
index 86995e8dc9135162233959920827b615534845df..a62ee05c54097253d3514ffbc1c2c7e95e1141d7 100644 (file)
@@ -16,7 +16,7 @@
 #include "pci.h"
 #include "pcic.h"
 
-#define MHI_TIMEOUT_DEFAULT_MS 90000
+#define MHI_TIMEOUT_DEFAULT_MS 20000
 #define RDDM_DUMP_SIZE 0x420000
 
 static struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
index 3363fc4e89661a98d1e1a96a7b3cccf5dafd15fb..a0845002d6fe325584e6c35030809fabf15c4207 100644 (file)
@@ -646,9 +646,7 @@ void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
        struct ath_hw *ah = sc->sc_ah;
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
        struct ath9k_channel *chan = ah->curchan;
-       static const u32 channelmap[] = {
-               0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff
-       };
+       u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
        int i;
        s16 chan_start, chan_end;
        u16 wlan_chan;
index b7c918f241c91e77ce30876232f25f5ba80fe031..65d4799a5658404cfad861367d7ba69559db7635 100644 (file)
@@ -994,15 +994,34 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
 
 
-static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev,
-                                                 int val)
+static void brcmf_sdiod_acpi_save_power_manageable(struct brcmf_sdio_dev *sdiodev)
 {
 #if IS_ENABLED(CONFIG_ACPI)
        struct acpi_device *adev;
 
-       adev = ACPI_COMPANION(dev);
+       adev = ACPI_COMPANION(&sdiodev->func1->dev);
        if (adev)
-               adev->flags.power_manageable = 0;
+               sdiodev->func1_power_manageable = adev->flags.power_manageable;
+
+       adev = ACPI_COMPANION(&sdiodev->func2->dev);
+       if (adev)
+               sdiodev->func2_power_manageable = adev->flags.power_manageable;
+#endif
+}
+
+static void brcmf_sdiod_acpi_set_power_manageable(struct brcmf_sdio_dev *sdiodev,
+                                                 int enable)
+{
+#if IS_ENABLED(CONFIG_ACPI)
+       struct acpi_device *adev;
+
+       adev = ACPI_COMPANION(&sdiodev->func1->dev);
+       if (adev)
+               adev->flags.power_manageable = enable ? sdiodev->func1_power_manageable : 0;
+
+       adev = ACPI_COMPANION(&sdiodev->func2->dev);
+       if (adev)
+               adev->flags.power_manageable = enable ? sdiodev->func2_power_manageable : 0;
 #endif
 }
 
@@ -1012,7 +1031,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        int err;
        struct brcmf_sdio_dev *sdiodev;
        struct brcmf_bus *bus_if;
-       struct device *dev;
 
        brcmf_dbg(SDIO, "Enter\n");
        brcmf_dbg(SDIO, "Class=%x\n", func->class);
@@ -1020,14 +1038,9 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device);
        brcmf_dbg(SDIO, "Function#: %d\n", func->num);
 
-       dev = &func->dev;
-
        /* Set MMC_QUIRK_LENIENT_FN0 for this card */
        func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 
-       /* prohibit ACPI power management for this device */
-       brcmf_sdiod_acpi_set_power_manageable(dev, 0);
-
        /* Consume func num 1 but dont do anything with it. */
        if (func->num == 1)
                return 0;
@@ -1059,6 +1072,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
        dev_set_drvdata(&sdiodev->func1->dev, bus_if);
        sdiodev->dev = &sdiodev->func1->dev;
 
+       brcmf_sdiod_acpi_save_power_manageable(sdiodev);
        brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
 
        brcmf_dbg(SDIO, "F2 found, calling brcmf_sdiod_probe...\n");
@@ -1124,6 +1138,8 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
 
        if (sdiodev->settings->bus.sdio.oob_irq_supported ||
            pm_caps & MMC_PM_WAKE_SDIO_IRQ) {
+               /* Stop ACPI from turning off the device when wowl is enabled */
+               brcmf_sdiod_acpi_set_power_manageable(sdiodev, !enabled);
                sdiodev->wowl_enabled = enabled;
                brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
                return;
index b76d34d36bde6435f11390a3c10e3f5ccb243acd..0d18ed15b4032a9925660384ff9918cd3f38e76b 100644 (file)
@@ -188,6 +188,8 @@ struct brcmf_sdio_dev {
        char nvram_name[BRCMF_FW_NAME_LEN];
        char clm_name[BRCMF_FW_NAME_LEN];
        bool wowl_enabled;
+       bool func1_power_manageable;
+       bool func2_power_manageable;
        enum brcmf_sdiod_state state;
        struct brcmf_sdiod_freezer *freezer;
        const struct firmware *clm_fw;
index 565522466eba5465f15be91a72b370f40afae71e..b55b1b17f4d197cf32775699087702bae2396bff 100644 (file)
@@ -732,7 +732,10 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
 
        rcu_read_lock();
        do {
-               while (likely(!mvmtxq->stopped &&
+               while (likely(!test_bit(IWL_MVM_TXQ_STATE_STOP_FULL,
+                                       &mvmtxq->state) &&
+                             !test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT,
+                                       &mvmtxq->state) &&
                              !test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) {
                        skb = ieee80211_tx_dequeue(hw, txq);
 
@@ -757,42 +760,25 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
 
-       /*
-        * Please note that racing is handled very carefully here:
-        * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
-        * deleted afterwards.
-        * This means that if:
-        * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
-        *      queue is allocated and we can TX.
-        * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
-        *      a race, should defer the frame.
-        * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
-        *      need to allocate the queue and defer the frame.
-        * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
-        *      queue is already scheduled for allocation, no need to allocate,
-        *      should defer the frame.
-        */
-
-       /* If the queue is allocated TX and return. */
-       if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
-               /*
-                * Check that list is empty to avoid a race where txq_id is
-                * already updated, but the queue allocation work wasn't
-                * finished
-                */
-               if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
-                       return;
-
+       if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
+           !txq->sta) {
                iwl_mvm_mac_itxq_xmit(hw, txq);
                return;
        }
 
-       /* The list is being deleted only after the queue is fully allocated. */
-       if (!list_empty(&mvmtxq->list))
-               return;
+       /* iwl_mvm_mac_itxq_xmit() will later be called by the worker
+        * to handle any packets we leave on the txq now
+        */
 
-       list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
-       schedule_work(&mvm->add_stream_wk);
+       spin_lock_bh(&mvm->add_stream_lock);
+       /* The list is being deleted only after the queue is fully allocated. */
+       if (list_empty(&mvmtxq->list) &&
+           /* recheck under lock */
+           !test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) {
+               list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
+               schedule_work(&mvm->add_stream_wk);
+       }
+       spin_unlock_bh(&mvm->add_stream_lock);
 }
 
 #define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...)          \
index 90bc95d96a78e8894a5b5bc6f0eba4d8ac9037da..f307c345dfa0b4b9b815daa717f51751d17cdf0d 100644 (file)
@@ -729,7 +729,10 @@ struct iwl_mvm_txq {
        struct list_head list;
        u16 txq_id;
        atomic_t tx_request;
-       bool stopped;
+#define IWL_MVM_TXQ_STATE_STOP_FULL    0
+#define IWL_MVM_TXQ_STATE_STOP_REDIRECT        1
+#define IWL_MVM_TXQ_STATE_READY                2
+       unsigned long state;
 };
 
 static inline struct iwl_mvm_txq *
@@ -827,6 +830,7 @@ struct iwl_mvm {
                struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES];
        };
        struct work_struct add_stream_wk; /* To add streams to queues */
+       spinlock_t add_stream_lock;
 
        const char *nvm_file_name;
        struct iwl_nvm_data *nvm_data;
index f4e9446d9dc2d959b52fa6ab84ae12573f050141..9711841bb4564d33b8edaab378ced12db0a295b6 100644 (file)
@@ -1195,6 +1195,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
        INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
        INIT_LIST_HEAD(&mvm->add_stream_txqs);
+       spin_lock_init(&mvm->add_stream_lock);
 
        init_waitqueue_head(&mvm->rx_sync_waitq);
 
@@ -1691,7 +1692,10 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
 
                txq = sta->txq[tid];
                mvmtxq = iwl_mvm_txq_from_mac80211(txq);
-               mvmtxq->stopped = !start;
+               if (start)
+                       clear_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
+               else
+                       set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
 
                if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
                        iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
index 69634fb82a9bf104530e04eac0d3e6f44dbff9c8..9caae77995ca933cdce204fac7663c51213f9389 100644 (file)
@@ -384,8 +384,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
                struct iwl_mvm_txq *mvmtxq =
                        iwl_mvm_txq_from_tid(sta, tid);
 
-               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_lock_bh(&mvm->add_stream_lock);
                list_del_init(&mvmtxq->list);
+               clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_unlock_bh(&mvm->add_stream_lock);
        }
 
        /* Regardless if this is a reserved TXQ for a STA - mark it as false */
@@ -479,8 +482,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
                        disable_agg_tids |= BIT(tid);
                mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
 
-               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_lock_bh(&mvm->add_stream_lock);
                list_del_init(&mvmtxq->list);
+               clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+               spin_unlock_bh(&mvm->add_stream_lock);
        }
 
        mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */
@@ -693,7 +699,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
                            queue, iwl_mvm_ac_to_tx_fifo[ac]);
 
        /* Stop the queue and wait for it to empty */
-       txq->stopped = true;
+       set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
 
        ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));
        if (ret) {
@@ -736,7 +742,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
 
 out:
        /* Continue using the queue */
-       txq->stopped = false;
+       clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
 
        return ret;
 }
@@ -1444,12 +1450,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
                 * a queue in the function itself.
                 */
                if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) {
+                       spin_lock_bh(&mvm->add_stream_lock);
                        list_del_init(&mvmtxq->list);
+                       spin_unlock_bh(&mvm->add_stream_lock);
                        continue;
                }
 
-               list_del_init(&mvmtxq->list);
+               /* now we're ready, any remaining races/concurrency will be
+                * handled in iwl_mvm_mac_itxq_xmit()
+                */
+               set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+
                local_bh_disable();
+               spin_lock(&mvm->add_stream_lock);
+               list_del_init(&mvmtxq->list);
+               spin_unlock(&mvm->add_stream_lock);
+
                iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
                local_bh_enable();
        }
@@ -1864,8 +1880,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
                struct iwl_mvm_txq *mvmtxq =
                        iwl_mvm_txq_from_mac80211(sta->txq[i]);
 
+               spin_lock_bh(&mvm->add_stream_lock);
                mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
                list_del_init(&mvmtxq->list);
+               clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+               spin_unlock_bh(&mvm->add_stream_lock);
        }
 }
 
index 5dcf61761a165ae0d1b9c19cd84f4e740c47a09a..9a698a16a8f38e8cde08ff078b3021cb042224db 100644 (file)
@@ -172,7 +172,7 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = {
        .can_ext_scan = true,
 };
 
-static const struct of_device_id mwifiex_pcie_of_match_table[] = {
+static const struct of_device_id mwifiex_pcie_of_match_table[] __maybe_unused = {
        { .compatible = "pci11ab,2b42" },
        { .compatible = "pci1b4b,2b42" },
        { }
index c64e24c10ea659908cd697321ac6adc996ddf835..a24bd40dd41ab88cdc7bd3ddcee7927df796e0fc 100644 (file)
@@ -495,7 +495,7 @@ static struct memory_type_mapping mem_type_mapping_tbl[] = {
        {"EXTLAST", NULL, 0, 0xFE},
 };
 
-static const struct of_device_id mwifiex_sdio_of_match_table[] = {
+static const struct of_device_id mwifiex_sdio_of_match_table[] __maybe_unused = {
        { .compatible = "marvell,sd8787" },
        { .compatible = "marvell,sd8897" },
        { .compatible = "marvell,sd8978" },
index b117e4467c87033a130b9a9bd44c14eb1b5fb015..34abf70f44aff8cf45f0e8d0d706643d3a10a06c 100644 (file)
@@ -539,6 +539,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
        if (ret)
                return ret;
 
+       set_bit(MT76_STATE_REGISTERED, &phy->state);
        phy->dev->phys[phy->band_idx] = phy;
 
        return 0;
@@ -549,6 +550,9 @@ void mt76_unregister_phy(struct mt76_phy *phy)
 {
        struct mt76_dev *dev = phy->dev;
 
+       if (!test_bit(MT76_STATE_REGISTERED, &phy->state))
+               return;
+
        if (IS_ENABLED(CONFIG_MT76_LEDS))
                mt76_led_cleanup(phy);
        mt76_tx_status_check(dev, true);
@@ -719,6 +723,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
                return ret;
 
        WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
+       set_bit(MT76_STATE_REGISTERED, &phy->state);
        sched_set_fifo_low(dev->tx_worker.task);
 
        return 0;
@@ -729,6 +734,9 @@ void mt76_unregister_device(struct mt76_dev *dev)
 {
        struct ieee80211_hw *hw = dev->hw;
 
+       if (!test_bit(MT76_STATE_REGISTERED, &dev->phy.state))
+               return;
+
        if (IS_ENABLED(CONFIG_MT76_LEDS))
                mt76_led_cleanup(&dev->phy);
        mt76_tx_status_check(dev, true);
index ccca0162c8f82cd3983a43dffad4cef8daff4952..183b0fc5a2d48c61d7cd5f554cc4b95a5cd74b74 100644 (file)
@@ -402,6 +402,7 @@ struct mt76_tx_cb {
 
 enum {
        MT76_STATE_INITIALIZED,
+       MT76_STATE_REGISTERED,
        MT76_STATE_RUNNING,
        MT76_STATE_MCU_RUNNING,
        MT76_SCANNING,
index ca50feb0b3a9d31fb768df9d1c1d8791f69f2d38..1b1358c6bb4642602f190579e1f36c1fcd79d850 100644 (file)
@@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
            !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
                return -EOPNOTSUPP;
 
-       if (cmd == SET_KEY) {
-               key->hw_key_idx = wcid->idx;
-               wcid->hw_key_idx = idx;
-       } else {
+       if (cmd != SET_KEY) {
                if (idx == wcid->hw_key_idx)
                        wcid->hw_key_idx = -1;
 
-               key = NULL;
+               return 0;
        }
+
+       key->hw_key_idx = wcid->idx;
+       wcid->hw_key_idx = idx;
        mt76_wcid_key_setup(&dev->mt76, wcid, key);
 
        return mt7603_wtbl_set_key(dev, wcid->idx, key);
index a95602473359e396f76107a6f022ff2d234405e8..51a968a6afdc9d17fdf290891f59ff2ccc6a0084 100644 (file)
@@ -1193,8 +1193,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
 static int
 mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
                           struct ieee80211_key_conf *key,
-                          enum mt76_cipher_type cipher, u16 cipher_mask,
-                          enum set_key_cmd cmd)
+                          enum mt76_cipher_type cipher, u16 cipher_mask)
 {
        u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
        u8 data[32] = {};
@@ -1203,27 +1202,18 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
                return -EINVAL;
 
        mt76_rr_copy(dev, addr, data, sizeof(data));
-       if (cmd == SET_KEY) {
-               if (cipher == MT_CIPHER_TKIP) {
-                       /* Rx/Tx MIC keys are swapped */
-                       memcpy(data, key->key, 16);
-                       memcpy(data + 16, key->key + 24, 8);
-                       memcpy(data + 24, key->key + 16, 8);
-               } else {
-                       if (cipher_mask == BIT(cipher))
-                               memcpy(data, key->key, key->keylen);
-                       else if (cipher != MT_CIPHER_BIP_CMAC_128)
-                               memcpy(data, key->key, 16);
-                       if (cipher == MT_CIPHER_BIP_CMAC_128)
-                               memcpy(data + 16, key->key, 16);
-               }
+       if (cipher == MT_CIPHER_TKIP) {
+               /* Rx/Tx MIC keys are swapped */
+               memcpy(data, key->key, 16);
+               memcpy(data + 16, key->key + 24, 8);
+               memcpy(data + 24, key->key + 16, 8);
        } else {
+               if (cipher_mask == BIT(cipher))
+                       memcpy(data, key->key, key->keylen);
+               else if (cipher != MT_CIPHER_BIP_CMAC_128)
+                       memcpy(data, key->key, 16);
                if (cipher == MT_CIPHER_BIP_CMAC_128)
-                       memset(data + 16, 0, 16);
-               else if (cipher_mask)
-                       memset(data, 0, 16);
-               if (!cipher_mask)
-                       memset(data, 0, sizeof(data));
+                       memcpy(data + 16, key->key, 16);
        }
 
        mt76_wr_copy(dev, addr, data, sizeof(data));
@@ -1234,7 +1224,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
 static int
 mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
                          enum mt76_cipher_type cipher, u16 cipher_mask,
-                         int keyidx, enum set_key_cmd cmd)
+                         int keyidx)
 {
        u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;
 
@@ -1253,9 +1243,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
        else
                w0 &= ~MT_WTBL_W0_RX_IK_VALID;
 
-       if (cmd == SET_KEY &&
-           (cipher != MT_CIPHER_BIP_CMAC_128 ||
-            cipher_mask == BIT(cipher))) {
+       if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) {
                w0 &= ~MT_WTBL_W0_KEY_IDX;
                w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
        }
@@ -1272,19 +1260,10 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
 
 static void
 mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
-                             enum mt76_cipher_type cipher, u16 cipher_mask,
-                             enum set_key_cmd cmd)
+                             enum mt76_cipher_type cipher, u16 cipher_mask)
 {
        u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);
 
-       if (!cipher_mask) {
-               mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
-               return;
-       }
-
-       if (cmd != SET_KEY)
-               return;
-
        if (cipher == MT_CIPHER_BIP_CMAC_128 &&
            cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
                return;
@@ -1295,8 +1274,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
 
 int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
                              struct mt76_wcid *wcid,
-                             struct ieee80211_key_conf *key,
-                             enum set_key_cmd cmd)
+                             struct ieee80211_key_conf *key)
 {
        enum mt76_cipher_type cipher;
        u16 cipher_mask = wcid->cipher;
@@ -1306,19 +1284,14 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
        if (cipher == MT_CIPHER_NONE)
                return -EOPNOTSUPP;
 
-       if (cmd == SET_KEY)
-               cipher_mask |= BIT(cipher);
-       else
-               cipher_mask &= ~BIT(cipher);
-
-       mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
-       err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
-                                        cmd);
+       cipher_mask |= BIT(cipher);
+       mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask);
+       err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask);
        if (err < 0)
                return err;
 
        err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
-                                       key->keyidx, cmd);
+                                       key->keyidx);
        if (err < 0)
                return err;
 
@@ -1329,13 +1302,12 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
 
 int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
                            struct mt76_wcid *wcid,
-                           struct ieee80211_key_conf *key,
-                           enum set_key_cmd cmd)
+                           struct ieee80211_key_conf *key)
 {
        int err;
 
        spin_lock_bh(&dev->mt76.lock);
-       err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+       err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
        spin_unlock_bh(&dev->mt76.lock);
 
        return err;
index ab4c1b4478aa99df2b82ea4980af4f7d1a500674..dadb13f2ca09568b7f706661146b3b90a2e1cbce 100644 (file)
@@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        if (cmd == SET_KEY)
                *wcid_keyidx = idx;
-       else if (idx == *wcid_keyidx)
-               *wcid_keyidx = -1;
-       else
+       else {
+               if (idx == *wcid_keyidx)
+                       *wcid_keyidx = -1;
                goto out;
+       }
 
-       mt76_wcid_key_setup(&dev->mt76, wcid,
-                           cmd == SET_KEY ? key : NULL);
-
+       mt76_wcid_key_setup(&dev->mt76, wcid, key);
        if (mt76_is_mmio(&dev->mt76))
-               err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+               err = mt7615_mac_wtbl_set_key(dev, wcid, key);
        else
-               err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
+               err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
 
 out:
        mt7615_mutex_release(dev);
index 43591b4c1d9afc38d516b62862a0995c9bc99a5e..9e58f6924493f6c3db605122b7c9aa8ef189c80c 100644 (file)
@@ -490,11 +490,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
 void mt7615_mac_set_timing(struct mt7615_phy *phy);
 int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
                              struct mt76_wcid *wcid,
-                             struct ieee80211_key_conf *key,
-                             enum set_key_cmd cmd);
+                             struct ieee80211_key_conf *key);
 int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
-                           struct ieee80211_key_conf *key,
-                           enum set_key_cmd cmd);
+                           struct ieee80211_key_conf *key);
 void mt7615_mac_reset_work(struct work_struct *work);
 u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);
 
index efb9bfaa187f295441f01ddf67ddcdf6eb314b62..008ece1b16f8ebc9b5c122c82723847aaac79ba7 100644 (file)
@@ -1221,6 +1221,9 @@ EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv);
 
 int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb)
 {
+       if (!mt76_is_mmio(dev))
+               return 0;
+
        if (!mtk_wed_device_active(&dev->mmio.wed))
                return 0;
 
index 7451a63206a5f73da99b2c251b1d29c10e2677d1..dcbb5c605dfe69b450d8bae760e806b48142e9a1 100644 (file)
@@ -454,20 +454,20 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
        wcid = msta ? &msta->wcid : &mvif->group_wcid;
 
-       if (cmd == SET_KEY) {
-               key->hw_key_idx = wcid->idx;
-               wcid->hw_key_idx = idx;
-               if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
-                       key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
-                       wcid->sw_iv = true;
-               }
-       } else {
+       if (cmd != SET_KEY) {
                if (idx == wcid->hw_key_idx) {
                        wcid->hw_key_idx = -1;
                        wcid->sw_iv = false;
                }
 
-               key = NULL;
+               return 0;
+       }
+
+       key->hw_key_idx = wcid->idx;
+       wcid->hw_key_idx = idx;
+       if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
+               key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+               wcid->sw_iv = true;
        }
        mt76_wcid_key_setup(&dev->mt76, wcid, key);
 
index 1ab768feccaac0f9511351d090e131d12e9d83b3..5e288116b1b010805269076eceaf8a7f82a2b4e9 100644 (file)
@@ -383,7 +383,6 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
        ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);
        ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID);
        ieee80211_hw_set(hw, WANT_MONITOR_VIF);
-       ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
 
        hw->max_tx_fragments = 4;
 
@@ -396,6 +395,9 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
        }
 
        if (phy->mt76->cap.has_5ghz) {
+               struct ieee80211_sta_vht_cap *vht_cap;
+
+               vht_cap = &phy->mt76->sband_5g.sband.vht_cap;
                phy->mt76->sband_5g.sband.ht_cap.cap |=
                        IEEE80211_HT_CAP_LDPC_CODING |
                        IEEE80211_HT_CAP_MAX_AMSDU;
@@ -403,19 +405,28 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
                        IEEE80211_HT_MPDU_DENSITY_4;
 
                if (is_mt7915(&dev->mt76)) {
-                       phy->mt76->sband_5g.sband.vht_cap.cap |=
+                       vht_cap->cap |=
                                IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
                                IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+
+                       if (!dev->dbdc_support)
+                               vht_cap->cap |=
+                                       IEEE80211_VHT_CAP_SHORT_GI_160 |
+                                       IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
+                                       FIELD_PREP(IEEE80211_VHT_CAP_EXT_NSS_BW_MASK, 1);
                } else {
-                       phy->mt76->sband_5g.sband.vht_cap.cap |=
+                       vht_cap->cap |=
                                IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
                                IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
 
                        /* mt7916 dbdc with 2g 2x2 bw40 and 5g 2x2 bw160c */
-                       phy->mt76->sband_5g.sband.vht_cap.cap |=
+                       vht_cap->cap |=
                                IEEE80211_VHT_CAP_SHORT_GI_160 |
                                IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
                }
+
+               if (!is_mt7915(&dev->mt76) || !dev->dbdc_support)
+                       ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);
        }
 
        mt76_set_stream_caps(phy->mt76, true);
@@ -841,9 +852,13 @@ mt7915_set_stream_he_txbf_caps(struct mt7915_phy *phy,
        int sts = hweight8(phy->mt76->chainmask);
        u8 c, sts_160 = sts;
 
-       /* mt7915 doesn't support bw160 */
-       if (is_mt7915(&dev->mt76))
-               sts_160 = 0;
+       /* Can do 1/2 of STS in 160Mhz mode for mt7915 */
+       if (is_mt7915(&dev->mt76)) {
+               if (!dev->dbdc_support)
+                       sts_160 /= 2;
+               else
+                       sts_160 = 0;
+       }
 
 #ifdef CONFIG_MAC80211_MESH
        if (vif == NL80211_IFTYPE_MESH_POINT)
@@ -944,10 +959,15 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
        int i, idx = 0, nss = hweight8(phy->mt76->antenna_mask);
        u16 mcs_map = 0;
        u16 mcs_map_160 = 0;
-       u8 nss_160 = nss;
+       u8 nss_160;
 
-       /* Can't do 160MHz with mt7915 */
-       if (is_mt7915(&dev->mt76))
+       if (!is_mt7915(&dev->mt76))
+               nss_160 = nss;
+       else if (!dev->dbdc_support)
+               /* Can do 1/2 of NSS streams in 160Mhz mode for mt7915 */
+               nss_160 = nss / 2;
+       else
+               /* Can't do 160MHz with mt7915 dbdc */
                nss_160 = 0;
 
        for (i = 0; i < 8; i++) {
index 3bbccbdfc5eb0ad5ee2f6c70959391bbfb085a38..784191ec48029150abd23912d4c166e8efbfc4d2 100644 (file)
@@ -410,16 +410,15 @@ static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                mt7915_mcu_add_bss_info(phy, vif, true);
        }
 
-       if (cmd == SET_KEY)
+       if (cmd == SET_KEY) {
                *wcid_keyidx = idx;
-       else if (idx == *wcid_keyidx)
-               *wcid_keyidx = -1;
-       else
+       } else {
+               if (idx == *wcid_keyidx)
+                       *wcid_keyidx = -1;
                goto out;
+       }
 
-       mt76_wcid_key_setup(&dev->mt76, wcid,
-                           cmd == SET_KEY ? key : NULL);
-
+       mt76_wcid_key_setup(&dev->mt76, wcid, key);
        err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
                                      key, MCU_EXT_CMD(STA_REC_UPDATE),
                                      &msta->wcid, cmd);
index 80c71acfe1591cc0afd898c1e08fbd6e4b4cdeb9..cc94531185dac2b7a1fef4b333b469bb8e46c5c0 100644 (file)
@@ -171,12 +171,12 @@ mt7921_mac_init_band(struct mt7921_dev *dev, u8 band)
 
 u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
 {
-       struct mt7921_fw_features *features = NULL;
        const struct mt76_connac2_fw_trailer *hdr;
        struct mt7921_realease_info *rel_info;
        const struct firmware *fw;
        int ret, i, offset = 0;
        const u8 *data, *end;
+       u8 offload_caps = 0;
 
        ret = request_firmware(&fw, fw_wm, dev);
        if (ret)
@@ -208,7 +208,10 @@ u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
                data += sizeof(*rel_info);
 
                if (rel_info->tag == MT7921_FW_TAG_FEATURE) {
+                       struct mt7921_fw_features *features;
+
                        features = (struct mt7921_fw_features *)data;
+                       offload_caps = features->data;
                        break;
                }
 
@@ -218,7 +221,7 @@ u8 mt7921_check_offload_capability(struct device *dev, const char *fw_wm)
 out:
        release_firmware(fw);
 
-       return features ? features->data : 0;
+       return offload_caps;
 }
 EXPORT_SYMBOL_GPL(mt7921_check_offload_capability);
 
index 75eaf86c6a78e9ab287e4bbb3c73d9c0f8485522..42933a6b7334b391cf32dc873abbd08ef23742e0 100644 (file)
@@ -569,16 +569,15 @@ static int mt7921_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        mt7921_mutex_acquire(dev);
 
-       if (cmd == SET_KEY)
+       if (cmd == SET_KEY) {
                *wcid_keyidx = idx;
-       else if (idx == *wcid_keyidx)
-               *wcid_keyidx = -1;
-       else
+       } else {
+               if (idx == *wcid_keyidx)
+                       *wcid_keyidx = -1;
                goto out;
+       }
 
-       mt76_wcid_key_setup(&dev->mt76, wcid,
-                           cmd == SET_KEY ? key : NULL);
-
+       mt76_wcid_key_setup(&dev->mt76, wcid, key);
        err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip,
                                      key, MCU_UNI_CMD(STA_REC_UPDATE),
                                      &msta->wcid, cmd);
index cb72ded372564ea5bf52bea2f66e80cab767fe9a..5c23c827abe476df6f5f7f5b53aeeeb4af5313e5 100644 (file)
@@ -20,7 +20,7 @@ static const struct pci_device_id mt7921_pci_device_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0608),
                .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
        { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x0616),
-               .driver_data = (kernel_ulong_t)MT7921_FIRMWARE_WM },
+               .driver_data = (kernel_ulong_t)MT7922_FIRMWARE_WM },
        { },
 };
 
index 3e4da0350d965b282e3b722c1019f519479a0231..1ba22d147949bc9d995676c8602f1e465cd7ad99 100644 (file)
@@ -351,16 +351,15 @@ static int mt7996_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                mt7996_mcu_add_bss_info(phy, vif, true);
        }
 
-       if (cmd == SET_KEY)
+       if (cmd == SET_KEY) {
                *wcid_keyidx = idx;
-       else if (idx == *wcid_keyidx)
-               *wcid_keyidx = -1;
-       else
+       } else {
+               if (idx == *wcid_keyidx)
+                       *wcid_keyidx = -1;
                goto out;
+       }
 
-       mt76_wcid_key_setup(&dev->mt76, wcid,
-                           cmd == SET_KEY ? key : NULL);
-
+       mt76_wcid_key_setup(&dev->mt76, wcid, key);
        err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip,
                                 key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
                                 &msta->wcid, cmd);
index 2d2edddc77bdd146027b8ccaa73d3ff52b9a0b6c..3f88e6a0a510ed14f84a0d7a1e0147509293e262 100644 (file)
@@ -447,8 +447,7 @@ static int wlcore_probe_of(struct spi_device *spi, struct wl12xx_spi_glue *glue,
        dev_info(&spi->dev, "selected chip family is %s\n",
                 pdev_data->family->name);
 
-       if (of_find_property(dt_node, "clock-xtal", NULL))
-               pdev_data->ref_clock_xtal = true;
+       pdev_data->ref_clock_xtal = of_property_read_bool(dt_node, "clock-xtal");
 
        /* optional clock frequency params */
        of_property_read_u32(dt_node, "ref-clock-frequency",
index 1e6a47976642907ef9d2e606f4d07a485146ab55..c066b0040a3fe5fb6668bd35d45694495dc1647a 100644 (file)
@@ -587,6 +587,13 @@ static void ipc_imem_run_state_worker(struct work_struct *instance)
        while (ctrl_chl_idx < IPC_MEM_MAX_CHANNELS) {
                if (!ipc_chnl_cfg_get(&chnl_cfg_port, ctrl_chl_idx)) {
                        ipc_imem->ipc_port[ctrl_chl_idx] = NULL;
+
+                       if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID &&
+                           chnl_cfg_port.wwan_port_type == WWAN_PORT_XMMRPC) {
+                               ctrl_chl_idx++;
+                               continue;
+                       }
+
                        if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7360_ID &&
                            chnl_cfg_port.wwan_port_type == WWAN_PORT_MBIM) {
                                ctrl_chl_idx++;
index 5bf5a93937c9c4dd898d41407f26606742735a3a..04517bd3325a2abb3871f640aab0666d53467352 100644 (file)
@@ -295,7 +295,7 @@ static int ipc_pcie_probe(struct pci_dev *pci,
        ret = dma_set_mask(ipc_pcie->dev, DMA_BIT_MASK(64));
        if (ret) {
                dev_err(ipc_pcie->dev, "Could not set PCI DMA mask: %d", ret);
-               return ret;
+               goto set_mask_fail;
        }
 
        ipc_pcie_config_aspm(ipc_pcie);
@@ -323,6 +323,7 @@ static int ipc_pcie_probe(struct pci_dev *pci,
 imem_init_fail:
        ipc_pcie_resources_release(ipc_pcie);
 resources_req_fail:
+set_mask_fail:
        pci_disable_device(pci);
 pci_enable_fail:
        kfree(ipc_pcie);
index 268ff9e87e5b3069af67858dd762283d1199c8a1..2652cd00504e6eb943d4b13191dcfed21030565e 100644 (file)
@@ -1,7 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-ccflags-y += -Werror
-
 obj-${CONFIG_MTK_T7XX} := mtk_t7xx.o
 mtk_t7xx-y:=   t7xx_pci.o \
                t7xx_pcie_mac.o \
index 3dbfc8a6924ed33bb1700293d56fb11914bdc043..1fcbd83f7ff2e3e46e0c230da0ea60f0665e7e78 100644 (file)
@@ -166,7 +166,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
        struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
        grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
 
-       struct gnttab_copy tx_copy_ops[MAX_PENDING_REQS];
+       struct gnttab_copy tx_copy_ops[2 * MAX_PENDING_REQS];
        struct gnttab_map_grant_ref tx_map_ops[MAX_PENDING_REQS];
        struct gnttab_unmap_grant_ref tx_unmap_ops[MAX_PENDING_REQS];
        /* passed to gnttab_[un]map_refs with pages under (un)mapping */
index 1b42676ca1418d274ee3a1c0ed805814659f6e72..c1501f41e2d825be75cf9b71a38cf1ecc64a2c6c 100644 (file)
@@ -334,6 +334,7 @@ static int xenvif_count_requests(struct xenvif_queue *queue,
 struct xenvif_tx_cb {
        u16 copy_pending_idx[XEN_NETBK_LEGACY_SLOTS_MAX + 1];
        u8 copy_count;
+       u32 split_mask;
 };
 
 #define XENVIF_TX_CB(skb) ((struct xenvif_tx_cb *)(skb)->cb)
@@ -361,6 +362,8 @@ static inline struct sk_buff *xenvif_alloc_skb(unsigned int size)
        struct sk_buff *skb =
                alloc_skb(size + NET_SKB_PAD + NET_IP_ALIGN,
                          GFP_ATOMIC | __GFP_NOWARN);
+
+       BUILD_BUG_ON(sizeof(*XENVIF_TX_CB(skb)) > sizeof(skb->cb));
        if (unlikely(skb == NULL))
                return NULL;
 
@@ -396,11 +399,13 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
        nr_slots = shinfo->nr_frags + 1;
 
        copy_count(skb) = 0;
+       XENVIF_TX_CB(skb)->split_mask = 0;
 
        /* Create copy ops for exactly data_len bytes into the skb head. */
        __skb_put(skb, data_len);
        while (data_len > 0) {
                int amount = data_len > txp->size ? txp->size : data_len;
+               bool split = false;
 
                cop->source.u.ref = txp->gref;
                cop->source.domid = queue->vif->domid;
@@ -413,6 +418,13 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
                cop->dest.u.gmfn = virt_to_gfn(skb->data + skb_headlen(skb)
                                               - data_len);
 
+               /* Don't cross local page boundary! */
+               if (cop->dest.offset + amount > XEN_PAGE_SIZE) {
+                       amount = XEN_PAGE_SIZE - cop->dest.offset;
+                       XENVIF_TX_CB(skb)->split_mask |= 1U << copy_count(skb);
+                       split = true;
+               }
+
                cop->len = amount;
                cop->flags = GNTCOPY_source_gref;
 
@@ -420,7 +432,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
                pending_idx = queue->pending_ring[index];
                callback_param(queue, pending_idx).ctx = NULL;
                copy_pending_idx(skb, copy_count(skb)) = pending_idx;
-               copy_count(skb)++;
+               if (!split)
+                       copy_count(skb)++;
 
                cop++;
                data_len -= amount;
@@ -441,7 +454,8 @@ static void xenvif_get_requests(struct xenvif_queue *queue,
                        nr_slots--;
                } else {
                        /* The copy op partially covered the tx_request.
-                        * The remainder will be mapped.
+                        * The remainder will be mapped or copied in the next
+                        * iteration.
                         */
                        txp->offset += amount;
                        txp->size -= amount;
@@ -539,6 +553,13 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
                pending_idx = copy_pending_idx(skb, i);
 
                newerr = (*gopp_copy)->status;
+
+               /* Split copies need to be handled together. */
+               if (XENVIF_TX_CB(skb)->split_mask & (1U << i)) {
+                       (*gopp_copy)++;
+                       if (!newerr)
+                               newerr = (*gopp_copy)->status;
+               }
                if (likely(!newerr)) {
                        /* The first frag might still have this slot mapped */
                        if (i < copy_count(skb) - 1 || !sharedslot)
@@ -973,10 +994,8 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                /* No crossing a page as the payload mustn't fragment. */
                if (unlikely((txreq.offset + txreq.size) > XEN_PAGE_SIZE)) {
-                       netdev_err(queue->vif->dev,
-                                  "txreq.offset: %u, size: %u, end: %lu\n",
-                                  txreq.offset, txreq.size,
-                                  (unsigned long)(txreq.offset&~XEN_PAGE_MASK) + txreq.size);
+                       netdev_err(queue->vif->dev, "Cross page boundary, txreq.offset: %u, size: %u\n",
+                                  txreq.offset, txreq.size);
                        xenvif_fatal_tx_err(queue->vif);
                        break;
                }
@@ -1061,10 +1080,6 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
                __skb_queue_tail(&queue->tx_queue, skb);
 
                queue->tx.req_cons = idx;
-
-               if ((*map_ops >= ARRAY_SIZE(queue->tx_map_ops)) ||
-                   (*copy_ops >= ARRAY_SIZE(queue->tx_copy_ops)))
-                       break;
        }
 
        return;
index ed9c5e2cf3ad43feaa590820202ec844ee96ed6c..a187f0e0b0f7d1799f3f8d8d6ad36a801b7ca756 100644 (file)
@@ -175,6 +175,7 @@ static int pn533_usb_send_frame(struct pn533 *dev,
        print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
                             out->data, out->len, false);
 
+       arg.phy = phy;
        init_completion(&arg.done);
        cntx = phy->out_urb->context;
        phy->out_urb->context = &arg;
index 755460a73c0dce184dbe1dbd42c93993b2b3aecd..d2aa9f766738ecfe898f19733f89cd459b5124aa 100644 (file)
@@ -282,13 +282,15 @@ EXPORT_SYMBOL(ndlc_probe);
 
 void ndlc_remove(struct llt_ndlc *ndlc)
 {
-       st_nci_remove(ndlc->ndev);
-
        /* cancel timers */
        del_timer_sync(&ndlc->t1_timer);
        del_timer_sync(&ndlc->t2_timer);
        ndlc->t2_active = false;
        ndlc->t1_active = false;
+       /* cancel work */
+       cancel_work_sync(&ndlc->sm_work);
+
+       st_nci_remove(ndlc->ndev);
 
        skb_queue_purge(&ndlc->rcv_q);
        skb_queue_purge(&ndlc->send_q);
index 17fad660032c83ae4b22fcce98744e4d3963fec0..72921e4f35f6e6b5414fd98b64ef851879464356 100644 (file)
 #define to_nubus_board(d)       container_of(d, struct nubus_board, dev)
 #define to_nubus_driver(d)      container_of(d, struct nubus_driver, driver)
 
-static int nubus_bus_match(struct device *dev, struct device_driver *driver)
-{
-       return 1;
-}
-
 static int nubus_device_probe(struct device *dev)
 {
        struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
@@ -39,7 +34,6 @@ static void nubus_device_remove(struct device *dev)
 
 struct bus_type nubus_bus_type = {
        .name           = "nubus",
-       .match          = nubus_bus_match,
        .probe          = nubus_device_probe,
        .remove         = nubus_device_remove,
 };
index c2730b116dc680eac04df43a81c81a3826c5da16..d6a9bac91a4cda9a67d17935c0fd91c88f3119be 100644 (file)
@@ -781,16 +781,26 @@ static blk_status_t nvme_setup_discard(struct nvme_ns *ns, struct request *req,
                range = page_address(ns->ctrl->discard_page);
        }
 
-       __rq_for_each_bio(bio, req) {
-               u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector);
-               u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift;
-
-               if (n < segments) {
-                       range[n].cattr = cpu_to_le32(0);
-                       range[n].nlb = cpu_to_le32(nlb);
-                       range[n].slba = cpu_to_le64(slba);
+       if (queue_max_discard_segments(req->q) == 1) {
+               u64 slba = nvme_sect_to_lba(ns, blk_rq_pos(req));
+               u32 nlb = blk_rq_sectors(req) >> (ns->lba_shift - 9);
+
+               range[0].cattr = cpu_to_le32(0);
+               range[0].nlb = cpu_to_le32(nlb);
+               range[0].slba = cpu_to_le64(slba);
+               n = 1;
+       } else {
+               __rq_for_each_bio(bio, req) {
+                       u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector);
+                       u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift;
+
+                       if (n < segments) {
+                               range[n].cattr = cpu_to_le32(0);
+                               range[n].nlb = cpu_to_le32(nlb);
+                               range[n].slba = cpu_to_le64(slba);
+                       }
+                       n++;
                }
-               n++;
        }
 
        if (WARN_ON_ONCE(n != segments)) {
@@ -1664,6 +1674,9 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
        struct request_queue *queue = disk->queue;
        u32 size = queue_logical_block_size(queue);
 
+       if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns, UINT_MAX))
+               ctrl->max_discard_sectors = nvme_lba_to_sect(ns, ctrl->dmrsl);
+
        if (ctrl->max_discard_sectors == 0) {
                blk_queue_max_discard_sectors(queue, 0);
                return;
@@ -1678,9 +1691,6 @@ static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
        if (queue->limits.max_discard_sectors)
                return;
 
-       if (ctrl->dmrsl && ctrl->dmrsl <= nvme_sect_to_lba(ns, UINT_MAX))
-               ctrl->max_discard_sectors = nvme_lba_to_sect(ns, ctrl->dmrsl);
-
        blk_queue_max_discard_sectors(queue, ctrl->max_discard_sectors);
        blk_queue_max_discard_segments(queue, ctrl->max_discard_segments);
 
@@ -3053,7 +3063,8 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl)
        else
                ctrl->max_zeroes_sectors = 0;
 
-       if (nvme_ctrl_limited_cns(ctrl))
+       if (ctrl->subsys->subtype != NVME_NQN_NVME ||
+           nvme_ctrl_limited_cns(ctrl))
                return 0;
 
        id = kzalloc(sizeof(*id), GFP_KERNEL);
index 723e7d5b778f2c68aa3eb79decba51c8f2223f90..d24ea2e051564670254c44152de5660b32048a86 100644 (file)
@@ -464,7 +464,8 @@ static inline struct nvme_uring_cmd_pdu *nvme_uring_cmd_pdu(
        return (struct nvme_uring_cmd_pdu *)&ioucmd->pdu;
 }
 
-static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd)
+static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd,
+                                   unsigned issue_flags)
 {
        struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
        struct request *req = pdu->req;
@@ -485,17 +486,18 @@ static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd)
                blk_rq_unmap_user(req->bio);
        blk_mq_free_request(req);
 
-       io_uring_cmd_done(ioucmd, status, result);
+       io_uring_cmd_done(ioucmd, status, result, issue_flags);
 }
 
-static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd)
+static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd,
+                              unsigned issue_flags)
 {
        struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
 
        if (pdu->bio)
                blk_rq_unmap_user(pdu->bio);
 
-       io_uring_cmd_done(ioucmd, pdu->nvme_status, pdu->u.result);
+       io_uring_cmd_done(ioucmd, pdu->nvme_status, pdu->u.result, issue_flags);
 }
 
 static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
@@ -517,7 +519,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
         * Otherwise, move the completion to task work.
         */
        if (cookie != NULL && blk_rq_is_poll(req))
-               nvme_uring_task_cb(ioucmd);
+               nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED);
        else
                io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb);
 
@@ -539,7 +541,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
         * Otherwise, move the completion to task work.
         */
        if (cookie != NULL && blk_rq_is_poll(req))
-               nvme_uring_task_meta_cb(ioucmd);
+               nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED);
        else
                io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_meta_cb);
 
index fc39d01e7b63be8a4f9e794f915715cbc2c8609b..9171452e2f6d4e2eed95d0c6ef9ec0cbf05bc7ef 100644 (file)
@@ -123,9 +123,8 @@ void nvme_mpath_start_request(struct request *rq)
                return;
 
        nvme_req(rq)->flags |= NVME_MPATH_IO_STATS;
-       nvme_req(rq)->start_time = bdev_start_io_acct(disk->part0,
-                                       blk_rq_bytes(rq) >> SECTOR_SHIFT,
-                                       req_op(rq), jiffies);
+       nvme_req(rq)->start_time = bdev_start_io_acct(disk->part0, req_op(rq),
+                                                     jiffies);
 }
 EXPORT_SYMBOL_GPL(nvme_mpath_start_request);
 
@@ -136,7 +135,8 @@ void nvme_mpath_end_request(struct request *rq)
        if (!(nvme_req(rq)->flags & NVME_MPATH_IO_STATS))
                return;
        bdev_end_io_acct(ns->head->disk->part0, req_op(rq),
-               nvme_req(rq)->start_time);
+                        blk_rq_bytes(rq) >> SECTOR_SHIFT,
+                        nvme_req(rq)->start_time);
 }
 
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
index 5b95c94ee40f209e8d1cef39ee65da67a0b1736a..cd7873de312154696079e390e83439983bc0762e 100644 (file)
@@ -3073,6 +3073,7 @@ out_dev_unmap:
        nvme_dev_unmap(dev);
 out_uninit_ctrl:
        nvme_uninit_ctrl(&dev->ctrl);
+       nvme_put_ctrl(&dev->ctrl);
        return result;
 }
 
@@ -3415,6 +3416,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x2646, 0x501E),   /* KINGSTON OM3PGP4xxxxQ OS21011 NVMe SSD */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x1f40, 0x1202),   /* Netac Technologies Co. NV3000 NVMe SSD */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1f40, 0x5236),   /* Netac Technologies Co. NV7000 NVMe SSD */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1e4B, 0x1001),   /* MAXIO MAP1001 */
@@ -3435,7 +3438,12 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1d97, 0x2263), /* Lexar NM610 */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
+       { PCI_DEVICE(0x1d97, 0x1d97), /* Lexar NM620 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1d97, 0x2269), /* Lexar NM760 */
+               .driver_data = NVME_QUIRK_BOGUS_NID |
+                               NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+       { PCI_DEVICE(0x10ec, 0x5763), /* TEAMGROUP T-FORCE CARDEA ZERO Z330 SSD */
                .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061),
                .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, },
index 7723a498952442c14c5346a5e30fd1383aa0940e..49c9e7bc9116be5651e50336c91e331fdf643aa1 100644 (file)
@@ -208,6 +208,18 @@ static inline u8 nvme_tcp_ddgst_len(struct nvme_tcp_queue *queue)
        return queue->data_digest ? NVME_TCP_DIGEST_LENGTH : 0;
 }
 
+static inline void *nvme_tcp_req_cmd_pdu(struct nvme_tcp_request *req)
+{
+       return req->pdu;
+}
+
+static inline void *nvme_tcp_req_data_pdu(struct nvme_tcp_request *req)
+{
+       /* use the pdu space in the back for the data pdu */
+       return req->pdu + sizeof(struct nvme_tcp_cmd_pdu) -
+               sizeof(struct nvme_tcp_data_pdu);
+}
+
 static inline size_t nvme_tcp_inline_data_size(struct nvme_tcp_request *req)
 {
        if (nvme_is_fabrics(req->req.cmd))
@@ -614,7 +626,7 @@ static int nvme_tcp_handle_comp(struct nvme_tcp_queue *queue,
 
 static void nvme_tcp_setup_h2c_data_pdu(struct nvme_tcp_request *req)
 {
-       struct nvme_tcp_data_pdu *data = req->pdu;
+       struct nvme_tcp_data_pdu *data = nvme_tcp_req_data_pdu(req);
        struct nvme_tcp_queue *queue = req->queue;
        struct request *rq = blk_mq_rq_from_pdu(req);
        u32 h2cdata_sent = req->pdu_len;
@@ -1038,7 +1050,7 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
 static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req)
 {
        struct nvme_tcp_queue *queue = req->queue;
-       struct nvme_tcp_cmd_pdu *pdu = req->pdu;
+       struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req);
        bool inline_data = nvme_tcp_has_inline_data(req);
        u8 hdgst = nvme_tcp_hdgst_len(queue);
        int len = sizeof(*pdu) + hdgst - req->offset;
@@ -1077,7 +1089,7 @@ static int nvme_tcp_try_send_cmd_pdu(struct nvme_tcp_request *req)
 static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req)
 {
        struct nvme_tcp_queue *queue = req->queue;
-       struct nvme_tcp_data_pdu *pdu = req->pdu;
+       struct nvme_tcp_data_pdu *pdu = nvme_tcp_req_data_pdu(req);
        u8 hdgst = nvme_tcp_hdgst_len(queue);
        int len = sizeof(*pdu) - req->offset + hdgst;
        int ret;
@@ -1608,22 +1620,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid)
        if (ret)
                goto err_init_connect;
 
-       queue->rd_enabled = true;
        set_bit(NVME_TCP_Q_ALLOCATED, &queue->flags);
-       nvme_tcp_init_recv_ctx(queue);
-
-       write_lock_bh(&queue->sock->sk->sk_callback_lock);
-       queue->sock->sk->sk_user_data = queue;
-       queue->state_change = queue->sock->sk->sk_state_change;
-       queue->data_ready = queue->sock->sk->sk_data_ready;
-       queue->write_space = queue->sock->sk->sk_write_space;
-       queue->sock->sk->sk_data_ready = nvme_tcp_data_ready;
-       queue->sock->sk->sk_state_change = nvme_tcp_state_change;
-       queue->sock->sk->sk_write_space = nvme_tcp_write_space;
-#ifdef CONFIG_NET_RX_BUSY_POLL
-       queue->sock->sk->sk_ll_usec = 1;
-#endif
-       write_unlock_bh(&queue->sock->sk->sk_callback_lock);
 
        return 0;
 
@@ -1643,7 +1640,7 @@ err_destroy_mutex:
        return ret;
 }
 
-static void nvme_tcp_restore_sock_calls(struct nvme_tcp_queue *queue)
+static void nvme_tcp_restore_sock_ops(struct nvme_tcp_queue *queue)
 {
        struct socket *sock = queue->sock;
 
@@ -1658,7 +1655,7 @@ static void nvme_tcp_restore_sock_calls(struct nvme_tcp_queue *queue)
 static void __nvme_tcp_stop_queue(struct nvme_tcp_queue *queue)
 {
        kernel_sock_shutdown(queue->sock, SHUT_RDWR);
-       nvme_tcp_restore_sock_calls(queue);
+       nvme_tcp_restore_sock_ops(queue);
        cancel_work_sync(&queue->io_work);
 }
 
@@ -1676,21 +1673,42 @@ static void nvme_tcp_stop_queue(struct nvme_ctrl *nctrl, int qid)
        mutex_unlock(&queue->queue_lock);
 }
 
+static void nvme_tcp_setup_sock_ops(struct nvme_tcp_queue *queue)
+{
+       write_lock_bh(&queue->sock->sk->sk_callback_lock);
+       queue->sock->sk->sk_user_data = queue;
+       queue->state_change = queue->sock->sk->sk_state_change;
+       queue->data_ready = queue->sock->sk->sk_data_ready;
+       queue->write_space = queue->sock->sk->sk_write_space;
+       queue->sock->sk->sk_data_ready = nvme_tcp_data_ready;
+       queue->sock->sk->sk_state_change = nvme_tcp_state_change;
+       queue->sock->sk->sk_write_space = nvme_tcp_write_space;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+       queue->sock->sk->sk_ll_usec = 1;
+#endif
+       write_unlock_bh(&queue->sock->sk->sk_callback_lock);
+}
+
 static int nvme_tcp_start_queue(struct nvme_ctrl *nctrl, int idx)
 {
        struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
+       struct nvme_tcp_queue *queue = &ctrl->queues[idx];
        int ret;
 
+       queue->rd_enabled = true;
+       nvme_tcp_init_recv_ctx(queue);
+       nvme_tcp_setup_sock_ops(queue);
+
        if (idx)
                ret = nvmf_connect_io_queue(nctrl, idx);
        else
                ret = nvmf_connect_admin_queue(nctrl);
 
        if (!ret) {
-               set_bit(NVME_TCP_Q_LIVE, &ctrl->queues[idx].flags);
+               set_bit(NVME_TCP_Q_LIVE, &queue->flags);
        } else {
-               if (test_bit(NVME_TCP_Q_ALLOCATED, &ctrl->queues[idx].flags))
-                       __nvme_tcp_stop_queue(&ctrl->queues[idx]);
+               if (test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
+                       __nvme_tcp_stop_queue(queue);
                dev_err(nctrl->device,
                        "failed to connect queue: %d ret=%d\n", idx, ret);
        }
@@ -2284,7 +2302,7 @@ static enum blk_eh_timer_return nvme_tcp_timeout(struct request *rq)
 {
        struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
        struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl;
-       struct nvme_tcp_cmd_pdu *pdu = req->pdu;
+       struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req);
        u8 opc = pdu->cmd.common.opcode, fctype = pdu->cmd.fabrics.fctype;
        int qid = nvme_tcp_queue_id(req->queue);
 
@@ -2323,7 +2341,7 @@ static blk_status_t nvme_tcp_map_data(struct nvme_tcp_queue *queue,
                        struct request *rq)
 {
        struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
-       struct nvme_tcp_cmd_pdu *pdu = req->pdu;
+       struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req);
        struct nvme_command *c = &pdu->cmd;
 
        c->common.flags |= NVME_CMD_SGL_METABUF;
@@ -2343,7 +2361,7 @@ static blk_status_t nvme_tcp_setup_cmd_pdu(struct nvme_ns *ns,
                struct request *rq)
 {
        struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
-       struct nvme_tcp_cmd_pdu *pdu = req->pdu;
+       struct nvme_tcp_cmd_pdu *pdu = nvme_tcp_req_cmd_pdu(req);
        struct nvme_tcp_queue *queue = req->queue;
        u8 hdgst = nvme_tcp_hdgst_len(queue), ddgst = 0;
        blk_status_t ret;
@@ -2682,6 +2700,15 @@ static struct nvmf_transport_ops nvme_tcp_transport = {
 
 static int __init nvme_tcp_init_module(void)
 {
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_hdr) != 8);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_cmd_pdu) != 72);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_data_pdu) != 24);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_rsp_pdu) != 24);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_r2t_pdu) != 24);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_icreq_pdu) != 128);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_icresp_pdu) != 128);
+       BUILD_BUG_ON(sizeof(struct nvme_tcp_term_pdu) != 24);
+
        nvme_tcp_wq = alloc_workqueue("nvme_tcp_wq",
                        WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
        if (!nvme_tcp_wq)
index f66ed13d7c11deacbdfdd982ff8548f913f1b933..3935165048e74199cd4a9706811dd7d63fc39476 100644 (file)
@@ -756,8 +756,10 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 
 void nvmet_req_complete(struct nvmet_req *req, u16 status)
 {
+       struct nvmet_sq *sq = req->sq;
+
        __nvmet_req_complete(req, status);
-       percpu_ref_put(&req->sq->ref);
+       percpu_ref_put(&sq->ref);
 }
 EXPORT_SYMBOL_GPL(nvmet_req_complete);
 
index 174ef3574e07f5cb7e771d108deeb2e09056f971..22024b830788f86d23a213809222511c7ae6ea84 100644 (file)
@@ -1231,7 +1231,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
                                                  "#nvmem-cell-cells",
                                                  index, &cell_spec);
        if (ret)
-               return ERR_PTR(ret);
+               return ERR_PTR(-ENOENT);
 
        if (cell_spec.args_count > 1)
                return ERR_PTR(-EINVAL);
index 07d93753b12f5f4d2ccc0b6f00fa1e2aefef5bd6..e311d406b17053065b2f0699e92cda1c2e5db481 100644 (file)
@@ -226,6 +226,7 @@ static void __of_attach_node(struct device_node *np)
        np->sibling = np->parent->child;
        np->parent->child = np;
        of_node_clear_flag(np, OF_DETACHED);
+       np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE;
 }
 
 /**
index b2bd2e783445dd78e40beefb31d83bfa8c7eac6d..78ae8418744905c9b038378e78699a1aeb111a1c 100644 (file)
@@ -737,6 +737,11 @@ static int of_platform_notify(struct notifier_block *nb,
                if (of_node_check_flag(rd->dn, OF_POPULATED))
                        return NOTIFY_OK;
 
+               /*
+                * Clear the flag before adding the device so that fw_devlink
+                * doesn't skip adding consumers to this device.
+                */
+               rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
                /* pdev_parent may be NULL when no bus platform device */
                pdev_parent = of_find_device_by_node(rd->dn->parent);
                pdev = of_platform_device_create(rd->dn, NULL,
index 83ae838ceb5f0a3ea93750ea51568eb83bd91764..549c4bd5caecafd925692f308d45fa6c40a3387f 100644 (file)
@@ -76,6 +76,27 @@ struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n)
 }
 EXPORT_SYMBOL_GPL(pci_bus_resource_n);
 
+void pci_bus_remove_resource(struct pci_bus *bus, struct resource *res)
+{
+       struct pci_bus_resource *bus_res, *tmp;
+       int i;
+
+       for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
+               if (bus->resource[i] == res) {
+                       bus->resource[i] = NULL;
+                       return;
+               }
+       }
+
+       list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
+               if (bus_res->res == res) {
+                       list_del(&bus_res->list);
+                       kfree(bus_res);
+                       return;
+               }
+       }
+}
+
 void pci_bus_remove_resources(struct pci_bus *bus)
 {
        int i;
index 53a16b8b6ac23ae796defd67dbacf56469acfb20..8e33e6e59e686b5d5e8462fdc737ca84ea349397 100644 (file)
@@ -1001,11 +1001,6 @@ void dw_pcie_setup(struct dw_pcie *pci)
                dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
        }
 
-       val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
-       val &= ~PORT_LINK_FAST_LINK_MODE;
-       val |= PORT_LINK_DLL_LINK_EN;
-       dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
-
        if (dw_pcie_cap_is(pci, CDM_CHECK)) {
                val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
                val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS |
@@ -1013,6 +1008,11 @@ void dw_pcie_setup(struct dw_pcie *pci)
                dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
        }
 
+       val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
+       val &= ~PORT_LINK_FAST_LINK_MODE;
+       val |= PORT_LINK_DLL_LINK_EN;
+       dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
+
        if (!pci->num_lanes) {
                dev_dbg(pci->dev, "Using h/w default number of lanes\n");
                return;
index 66d9ab2886468d02a32eb40353ad5bb24909f3ac..e5e9b287b9766e3c164bb2c2a6c1bcca72a59c96 100644 (file)
@@ -128,7 +128,7 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
                return -EIO;
 
        /* Length is 2 DW of header + length of payload in DW */
-       length = 2 + task->request_pl_sz / sizeof(u32);
+       length = 2 + task->request_pl_sz / sizeof(__le32);
        if (length > PCI_DOE_MAX_LENGTH)
                return -EIO;
        if (length == PCI_DOE_MAX_LENGTH)
@@ -141,9 +141,9 @@ static int pci_doe_send_req(struct pci_doe_mb *doe_mb,
        pci_write_config_dword(pdev, offset + PCI_DOE_WRITE,
                               FIELD_PREP(PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH,
                                          length));
-       for (i = 0; i < task->request_pl_sz / sizeof(u32); i++)
+       for (i = 0; i < task->request_pl_sz / sizeof(__le32); i++)
                pci_write_config_dword(pdev, offset + PCI_DOE_WRITE,
-                                      task->request_pl[i]);
+                                      le32_to_cpu(task->request_pl[i]));
 
        pci_doe_write_ctrl(doe_mb, PCI_DOE_CTRL_GO);
 
@@ -195,11 +195,11 @@ static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *tas
 
        /* First 2 dwords have already been read */
        length -= 2;
-       payload_length = min(length, task->response_pl_sz / sizeof(u32));
+       payload_length = min(length, task->response_pl_sz / sizeof(__le32));
        /* Read the rest of the response payload */
        for (i = 0; i < payload_length; i++) {
-               pci_read_config_dword(pdev, offset + PCI_DOE_READ,
-                                     &task->response_pl[i]);
+               pci_read_config_dword(pdev, offset + PCI_DOE_READ, &val);
+               task->response_pl[i] = cpu_to_le32(val);
                /* Prior to the last ack, ensure Data Object Ready */
                if (i == (payload_length - 1) && !pci_doe_data_obj_ready(doe_mb))
                        return -EIO;
@@ -217,13 +217,14 @@ static int pci_doe_recv_resp(struct pci_doe_mb *doe_mb, struct pci_doe_task *tas
        if (FIELD_GET(PCI_DOE_STATUS_ERROR, val))
                return -EIO;
 
-       return min(length, task->response_pl_sz / sizeof(u32)) * sizeof(u32);
+       return min(length, task->response_pl_sz / sizeof(__le32)) * sizeof(__le32);
 }
 
 static void signal_task_complete(struct pci_doe_task *task, int rv)
 {
        task->rv = rv;
        task->complete(task);
+       destroy_work_on_stack(&task->work);
 }
 
 static void signal_task_abort(struct pci_doe_task *task, int rv)
@@ -317,14 +318,16 @@ static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid,
 {
        u32 request_pl = FIELD_PREP(PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX,
                                    *index);
+       __le32 request_pl_le = cpu_to_le32(request_pl);
+       __le32 response_pl_le;
        u32 response_pl;
        DECLARE_COMPLETION_ONSTACK(c);
        struct pci_doe_task task = {
                .prot.vid = PCI_VENDOR_ID_PCI_SIG,
                .prot.type = PCI_DOE_PROTOCOL_DISCOVERY,
-               .request_pl = &request_pl,
+               .request_pl = &request_pl_le,
                .request_pl_sz = sizeof(request_pl),
-               .response_pl = &response_pl,
+               .response_pl = &response_pl_le,
                .response_pl_sz = sizeof(response_pl),
                .complete = pci_doe_task_complete,
                .private = &c,
@@ -340,6 +343,7 @@ static int pci_doe_discovery(struct pci_doe_mb *doe_mb, u8 *index, u16 *vid,
        if (task.rv != sizeof(response_pl))
                return -EIO;
 
+       response_pl = le32_to_cpu(response_pl_le);
        *vid = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID, response_pl);
        *protocol = FIELD_GET(PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL,
                              response_pl);
@@ -520,6 +524,8 @@ EXPORT_SYMBOL_GPL(pci_doe_supports_prot);
  * task->complete will be called when the state machine is done processing this
  * task.
  *
+ * @task must be allocated on the stack.
+ *
  * Excess data will be discarded.
  *
  * RETURNS: 0 when task has been successfully queued, -ERRNO on error
@@ -533,15 +539,15 @@ int pci_doe_submit_task(struct pci_doe_mb *doe_mb, struct pci_doe_task *task)
         * DOE requests must be a whole number of DW and the response needs to
         * be big enough for at least 1 DW
         */
-       if (task->request_pl_sz % sizeof(u32) ||
-           task->response_pl_sz < sizeof(u32))
+       if (task->request_pl_sz % sizeof(__le32) ||
+           task->response_pl_sz < sizeof(__le32))
                return -EINVAL;
 
        if (test_bit(PCI_DOE_FLAG_DEAD, &doe_mb->flags))
                return -EIO;
 
        task->doe_mb = doe_mb;
-       INIT_WORK(&task->work, doe_statemachine_work);
+       INIT_WORK_ONSTACK(&task->work, doe_statemachine_work);
        queue_work(doe_mb->work_queue, &task->work);
        return 0;
 }
index 1f716624ca563421b4b6561150b33ff478f68fea..ef1d8857a51ba691701e049efb9c05d668e9dc27 100644 (file)
@@ -750,8 +750,7 @@ out_disable:
        return ret;
 }
 
-static bool pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *entries,
-                                     int nvec, int hwsize)
+static bool pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *entries, int nvec)
 {
        bool nogap;
        int i, j;
@@ -762,10 +761,6 @@ static bool pci_msix_validate_entries(struct pci_dev *dev, struct msix_entry *en
        nogap = pci_msi_domain_supports(dev, MSI_FLAG_MSIX_CONTIGUOUS, DENY_LEGACY);
 
        for (i = 0; i < nvec; i++) {
-               /* Entry within hardware limit? */
-               if (entries[i].entry >= hwsize)
-                       return false;
-
                /* Check for duplicate entries */
                for (j = i + 1; j < nvec; j++) {
                        if (entries[i].entry == entries[j].entry)
@@ -805,7 +800,7 @@ int __pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, int
        if (hwsize < 0)
                return hwsize;
 
-       if (!pci_msix_validate_entries(dev, entries, nvec, hwsize))
+       if (!pci_msix_validate_entries(dev, entries, nvec))
                return -EINVAL;
 
        if (hwsize < nvec) {
index 196834ed44fe84595a696159dd42deb24ec42b71..4c2ef2e28fb5e9030a0e8ed41d2bcd883a00c16c 100644 (file)
 #include "pci.h"
 
 #ifdef CONFIG_PCI
-void pci_set_of_node(struct pci_dev *dev)
+/**
+ * pci_set_of_node - Find and set device's DT device_node
+ * @dev: the PCI device structure to fill
+ *
+ * Returns 0 on success with of_node set or when no device is described in the
+ * DT. Returns -ENODEV if the device is present, but disabled in the DT.
+ */
+int pci_set_of_node(struct pci_dev *dev)
 {
+       struct device_node *node;
+
        if (!dev->bus->dev.of_node)
-               return;
-       dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
-                                                   dev->devfn);
-       if (dev->dev.of_node)
-               dev->dev.fwnode = &dev->dev.of_node->fwnode;
+               return 0;
+
+       node = of_pci_find_child_device(dev->bus->dev.of_node, dev->devfn);
+       if (!node)
+               return 0;
+
+       if (!of_device_is_available(node)) {
+               of_node_put(node);
+               return -ENODEV;
+       }
+
+       dev->dev.of_node = node;
+       dev->dev.fwnode = &node->fwnode;
+       return 0;
 }
 
 void pci_release_of_node(struct pci_dev *dev)
index d2c08670a20ed77823e65a748365d15f0a0bf875..2b48a0aa8008e5547ee258ad83759fb3177e2dd4 100644 (file)
@@ -624,7 +624,7 @@ int of_pci_get_max_link_speed(struct device_node *node);
 u32 of_pci_get_slot_power_limit(struct device_node *node,
                                u8 *slot_power_limit_value,
                                u8 *slot_power_limit_scale);
-void pci_set_of_node(struct pci_dev *dev);
+int pci_set_of_node(struct pci_dev *dev);
 void pci_release_of_node(struct pci_dev *dev);
 void pci_set_bus_of_node(struct pci_bus *bus);
 void pci_release_bus_of_node(struct pci_bus *bus);
@@ -662,7 +662,7 @@ of_pci_get_slot_power_limit(struct device_node *node,
        return 0;
 }
 
-static inline void pci_set_of_node(struct pci_dev *dev) { }
+static inline int pci_set_of_node(struct pci_dev *dev) { return 0; }
 static inline void pci_release_of_node(struct pci_dev *dev) { }
 static inline void pci_set_bus_of_node(struct pci_bus *bus) { }
 static inline void pci_release_bus_of_node(struct pci_bus *bus) { }
index a3f68b6ba6ac2db4500e5f5f416b972e479746d9..f96fa83f2627386677a4efcf10c7a971873dbd99 100644 (file)
@@ -1826,7 +1826,7 @@ int pci_setup_device(struct pci_dev *dev)
        u32 class;
        u16 cmd;
        u8 hdr_type;
-       int pos = 0;
+       int err, pos = 0;
        struct pci_bus_region region;
        struct resource *res;
 
@@ -1840,10 +1840,10 @@ int pci_setup_device(struct pci_dev *dev)
        dev->error_state = pci_channel_io_normal;
        set_pcie_port_type(dev);
 
-       pci_set_of_node(dev);
+       err = pci_set_of_node(dev);
+       if (err)
+               return err;
        pci_set_acpi_fwnode(dev);
-       if (dev->dev.fwnode && !fwnode_device_is_available(dev->dev.fwnode))
-               return -ENODEV;
 
        pci_dev_assign_slot(dev);
 
index 0145aef1b9301823e3a406611353b596036e8a77..22d39e12b236a69901628e580bccc4b8ee403bcd 100644 (file)
@@ -157,8 +157,6 @@ void pci_remove_root_bus(struct pci_bus *bus)
        list_for_each_entry_safe(child, tmp,
                                 &bus->devices, bus_list)
                pci_remove_bus_device(child);
-       pci_remove_bus(bus);
-       host_bridge->bus = NULL;
 
 #ifdef CONFIG_PCI_DOMAINS_GENERIC
        /* Release domain_nr if it was dynamically allocated */
@@ -166,6 +164,9 @@ void pci_remove_root_bus(struct pci_bus *bus)
                pci_bus_release_domain_nr(bus, host_bridge->dev.parent);
 #endif
 
+       pci_remove_bus(bus);
+       host_bridge->bus = NULL;
+
        /* remove the host bridge */
        device_del(&host_bridge->dev);
 }
index a78fdb15e26c20fa8b7e39e4490bc59bfddbdfd5..8b643888d50369ebdf3be0d3796d05f394f6c990 100644 (file)
 #define DMC_QOS_IRQ            BIT(30)
 
 /* DMC bandwidth monitor register address offset */
-#define DMC_MON_G12_CTRL0              (0x20  << 2)
-#define DMC_MON_G12_CTRL1              (0x21  << 2)
-#define DMC_MON_G12_CTRL2              (0x22  << 2)
-#define DMC_MON_G12_CTRL3              (0x23  << 2)
-#define DMC_MON_G12_CTRL4              (0x24  << 2)
-#define DMC_MON_G12_CTRL5              (0x25  << 2)
-#define DMC_MON_G12_CTRL6              (0x26  << 2)
-#define DMC_MON_G12_CTRL7              (0x27  << 2)
-#define DMC_MON_G12_CTRL8              (0x28  << 2)
-
-#define DMC_MON_G12_ALL_REQ_CNT                (0x29  << 2)
-#define DMC_MON_G12_ALL_GRANT_CNT      (0x2a  << 2)
-#define DMC_MON_G12_ONE_GRANT_CNT      (0x2b  << 2)
-#define DMC_MON_G12_SEC_GRANT_CNT      (0x2c  << 2)
-#define DMC_MON_G12_THD_GRANT_CNT      (0x2d  << 2)
-#define DMC_MON_G12_FOR_GRANT_CNT      (0x2e  << 2)
-#define DMC_MON_G12_TIMER              (0x2f  << 2)
+#define DMC_MON_G12_CTRL0              (0x0  << 2)
+#define DMC_MON_G12_CTRL1              (0x1  << 2)
+#define DMC_MON_G12_CTRL2              (0x2  << 2)
+#define DMC_MON_G12_CTRL3              (0x3  << 2)
+#define DMC_MON_G12_CTRL4              (0x4  << 2)
+#define DMC_MON_G12_CTRL5              (0x5  << 2)
+#define DMC_MON_G12_CTRL6              (0x6  << 2)
+#define DMC_MON_G12_CTRL7              (0x7  << 2)
+#define DMC_MON_G12_CTRL8              (0x8  << 2)
+
+#define DMC_MON_G12_ALL_REQ_CNT                (0x9  << 2)
+#define DMC_MON_G12_ALL_GRANT_CNT      (0xa  << 2)
+#define DMC_MON_G12_ONE_GRANT_CNT      (0xb  << 2)
+#define DMC_MON_G12_SEC_GRANT_CNT      (0xc  << 2)
+#define DMC_MON_G12_THD_GRANT_CNT      (0xd  << 2)
+#define DMC_MON_G12_FOR_GRANT_CNT      (0xe  << 2)
+#define DMC_MON_G12_TIMER              (0xf  << 2)
 
 /* Each bit represent a axi line */
 PMU_FORMAT_ATTR(event, "config:0-7");
index f20c28334bcbf68e85665c31b49357d79508904c..a71874fed3d60d35c49cf78978468a288847cc36 100644 (file)
@@ -45,35 +45,35 @@ config PINCTRL_MTK_PARIS
 
 # For ARMv7 SoCs
 config PINCTRL_MT2701
-       bool "Mediatek MT2701 pin control"
+       bool "MediaTek MT2701 pin control"
        depends on MACH_MT7623 || MACH_MT2701 || COMPILE_TEST
        depends on OF
        default MACH_MT2701
        select PINCTRL_MTK
 
 config PINCTRL_MT7623
-       bool "Mediatek MT7623 pin control with generic binding"
+       bool "MediaTek MT7623 pin control with generic binding"
        depends on MACH_MT7623 || COMPILE_TEST
        depends on OF
        default MACH_MT7623
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT7629
-       bool "Mediatek MT7629 pin control"
+       bool "MediaTek MT7629 pin control"
        depends on MACH_MT7629 || COMPILE_TEST
        depends on OF
        default MACH_MT7629
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT8135
-       bool "Mediatek MT8135 pin control"
+       bool "MediaTek MT8135 pin control"
        depends on MACH_MT8135 || COMPILE_TEST
        depends on OF
        default MACH_MT8135
        select PINCTRL_MTK
 
 config PINCTRL_MT8127
-       bool "Mediatek MT8127 pin control"
+       bool "MediaTek MT8127 pin control"
        depends on MACH_MT8127 || COMPILE_TEST
        depends on OF
        default MACH_MT8127
@@ -88,33 +88,33 @@ config PINCTRL_MT2712
        select PINCTRL_MTK
 
 config PINCTRL_MT6765
-       tristate "Mediatek MT6765 pin control"
+       tristate "MediaTek MT6765 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_PARIS
 
 config PINCTRL_MT6779
-       tristate "Mediatek MT6779 pin control"
+       tristate "MediaTek MT6779 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_PARIS
        help
          Say yes here to support pin controller and gpio driver
-         on Mediatek MT6779 SoC.
+         on MediaTek MT6779 SoC.
          In MTK platform, we support virtual gpio and use it to
          map specific eint which doesn't have real gpio pin.
 
 config PINCTRL_MT6795
-       bool "Mediatek MT6795 pin control"
+       bool "MediaTek MT6795 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_PARIS
 
 config PINCTRL_MT6797
-       bool "Mediatek MT6797 pin control"
+       bool "MediaTek MT6797 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
@@ -128,40 +128,42 @@ config PINCTRL_MT7622
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT7981
-       bool "Mediatek MT7981 pin control"
+       bool "MediaTek MT7981 pin control"
        depends on OF
+       depends on ARM64 || COMPILE_TEST
+       default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT7986
-       bool "Mediatek MT7986 pin control"
+       bool "MediaTek MT7986 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT8167
-       bool "Mediatek MT8167 pin control"
+       bool "MediaTek MT8167 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK
 
 config PINCTRL_MT8173
-       bool "Mediatek MT8173 pin control"
+       bool "MediaTek MT8173 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK
 
 config PINCTRL_MT8183
-       bool "Mediatek MT8183 pin control"
+       bool "MediaTek MT8183 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_PARIS
 
 config PINCTRL_MT8186
-       bool "Mediatek MT8186 pin control"
+       bool "MediaTek MT8186 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
@@ -180,28 +182,28 @@ config PINCTRL_MT8188
          map specific eint which doesn't have real gpio pin.
 
 config PINCTRL_MT8192
-       bool "Mediatek MT8192 pin control"
+       bool "MediaTek MT8192 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_PARIS
 
 config PINCTRL_MT8195
-       bool "Mediatek MT8195 pin control"
+       bool "MediaTek MT8195 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_PARIS
 
 config PINCTRL_MT8365
-       bool "Mediatek MT8365 pin control"
+       bool "MediaTek MT8365 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK
 
 config PINCTRL_MT8516
-       bool "Mediatek MT8516 pin control"
+       bool "MediaTek MT8516 pin control"
        depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
@@ -209,7 +211,7 @@ config PINCTRL_MT8516
 
 # For PMIC
 config PINCTRL_MT6397
-       bool "Mediatek MT6397 pin control"
+       bool "MediaTek MT6397 pin control"
        depends on MFD_MT6397 || COMPILE_TEST
        depends on OF
        default MFD_MT6397
index 373eed8bc4be93db2a43069e015f6d208d8f6c88..c775d239444a6fcbf2dbcdf88c2a9aeb90e31edc 100644 (file)
@@ -1206,7 +1206,6 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
                dev_err(dev, "can't add the irq domain\n");
                return -ENODEV;
        }
-       atmel_pioctrl->irq_domain->name = "atmel gpio";
 
        for (i = 0; i < atmel_pioctrl->npins; i++) {
                int irq = irq_create_mapping(atmel_pioctrl->irq_domain, i);
index 29e4a6282a64140e0af3b7b867b96fb7a69b1bd5..1dcbd0937ef5ae3f5df98e3c0f4ab29dd736f70b 100644 (file)
@@ -1204,7 +1204,7 @@ static int ocelot_pinmux_set_mux(struct pinctrl_dev *pctldev,
        regmap_update_bits(info->map, REG_ALT(0, info, pin->pin),
                           BIT(p), f << p);
        regmap_update_bits(info->map, REG_ALT(1, info, pin->pin),
-                          BIT(p), f << (p - 1));
+                          BIT(p), (f >> 1) << p);
 
        return 0;
 }
index cb33a23ab0c1120c7d30c4a1d01f3f41a08f11d3..04ace4c7bd5826ed7eaa4db68d5345841093223c 100644 (file)
@@ -1330,7 +1330,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode
        if (fwnode_property_read_u32(fwnode, "st,bank-ioport", &bank_ioport_nr))
                bank_ioport_nr = bank_nr;
 
-       bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK;
+       bank->gpio_chip.base = -1;
 
        bank->gpio_chip.ngpio = npins;
        bank->gpio_chip.fwnode = fwnode;
index 0de7c255254e0ba7f4e33c4da8a7b7573e815bb5..d6de5a29412820d14e3a55dce951b94228bb60de 100644 (file)
@@ -284,7 +284,7 @@ static long cros_ec_chardev_ioctl_xcmd(struct cros_ec_dev *ec, void __user *arg)
            u_cmd.insize > EC_MAX_MSG_BYTES)
                return -EINVAL;
 
-       s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
+       s_cmd = kzalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
                        GFP_KERNEL);
        if (!s_cmd)
                return -ENOMEM;
index aaad41294200de2d1bca1ec1bf742bf166c3d171..42ccd7f1c9b9c3aac498af13878305724d8aa04b 100644 (file)
@@ -485,8 +485,10 @@ int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
                 * device, so ignore it and continue with the next one.
                 */
                status = ssam_add_client_device(parent, ctrl, child);
-               if (status && status != -ENODEV)
+               if (status && status != -ENODEV) {
+                       fwnode_handle_put(child);
                        goto err;
+               }
        }
 
        return 0;
index cb15acdf14a30a53a2cf5f53fbc618c3f1abbba2..e2c9a68d12df9cc00ce3deda7964fb12bfd23a0f 100644 (file)
@@ -464,7 +464,8 @@ static const struct dmi_system_id asus_quirks[] = {
                .ident = "ASUS ROG FLOW X13",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "GV301Q"),
+                       /* Match GV301** */
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GV301"),
                },
                .driver_data = &quirk_asus_tablet_mode,
        },
index 322cfaeda17badd650ee3e74cee779e9f7cf6fb7..2a426040f749efec340301127caa9baf57adf17a 100644 (file)
@@ -140,6 +140,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev)
        }}
 
 static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("A320M-S2H V2-CF"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"),
@@ -150,6 +151,7 @@ static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550I AORUS PRO AX"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B650 AORUS ELITE AX"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660 GAMING X DDR4"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B660I AORUS PRO DDR4"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"),
@@ -159,6 +161,7 @@ static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570S AORUS ELITE"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z690M AORUS ELITE AX DDR4"),
        { }
 };
index 0eb5bfdd823a1d58bd3d4e153048261ccd664221..959ec3c5f376e737f0b9d2c0e566b291160cd226 100644 (file)
@@ -1170,7 +1170,6 @@ static const struct key_entry ideapad_keymap[] = {
        { KE_KEY,  65, { KEY_PROG4 } },
        { KE_KEY,  66, { KEY_TOUCHPAD_OFF } },
        { KE_KEY,  67, { KEY_TOUCHPAD_ON } },
-       { KE_KEY,  68, { KEY_TOUCHPAD_TOGGLE } },
        { KE_KEY, 128, { KEY_ESC } },
 
        /*
@@ -1526,18 +1525,16 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv, bool send_
        if (priv->features.ctrl_ps2_aux_port)
                i8042_command(&param, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
 
-       if (send_events) {
-               /*
-                * On older models the EC controls the touchpad and toggles it
-                * on/off itself, in this case we report KEY_TOUCHPAD_ON/_OFF.
-                * If the EC did not toggle, report KEY_TOUCHPAD_TOGGLE.
-                */
-               if (value != priv->r_touchpad_val) {
-                       ideapad_input_report(priv, value ? 67 : 66);
-                       sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
-               } else {
-                       ideapad_input_report(priv, 68);
-               }
+       /*
+        * On older models the EC controls the touchpad and toggles it on/off
+        * itself, in this case we report KEY_TOUCHPAD_ON/_OFF. Some models do
+        * an acpi-notify with VPC bit 5 set on resume, so this function get
+        * called with send_events=true on every resume. Therefor if the EC did
+        * not toggle, do nothing to avoid sending spurious KEY_TOUCHPAD_TOGGLE.
+        */
+       if (send_events && value != priv->r_touchpad_val) {
+               ideapad_input_report(priv, value ? 67 : 66);
+               sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
        }
 
        priv->r_touchpad_val = value;
index 3a15d32d7644c000e009c801261318cf9da794dd..b9591969e0fa119bf84710e2cee4cddf61541ee0 100644 (file)
@@ -66,7 +66,18 @@ static inline void pmc_core_reg_write(struct pmc_dev *pmcdev, int reg_offset,
 
 static inline u64 pmc_core_adjust_slp_s0_step(struct pmc_dev *pmcdev, u32 value)
 {
-       return (u64)value * pmcdev->map->slp_s0_res_counter_step;
+       /*
+        * ADL PCH does not have the SLP_S0 counter and LPM Residency counters are
+        * used as a workaround which uses 30.5 usec tick. All other client
+        * programs have the legacy SLP_S0 residency counter that is using the 122
+        * usec tick.
+        */
+       const int lpm_adj_x2 = pmcdev->map->lpm_res_counter_step_x2;
+
+       if (pmcdev->map == &adl_reg_map)
+               return (u64)value * GET_X2_COUNTER((u64)lpm_adj_x2);
+       else
+               return (u64)value * pmcdev->map->slp_s0_res_counter_step;
 }
 
 static int set_etr3(struct pmc_dev *pmcdev)
index c999732b0f1e5d3faf8c74bac78829efb82a14e1..a5227951decce90f3eaf95aedfa0383a1c2bf957 100644 (file)
@@ -203,7 +203,7 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
        struct intel_vsec_device *feature_vsec_dev;
        struct resource *res, *tmp;
        const char *name;
-       int ret, i;
+       int i;
 
        name = intel_tpmi_name(pfs->pfs_header.tpmi_id);
        if (!name)
@@ -215,8 +215,8 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
 
        feature_vsec_dev = kzalloc(sizeof(*feature_vsec_dev), GFP_KERNEL);
        if (!feature_vsec_dev) {
-               ret = -ENOMEM;
-               goto free_res;
+               kfree(res);
+               return -ENOMEM;
        }
 
        snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name);
@@ -239,20 +239,11 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info,
        /*
         * intel_vsec_add_aux() is resource managed, no explicit
         * delete is required on error or on module unload.
-        * feature_vsec_dev memory is also freed as part of device
-        * delete.
+        * feature_vsec_dev and res memory are also freed as part of
+        * device deletion.
         */
-       ret = intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
-                                feature_vsec_dev, feature_id_name);
-       if (ret)
-               goto free_res;
-
-       return 0;
-
-free_res:
-       kfree(res);
-
-       return ret;
+       return intel_vsec_add_aux(vsec_dev->pcidev, &vsec_dev->auxdev.dev,
+                                 feature_vsec_dev, feature_id_name);
 }
 
 static int tpmi_create_devices(struct intel_tpmi_info *tpmi_info)
index 13decf36c6ded9740ce67b9adbd3c637e1829517..2311c16cb975de8b44f99d97b14e5dcfd3af5f48 100644 (file)
@@ -154,6 +154,7 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
        ret = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL);
        mutex_unlock(&vsec_ida_lock);
        if (ret < 0) {
+               kfree(intel_vsec_dev->resource);
                kfree(intel_vsec_dev);
                return ret;
        }
index 86b33b74519bed079c0360381b3e45ee962e6abd..78dc82bda4ddeac371580b48aacbcc5a3ad6e5be 100644 (file)
@@ -920,7 +920,7 @@ static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *at
 static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
        struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
-       char *item, *value;
+       char *item, *value, *p;
        int ret;
 
        ret = tlmi_setting(setting->index, &item, LENOVO_BIOS_SETTING_GUID);
@@ -930,10 +930,15 @@ static ssize_t current_value_show(struct kobject *kobj, struct kobj_attribute *a
        /* validate and split from `item,value` -> `value` */
        value = strpbrk(item, ",");
        if (!value || value == item || !strlen(value + 1))
-               return -EINVAL;
-
-       ret = sysfs_emit(buf, "%s\n", value + 1);
+               ret = -EINVAL;
+       else {
+               /* On Workstations remove the Options part after the value */
+               p = strchrnul(value, ';');
+               *p = '\0';
+               ret = sysfs_emit(buf, "%s\n", value + 1);
+       }
        kfree(item);
+
        return ret;
 }
 
@@ -941,12 +946,23 @@ static ssize_t possible_values_show(struct kobject *kobj, struct kobj_attribute
 {
        struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
 
-       if (!tlmi_priv.can_get_bios_selections)
-               return -EOPNOTSUPP;
-
        return sysfs_emit(buf, "%s\n", setting->possible_values);
 }
 
+static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf)
+{
+       struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
+
+       if (setting->possible_values) {
+               /* Figure out what setting type is as BIOS does not return this */
+               if (strchr(setting->possible_values, ';'))
+                       return sysfs_emit(buf, "enumeration\n");
+       }
+       /* Anything else is going to be a string */
+       return sysfs_emit(buf, "string\n");
+}
+
 static ssize_t current_value_store(struct kobject *kobj,
                struct kobj_attribute *attr,
                const char *buf, size_t count)
@@ -1036,14 +1052,30 @@ static struct kobj_attribute attr_possible_values = __ATTR_RO(possible_values);
 
 static struct kobj_attribute attr_current_val = __ATTR_RW_MODE(current_value, 0600);
 
+static struct kobj_attribute attr_type = __ATTR_RO(type);
+
+static umode_t attr_is_visible(struct kobject *kobj,
+                                            struct attribute *attr, int n)
+{
+       struct tlmi_attr_setting *setting = to_tlmi_attr_setting(kobj);
+
+       /* We don't want to display possible_values attributes if not available */
+       if ((attr == &attr_possible_values.attr) && (!setting->possible_values))
+               return 0;
+
+       return attr->mode;
+}
+
 static struct attribute *tlmi_attrs[] = {
        &attr_displ_name.attr,
        &attr_current_val.attr,
        &attr_possible_values.attr,
+       &attr_type.attr,
        NULL
 };
 
 static const struct attribute_group tlmi_attr_group = {
+       .is_visible = attr_is_visible,
        .attrs = tlmi_attrs,
 };
 
@@ -1423,7 +1455,35 @@ static int tlmi_analyze(void)
                        if (ret || !setting->possible_values)
                                pr_info("Error retrieving possible values for %d : %s\n",
                                                i, setting->display_name);
+               } else {
+                       /*
+                        * Older Thinkstations don't support the bios_selections API.
+                        * Instead they store this as a [Optional:Option1,Option2] section of the
+                        * name string.
+                        * Try and pull that out if it's available.
+                        */
+                       char *optitem, *optstart, *optend;
+
+                       if (!tlmi_setting(setting->index, &optitem, LENOVO_BIOS_SETTING_GUID)) {
+                               optstart = strstr(optitem, "[Optional:");
+                               if (optstart) {
+                                       optstart += strlen("[Optional:");
+                                       optend = strstr(optstart, "]");
+                                       if (optend)
+                                               setting->possible_values =
+                                                       kstrndup(optstart, optend - optstart,
+                                                                       GFP_KERNEL);
+                               }
+                               kfree(optitem);
+                       }
                }
+               /*
+                * firmware-attributes requires that possible_values are separated by ';' but
+                * Lenovo FW uses ','. Replace appropriately.
+                */
+               if (setting->possible_values)
+                       strreplace(setting->possible_values, ',', ';');
+
                kobject_init(&setting->kobj, &tlmi_attr_setting_ktype);
                tlmi_priv.setting[i] = setting;
                kfree(item);
index 32c10457399e442ac15ec28ada09d851155f34d8..7191ff2625b1ef8c223037d229485836dadb0952 100644 (file)
@@ -4478,6 +4478,14 @@ static const struct dmi_system_id fwbug_list[] __initconst = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
                }
        },
+       {
+               .ident = "T14s Gen1 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
+               }
+       },
        {
                .ident = "P14s Gen1 AMD",
                .driver_data = &quirk_s2idle_bug,
index 8e6f8a655079066975acd420d230c7f5ff150511..05f41317846296b067f41d050abc66d26cf09ff0 100644 (file)
@@ -724,6 +724,8 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 
        for (i = 0; i < AXP288_FG_INTR_NUM; i++) {
                pirq = platform_get_irq(pdev, i);
+               if (pirq < 0)
+                       continue;
                ret = regmap_irq_get_virq(axp20x->regmap_irqc, pirq);
                if (ret < 0)
                        return dev_err_probe(dev, ret, "getting vIRQ %d\n", pirq);
index be34b98484508a980db556af6352aaf12f622864..de67b985f0a913a355ea3c27e3897d7373b78db2 100644 (file)
@@ -1906,6 +1906,7 @@ static void bq24190_remove(struct i2c_client *client)
        struct bq24190_dev_info *bdi = i2c_get_clientdata(client);
        int error;
 
+       cancel_delayed_work_sync(&bdi->input_current_limit_work);
        error = pm_runtime_resume_and_get(bdi->dev);
        if (error < 0)
                dev_warn(bdi->dev, "pm_runtime_get failed: %i\n", error);
index cadb6a0c2cc7e0a5e0e4e91951e0b6c758c27f8e..b6c96376776a9aa36f3d06fa0654f3bd8ddd3e14 100644 (file)
@@ -276,7 +276,7 @@ static int cros_usbpd_charger_get_power_info(struct port_data *port)
                port->psy_current_max = 0;
                break;
        default:
-               dev_err(dev, "Port %d: default case!\n", port->port_number);
+               dev_dbg(dev, "Port %d: default case!\n", port->port_number);
                port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
        }
 
index 14da5c595dd9f31a720118112395af87810fe32f..a87aeaea38e1395c142d2bfad50cec37d3bf919c 100644 (file)
@@ -657,6 +657,7 @@ static int da9150_charger_remove(struct platform_device *pdev)
 
        if (!IS_ERR_OR_NULL(charger->usb_phy))
                usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+       cancel_work_sync(&charger->otg_work);
 
        power_supply_unregister(charger->battery);
        power_supply_unregister(charger->usb);
index 4f9c1c417916550d76706253347acc7e64d18f3d..36f807b5ec4425c30646d82f558b551cda19d9c7 100644 (file)
@@ -785,8 +785,6 @@ rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger,
                regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
                                 bulk_reg, 4);
                tmp = get_unaligned_be32(bulk_reg);
-               if (tmp < 0)
-                       tmp = 0;
                boot_charge_mah = ADC_TO_CHARGE_UAH(tmp,
                                                    charger->res_div) / 1000;
                /*
@@ -825,8 +823,6 @@ rk817_read_or_set_full_charge_on_boot(struct rk817_charger *charger,
        regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
                         bulk_reg, 4);
        tmp = get_unaligned_be32(bulk_reg);
-       if (tmp < 0)
-               tmp = 0;
        boot_charge_mah = ADC_TO_CHARGE_UAH(tmp, charger->res_div) / 1000;
        regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_OCV_VOL_H,
                         bulk_reg, 2);
index 61530167efe4afac332a8fc3b615c8afa9e183c8..350154e4c2b540ce0afbe2a8612331e3f33426e9 100644 (file)
@@ -637,7 +637,7 @@ static int ptp_qoriq_probe(struct platform_device *dev)
        return 0;
 
 no_clock:
-       iounmap(ptp_qoriq->base);
+       iounmap(base);
 no_ioremap:
        release_resource(ptp_qoriq->rsrc);
 no_resource:
index e01147f66e15aa752c8a1331372ffa0440c07d4c..474725714a05b74206dc412fe0cbca464fd4f505 100644 (file)
@@ -115,7 +115,14 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
        }
 
        if (pwm->chip->ops->get_state) {
-               struct pwm_state state;
+               /*
+                * Zero-initialize state because most drivers are unaware of
+                * .usage_power. The other members of state are supposed to be
+                * set by lowlevel drivers. We still initialize the whole
+                * structure for simplicity even though this might paper over
+                * faulty implementations of .get_state().
+                */
+               struct pwm_state state = { 0, };
 
                err = pwm->chip->ops->get_state(pwm->chip, pwm, &state);
                trace_pwm_get(pwm, &state, err);
@@ -448,7 +455,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
 {
        struct pwm_state *last = &pwm->last;
        struct pwm_chip *chip = pwm->chip;
-       struct pwm_state s1, s2;
+       struct pwm_state s1 = { 0 }, s2 = { 0 };
        int err;
 
        if (!IS_ENABLED(CONFIG_PWM_DEBUG))
@@ -530,6 +537,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
                return;
        }
 
+       *last = (struct pwm_state){ 0 };
        err = chip->ops->get_state(chip, pwm, last);
        trace_pwm_get(pwm, last, err);
        if (err)
index 86df6702cb8358233cdfa5cf45b7946837ceefbe..ad18b0ebe3f1ee3446d21d646412c69156f9859b 100644 (file)
@@ -198,6 +198,7 @@ static int cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 
        state->enabled = (ret > 0);
        state->period = EC_PWM_MAX_DUTY;
+       state->polarity = PWM_POLARITY_NORMAL;
 
        /*
         * Note that "disabled" and "duty cycle == 0" are treated the same. If
index 12c05c155cab0dbeda330fa080dc9dc040c50a93..1b9274c5ad8724c0419ea172266917c6568bdf42 100644 (file)
@@ -146,6 +146,7 @@ static int hibvt_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
 
        value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
        state->enabled = (PWM_ENABLE_MASK & value);
+       state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
 
        return 0;
 }
index 8362b4870c66c464b7012af7cb8be349f3760dc8..47b3141135f38eccdcde2c66330a72b6000fdb0a 100644 (file)
@@ -126,6 +126,7 @@ static int iqs620_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
        mutex_unlock(&iqs620_pwm->lock);
 
        state->period = IQS620_PWM_PERIOD_NS;
+       state->polarity = PWM_POLARITY_NORMAL;
 
        return 0;
 }
index 16d79ca5d8f5395d763432ad8f15801a54e5b113..5cd7b90872c627e29fb409968df1513226cc5fb8 100644 (file)
@@ -162,6 +162,12 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
        duty = state->duty_cycle;
        period = state->period;
 
+       /*
+        * Note this is wrong. The result is an output wave that isn't really
+        * inverted and so is wrongly identified by .get_state as normal.
+        * Fixing this needs some care however as some machines might rely on
+        * this.
+        */
        if (state->polarity == PWM_POLARITY_INVERSED)
                duty = period - duty;
 
@@ -358,6 +364,8 @@ static int meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
                state->duty_cycle = 0;
        }
 
+       state->polarity = PWM_POLARITY_NORMAL;
+
        return 0;
 }
 
index d866ce345f97707e9bd5f8943d5d62723802dcb0..bde579a338c270323703e045976c9546a888b0fb 100644 (file)
@@ -109,6 +109,7 @@ static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
        duty = val & SPRD_PWM_DUTY_MSK;
        tmp = (prescale + 1) * NSEC_PER_SEC * duty;
        state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
+       state->polarity = PWM_POLARITY_NORMAL;
 
        /* Disable PWM clocks if the PWM channel is not in enable state. */
        if (!state->enabled)
index 529963a7e4f52b1e84ef3e51bfb05f461f40e320..41537c45f0367dd4b0301ecb8c445925d3c858c8 100644 (file)
@@ -8,18 +8,19 @@
 // Copyright (c) 2012 Marvell Technology Ltd.
 // Yunfan Zhang <yfzhang@marvell.com>
 
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/param.h>
-#include <linux/err.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/fan53555.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
-#include <linux/of_device.h>
-#include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/regmap.h>
-#include <linux/regulator/fan53555.h>
 
 /* Voltage setting */
 #define FAN53555_VSEL0         0x00
@@ -60,7 +61,7 @@
 #define TCS_VSEL1_MODE         (1 << 6)
 
 #define TCS_SLEW_SHIFT         3
-#define TCS_SLEW_MASK          (0x3 < 3)
+#define TCS_SLEW_MASK          GENMASK(4, 3)
 
 enum fan53555_vendor {
        FAN53526_VENDOR_FAIRCHILD = 0,
index 2a9867abba20c256ea4304acd301ea988b7384ba..e6724a229d2374d521f56b7f8f326a264677dcaf 100644 (file)
@@ -215,7 +215,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
                drvdata->enable_clock = devm_clk_get(dev, NULL);
                if (IS_ERR(drvdata->enable_clock)) {
                        dev_err(dev, "Can't get enable-clock from devicetree\n");
-                       return -ENOENT;
+                       return PTR_ERR(drvdata->enable_clock);
                }
        } else if (drvtype && drvtype->has_performance_state) {
                drvdata->desc.ops = &fixed_voltage_domain_ops;
index 05ad28fc4da8cd4222af726bf1b18c44a2c029bb..229df7170792ce25cd1d4670243a93ea1898fc81 100644 (file)
@@ -42,6 +42,7 @@ static const int sm5703_buck_voltagemap[] = {
                .type = REGULATOR_VOLTAGE,                              \
                .id = SM5703_USBLDO ## _id,                             \
                .ops = &sm5703_regulator_ops_fixed,                     \
+               .n_voltages = 1,                                        \
                .fixed_uV = SM5703_USBLDO_MICROVOLT,                    \
                .enable_reg = SM5703_REG_USBLDO12,                      \
                .enable_mask = SM5703_REG_EN_USBLDO ##_id,              \
@@ -56,6 +57,7 @@ static const int sm5703_buck_voltagemap[] = {
                .type = REGULATOR_VOLTAGE,                              \
                .id = SM5703_VBUS,                                      \
                .ops = &sm5703_regulator_ops_fixed,                     \
+               .n_voltages = 1,                                        \
                .fixed_uV = SM5703_VBUS_MICROVOLT,                      \
                .enable_reg = SM5703_REG_CNTL,                          \
                .enable_mask = SM5703_OPERATION_MODE_MASK,              \
index ab053084f7a22d3d6f21a11370f675e2b057b37c..1ba711bc01000beef454922fe35a58cc927c5445 100644 (file)
@@ -235,8 +235,8 @@ struct q6v5 {
        bool has_qaccept_regs;
        bool has_ext_cntl_regs;
        bool has_vq6;
-       int mpss_perm;
-       int mba_perm;
+       u64 mpss_perm;
+       u64 mba_perm;
        const char *hexagon_mdt_image;
        int version;
 };
@@ -414,7 +414,7 @@ static void q6v5_pds_disable(struct q6v5 *qproc, struct device **pds,
        }
 }
 
-static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, int *current_perm,
+static int q6v5_xfer_mem_ownership(struct q6v5 *qproc, u64 *current_perm,
                                   bool local, bool remote, phys_addr_t addr,
                                   size_t size)
 {
@@ -967,7 +967,7 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw,
        unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
        dma_addr_t phys;
        void *metadata;
-       int mdata_perm;
+       u64 mdata_perm;
        int xferop_ret;
        size_t size;
        void *ptr;
index 0871108fb4dc5e4b9a07086437dd48ddbcd13f97..c99a20542685141c892f4f3813c36fca420d34e9 100644 (file)
@@ -94,7 +94,7 @@ struct qcom_adsp {
        size_t region_assign_size;
 
        int region_assign_idx;
-       int region_assign_perms;
+       u64 region_assign_perms;
 
        struct qcom_rproc_glink glink_subdev;
        struct qcom_rproc_subdev smd_subdev;
index 997b524bdd2b5bffbd01782e970e318c6d40c013..a48c6938ae68f256744ceecce22852c8bb586e57 100644 (file)
@@ -54,8 +54,9 @@ static struct ap_driver vfio_ap_drv = {
 
 static void vfio_ap_matrix_dev_release(struct device *dev)
 {
-       struct ap_matrix_dev *matrix_dev = dev_get_drvdata(dev);
+       struct ap_matrix_dev *matrix_dev;
 
+       matrix_dev = container_of(dev, struct ap_matrix_dev, device);
        kfree(matrix_dev);
 }
 
index e300cf26bc2a8724648a16b772bf14200327de22..d698ca506ccab73d698ba28665e78a2de2f2e85b 100644 (file)
@@ -18,7 +18,7 @@
  * the recommended way for applications to use the coprocessor, and
  * the driver interface is not intended for general use.
  *
- * See Documentation/sparc/oradax/oracle-dax.rst for more details.
+ * See Documentation/arch/sparc/oradax/oracle-dax.rst for more details.
  */
 
 #include <linux/uaccess.h>
index 362fa631f39b2654ee051209826fad0ff3648c36..a226dc1b65d715f03addcf638fa52510360b1272 100644 (file)
@@ -1145,10 +1145,12 @@ static int alua_activate(struct scsi_device *sdev,
        rcu_read_unlock();
        mutex_unlock(&h->init_mutex);
 
-       if (alua_rtpg_queue(pg, sdev, qdata, true))
+       if (alua_rtpg_queue(pg, sdev, qdata, true)) {
                fn = NULL;
-       else
+       } else {
+               kfree(qdata);
                err = SCSI_DH_DEV_OFFLINED;
+       }
        kref_put(&pg->kref, release_port_group);
 out:
        if (fn)
index f7f62e56afcae6db20711357ed93242562ddcfed..9b6fbbe15d9226a0f48c842a781e59494540f7d3 100644 (file)
@@ -341,9 +341,6 @@ static void scsi_host_dev_release(struct device *dev)
        struct Scsi_Host *shost = dev_to_shost(dev);
        struct device *parent = dev->parent;
 
-       /* In case scsi_remove_host() has not been called. */
-       scsi_proc_hostdir_rm(shost->hostt);
-
        /* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */
        rcu_barrier();
 
index c76f82fb8b6361263b4be1f597d0a6048b4ec902..15f4529089262099ff7c984e7f80350136ef4ab2 100644 (file)
@@ -771,13 +771,12 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn,
                iscsi_set_param(cls_conn, param, buf, buflen);
                break;
        case ISCSI_PARAM_DATADGST_EN:
-               iscsi_set_param(cls_conn, param, buf, buflen);
-
                mutex_lock(&tcp_sw_conn->sock_lock);
                if (!tcp_sw_conn->sock) {
                        mutex_unlock(&tcp_sw_conn->sock_lock);
                        return -ENOTCONN;
                }
+               iscsi_set_param(cls_conn, param, buf, buflen);
                tcp_sw_conn->sendpage = conn->datadgst_en ?
                        sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage;
                mutex_unlock(&tcp_sw_conn->sock_lock);
index 3ceece9883383b78969fac6c87bcca3bbd5a61b1..c895189375e2b6afc5c2616c9934ba9b334bdb59 100644 (file)
@@ -3298,7 +3298,7 @@ fw_crash_buffer_show(struct device *cdev,
 
        spin_lock_irqsave(&instance->crashdump_lock, flags);
        buff_offset = instance->fw_crash_buffer_offset;
-       if (!instance->crash_dump_buf &&
+       if (!instance->crash_dump_buf ||
                !((instance->fw_crash_state == AVAILABLE) ||
                (instance->fw_crash_state == COPYING))) {
                dev_err(&instance->pdev->dev,
index 84c9a55a5794c814c9bf8960d503130f2f3b451b..8a83f3fc2b865e7c6a430168c86b2f5fb5c5822e 100644 (file)
@@ -4771,7 +4771,7 @@ int megasas_task_abort_fusion(struct scsi_cmnd *scmd)
        devhandle = megasas_get_tm_devhandle(scmd->device);
 
        if (devhandle == (u16)ULONG_MAX) {
-               ret = SUCCESS;
+               ret = FAILED;
                sdev_printk(KERN_INFO, scmd->device,
                        "task abort issued for invalid devhandle\n");
                mutex_unlock(&instance->reset_mutex);
@@ -4841,7 +4841,7 @@ int megasas_reset_target_fusion(struct scsi_cmnd *scmd)
        devhandle = megasas_get_tm_devhandle(scmd->device);
 
        if (devhandle == (u16)ULONG_MAX) {
-               ret = SUCCESS;
+               ret = FAILED;
                sdev_printk(KERN_INFO, scmd->device,
                        "target reset issued for invalid devhandle\n");
                mutex_unlock(&instance->reset_mutex);
index 40f238fa80cc18341b329a7e5eb1a2060a5e70d8..364fb1b5e45ace6cd4c5e5aa3ddcc706dee47063 100644 (file)
@@ -1393,4 +1393,6 @@ void mpi3mr_flush_drv_cmds(struct mpi3mr_ioc *mrioc);
 void mpi3mr_flush_cmds_for_unrecovered_controller(struct mpi3mr_ioc *mrioc);
 void mpi3mr_free_enclosure_list(struct mpi3mr_ioc *mrioc);
 int mpi3mr_process_admin_reply_q(struct mpi3mr_ioc *mrioc);
+void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
+       struct mpi3mr_sas_node *sas_expander);
 #endif /*MPI3MR_H_INCLUDED*/
index 29acf6111db302d3a0e9dba2c48aaa046b8f97ba..d109a4ceb72b1bef3cd165585dc7863c41d5df69 100644 (file)
@@ -2526,7 +2526,7 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
                mrioc->unrecoverable = 1;
                goto schedule_work;
        case MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS:
-               return;
+               goto schedule_work;
        case MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET:
                reset_reason = MPI3MR_RESET_FROM_CIACTIV_FAULT;
                break;
@@ -3837,29 +3837,34 @@ retry_init:
 
        mpi3mr_print_ioc_info(mrioc);
 
-       dprint_init(mrioc, "allocating config page buffers\n");
-       mrioc->cfg_page = dma_alloc_coherent(&mrioc->pdev->dev,
-           MPI3MR_DEFAULT_CFG_PAGE_SZ, &mrioc->cfg_page_dma, GFP_KERNEL);
        if (!mrioc->cfg_page) {
-               retval = -1;
-               goto out_failed_noretry;
+               dprint_init(mrioc, "allocating config page buffers\n");
+               mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ;
+               mrioc->cfg_page = dma_alloc_coherent(&mrioc->pdev->dev,
+                   mrioc->cfg_page_sz, &mrioc->cfg_page_dma, GFP_KERNEL);
+               if (!mrioc->cfg_page) {
+                       retval = -1;
+                       goto out_failed_noretry;
+               }
        }
 
-       mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ;
-
-       retval = mpi3mr_alloc_reply_sense_bufs(mrioc);
-       if (retval) {
-               ioc_err(mrioc,
-                   "%s :Failed to allocated reply sense buffers %d\n",
-                   __func__, retval);
-               goto out_failed_noretry;
+       if (!mrioc->init_cmds.reply) {
+               retval = mpi3mr_alloc_reply_sense_bufs(mrioc);
+               if (retval) {
+                       ioc_err(mrioc,
+                           "%s :Failed to allocated reply sense buffers %d\n",
+                           __func__, retval);
+                       goto out_failed_noretry;
+               }
        }
 
-       retval = mpi3mr_alloc_chain_bufs(mrioc);
-       if (retval) {
-               ioc_err(mrioc, "Failed to allocated chain buffers %d\n",
-                   retval);
-               goto out_failed_noretry;
+       if (!mrioc->chain_sgl_list) {
+               retval = mpi3mr_alloc_chain_bufs(mrioc);
+               if (retval) {
+                       ioc_err(mrioc, "Failed to allocated chain buffers %d\n",
+                           retval);
+                       goto out_failed_noretry;
+               }
        }
 
        retval = mpi3mr_issue_iocinit(mrioc);
@@ -4382,13 +4387,20 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
                    mrioc->admin_req_base, mrioc->admin_req_dma);
                mrioc->admin_req_base = NULL;
        }
-
+       if (mrioc->cfg_page) {
+               dma_free_coherent(&mrioc->pdev->dev, mrioc->cfg_page_sz,
+                   mrioc->cfg_page, mrioc->cfg_page_dma);
+               mrioc->cfg_page = NULL;
+       }
        if (mrioc->pel_seqnum_virt) {
                dma_free_coherent(&mrioc->pdev->dev, mrioc->pel_seqnum_sz,
                    mrioc->pel_seqnum_virt, mrioc->pel_seqnum_dma);
                mrioc->pel_seqnum_virt = NULL;
        }
 
+       kfree(mrioc->throttle_groups);
+       mrioc->throttle_groups = NULL;
+
        kfree(mrioc->logdata_buf);
        mrioc->logdata_buf = NULL;
 
index a794cc8a1c0b137697624d2e90f3a257e8e7983d..6d55698ea4d16c9ca22c6ca136e18ca7be2977d0 100644 (file)
@@ -5078,6 +5078,8 @@ static void mpi3mr_remove(struct pci_dev *pdev)
        struct workqueue_struct *wq;
        unsigned long flags;
        struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next;
+       struct mpi3mr_hba_port *port, *hba_port_next;
+       struct mpi3mr_sas_node *sas_expander, *sas_expander_next;
 
        if (!shost)
                return;
@@ -5117,6 +5119,28 @@ static void mpi3mr_remove(struct pci_dev *pdev)
        mpi3mr_free_mem(mrioc);
        mpi3mr_cleanup_resources(mrioc);
 
+       spin_lock_irqsave(&mrioc->sas_node_lock, flags);
+       list_for_each_entry_safe_reverse(sas_expander, sas_expander_next,
+           &mrioc->sas_expander_list, list) {
+               spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
+               mpi3mr_expander_node_remove(mrioc, sas_expander);
+               spin_lock_irqsave(&mrioc->sas_node_lock, flags);
+       }
+       list_for_each_entry_safe(port, hba_port_next, &mrioc->hba_port_table_list, list) {
+               ioc_info(mrioc,
+                   "removing hba_port entry: %p port: %d from hba_port list\n",
+                   port, port->port_id);
+               list_del(&port->list);
+               kfree(port);
+       }
+       spin_unlock_irqrestore(&mrioc->sas_node_lock, flags);
+
+       if (mrioc->sas_hba.num_phys) {
+               kfree(mrioc->sas_hba.phy);
+               mrioc->sas_hba.phy = NULL;
+               mrioc->sas_hba.num_phys = 0;
+       }
+
        spin_lock(&mrioc_list_lock);
        list_del(&mrioc->list);
        spin_unlock(&mrioc_list_lock);
index be25f242fa79495f796bc21180105927440e4011..5748bd9369ff78495085f15595b4c580742cdd67 100644 (file)
@@ -9,9 +9,6 @@
 
 #include "mpi3mr.h"
 
-static void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
-       struct mpi3mr_sas_node *sas_expander);
-
 /**
  * mpi3mr_post_transport_req - Issue transport requests and wait
  * @mrioc: Adapter instance reference
@@ -2164,7 +2161,7 @@ out_fail:
  *
  * Return nothing.
  */
-static void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
+void mpi3mr_expander_node_remove(struct mpi3mr_ioc *mrioc,
        struct mpi3mr_sas_node *sas_expander)
 {
        struct mpi3mr_sas_port *mr_sas_port, *next;
index 2ee9ea57554d70a1b04f65962052d87c9eaf920b..14ae0a9c5d3d84e20ca5a030638937c07789cd51 100644 (file)
@@ -6616,11 +6616,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
        else if (rc == -EAGAIN)
                goto try_32bit_dma;
        total_sz += sense_sz;
-       ioc_info(ioc,
-           "sense pool(0x%p)- dma(0x%llx): depth(%d),"
-           "element_size(%d), pool_size(%d kB)\n",
-           ioc->sense, (unsigned long long)ioc->sense_dma, ioc->scsiio_depth,
-           SCSI_SENSE_BUFFERSIZE, sz / 1024);
        /* reply pool, 4 byte align */
        sz = ioc->reply_free_queue_depth * ioc->reply_sz;
        rc = _base_allocate_reply_pool(ioc, sz);
index e5ecd6ada6cdd851e833fce012d1e6f987bc3c3d..e8a4750f6ec473bd6e41385fa2c920179e0c4ba5 100644 (file)
@@ -785,7 +785,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
                goto out_fail;
        }
        port = sas_port_alloc_num(sas_node->parent_dev);
-       if ((sas_port_add(port))) {
+       if (!port || (sas_port_add(port))) {
                ioc_err(ioc, "failure at %s:%d/%s()!\n",
                        __FILE__, __LINE__, __func__);
                goto out_fail;
@@ -824,6 +824,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
                            mpt3sas_port->remote_identify.sas_address;
        }
 
+       if (!rphy) {
+               ioc_err(ioc, "failure at %s:%d/%s()!\n",
+                       __FILE__, __LINE__, __func__);
+               goto out_delete_port;
+       }
+
        rphy->identify = mpt3sas_port->remote_identify;
 
        if ((sas_rphy_add(rphy))) {
@@ -831,6 +837,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
                        __FILE__, __LINE__, __func__);
                sas_rphy_free(rphy);
                rphy = NULL;
+               goto out_delete_port;
        }
 
        if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
@@ -857,7 +864,10 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
                    rphy_to_expander_device(rphy), hba_port->port_id);
        return mpt3sas_port;
 
- out_fail:
+out_delete_port:
+       sas_port_delete(port);
+
+out_fail:
        list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
            port_siblings)
                list_del(&mpt3sas_phy->port_siblings);
index 030625ebb4e653a0da4df20f62751f4926332354..71feda2cdb63046a713c5018ae64948abed1084f 100644 (file)
@@ -1900,6 +1900,8 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func,
        }
 
        req->outstanding_cmds[index] = NULL;
+
+       qla_put_fw_resources(sp->qpair, &sp->iores);
        return sp;
 }
 
@@ -3112,7 +3114,6 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
        }
        bsg_reply->reply_payload_rcv_len = 0;
 
-       qla_put_fw_resources(sp->qpair, &sp->iores);
 done:
        /* Return the vendor specific reply to API */
        bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
index 80c4ee9df2a4ff86fe6243c9201cb29e2f54899b..d0cdbfe771a9cd09bf5c482cb96a35dba10ca366 100644 (file)
@@ -1865,6 +1865,17 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
        for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
                sp = req->outstanding_cmds[cnt];
                if (sp) {
+                       /*
+                        * perform lockless completion during driver unload
+                        */
+                       if (qla2x00_chip_is_down(vha)) {
+                               req->outstanding_cmds[cnt] = NULL;
+                               spin_unlock_irqrestore(qp->qp_lock_ptr, flags);
+                               sp->done(sp, res);
+                               spin_lock_irqsave(qp->qp_lock_ptr, flags);
+                               continue;
+                       }
+
                        switch (sp->cmd_type) {
                        case TYPE_SRB:
                                qla2x00_abort_srb(qp, sp, res, &flags);
@@ -3606,6 +3617,7 @@ skip_dpc:
 probe_failed:
        qla_enode_stop(base_vha);
        qla_edb_stop(base_vha);
+       vfree(base_vha->scan.l);
        if (base_vha->gnl.l) {
                dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
                                base_vha->gnl.l, base_vha->gnl.ldma);
index 7d2210a006f0d44b1c71233e0bc8d684ec4f77ae..09ef0b31dfc09c5d9950bf458c4ae8758862358e 100644 (file)
@@ -314,11 +314,18 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer,
        if (result)
                return -EIO;
 
-       /* Sanity check that we got the page back that we asked for */
+       /*
+        * Sanity check that we got the page back that we asked for and that
+        * the page size is not 0.
+        */
        if (buffer[1] != page)
                return -EIO;
 
-       return get_unaligned_be16(&buffer[2]) + 4;
+       result = get_unaligned_be16(&buffer[2]);
+       if (!result)
+               return -EIO;
+
+       return result + 4;
 }
 
 static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page)
@@ -326,6 +333,9 @@ static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page)
        unsigned char vpd_header[SCSI_VPD_HEADER_SIZE] __aligned(4);
        int result;
 
+       if (sdev->no_vpd_size)
+               return SCSI_DEFAULT_VPD_LEN;
+
        /*
         * Fetch the VPD page header to find out how big the page
         * is. This is done to prevent problems on legacy devices
index c7080454aea997a66202badf18fbfe383c42f32b..3fcaf10a9dfe76daa651db71c9a2f0f6b1bbd1b0 100644 (file)
@@ -134,7 +134,7 @@ static struct {
        {"3PARdata", "VV", NULL, BLIST_REPORTLUN2},
        {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN},
        {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN},
-       {"AIX", "VDASD", NULL, BLIST_TRY_VPD_PAGES},
+       {"AIX", "VDASD", NULL, BLIST_TRY_VPD_PAGES | BLIST_NO_VPD_SIZE},
        {"AFT PRO", "-IX CF", "0.0>", BLIST_FORCELUN},
        {"BELKIN", "USB 2 HS-CF", "1.95",  BLIST_FORCELUN | BLIST_INQUIRY_36},
        {"BROWNIE", "1200U3P", NULL, BLIST_NOREPORTLUN},
@@ -188,6 +188,7 @@ static struct {
        {"HPE", "OPEN-", "*", BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES},
        {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN},
        {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+       {"IBM", "2076", NULL, BLIST_NO_VPD_SIZE},
        {"IBM", "2105", NULL, BLIST_RETRY_HWERROR},
        {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
        {"IOMEGA", "ZIP", NULL, BLIST_NOTQ | BLIST_NOLUN},
@@ -233,6 +234,7 @@ static struct {
        {"SGI", "RAID5", "*", BLIST_SPARSELUN},
        {"SGI", "TP9100", "*", BLIST_REPORTLUN2},
        {"SGI", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
+       {"SKhynix", "H28U74301AMR", NULL, BLIST_SKIP_VPD_PAGES},
        {"IBM", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"SUN", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
        {"DELL", "Universal Xport", "*", BLIST_NO_ULD_ATTACH},
index 4e842d79de317c2e7ed5a54e45f1fd32aa07b908..d217be323cc690f0736df29349d085bd27575170 100644 (file)
@@ -1057,6 +1057,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
        else if (*bflags & BLIST_SKIP_VPD_PAGES)
                sdev->skip_vpd_pages = 1;
 
+       if (*bflags & BLIST_NO_VPD_SIZE)
+               sdev->no_vpd_size = 1;
+
        transport_configure_device(&sdev->sdev_gendev);
 
        if (sdev->host->hostt->slave_configure) {
index b11a9162e73aaeed994667a3ba04f2fa59cae240..b54f2c6c08c362799e31141b9abbaf3a4667ed71 100644 (file)
@@ -509,9 +509,6 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
        int i;
        struct ses_component *scomp;
 
-       if (!edev->component[0].scratch)
-               return 0;
-
        for (i = 0; i < edev->components; i++) {
                scomp = edev->component[i].scratch;
                if (scomp->addr != efd->addr)
@@ -602,8 +599,10 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
                                                components++,
                                                type_ptr[0],
                                                name);
-                               else
+                               else if (components < edev->components)
                                        ecomp = &edev->component[components++];
+                               else
+                                       ecomp = ERR_PTR(-EINVAL);
 
                                if (!IS_ERR(ecomp)) {
                                        if (addl_desc_ptr) {
@@ -734,11 +733,6 @@ static int ses_intf_add(struct device *cdev,
                        components += type_ptr[1];
        }
 
-       if (components == 0) {
-               sdev_printk(KERN_WARNING, sdev, "enclosure has no enumerated components\n");
-               goto err_free;
-       }
-
        ses_dev->page1 = buf;
        ses_dev->page1_len = len;
        buf = NULL;
@@ -780,9 +774,11 @@ static int ses_intf_add(struct device *cdev,
                buf = NULL;
        }
 page2_not_supported:
-       scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
-       if (!scomp)
-               goto err_free;
+       if (components > 0) {
+               scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
+               if (!scomp)
+                       goto err_free;
+       }
 
        edev = enclosure_register(cdev->parent, dev_name(&sdev->sdev_gendev),
                                  components, &ses_enclosure_callbacks);
index 312fd9afccb01c1e7dc8a86999f173733dd5eeff..5d4f12800d9383084fc8ee53b88412a7be9f8d67 100644 (file)
@@ -308,11 +308,9 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
        }
 
        rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
-       if (IS_ERR(rstc)) {
-               if (PTR_ERR(rstc) != -EPROBE_DEFER)
-                       dev_err(&pdev->dev, "failed to get reset lines\n");
-               return PTR_ERR(rstc);
-       }
+       if (IS_ERR(rstc))
+               return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
+                                    "failed to get reset lines\n");
 
        vpu_clk = devm_clk_get(&pdev->dev, "vpu");
        if (IS_ERR(vpu_clk)) {
index 35ec35aa500d67334a81231d87eaab3c6e7547d3..d9f19dc99da5e824b327c1a334e5d44e8f7c392b 100644 (file)
@@ -55,7 +55,7 @@ enum {
 
 #define APPLE_RTKIT_BUFFER_REQUEST     1
 #define APPLE_RTKIT_BUFFER_REQUEST_SIZE GENMASK_ULL(51, 44)
-#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK_ULL(41, 0)
+#define APPLE_RTKIT_BUFFER_REQUEST_IOVA GENMASK_ULL(43, 0)
 
 #define APPLE_RTKIT_SYSLOG_TYPE GENMASK_ULL(59, 52)
 
@@ -409,11 +409,17 @@ static void apple_rtkit_syslog_rx_init(struct apple_rtkit *rtk, u64 msg)
                rtk->syslog_n_entries, rtk->syslog_msg_size);
 }
 
+static bool should_crop_syslog_char(char c)
+{
+       return c == '\n' || c == '\r' || c == ' ' || c == '\0';
+}
+
 static void apple_rtkit_syslog_rx_log(struct apple_rtkit *rtk, u64 msg)
 {
        u8 idx = msg & 0xff;
        char log_context[24];
        size_t entry_size = 0x20 + rtk->syslog_msg_size;
+       int msglen;
 
        if (!rtk->syslog_msg_buffer) {
                dev_warn(
@@ -446,7 +452,13 @@ static void apple_rtkit_syslog_rx_log(struct apple_rtkit *rtk, u64 msg)
                           rtk->syslog_msg_size);
 
        log_context[sizeof(log_context) - 1] = 0;
-       rtk->syslog_msg_buffer[rtk->syslog_msg_size - 1] = 0;
+
+       msglen = rtk->syslog_msg_size - 1;
+       while (msglen > 0 &&
+                  should_crop_syslog_char(rtk->syslog_msg_buffer[msglen - 1]))
+               msglen--;
+
+       rtk->syslog_msg_buffer[msglen] = 0;
        dev_info(rtk->dev, "RTKit: syslog message: %s: %s\n", log_context,
                 rtk->syslog_msg_buffer);
 
index bf51f03f77d6470ee39ab487793c582a6a28437e..1a179d4e011cfe98a3932be49852bae6137d16aa 100644 (file)
@@ -711,4 +711,3 @@ module_platform_driver(bcm2835_power_driver);
 
 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
 MODULE_DESCRIPTION("Driver for Broadcom BCM2835 PM power domains and reset");
-MODULE_LICENSE("GPL");
index 38e476905d96a8139f69e731ba99e1fa6ac07e90..c68d0e5267c42e68cb9c9703ad38e5a29835715b 100644 (file)
@@ -4,8 +4,6 @@ if SOC_BRCMSTB
 config BRCMSTB_PM
        bool "Support suspend/resume for STB platforms"
        default y
-       depends on PM
-       depends on ARCH_BRCMSTB || BMIPS_GENERIC
-       select ARM_CPU_SUSPEND if ARM
+       depends on PM && BMIPS_GENERIC
 
 endif # SOC_BRCMSTB
index e1d7b45432485a0601d26886a7834cc58e4c2963..364ddbe365c248ca3b8464492791f4a9485afc3e 100644 (file)
@@ -288,6 +288,10 @@ static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
        if (BRCM_ID(family_id) == 0x7260 && BRCM_REV(family_id) == 0)
                cpubiuctrl_regs = b53_cpubiuctrl_no_wb_regs;
 out:
+       if (ret && cpubiuctrl_base) {
+               iounmap(cpubiuctrl_base);
+               cpubiuctrl_base = NULL;
+       }
        return ret;
 }
 
index f849cfa69446b8c965e141456700d63f2b3ce2b4..9133a9ee0782d6c663f8d72303f7df5857c28e08 100644 (file)
@@ -1,3 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_ARM)              += s2-arm.o pm-arm.o
 obj-$(CONFIG_BMIPS_GENERIC)    += s2-mips.o s3-mips.o pm-mips.o
diff --git a/drivers/soc/bcm/brcmstb/pm/aon_defs.h b/drivers/soc/bcm/brcmstb/pm/aon_defs.h
deleted file mode 100644 (file)
index f695262..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Always ON (AON) register interface between bootloader and Linux
- *
- * Copyright © 2014-2017 Broadcom
- */
-
-#ifndef __BRCMSTB_AON_DEFS_H__
-#define __BRCMSTB_AON_DEFS_H__
-
-#include <linux/compiler.h>
-
-/* Magic number in upper 16-bits */
-#define BRCMSTB_S3_MAGIC_MASK                   0xffff0000
-#define BRCMSTB_S3_MAGIC_SHORT                  0x5AFE0000
-
-enum {
-       /* Restore random key for AES memory verification (off = fixed key) */
-       S3_FLAG_LOAD_RANDKEY            = (1 << 0),
-
-       /* Scratch buffer page table is present */
-       S3_FLAG_SCRATCH_BUFFER_TABLE    = (1 << 1),
-
-       /* Skip all memory verification */
-       S3_FLAG_NO_MEM_VERIFY           = (1 << 2),
-
-       /*
-        * Modification of this bit reserved for bootloader only.
-        * 1=PSCI started Linux, 0=Direct jump to Linux.
-        */
-       S3_FLAG_PSCI_BOOT               = (1 << 3),
-
-       /*
-        * Modification of this bit reserved for bootloader only.
-        * 1=64 bit boot, 0=32 bit boot.
-        */
-       S3_FLAG_BOOTED64                = (1 << 4),
-};
-
-#define BRCMSTB_HASH_LEN                       (128 / 8) /* 128-bit hash */
-
-#define AON_REG_MAGIC_FLAGS                    0x00
-#define AON_REG_CONTROL_LOW                    0x04
-#define AON_REG_CONTROL_HIGH                   0x08
-#define AON_REG_S3_HASH                                0x0c /* hash of S3 params */
-#define AON_REG_CONTROL_HASH_LEN               0x1c
-#define AON_REG_PANIC                          0x20
-
-#define BRCMSTB_S3_MAGIC               0x5AFEB007
-#define BRCMSTB_PANIC_MAGIC            0x512E115E
-#define BOOTLOADER_SCRATCH_SIZE                64
-#define BRCMSTB_DTU_STATE_MAP_ENTRIES  (8*1024)
-#define BRCMSTB_DTU_CONFIG_ENTRIES     (512)
-#define BRCMSTB_DTU_COUNT              (2)
-
-#define IMAGE_DESCRIPTORS_BUFSIZE      (2 * 1024)
-#define S3_BOOTLOADER_RESERVED         (S3_FLAG_PSCI_BOOT | S3_FLAG_BOOTED64)
-
-struct brcmstb_bootloader_dtu_table {
-       uint32_t        dtu_state_map[BRCMSTB_DTU_STATE_MAP_ENTRIES];
-       uint32_t        dtu_config[BRCMSTB_DTU_CONFIG_ENTRIES];
-};
-
-/*
- * Bootloader utilizes a custom parameter block left in DRAM for handling S3
- * warm resume
- */
-struct brcmstb_s3_params {
-       /* scratch memory for bootloader */
-       uint8_t scratch[BOOTLOADER_SCRATCH_SIZE];
-
-       uint32_t magic; /* BRCMSTB_S3_MAGIC */
-       uint64_t reentry; /* PA */
-
-       /* descriptors */
-       uint32_t hash[BRCMSTB_HASH_LEN / 4];
-
-       /*
-        * If 0, then ignore this parameter (there is only one set of
-        *   descriptors)
-        *
-        * If non-0, then a second set of descriptors is stored at:
-        *
-        *   descriptors + desc_offset_2
-        *
-        * The MAC result of both descriptors is XOR'd and stored in @hash
-        */
-       uint32_t desc_offset_2;
-
-       /*
-        * (Physical) address of a brcmstb_bootloader_scratch_table, for
-        * providing a large DRAM buffer to the bootloader
-        */
-       uint64_t buffer_table;
-
-       uint32_t spare[70];
-
-       uint8_t descriptors[IMAGE_DESCRIPTORS_BUFSIZE];
-       /*
-        * Must be last member of struct. See brcmstb_pm_s3_finish() for reason.
-        */
-       struct brcmstb_bootloader_dtu_table dtu[BRCMSTB_DTU_COUNT];
-} __packed;
-
-#endif /* __BRCMSTB_AON_DEFS_H__ */
diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
deleted file mode 100644 (file)
index d681cd2..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * ARM-specific support for Broadcom STB S2/S3/S5 power management
- *
- * S2: clock gate CPUs and as many peripherals as possible
- * S3: power off all of the chip except the Always ON (AON) island; keep DDR is
- *     self-refresh
- * S5: (a.k.a. S3 cold boot) much like S3, except DDR is powered down, so we
- *     treat this mode like a soft power-off, with wakeup allowed from AON
- *
- * Copyright © 2014-2017 Broadcom
- */
-
-#define pr_fmt(fmt) "brcmstb-pm: " fmt
-
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/kconfig.h>
-#include <linux/kernel.h>
-#include <linux/memblock.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/panic_notifier.h>
-#include <linux/platform_device.h>
-#include <linux/pm.h>
-#include <linux/printk.h>
-#include <linux/proc_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/sort.h>
-#include <linux/suspend.h>
-#include <linux/types.h>
-#include <linux/uaccess.h>
-#include <linux/soc/brcmstb/brcmstb.h>
-
-#include <asm/fncpy.h>
-#include <asm/setup.h>
-#include <asm/suspend.h>
-
-#include "pm.h"
-#include "aon_defs.h"
-
-#define SHIMPHY_DDR_PAD_CNTRL          0x8c
-
-/* Method #0 */
-#define SHIMPHY_PAD_PLL_SEQUENCE       BIT(8)
-#define SHIMPHY_PAD_GATE_PLL_S3                BIT(9)
-
-/* Method #1 */
-#define PWRDWN_SEQ_NO_SEQUENCING       0
-#define PWRDWN_SEQ_HOLD_CHANNEL                1
-#define        PWRDWN_SEQ_RESET_PLL            2
-#define PWRDWN_SEQ_POWERDOWN_PLL       3
-
-#define SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK 0x00f00000
-#define SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT        20
-
-#define        DDR_FORCE_CKE_RST_N             BIT(3)
-#define        DDR_PHY_RST_N                   BIT(2)
-#define        DDR_PHY_CKE                     BIT(1)
-
-#define        DDR_PHY_NO_CHANNEL              0xffffffff
-
-#define MAX_NUM_MEMC                   3
-
-struct brcmstb_memc {
-       void __iomem *ddr_phy_base;
-       void __iomem *ddr_shimphy_base;
-       void __iomem *ddr_ctrl;
-};
-
-struct brcmstb_pm_control {
-       void __iomem *aon_ctrl_base;
-       void __iomem *aon_sram;
-       struct brcmstb_memc memcs[MAX_NUM_MEMC];
-
-       void __iomem *boot_sram;
-       size_t boot_sram_len;
-
-       bool support_warm_boot;
-       size_t pll_status_offset;
-       int num_memc;
-
-       struct brcmstb_s3_params *s3_params;
-       dma_addr_t s3_params_pa;
-       int s3entry_method;
-       u32 warm_boot_offset;
-       u32 phy_a_standby_ctrl_offs;
-       u32 phy_b_standby_ctrl_offs;
-       bool needs_ddr_pad;
-       struct platform_device *pdev;
-};
-
-enum bsp_initiate_command {
-       BSP_CLOCK_STOP          = 0x00,
-       BSP_GEN_RANDOM_KEY      = 0x4A,
-       BSP_RESTORE_RANDOM_KEY  = 0x55,
-       BSP_GEN_FIXED_KEY       = 0x63,
-};
-
-#define PM_INITIATE            0x01
-#define PM_INITIATE_SUCCESS    0x00
-#define PM_INITIATE_FAIL       0xfe
-
-static struct brcmstb_pm_control ctrl;
-
-noinline int brcmstb_pm_s3_finish(void);
-
-static int (*brcmstb_pm_do_s2_sram)(void __iomem *aon_ctrl_base,
-               void __iomem *ddr_phy_pll_status);
-
-static int brcmstb_init_sram(struct device_node *dn)
-{
-       void __iomem *sram;
-       struct resource res;
-       int ret;
-
-       ret = of_address_to_resource(dn, 0, &res);
-       if (ret)
-               return ret;
-
-       /* Uncached, executable remapping of SRAM */
-       sram = __arm_ioremap_exec(res.start, resource_size(&res), false);
-       if (!sram)
-               return -ENOMEM;
-
-       ctrl.boot_sram = sram;
-       ctrl.boot_sram_len = resource_size(&res);
-
-       return 0;
-}
-
-static const struct of_device_id sram_dt_ids[] = {
-       { .compatible = "mmio-sram" },
-       { /* sentinel */ }
-};
-
-static int do_bsp_initiate_command(enum bsp_initiate_command cmd)
-{
-       void __iomem *base = ctrl.aon_ctrl_base;
-       int ret;
-       int timeo = 1000 * 1000; /* 1 second */
-
-       writel_relaxed(0, base + AON_CTRL_PM_INITIATE);
-       (void)readl_relaxed(base + AON_CTRL_PM_INITIATE);
-
-       /* Go! */
-       writel_relaxed((cmd << 1) | PM_INITIATE, base + AON_CTRL_PM_INITIATE);
-
-       /*
-        * If firmware doesn't support the 'ack', then just assume it's done
-        * after 10ms. Note that this only works for command 0, BSP_CLOCK_STOP
-        */
-       if (of_machine_is_compatible("brcm,bcm74371a0")) {
-               (void)readl_relaxed(base + AON_CTRL_PM_INITIATE);
-               mdelay(10);
-               return 0;
-       }
-
-       for (;;) {
-               ret = readl_relaxed(base + AON_CTRL_PM_INITIATE);
-               if (!(ret & PM_INITIATE))
-                       break;
-               if (timeo <= 0) {
-                       pr_err("error: timeout waiting for BSP (%x)\n", ret);
-                       break;
-               }
-               timeo -= 50;
-               udelay(50);
-       }
-
-       return (ret & 0xff) != PM_INITIATE_SUCCESS;
-}
-
-static int brcmstb_pm_handshake(void)
-{
-       void __iomem *base = ctrl.aon_ctrl_base;
-       u32 tmp;
-       int ret;
-
-       /* BSP power handshake, v1 */
-       tmp = readl_relaxed(base + AON_CTRL_HOST_MISC_CMDS);
-       tmp &= ~1UL;
-       writel_relaxed(tmp, base + AON_CTRL_HOST_MISC_CMDS);
-       (void)readl_relaxed(base + AON_CTRL_HOST_MISC_CMDS);
-
-       ret = do_bsp_initiate_command(BSP_CLOCK_STOP);
-       if (ret)
-               pr_err("BSP handshake failed\n");
-
-       /*
-        * HACK: BSP may have internal race on the CLOCK_STOP command.
-        * Avoid touching the BSP for a few milliseconds.
-        */
-       mdelay(3);
-
-       return ret;
-}
-
-static inline void shimphy_set(u32 value, u32 mask)
-{
-       int i;
-
-       if (!ctrl.needs_ddr_pad)
-               return;
-
-       for (i = 0; i < ctrl.num_memc; i++) {
-               u32 tmp;
-
-               tmp = readl_relaxed(ctrl.memcs[i].ddr_shimphy_base +
-                       SHIMPHY_DDR_PAD_CNTRL);
-               tmp = value | (tmp & mask);
-               writel_relaxed(tmp, ctrl.memcs[i].ddr_shimphy_base +
-                       SHIMPHY_DDR_PAD_CNTRL);
-       }
-       wmb(); /* Complete sequence in order. */
-}
-
-static inline void ddr_ctrl_set(bool warmboot)
-{
-       int i;
-
-       for (i = 0; i < ctrl.num_memc; i++) {
-               u32 tmp;
-
-               tmp = readl_relaxed(ctrl.memcs[i].ddr_ctrl +
-                               ctrl.warm_boot_offset);
-               if (warmboot)
-                       tmp |= 1;
-               else
-                       tmp &= ~1; /* Cold boot */
-               writel_relaxed(tmp, ctrl.memcs[i].ddr_ctrl +
-                               ctrl.warm_boot_offset);
-       }
-       /* Complete sequence in order */
-       wmb();
-}
-
-static inline void s3entry_method0(void)
-{
-       shimphy_set(SHIMPHY_PAD_GATE_PLL_S3 | SHIMPHY_PAD_PLL_SEQUENCE,
-                   0xffffffff);
-}
-
-static inline void s3entry_method1(void)
-{
-       /*
-        * S3 Entry Sequence
-        * -----------------
-        * Step 1: SHIMPHY_ADDR_CNTL_0_DDR_PAD_CNTRL [ S3_PWRDWN_SEQ ] = 3
-        * Step 2: MEMC_DDR_0_WARM_BOOT [ WARM_BOOT ] = 1
-        */
-       shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
-                   SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                   ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-
-       ddr_ctrl_set(true);
-}
-
-static inline void s5entry_method1(void)
-{
-       int i;
-
-       /*
-        * S5 Entry Sequence
-        * -----------------
-        * Step 1: SHIMPHY_ADDR_CNTL_0_DDR_PAD_CNTRL [ S3_PWRDWN_SEQ ] = 3
-        * Step 2: MEMC_DDR_0_WARM_BOOT [ WARM_BOOT ] = 0
-        * Step 3: DDR_PHY_CONTROL_REGS_[AB]_0_STANDBY_CONTROL[ CKE ] = 0
-        *         DDR_PHY_CONTROL_REGS_[AB]_0_STANDBY_CONTROL[ RST_N ] = 0
-        */
-       shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
-                   SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                   ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-
-       ddr_ctrl_set(false);
-
-       for (i = 0; i < ctrl.num_memc; i++) {
-               u32 tmp;
-
-               /* Step 3: Channel A (RST_N = CKE = 0) */
-               tmp = readl_relaxed(ctrl.memcs[i].ddr_phy_base +
-                                 ctrl.phy_a_standby_ctrl_offs);
-               tmp &= ~(DDR_PHY_RST_N | DDR_PHY_RST_N);
-               writel_relaxed(tmp, ctrl.memcs[i].ddr_phy_base +
-                            ctrl.phy_a_standby_ctrl_offs);
-
-               /* Step 3: Channel B? */
-               if (ctrl.phy_b_standby_ctrl_offs != DDR_PHY_NO_CHANNEL) {
-                       tmp = readl_relaxed(ctrl.memcs[i].ddr_phy_base +
-                                         ctrl.phy_b_standby_ctrl_offs);
-                       tmp &= ~(DDR_PHY_RST_N | DDR_PHY_RST_N);
-                       writel_relaxed(tmp, ctrl.memcs[i].ddr_phy_base +
-                                    ctrl.phy_b_standby_ctrl_offs);
-               }
-       }
-       /* Must complete */
-       wmb();
-}
-
-/*
- * Run a Power Management State Machine (PMSM) shutdown command and put the CPU
- * into a low-power mode
- */
-static void brcmstb_do_pmsm_power_down(unsigned long base_cmd, bool onewrite)
-{
-       void __iomem *base = ctrl.aon_ctrl_base;
-
-       if ((ctrl.s3entry_method == 1) && (base_cmd == PM_COLD_CONFIG))
-               s5entry_method1();
-
-       /* pm_start_pwrdn transition 0->1 */
-       writel_relaxed(base_cmd, base + AON_CTRL_PM_CTRL);
-
-       if (!onewrite) {
-               (void)readl_relaxed(base + AON_CTRL_PM_CTRL);
-
-               writel_relaxed(base_cmd | PM_PWR_DOWN, base + AON_CTRL_PM_CTRL);
-               (void)readl_relaxed(base + AON_CTRL_PM_CTRL);
-       }
-       wfi();
-}
-
-/* Support S5 cold boot out of "poweroff" */
-static void brcmstb_pm_poweroff(void)
-{
-       brcmstb_pm_handshake();
-
-       /* Clear magic S3 warm-boot value */
-       writel_relaxed(0, ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-       (void)readl_relaxed(ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-
-       /* Skip wait-for-interrupt signal; just use a countdown */
-       writel_relaxed(0x10, ctrl.aon_ctrl_base + AON_CTRL_PM_CPU_WAIT_COUNT);
-       (void)readl_relaxed(ctrl.aon_ctrl_base + AON_CTRL_PM_CPU_WAIT_COUNT);
-
-       if (ctrl.s3entry_method == 1) {
-               shimphy_set((PWRDWN_SEQ_POWERDOWN_PLL <<
-                            SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                            ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-               ddr_ctrl_set(false);
-               brcmstb_do_pmsm_power_down(M1_PM_COLD_CONFIG, true);
-               return; /* We should never actually get here */
-       }
-
-       brcmstb_do_pmsm_power_down(PM_COLD_CONFIG, false);
-}
-
-static void *brcmstb_pm_copy_to_sram(void *fn, size_t len)
-{
-       unsigned int size = ALIGN(len, FNCPY_ALIGN);
-
-       if (ctrl.boot_sram_len < size) {
-               pr_err("standby code will not fit in SRAM\n");
-               return NULL;
-       }
-
-       return fncpy(ctrl.boot_sram, fn, size);
-}
-
-/*
- * S2 suspend/resume picks up where we left off, so we must execute carefully
- * from SRAM, in order to allow DDR to come back up safely before we continue.
- */
-static int brcmstb_pm_s2(void)
-{
-       /* A previous S3 can set a value hazardous to S2, so make sure. */
-       if (ctrl.s3entry_method == 1) {
-               shimphy_set((PWRDWN_SEQ_NO_SEQUENCING <<
-                           SHIMPHY_PAD_S3_PWRDWN_SEQ_SHIFT),
-                           ~SHIMPHY_PAD_S3_PWRDWN_SEQ_MASK);
-               ddr_ctrl_set(false);
-       }
-
-       brcmstb_pm_do_s2_sram = brcmstb_pm_copy_to_sram(&brcmstb_pm_do_s2,
-                       brcmstb_pm_do_s2_sz);
-       if (!brcmstb_pm_do_s2_sram)
-               return -EINVAL;
-
-       return brcmstb_pm_do_s2_sram(ctrl.aon_ctrl_base,
-                       ctrl.memcs[0].ddr_phy_base +
-                       ctrl.pll_status_offset);
-}
-
-/*
- * This function is called on a new stack, so don't allow inlining (which will
- * generate stack references on the old stack). It cannot be made static because
- * it is referenced from brcmstb_pm_s3()
- */
-noinline int brcmstb_pm_s3_finish(void)
-{
-       struct brcmstb_s3_params *params = ctrl.s3_params;
-       dma_addr_t params_pa = ctrl.s3_params_pa;
-       phys_addr_t reentry = virt_to_phys(&cpu_resume_arm);
-       enum bsp_initiate_command cmd;
-       u32 flags;
-
-       /*
-        * Clear parameter structure, but not DTU area, which has already been
-        * filled in. We know DTU is a the end, so we can just subtract its
-        * size.
-        */
-       memset(params, 0, sizeof(*params) - sizeof(params->dtu));
-
-       flags = readl_relaxed(ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-
-       flags &= S3_BOOTLOADER_RESERVED;
-       flags |= S3_FLAG_NO_MEM_VERIFY;
-       flags |= S3_FLAG_LOAD_RANDKEY;
-
-       /* Load random / fixed key */
-       if (flags & S3_FLAG_LOAD_RANDKEY)
-               cmd = BSP_GEN_RANDOM_KEY;
-       else
-               cmd = BSP_GEN_FIXED_KEY;
-       if (do_bsp_initiate_command(cmd)) {
-               pr_info("key loading failed\n");
-               return -EIO;
-       }
-
-       params->magic = BRCMSTB_S3_MAGIC;
-       params->reentry = reentry;
-
-       /* No more writes to DRAM */
-       flush_cache_all();
-
-       flags |= BRCMSTB_S3_MAGIC_SHORT;
-
-       writel_relaxed(flags, ctrl.aon_sram + AON_REG_MAGIC_FLAGS);
-       writel_relaxed(lower_32_bits(params_pa),
-                      ctrl.aon_sram + AON_REG_CONTROL_LOW);
-       writel_relaxed(upper_32_bits(params_pa),
-                      ctrl.aon_sram + AON_REG_CONTROL_HIGH);
-
-       switch (ctrl.s3entry_method) {
-       case 0:
-               s3entry_method0();
-               brcmstb_do_pmsm_power_down(PM_WARM_CONFIG, false);
-               break;
-       case 1:
-               s3entry_method1();
-               brcmstb_do_pmsm_power_down(M1_PM_WARM_CONFIG, true);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* Must have been interrupted from wfi()? */
-       return -EINTR;
-}
-
-static int brcmstb_pm_do_s3(unsigned long sp)
-{
-       unsigned long save_sp;
-       int ret;
-
-       asm volatile (
-               "mov    %[save], sp\n"
-               "mov    sp, %[new]\n"
-               "bl     brcmstb_pm_s3_finish\n"
-               "mov    %[ret], r0\n"
-               "mov    %[new], sp\n"
-               "mov    sp, %[save]\n"
-               : [save] "=&r" (save_sp), [ret] "=&r" (ret)
-               : [new] "r" (sp)
-       );
-
-       return ret;
-}
-
-static int brcmstb_pm_s3(void)
-{
-       void __iomem *sp = ctrl.boot_sram + ctrl.boot_sram_len;
-
-       return cpu_suspend((unsigned long)sp, brcmstb_pm_do_s3);
-}
-
-static int brcmstb_pm_standby(bool deep_standby)
-{
-       int ret;
-
-       if (brcmstb_pm_handshake())
-               return -EIO;
-
-       if (deep_standby)
-               ret = brcmstb_pm_s3();
-       else
-               ret = brcmstb_pm_s2();
-       if (ret)
-               pr_err("%s: standby failed\n", __func__);
-
-       return ret;
-}
-
-static int brcmstb_pm_enter(suspend_state_t state)
-{
-       int ret = -EINVAL;
-
-       switch (state) {
-       case PM_SUSPEND_STANDBY:
-               ret = brcmstb_pm_standby(false);
-               break;
-       case PM_SUSPEND_MEM:
-               ret = brcmstb_pm_standby(true);
-               break;
-       }
-
-       return ret;
-}
-
-static int brcmstb_pm_valid(suspend_state_t state)
-{
-       switch (state) {
-       case PM_SUSPEND_STANDBY:
-               return true;
-       case PM_SUSPEND_MEM:
-               return ctrl.support_warm_boot;
-       default:
-               return false;
-       }
-}
-
-static const struct platform_suspend_ops brcmstb_pm_ops = {
-       .enter          = brcmstb_pm_enter,
-       .valid          = brcmstb_pm_valid,
-};
-
-static const struct of_device_id aon_ctrl_dt_ids[] = {
-       { .compatible = "brcm,brcmstb-aon-ctrl" },
-       {}
-};
-
-struct ddr_phy_ofdata {
-       bool supports_warm_boot;
-       size_t pll_status_offset;
-       int s3entry_method;
-       u32 warm_boot_offset;
-       u32 phy_a_standby_ctrl_offs;
-       u32 phy_b_standby_ctrl_offs;
-};
-
-static struct ddr_phy_ofdata ddr_phy_71_1 = {
-       .supports_warm_boot = true,
-       .pll_status_offset = 0x0c,
-       .s3entry_method = 1,
-       .warm_boot_offset = 0x2c,
-       .phy_a_standby_ctrl_offs = 0x198,
-       .phy_b_standby_ctrl_offs = DDR_PHY_NO_CHANNEL
-};
-
-static struct ddr_phy_ofdata ddr_phy_72_0 = {
-       .supports_warm_boot = true,
-       .pll_status_offset = 0x10,
-       .s3entry_method = 1,
-       .warm_boot_offset = 0x40,
-       .phy_a_standby_ctrl_offs = 0x2a4,
-       .phy_b_standby_ctrl_offs = 0x8a4
-};
-
-static struct ddr_phy_ofdata ddr_phy_225_1 = {
-       .supports_warm_boot = false,
-       .pll_status_offset = 0x4,
-       .s3entry_method = 0
-};
-
-static struct ddr_phy_ofdata ddr_phy_240_1 = {
-       .supports_warm_boot = true,
-       .pll_status_offset = 0x4,
-       .s3entry_method = 0
-};
-
-static const struct of_device_id ddr_phy_dt_ids[] = {
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v71.1",
-               .data = &ddr_phy_71_1,
-       },
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v72.0",
-               .data = &ddr_phy_72_0,
-       },
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v225.1",
-               .data = &ddr_phy_225_1,
-       },
-       {
-               .compatible = "brcm,brcmstb-ddr-phy-v240.1",
-               .data = &ddr_phy_240_1,
-       },
-       {
-               /* Same as v240.1, for the registers we care about */
-               .compatible = "brcm,brcmstb-ddr-phy-v240.2",
-               .data = &ddr_phy_240_1,
-       },
-       {}
-};
-
-struct ddr_seq_ofdata {
-       bool needs_ddr_pad;
-       u32 warm_boot_offset;
-};
-
-static const struct ddr_seq_ofdata ddr_seq_b22 = {
-       .needs_ddr_pad = false,
-       .warm_boot_offset = 0x2c,
-};
-
-static const struct ddr_seq_ofdata ddr_seq = {
-       .needs_ddr_pad = true,
-};
-
-static const struct of_device_id ddr_shimphy_dt_ids[] = {
-       { .compatible = "brcm,brcmstb-ddr-shimphy-v1.0" },
-       {}
-};
-
-static const struct of_device_id brcmstb_memc_of_match[] = {
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
-               .data = &ddr_seq,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
-               .data = &ddr_seq_b22,
-       },
-       {
-               .compatible = "brcm,brcmstb-memc-ddr",
-               .data = &ddr_seq,
-       },
-       {},
-};
-
-static void __iomem *brcmstb_ioremap_match(const struct of_device_id *matches,
-                                          int index, const void **ofdata)
-{
-       struct device_node *dn;
-       const struct of_device_id *match;
-
-       dn = of_find_matching_node_and_match(NULL, matches, &match);
-       if (!dn)
-               return ERR_PTR(-EINVAL);
-
-       if (ofdata)
-               *ofdata = match->data;
-
-       return of_io_request_and_map(dn, index, dn->full_name);
-}
-/*
- * The AON is a small domain in the SoC that can retain its state across
- * various system wide sleep states and specific reset conditions; the
- * AON DATA RAM is a small RAM of a few words (< 1KB) which can store
- * persistent information across such events.
- *
- * The purpose of the below panic notifier is to help with notifying
- * the bootloader that a panic occurred and so that it should try its
- * best to preserve the DRAM contents holding that buffer for recovery
- * by the kernel as opposed to wiping out DRAM clean again.
- *
- * Reference: comment from Florian Fainelli, at
- * https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com
- */
-static int brcmstb_pm_panic_notify(struct notifier_block *nb,
-               unsigned long action, void *data)
-{
-       writel_relaxed(BRCMSTB_PANIC_MAGIC, ctrl.aon_sram + AON_REG_PANIC);
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block brcmstb_pm_panic_nb = {
-       .notifier_call = brcmstb_pm_panic_notify,
-};
-
-static int brcmstb_pm_probe(struct platform_device *pdev)
-{
-       const struct ddr_phy_ofdata *ddr_phy_data;
-       const struct ddr_seq_ofdata *ddr_seq_data;
-       const struct of_device_id *of_id = NULL;
-       struct device_node *dn;
-       void __iomem *base;
-       int ret, i, s;
-
-       /* AON ctrl registers */
-       base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 0, NULL);
-       if (IS_ERR(base)) {
-               pr_err("error mapping AON_CTRL\n");
-               ret = PTR_ERR(base);
-               goto aon_err;
-       }
-       ctrl.aon_ctrl_base = base;
-
-       /* AON SRAM registers */
-       base = brcmstb_ioremap_match(aon_ctrl_dt_ids, 1, NULL);
-       if (IS_ERR(base)) {
-               /* Assume standard offset */
-               ctrl.aon_sram = ctrl.aon_ctrl_base +
-                                    AON_CTRL_SYSTEM_DATA_RAM_OFS;
-               s = 0;
-       } else {
-               ctrl.aon_sram = base;
-               s = 1;
-       }
-
-       writel_relaxed(0, ctrl.aon_sram + AON_REG_PANIC);
-
-       /* DDR PHY registers */
-       base = brcmstb_ioremap_match(ddr_phy_dt_ids, 0,
-                                    (const void **)&ddr_phy_data);
-       if (IS_ERR(base)) {
-               pr_err("error mapping DDR PHY\n");
-               ret = PTR_ERR(base);
-               goto ddr_phy_err;
-       }
-       ctrl.support_warm_boot = ddr_phy_data->supports_warm_boot;
-       ctrl.pll_status_offset = ddr_phy_data->pll_status_offset;
-       /* Only need DDR PHY 0 for now? */
-       ctrl.memcs[0].ddr_phy_base = base;
-       ctrl.s3entry_method = ddr_phy_data->s3entry_method;
-       ctrl.phy_a_standby_ctrl_offs = ddr_phy_data->phy_a_standby_ctrl_offs;
-       ctrl.phy_b_standby_ctrl_offs = ddr_phy_data->phy_b_standby_ctrl_offs;
-       /*
-        * Slightly gross to use the phy ver to get a memc,
-        * offset but that is the only versioned things so far
-        * we can test for.
-        */
-       ctrl.warm_boot_offset = ddr_phy_data->warm_boot_offset;
-
-       /* DDR SHIM-PHY registers */
-       for_each_matching_node(dn, ddr_shimphy_dt_ids) {
-               i = ctrl.num_memc;
-               if (i >= MAX_NUM_MEMC) {
-                       of_node_put(dn);
-                       pr_warn("too many MEMCs (max %d)\n", MAX_NUM_MEMC);
-                       break;
-               }
-
-               base = of_io_request_and_map(dn, 0, dn->full_name);
-               if (IS_ERR(base)) {
-                       of_node_put(dn);
-                       if (!ctrl.support_warm_boot)
-                               break;
-
-                       pr_err("error mapping DDR SHIMPHY %d\n", i);
-                       ret = PTR_ERR(base);
-                       goto ddr_shimphy_err;
-               }
-               ctrl.memcs[i].ddr_shimphy_base = base;
-               ctrl.num_memc++;
-       }
-
-       /* Sequencer DRAM Param and Control Registers */
-       i = 0;
-       for_each_matching_node(dn, brcmstb_memc_of_match) {
-               base = of_iomap(dn, 0);
-               if (!base) {
-                       of_node_put(dn);
-                       pr_err("error mapping DDR Sequencer %d\n", i);
-                       ret = -ENOMEM;
-                       goto brcmstb_memc_err;
-               }
-
-               of_id = of_match_node(brcmstb_memc_of_match, dn);
-               if (!of_id) {
-                       iounmap(base);
-                       of_node_put(dn);
-                       ret = -EINVAL;
-                       goto brcmstb_memc_err;
-               }
-
-               ddr_seq_data = of_id->data;
-               ctrl.needs_ddr_pad = ddr_seq_data->needs_ddr_pad;
-               /* Adjust warm boot offset based on the DDR sequencer */
-               if (ddr_seq_data->warm_boot_offset)
-                       ctrl.warm_boot_offset = ddr_seq_data->warm_boot_offset;
-
-               ctrl.memcs[i].ddr_ctrl = base;
-               i++;
-       }
-
-       pr_debug("PM: supports warm boot:%d, method:%d, wboffs:%x\n",
-               ctrl.support_warm_boot, ctrl.s3entry_method,
-               ctrl.warm_boot_offset);
-
-       dn = of_find_matching_node(NULL, sram_dt_ids);
-       if (!dn) {
-               pr_err("SRAM not found\n");
-               ret = -EINVAL;
-               goto brcmstb_memc_err;
-       }
-
-       ret = brcmstb_init_sram(dn);
-       of_node_put(dn);
-       if (ret) {
-               pr_err("error setting up SRAM for PM\n");
-               goto brcmstb_memc_err;
-       }
-
-       ctrl.pdev = pdev;
-
-       ctrl.s3_params = kmalloc(sizeof(*ctrl.s3_params), GFP_KERNEL);
-       if (!ctrl.s3_params) {
-               ret = -ENOMEM;
-               goto s3_params_err;
-       }
-       ctrl.s3_params_pa = dma_map_single(&pdev->dev, ctrl.s3_params,
-                                          sizeof(*ctrl.s3_params),
-                                          DMA_TO_DEVICE);
-       if (dma_mapping_error(&pdev->dev, ctrl.s3_params_pa)) {
-               pr_err("error mapping DMA memory\n");
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       atomic_notifier_chain_register(&panic_notifier_list,
-                                      &brcmstb_pm_panic_nb);
-
-       pm_power_off = brcmstb_pm_poweroff;
-       suspend_set_ops(&brcmstb_pm_ops);
-
-       return 0;
-
-out:
-       kfree(ctrl.s3_params);
-s3_params_err:
-       iounmap(ctrl.boot_sram);
-brcmstb_memc_err:
-       for (i--; i >= 0; i--)
-               iounmap(ctrl.memcs[i].ddr_ctrl);
-ddr_shimphy_err:
-       for (i = 0; i < ctrl.num_memc; i++)
-               iounmap(ctrl.memcs[i].ddr_shimphy_base);
-
-       iounmap(ctrl.memcs[0].ddr_phy_base);
-ddr_phy_err:
-       iounmap(ctrl.aon_ctrl_base);
-       if (s)
-               iounmap(ctrl.aon_sram);
-aon_err:
-       pr_warn("PM: initialization failed with code %d\n", ret);
-
-       return ret;
-}
-
-static struct platform_driver brcmstb_pm_driver = {
-       .driver = {
-               .name   = "brcmstb-pm",
-               .of_match_table = aon_ctrl_dt_ids,
-       },
-};
-
-static int __init brcmstb_pm_init(void)
-{
-       return platform_driver_probe(&brcmstb_pm_driver,
-                                    brcmstb_pm_probe);
-}
-module_init(brcmstb_pm_init);
diff --git a/drivers/soc/bcm/brcmstb/pm/s2-arm.S b/drivers/soc/bcm/brcmstb/pm/s2-arm.S
deleted file mode 100644 (file)
index 0d69379..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright © 2014-2017 Broadcom
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-#include "pm.h"
-
-       .arch armv7-a
-       .text
-       .align  3
-
-#define AON_CTRL_REG           r10
-#define DDR_PHY_STATUS_REG     r11
-
-/*
- * r0: AON_CTRL base address
- * r1: DDRY PHY PLL status register address
- */
-ENTRY(brcmstb_pm_do_s2)
-       stmfd   sp!, {r4-r11, lr}
-       mov     AON_CTRL_REG, r0
-       mov     DDR_PHY_STATUS_REG, r1
-
-       /* Flush memory transactions */
-       dsb
-
-       /* Cache DDR_PHY_STATUS_REG translation */
-       ldr     r0, [DDR_PHY_STATUS_REG]
-
-       /* power down request */
-       ldr     r0, =PM_S2_COMMAND
-       ldr     r1, =0
-       str     r1, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       ldr     r1, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       str     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       ldr     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-
-       /* Wait for interrupt */
-       wfi
-       nop
-
-       /* Bring MEMC back up */
-1:     ldr     r0, [DDR_PHY_STATUS_REG]
-       ands    r0, #1
-       beq     1b
-
-       /* Power-up handshake */
-       ldr     r0, =1
-       str     r0, [AON_CTRL_REG, #AON_CTRL_HOST_MISC_CMDS]
-       ldr     r0, [AON_CTRL_REG, #AON_CTRL_HOST_MISC_CMDS]
-
-       ldr     r0, =0
-       str     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-       ldr     r0, [AON_CTRL_REG, #AON_CTRL_PM_CTRL]
-
-       /* Return to caller */
-       ldr     r0, =0
-       ldmfd   sp!, {r4-r11, pc}
-
-       ENDPROC(brcmstb_pm_do_s2)
-
-       /* Place literal pool here */
-       .ltorg
-
-ENTRY(brcmstb_pm_do_s2_sz)
-       .word   . - brcmstb_pm_do_s2
index 068715d6e66d7e0bed4a2d099cc6385574e84bc7..58175af982a0dc836c07a1fc229508095967c90b 100644 (file)
@@ -243,4 +243,3 @@ builtin_platform_driver(rpi_power_driver);
 MODULE_AUTHOR("Alexander Aring <aar@pengutronix.de>");
 MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
 MODULE_DESCRIPTION("Raspberry Pi power domain driver");
-MODULE_LICENSE("GPL v2");
index 2527cf5757ec9693d0a698d0c32a5fca71466a08..43ced2bf844479f70cfdc3a1f1473e2e46ff4351 100644 (file)
@@ -3,8 +3,9 @@
 config SOC_K210_SYSCTL
        bool "Canaan Kendryte K210 SoC system controller"
        depends on RISCV && SOC_CANAAN && OF
+       depends on COMMON_CLK_K210
        default SOC_CANAAN
-        select PM
-        select MFD_SYSCON
+       select PM
+       select MFD_SYSCON
        help
          Canaan Kendryte K210 SoC system controller driver.
index 9dd8bb571dbc10f58100e19cb3615a307699a3ec..33751450047eda733f41a58520e9c401db15452b 100644 (file)
@@ -39,8 +39,7 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr,
 {
        struct device_node *mem_node;
        struct reserved_mem *rmem;
-       struct property *prop;
-       int len, err;
+       int err;
        __be32 *res_array;
 
        mem_node = of_parse_phandle(dev->of_node, "memory-region", idx);
@@ -63,8 +62,9 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr,
         * This is needed because QBMan HW does not allow the base address/
         * size to be modified once set.
         */
-       prop = of_find_property(mem_node, "reg", &len);
-       if (!prop) {
+       if (!of_property_present(mem_node, "reg")) {
+               struct property *prop;
+
                prop = devm_kzalloc(dev, sizeof(*prop), GFP_KERNEL);
                if (!prop)
                        return -ENOMEM;
index a8742fc58f018a541a34b8aadd6c3688f8820fed..76a4593baf0a2ecad591822de2da77819fb6afa7 100644 (file)
@@ -10,7 +10,7 @@ config IMX_GPCV2_PM_DOMAINS
        default y if SOC_IMX7D
 
 config SOC_IMX8M
-       bool "i.MX8M SoC family support"
+       tristate "i.MX8M SoC family support"
        depends on ARCH_MXC || COMPILE_TEST
        default ARCH_MXC && ARM64
        select SOC_BUS
index 399cb85105a181a934b74582e6a1c840724ec4ca..afbca0d48c14acc092849f332b4c26ca24fbb2e1 100644 (file)
@@ -38,10 +38,10 @@ struct imx8m_blk_ctrl {
 struct imx8m_blk_ctrl_domain_data {
        const char *name;
        const char * const *clk_names;
-       int num_clks;
        const char * const *path_names;
-       int num_paths;
        const char *gpc_name;
+       int num_clks;
+       int num_paths;
        u32 rst_mask;
        u32 clk_mask;
 
@@ -210,7 +210,7 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
        if (!bc->onecell_data.domains)
                return -ENOMEM;
 
-       bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
        if (IS_ERR(bc->bus_power_dev)) {
                if (PTR_ERR(bc->bus_power_dev) == -ENODEV)
                        return dev_err_probe(dev, -EPROBE_DEFER,
@@ -310,6 +310,10 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
 
        dev_set_drvdata(dev, bc);
 
+       ret = devm_of_platform_populate(dev);
+       if (ret)
+               goto cleanup_provider;
+
        return 0;
 
 cleanup_provider:
@@ -891,3 +895,4 @@ static struct platform_driver imx8m_blk_ctrl_driver = {
        },
 };
 module_platform_driver(imx8m_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
index a0592db8fa8646c441ffc644bdbef703b17552fa..870aecc0202aebd88c9af6d62a4cb94aa8f57401 100644 (file)
@@ -642,7 +642,7 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
        if (!bc->onecell_data.domains)
                return -ENOMEM;
 
-       bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
+       bc->bus_power_dev = dev_pm_domain_attach_by_name(dev, "bus");
        if (IS_ERR(bc->bus_power_dev))
                return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
                                     "failed to attach bus power domain\n");
@@ -852,7 +852,7 @@ static const struct of_device_id imx8mp_blk_ctrl_of_match[] = {
                /* Sentinel */
        }
 };
-MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
+MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
 
 static struct platform_driver imx8mp_blk_ctrl_driver = {
        .probe = imx8mp_blk_ctrl_probe,
@@ -864,3 +864,4 @@ static struct platform_driver imx8mp_blk_ctrl_driver = {
        },
 };
 module_platform_driver(imx8mp_blk_ctrl_driver);
+MODULE_LICENSE("GPL");
index 32ed9dc88e45563e346bbfdfda8b22d34b9c2139..1dcd243df5677aa39dcbc76b876cdbbd435ceb43 100644 (file)
@@ -242,3 +242,4 @@ free_soc:
        return ret;
 }
 device_initcall(imx8_soc_init);
+MODULE_LICENSE("GPL");
index d6b83a5508cab78018fe6961f32da315fc9c60dd..a88cf04fc803d54da72250cdff501c75e5f82eda 100644 (file)
@@ -76,6 +76,7 @@ config MTK_MMSYS
        tristate "MediaTek MMSYS Support"
        default ARCH_MEDIATEK
        depends on HAS_IOMEM
+       depends on MTK_CMDQ || MTK_CMDQ=n
        help
          Say yes here to add support for the MediaTek Multimedia
          Subsystem (MMSYS).
diff --git a/drivers/soc/mediatek/mt8173-mmsys.h b/drivers/soc/mediatek/mt8173-mmsys.h
new file mode 100644 (file)
index 0000000..9d24e38
--- /dev/null
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __SOC_MEDIATEK_MT8173_MMSYS_H
+#define __SOC_MEDIATEK_MT8173_MMSYS_H
+
+#define MT8173_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN       0x040
+#define MT8173_DISP_REG_CONFIG_DISP_OVL1_MOUT_EN       0x044
+#define MT8173_DISP_REG_CONFIG_DISP_OD_MOUT_EN         0x048
+#define MT8173_DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN      0x04c
+#define MT8173_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN       0x050
+#define MT8173_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN      0x084
+#define MT8173_DISP_REG_CONFIG_DISP_COLOR1_SEL_IN      0x088
+#define MT8173_DISP_REG_CONFIG_DISP_AAL_SEL_IN         0x08c
+#define MT8173_DISP_REG_CONFIG_DISP_UFOE_SEL_IN                0x0a0
+#define MT8173_DISP_REG_CONFIG_DSI0_SEL_IN             0x0a4
+#define MT8173_DISP_REG_CONFIG_DPI_SEL_IN              0x0ac
+#define MT8173_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN  0x0b0
+#define MT8173_DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN      0x0c8
+#define MT8173_DISP_REG_CONFIG_DISP_COLOR0_SOUT_SEL_IN 0x0bc
+
+#define MT8173_AAL_SEL_IN_MERGE                                BIT(0)
+#define MT8173_COLOR0_SEL_IN_OVL0                      BIT(0)
+#define MT8173_COLOR0_SOUT_MERGE                       BIT(0)
+#define MT8173_DPI0_SEL_IN_MASK                                GENMASK(1, 0)
+#define MT8173_DPI0_SEL_IN_RDMA1                       BIT(0)
+#define MT8173_DSI0_SEL_IN_UFOE                                BIT(0)
+#define MT8173_GAMMA_MOUT_EN_RDMA1                     BIT(0)
+#define MT8173_OD0_MOUT_EN_RDMA0                       BIT(0)
+#define MT8173_OVL0_MOUT_EN_COLOR0                     BIT(0)
+#define MT8173_OVL1_MOUT_EN_COLOR1                     BIT(0)
+#define MT8173_UFOE_MOUT_EN_DSI0                       BIT(0)
+#define MT8173_UFOE_SEL_IN_RDMA0                       BIT(0)
+#define MT8173_RDMA0_SOUT_COLOR0                       BIT(0)
+
+static const struct mtk_mmsys_routes mt8173_mmsys_routing_table[] = {
+       {
+               DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
+               MT8173_DISP_REG_CONFIG_DISP_OVL0_MOUT_EN,
+               MT8173_OVL0_MOUT_EN_COLOR0, MT8173_OVL0_MOUT_EN_COLOR0
+       }, {
+               DDP_COMPONENT_OD0, DDP_COMPONENT_RDMA0,
+               MT8173_DISP_REG_CONFIG_DISP_OD_MOUT_EN,
+               MT8173_OD0_MOUT_EN_RDMA0, MT8173_OD0_MOUT_EN_RDMA0
+       }, {
+               DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
+               MT8173_DISP_REG_CONFIG_DISP_UFOE_MOUT_EN,
+               MT8173_UFOE_MOUT_EN_DSI0, MT8173_UFOE_MOUT_EN_DSI0
+       }, {
+               DDP_COMPONENT_COLOR0, DDP_COMPONENT_AAL0,
+               MT8173_DISP_REG_CONFIG_DISP_COLOR0_SOUT_SEL_IN,
+               MT8173_COLOR0_SOUT_MERGE, 0 /* SOUT to AAL */
+       }, {
+               DDP_COMPONENT_RDMA0, DDP_COMPONENT_UFOE,
+               MT8173_DISP_REG_CONFIG_DISP_RDMA0_SOUT_SEL_IN,
+               MT8173_RDMA0_SOUT_COLOR0, 0 /* SOUT to UFOE */
+       }, {
+               DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0,
+               MT8173_DISP_REG_CONFIG_DISP_COLOR0_SEL_IN,
+               MT8173_COLOR0_SEL_IN_OVL0, MT8173_COLOR0_SEL_IN_OVL0
+       }, {
+               DDP_COMPONENT_AAL0, DDP_COMPONENT_COLOR0,
+               MT8173_DISP_REG_CONFIG_DISP_AAL_SEL_IN,
+               MT8173_AAL_SEL_IN_MERGE, 0 /* SEL_IN from COLOR0 */
+       }, {
+               DDP_COMPONENT_RDMA0, DDP_COMPONENT_UFOE,
+               MT8173_DISP_REG_CONFIG_DISP_UFOE_SEL_IN,
+               MT8173_UFOE_SEL_IN_RDMA0, 0 /* SEL_IN from RDMA0 */
+       }, {
+               DDP_COMPONENT_UFOE, DDP_COMPONENT_DSI0,
+               MT8173_DISP_REG_CONFIG_DSI0_SEL_IN,
+               MT8173_DSI0_SEL_IN_UFOE, 0, /* SEL_IN from UFOE */
+       }, {
+               DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
+               MT8173_DISP_REG_CONFIG_DISP_OVL1_MOUT_EN,
+               MT8173_OVL1_MOUT_EN_COLOR1, MT8173_OVL1_MOUT_EN_COLOR1
+       }, {
+               DDP_COMPONENT_GAMMA, DDP_COMPONENT_RDMA1,
+               MT8173_DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN,
+               MT8173_GAMMA_MOUT_EN_RDMA1, MT8173_GAMMA_MOUT_EN_RDMA1
+       }, {
+               DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+               MT8173_DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN,
+               RDMA1_SOUT_MASK, RDMA1_SOUT_DPI0
+       }, {
+               DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1,
+               MT8173_DISP_REG_CONFIG_DISP_COLOR1_SEL_IN,
+               COLOR1_SEL_IN_OVL1, COLOR1_SEL_IN_OVL1
+       }, {
+               DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0,
+               MT8173_DISP_REG_CONFIG_DPI_SEL_IN,
+               MT8173_DPI0_SEL_IN_MASK, MT8173_DPI0_SEL_IN_RDMA1
+       }
+};
+
+#endif /* __SOC_MEDIATEK_MT8173_MMSYS_H */
index a6652ae63431a051fb0e842cc028bd0b013ecc51..9be2df2832a4797b8c78c4462a230021d8419a18 100644 (file)
 #define MT8195_VDO1_MIXER_SOUT_SEL_IN                          0xf68
 #define MT8195_MIXER_SOUT_SEL_IN_FROM_DISP_MIXER                       0
 
+/* VPPSYS1 */
+#define MT8195_VPP1_HW_DCM_1ST_DIS0                            0x150
+#define MT8195_VPP1_HW_DCM_1ST_DIS1                            0x160
+#define MT8195_VPP1_HW_DCM_2ND_DIS0                            0x1a0
+#define MT8195_VPP1_HW_DCM_2ND_DIS1                            0x1b0
+#define MT8195_SVPP2_BUF_BF_RSZ_SWITCH                         0xf48
+#define MT8195_SVPP3_BUF_BF_RSZ_SWITCH                         0xf74
+
+/* VPPSYS1 HW DCM client*/
+#define MT8195_SVPP1_MDP_RSZ                                   BIT(25)
+#define MT8195_SVPP2_MDP_RSZ                                   BIT(4)
+#define MT8195_SVPP3_MDP_RSZ                                   BIT(5)
+
 static const struct mtk_mmsys_routes mmsys_mt8195_routing_table[] = {
        {
                DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0,
index eb4c7e57896cfb73dfe3b9146fe7f2a14636e28b..9619faa796e8fee95324ee9f0b79d435ce4ec432 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "mtk-mmsys.h"
 #include "mt8167-mmsys.h"
+#include "mt8173-mmsys.h"
 #include "mt8183-mmsys.h"
 #include "mt8186-mmsys.h"
 #include "mt8188-mmsys.h"
@@ -40,6 +41,14 @@ static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
        .clk_driver = "clk-mt6779-mm",
 };
 
+static const struct mtk_mmsys_driver_data mt6795_mmsys_driver_data = {
+       .clk_driver = "clk-mt6795-mm",
+       .routes = mt8173_mmsys_routing_table,
+       .num_routes = ARRAY_SIZE(mt8173_mmsys_routing_table),
+       .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
+       .num_resets = 64,
+};
+
 static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
        .clk_driver = "clk-mt6797-mm",
 };
@@ -52,10 +61,10 @@ static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
 
 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
        .clk_driver = "clk-mt8173-mm",
-       .routes = mmsys_default_routing_table,
-       .num_routes = ARRAY_SIZE(mmsys_default_routing_table),
+       .routes = mt8173_mmsys_routing_table,
+       .num_routes = ARRAY_SIZE(mt8173_mmsys_routing_table),
        .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B,
-       .num_resets = 32,
+       .num_resets = 64,
 };
 
 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
@@ -121,6 +130,8 @@ static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
 struct mtk_mmsys {
        void __iomem *regs;
        const struct mtk_mmsys_driver_data *data;
+       struct platform_device *clks_pdev;
+       struct platform_device *drm_pdev;
        spinlock_t lock; /* protects mmsys_sw_rst_b reg */
        struct reset_controller_dev rcdev;
        struct cmdq_client_reg cmdq_base;
@@ -129,21 +140,18 @@ struct mtk_mmsys {
 static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val,
                                  struct cmdq_pkt *cmdq_pkt)
 {
+       int ret;
        u32 tmp;
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       if (cmdq_pkt) {
-               if (mmsys->cmdq_base.size == 0) {
-                       pr_err("mmsys lose gce property, failed to update mmsys bits with cmdq");
+       if (mmsys->cmdq_base.size && cmdq_pkt) {
+               ret = cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
+                                         mmsys->cmdq_base.offset + offset, val,
+                                         mask);
+               if (ret)
+                       pr_debug("CMDQ unavailable: using CPU write\n");
+               else
                        return;
-               }
-               cmdq_pkt_write_mask(cmdq_pkt, mmsys->cmdq_base.subsys,
-                                   mmsys->cmdq_base.offset + offset, val,
-                                   mask);
-               return;
        }
-#endif
-
        tmp = readl_relaxed(mmsys->regs + offset);
        tmp = (tmp & ~mask) | (val & mask);
        writel_relaxed(tmp, mmsys->regs + offset);
@@ -242,6 +250,50 @@ void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val)
 }
 EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_dpi_fmt_config);
 
+void mtk_mmsys_vpp_rsz_merge_config(struct device *dev, u32 id, bool enable,
+                                   struct cmdq_pkt *cmdq_pkt)
+{
+       u32 reg;
+
+       switch (id) {
+       case 2:
+               reg = MT8195_SVPP2_BUF_BF_RSZ_SWITCH;
+               break;
+       case 3:
+               reg = MT8195_SVPP3_BUF_BF_RSZ_SWITCH;
+               break;
+       default:
+               dev_err(dev, "Invalid id %d\n", id);
+               return;
+       }
+
+       mtk_mmsys_update_bits(dev_get_drvdata(dev), reg, ~0, enable, cmdq_pkt);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_vpp_rsz_merge_config);
+
+void mtk_mmsys_vpp_rsz_dcm_config(struct device *dev, bool enable,
+                                 struct cmdq_pkt *cmdq_pkt)
+{
+       u32 client;
+
+       client = MT8195_SVPP1_MDP_RSZ;
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_1ST_DIS0, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_2ND_DIS0, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+
+       client = MT8195_SVPP2_MDP_RSZ | MT8195_SVPP3_MDP_RSZ;
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_1ST_DIS1, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+       mtk_mmsys_update_bits(dev_get_drvdata(dev),
+                             MT8195_VPP1_HW_DCM_2ND_DIS1, client,
+                             ((enable) ? client : 0), cmdq_pkt);
+}
+EXPORT_SYMBOL_GPL(mtk_mmsys_vpp_rsz_dcm_config);
+
 static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id,
                                  bool assert)
 {
@@ -330,11 +382,10 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
                }
        }
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       /* CMDQ is optional */
        ret = cmdq_dev_get_client_reg(dev, &mmsys->cmdq_base, 0);
        if (ret)
                dev_dbg(dev, "No mediatek,gce-client-reg!\n");
-#endif
 
        platform_set_drvdata(pdev, mmsys);
 
@@ -342,6 +393,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
                                             PLATFORM_DEVID_AUTO, NULL, 0);
        if (IS_ERR(clks))
                return PTR_ERR(clks);
+       mmsys->clks_pdev = clks;
 
        if (mmsys->data->is_vppsys)
                goto out_probe_done;
@@ -352,78 +404,44 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
                platform_device_unregister(clks);
                return PTR_ERR(drm);
        }
+       mmsys->drm_pdev = drm;
 
 out_probe_done:
        return 0;
 }
 
+static int mtk_mmsys_remove(struct platform_device *pdev)
+{
+       struct mtk_mmsys *mmsys = platform_get_drvdata(pdev);
+
+       platform_device_unregister(mmsys->drm_pdev);
+       platform_device_unregister(mmsys->clks_pdev);
+
+       return 0;
+}
+
 static const struct of_device_id of_match_mtk_mmsys[] = {
-       {
-               .compatible = "mediatek,mt2701-mmsys",
-               .data = &mt2701_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt2712-mmsys",
-               .data = &mt2712_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt6779-mmsys",
-               .data = &mt6779_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt6797-mmsys",
-               .data = &mt6797_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8167-mmsys",
-               .data = &mt8167_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8173-mmsys",
-               .data = &mt8173_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8183-mmsys",
-               .data = &mt8183_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8186-mmsys",
-               .data = &mt8186_mmsys_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8188-vdosys0",
-               .data = &mt8188_vdosys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8192-mmsys",
-               .data = &mt8192_mmsys_driver_data,
-       },
-       {       /* deprecated compatible */
-               .compatible = "mediatek,mt8195-mmsys",
-               .data = &mt8195_vdosys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vdosys0",
-               .data = &mt8195_vdosys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vdosys1",
-               .data = &mt8195_vdosys1_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vppsys0",
-               .data = &mt8195_vppsys0_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8195-vppsys1",
-               .data = &mt8195_vppsys1_driver_data,
-       },
-       {
-               .compatible = "mediatek,mt8365-mmsys",
-               .data = &mt8365_mmsys_driver_data,
-       },
-       { }
+       { .compatible = "mediatek,mt2701-mmsys", .data = &mt2701_mmsys_driver_data },
+       { .compatible = "mediatek,mt2712-mmsys", .data = &mt2712_mmsys_driver_data },
+       { .compatible = "mediatek,mt6779-mmsys", .data = &mt6779_mmsys_driver_data },
+       { .compatible = "mediatek,mt6795-mmsys", .data = &mt6795_mmsys_driver_data },
+       { .compatible = "mediatek,mt6797-mmsys", .data = &mt6797_mmsys_driver_data },
+       { .compatible = "mediatek,mt8167-mmsys", .data = &mt8167_mmsys_driver_data },
+       { .compatible = "mediatek,mt8173-mmsys", .data = &mt8173_mmsys_driver_data },
+       { .compatible = "mediatek,mt8183-mmsys", .data = &mt8183_mmsys_driver_data },
+       { .compatible = "mediatek,mt8186-mmsys", .data = &mt8186_mmsys_driver_data },
+       { .compatible = "mediatek,mt8188-vdosys0", .data = &mt8188_vdosys0_driver_data },
+       { .compatible = "mediatek,mt8192-mmsys", .data = &mt8192_mmsys_driver_data },
+       /* "mediatek,mt8195-mmsys" compatible is deprecated */
+       { .compatible = "mediatek,mt8195-mmsys", .data = &mt8195_vdosys0_driver_data },
+       { .compatible = "mediatek,mt8195-vdosys0", .data = &mt8195_vdosys0_driver_data },
+       { .compatible = "mediatek,mt8195-vdosys1", .data = &mt8195_vdosys1_driver_data },
+       { .compatible = "mediatek,mt8195-vppsys0", .data = &mt8195_vppsys0_driver_data },
+       { .compatible = "mediatek,mt8195-vppsys1", .data = &mt8195_vppsys1_driver_data },
+       { .compatible = "mediatek,mt8365-mmsys", .data = &mt8365_mmsys_driver_data },
+       { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, of_match_mtk_mmsys);
 
 static struct platform_driver mtk_mmsys_drv = {
        .driver = {
@@ -431,20 +449,9 @@ static struct platform_driver mtk_mmsys_drv = {
                .of_match_table = of_match_mtk_mmsys,
        },
        .probe = mtk_mmsys_probe,
+       .remove = mtk_mmsys_remove,
 };
-
-static int __init mtk_mmsys_init(void)
-{
-       return platform_driver_register(&mtk_mmsys_drv);
-}
-
-static void __exit mtk_mmsys_exit(void)
-{
-       platform_driver_unregister(&mtk_mmsys_drv);
-}
-
-module_init(mtk_mmsys_init);
-module_exit(mtk_mmsys_exit);
+module_platform_driver(mtk_mmsys_drv);
 
 MODULE_AUTHOR("Yongqiang Niu <yongqiang.niu@mediatek.com>");
 MODULE_DESCRIPTION("MediaTek SoC MMSYS driver");
index 56f8cc3a97b72bd550c453747b2197370ebef0f0..6725403d2e3ac4a91956c07276814445588fff3e 100644 (file)
@@ -96,7 +96,7 @@ struct mtk_mmsys_driver_data {
 };
 
 /*
- * Routes in mt8173, mt2701, mt2712 are different. That means
+ * Routes in mt2701 and mt2712 are different. That means
  * in the same register address, it controls different input/output
  * selection for each SoC. But, right now, they use the same table as
  * default routes meet their requirements. But we don't have the complete
index c5b1b42303ac26f388defbd9e6c6161dd07df4ab..26f3d9a4149641639b5db6293dca4190d41866f7 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/soc/mediatek/mtk-mutex.h>
 #include <linux/soc/mediatek/mtk-cmdq.h>
 
+#define MTK_MUTEX_MAX_HANDLES                  10
+
 #define MT2701_MUTEX0_MOD0                     0x2c
 #define MT2701_MUTEX0_SOF0                     0x30
 #define MT8183_MUTEX0_MOD0                     0x30
@@ -23,6 +25,7 @@
 #define DISP_REG_MUTEX(n)                      (0x24 + 0x20 * (n))
 #define DISP_REG_MUTEX_RST(n)                  (0x28 + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD(mutex_mod_reg, n)   (mutex_mod_reg + 0x20 * (n))
+#define DISP_REG_MUTEX_MOD1(mutex_mod_reg, n)  ((mutex_mod_reg) + 0x20 * (n) + 0x4)
 #define DISP_REG_MUTEX_SOF(mutex_sof_reg, n)   (mutex_sof_reg + 0x20 * (n))
 #define DISP_REG_MUTEX_MOD2(n)                 (0x34 + 0x20 * (n))
 
 #define MT8195_MUTEX_MOD_DISP1_DPI1            26
 #define MT8195_MUTEX_MOD_DISP1_DP_INTF0                27
 
+/* VPPSYS0 */
+#define MT8195_MUTEX_MOD_MDP_RDMA0             0
+#define MT8195_MUTEX_MOD_MDP_FG0               1
+#define MT8195_MUTEX_MOD_MDP_STITCH0           2
+#define MT8195_MUTEX_MOD_MDP_HDR0              3
+#define MT8195_MUTEX_MOD_MDP_AAL0              4
+#define MT8195_MUTEX_MOD_MDP_RSZ0              5
+#define MT8195_MUTEX_MOD_MDP_TDSHP0            6
+#define MT8195_MUTEX_MOD_MDP_COLOR0            7
+#define MT8195_MUTEX_MOD_MDP_OVL0              8
+#define MT8195_MUTEX_MOD_MDP_PAD0              9
+#define MT8195_MUTEX_MOD_MDP_TCC0              10
+#define MT8195_MUTEX_MOD_MDP_WROT0             11
+
+/* VPPSYS1 */
+#define MT8195_MUTEX_MOD_MDP_TCC1              3
+#define MT8195_MUTEX_MOD_MDP_RDMA1             4
+#define MT8195_MUTEX_MOD_MDP_RDMA2             5
+#define MT8195_MUTEX_MOD_MDP_RDMA3             6
+#define MT8195_MUTEX_MOD_MDP_FG1               7
+#define MT8195_MUTEX_MOD_MDP_FG2               8
+#define MT8195_MUTEX_MOD_MDP_FG3               9
+#define MT8195_MUTEX_MOD_MDP_HDR1              10
+#define MT8195_MUTEX_MOD_MDP_HDR2              11
+#define MT8195_MUTEX_MOD_MDP_HDR3              12
+#define MT8195_MUTEX_MOD_MDP_AAL1              13
+#define MT8195_MUTEX_MOD_MDP_AAL2              14
+#define MT8195_MUTEX_MOD_MDP_AAL3              15
+#define MT8195_MUTEX_MOD_MDP_RSZ1              16
+#define MT8195_MUTEX_MOD_MDP_RSZ2              17
+#define MT8195_MUTEX_MOD_MDP_RSZ3              18
+#define MT8195_MUTEX_MOD_MDP_TDSHP1            19
+#define MT8195_MUTEX_MOD_MDP_TDSHP2            20
+#define MT8195_MUTEX_MOD_MDP_TDSHP3            21
+#define MT8195_MUTEX_MOD_MDP_MERGE2            22
+#define MT8195_MUTEX_MOD_MDP_MERGE3            23
+#define MT8195_MUTEX_MOD_MDP_COLOR1            24
+#define MT8195_MUTEX_MOD_MDP_COLOR2            25
+#define MT8195_MUTEX_MOD_MDP_COLOR3            26
+#define MT8195_MUTEX_MOD_MDP_OVL1              27
+#define MT8195_MUTEX_MOD_MDP_PAD1              28
+#define MT8195_MUTEX_MOD_MDP_PAD2              29
+#define MT8195_MUTEX_MOD_MDP_PAD3              30
+#define MT8195_MUTEX_MOD_MDP_WROT1             31
+#define MT8195_MUTEX_MOD_MDP_WROT2             32
+#define MT8195_MUTEX_MOD_MDP_WROT3             33
+
 #define MT8365_MUTEX_MOD_DISP_OVL0             7
 #define MT8365_MUTEX_MOD_DISP_OVL0_2L          8
 #define MT8365_MUTEX_MOD_DISP_RDMA0            9
 #define MT8195_MUTEX_EOF_DPI1                  (MT8195_MUTEX_SOF_DPI1 << 7)
 
 struct mtk_mutex {
-       int id;
+       u8 id;
        bool claimed;
 };
 
@@ -264,7 +314,7 @@ struct mtk_mutex_ctx {
        struct device                   *dev;
        struct clk                      *clk;
        void __iomem                    *regs;
-       struct mtk_mutex                mutex[10];
+       struct mtk_mutex                mutex[MTK_MUTEX_MAX_HANDLES];
        const struct mtk_mutex_data     *data;
        phys_addr_t                     addr;
        struct cmdq_client_reg          cmdq_reg;
@@ -443,6 +493,52 @@ static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
        [DDP_COMPONENT_DP_INTF1] = MT8195_MUTEX_MOD_DISP1_DP_INTF0,
 };
 
+static const unsigned int mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+       [MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0,
+       [MUTEX_MOD_IDX_MDP_RDMA1] = MT8195_MUTEX_MOD_MDP_RDMA1,
+       [MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2,
+       [MUTEX_MOD_IDX_MDP_RDMA3] = MT8195_MUTEX_MOD_MDP_RDMA3,
+       [MUTEX_MOD_IDX_MDP_STITCH0] = MT8195_MUTEX_MOD_MDP_STITCH0,
+       [MUTEX_MOD_IDX_MDP_FG0] = MT8195_MUTEX_MOD_MDP_FG0,
+       [MUTEX_MOD_IDX_MDP_FG1] = MT8195_MUTEX_MOD_MDP_FG1,
+       [MUTEX_MOD_IDX_MDP_FG2] = MT8195_MUTEX_MOD_MDP_FG2,
+       [MUTEX_MOD_IDX_MDP_FG3] = MT8195_MUTEX_MOD_MDP_FG3,
+       [MUTEX_MOD_IDX_MDP_HDR0] = MT8195_MUTEX_MOD_MDP_HDR0,
+       [MUTEX_MOD_IDX_MDP_HDR1] = MT8195_MUTEX_MOD_MDP_HDR1,
+       [MUTEX_MOD_IDX_MDP_HDR2] = MT8195_MUTEX_MOD_MDP_HDR2,
+       [MUTEX_MOD_IDX_MDP_HDR3] = MT8195_MUTEX_MOD_MDP_HDR3,
+       [MUTEX_MOD_IDX_MDP_AAL0] = MT8195_MUTEX_MOD_MDP_AAL0,
+       [MUTEX_MOD_IDX_MDP_AAL1] = MT8195_MUTEX_MOD_MDP_AAL1,
+       [MUTEX_MOD_IDX_MDP_AAL2] = MT8195_MUTEX_MOD_MDP_AAL2,
+       [MUTEX_MOD_IDX_MDP_AAL3] = MT8195_MUTEX_MOD_MDP_AAL3,
+       [MUTEX_MOD_IDX_MDP_RSZ0] = MT8195_MUTEX_MOD_MDP_RSZ0,
+       [MUTEX_MOD_IDX_MDP_RSZ1] = MT8195_MUTEX_MOD_MDP_RSZ1,
+       [MUTEX_MOD_IDX_MDP_RSZ2] = MT8195_MUTEX_MOD_MDP_RSZ2,
+       [MUTEX_MOD_IDX_MDP_RSZ3] = MT8195_MUTEX_MOD_MDP_RSZ3,
+       [MUTEX_MOD_IDX_MDP_MERGE2] = MT8195_MUTEX_MOD_MDP_MERGE2,
+       [MUTEX_MOD_IDX_MDP_MERGE3] = MT8195_MUTEX_MOD_MDP_MERGE3,
+       [MUTEX_MOD_IDX_MDP_TDSHP0] = MT8195_MUTEX_MOD_MDP_TDSHP0,
+       [MUTEX_MOD_IDX_MDP_TDSHP1] = MT8195_MUTEX_MOD_MDP_TDSHP1,
+       [MUTEX_MOD_IDX_MDP_TDSHP2] = MT8195_MUTEX_MOD_MDP_TDSHP2,
+       [MUTEX_MOD_IDX_MDP_TDSHP3] = MT8195_MUTEX_MOD_MDP_TDSHP3,
+       [MUTEX_MOD_IDX_MDP_COLOR0] = MT8195_MUTEX_MOD_MDP_COLOR0,
+       [MUTEX_MOD_IDX_MDP_COLOR1] = MT8195_MUTEX_MOD_MDP_COLOR1,
+       [MUTEX_MOD_IDX_MDP_COLOR2] = MT8195_MUTEX_MOD_MDP_COLOR2,
+       [MUTEX_MOD_IDX_MDP_COLOR3] = MT8195_MUTEX_MOD_MDP_COLOR3,
+       [MUTEX_MOD_IDX_MDP_OVL0] = MT8195_MUTEX_MOD_MDP_OVL0,
+       [MUTEX_MOD_IDX_MDP_OVL1] = MT8195_MUTEX_MOD_MDP_OVL1,
+       [MUTEX_MOD_IDX_MDP_PAD0] = MT8195_MUTEX_MOD_MDP_PAD0,
+       [MUTEX_MOD_IDX_MDP_PAD1] = MT8195_MUTEX_MOD_MDP_PAD1,
+       [MUTEX_MOD_IDX_MDP_PAD2] = MT8195_MUTEX_MOD_MDP_PAD2,
+       [MUTEX_MOD_IDX_MDP_PAD3] = MT8195_MUTEX_MOD_MDP_PAD3,
+       [MUTEX_MOD_IDX_MDP_TCC0] = MT8195_MUTEX_MOD_MDP_TCC0,
+       [MUTEX_MOD_IDX_MDP_TCC1] = MT8195_MUTEX_MOD_MDP_TCC1,
+       [MUTEX_MOD_IDX_MDP_WROT0] = MT8195_MUTEX_MOD_MDP_WROT0,
+       [MUTEX_MOD_IDX_MDP_WROT1] = MT8195_MUTEX_MOD_MDP_WROT1,
+       [MUTEX_MOD_IDX_MDP_WROT2] = MT8195_MUTEX_MOD_MDP_WROT2,
+       [MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
+};
+
 static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
        [DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
        [DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
@@ -603,6 +699,13 @@ static const struct mtk_mutex_data mt8195_mutex_driver_data = {
        .mutex_sof_reg = MT8183_MUTEX0_SOF0,
 };
 
+static const struct mtk_mutex_data mt8195_vpp_mutex_driver_data = {
+       .mutex_sof = mt8195_mutex_sof,
+       .mutex_mod_reg = MT8183_MUTEX0_MOD0,
+       .mutex_sof_reg = MT8183_MUTEX0_SOF0,
+       .mutex_table_mod = mt8195_mutex_table_mod,
+};
+
 static const struct mtk_mutex_data mt8365_mutex_driver_data = {
        .mutex_mod = mt8365_mutex_mod,
        .mutex_sof = mt8183_mutex_sof,
@@ -616,7 +719,7 @@ struct mtk_mutex *mtk_mutex_get(struct device *dev)
        struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev);
        int i;
 
-       for (i = 0; i < 10; i++)
+       for (i = 0; i < MTK_MUTEX_MAX_HANDLES; i++)
                if (!mtx->mutex[i].claimed) {
                        mtx->mutex[i].claimed = true;
                        return &mtx->mutex[i];
@@ -768,23 +871,18 @@ int mtk_mutex_enable_by_cmdq(struct mtk_mutex *mutex, void *pkt)
 {
        struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
                                                 mutex[mutex->id]);
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
        struct cmdq_pkt *cmdq_pkt = (struct cmdq_pkt *)pkt;
 
        WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
        if (!mtx->cmdq_reg.size) {
                dev_err(mtx->dev, "mediatek,gce-client-reg hasn't been set");
-               return -EINVAL;
+               return -ENODEV;
        }
 
        cmdq_pkt_write(cmdq_pkt, mtx->cmdq_reg.subsys,
                       mtx->addr + DISP_REG_MUTEX_EN(mutex->id), 1);
        return 0;
-#else
-       dev_err(mtx->dev, "Not support for enable MUTEX by CMDQ");
-       return -ENODEV;
-#endif
 }
 EXPORT_SYMBOL_GPL(mtk_mutex_enable_by_cmdq);
 
@@ -828,7 +926,7 @@ int mtk_mutex_write_mod(struct mtk_mutex *mutex,
        struct mtk_mutex_ctx *mtx = container_of(mutex, struct mtk_mutex_ctx,
                                                 mutex[mutex->id]);
        unsigned int reg;
-       unsigned int offset;
+       u32 reg_offset, id_offset = 0;
 
        WARN_ON(&mtx->mutex[mutex->id] != mutex);
 
@@ -838,16 +936,34 @@ int mtk_mutex_write_mod(struct mtk_mutex *mutex,
                return -EINVAL;
        }
 
-       offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
-                                   mutex->id);
-       reg = readl_relaxed(mtx->regs + offset);
+       /*
+        * Some SoCs may have multiple MUTEX_MOD registers as more than 32 mods
+        * are present, hence requiring multiple 32-bits registers.
+        *
+        * The mutex_table_mod fully represents that by defining the number of
+        * the mod sequentially, later used as a bit number, which can be more
+        * than 0..31.
+        *
+        * In order to retain compatibility with older SoCs, we perform R/W on
+        * the single 32 bits registers, but this requires us to translate the
+        * mutex ID bit accordingly.
+        */
+       if (mtx->data->mutex_table_mod[idx] < 32) {
+               reg_offset = DISP_REG_MUTEX_MOD(mtx->data->mutex_mod_reg,
+                                               mutex->id);
+       } else {
+               reg_offset = DISP_REG_MUTEX_MOD1(mtx->data->mutex_mod_reg,
+                                                mutex->id);
+               id_offset = 32;
+       }
 
+       reg = readl_relaxed(mtx->regs + reg_offset);
        if (clear)
-               reg &= ~BIT(mtx->data->mutex_table_mod[idx]);
+               reg &= ~BIT(mtx->data->mutex_table_mod[idx] - id_offset);
        else
-               reg |= BIT(mtx->data->mutex_table_mod[idx]);
+               reg |= BIT(mtx->data->mutex_table_mod[idx] - id_offset);
 
-       writel_relaxed(reg, mtx->regs + offset);
+       writel_relaxed(reg, mtx->regs + reg_offset);
 
        return 0;
 }
@@ -879,27 +995,21 @@ static int mtk_mutex_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct mtk_mutex_ctx *mtx;
        struct resource *regs;
-       int i;
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
-       int ret;
-#endif
+       int i, ret;
 
        mtx = devm_kzalloc(dev, sizeof(*mtx), GFP_KERNEL);
        if (!mtx)
                return -ENOMEM;
 
-       for (i = 0; i < 10; i++)
+       for (i = 0; i < MTK_MUTEX_MAX_HANDLES; i++)
                mtx->mutex[i].id = i;
 
        mtx->data = of_device_get_match_data(dev);
 
        if (!mtx->data->no_clk) {
                mtx->clk = devm_clk_get(dev, NULL);
-               if (IS_ERR(mtx->clk)) {
-                       if (PTR_ERR(mtx->clk) != -EPROBE_DEFER)
-                               dev_err(dev, "Failed to get clock\n");
-                       return PTR_ERR(mtx->clk);
-               }
+               if (IS_ERR(mtx->clk))
+                       return dev_err_probe(dev, PTR_ERR(mtx->clk), "Failed to get clock\n");
        }
 
        mtx->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
@@ -909,11 +1019,10 @@ static int mtk_mutex_probe(struct platform_device *pdev)
        }
        mtx->addr = regs->start;
 
-#if IS_REACHABLE(CONFIG_MTK_CMDQ)
+       /* CMDQ is optional */
        ret = cmdq_dev_get_client_reg(dev, &mtx->cmdq_reg, 0);
        if (ret)
                dev_dbg(dev, "No mediatek,gce-client-reg!\n");
-#endif
 
        platform_set_drvdata(pdev, mtx);
 
@@ -921,31 +1030,20 @@ static int mtk_mutex_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id mutex_driver_dt_match[] = {
-       { .compatible = "mediatek,mt2701-disp-mutex",
-         .data = &mt2701_mutex_driver_data},
-       { .compatible = "mediatek,mt2712-disp-mutex",
-         .data = &mt2712_mutex_driver_data},
-       { .compatible = "mediatek,mt6795-disp-mutex",
-         .data = &mt6795_mutex_driver_data},
-       { .compatible = "mediatek,mt8167-disp-mutex",
-         .data = &mt8167_mutex_driver_data},
-       { .compatible = "mediatek,mt8173-disp-mutex",
-         .data = &mt8173_mutex_driver_data},
-       { .compatible = "mediatek,mt8183-disp-mutex",
-         .data = &mt8183_mutex_driver_data},
-       { .compatible = "mediatek,mt8186-disp-mutex",
-         .data = &mt8186_mutex_driver_data},
-       { .compatible = "mediatek,mt8186-mdp3-mutex",
-         .data = &mt8186_mdp_mutex_driver_data},
-       { .compatible = "mediatek,mt8188-disp-mutex",
-         .data = &mt8188_mutex_driver_data},
-       { .compatible = "mediatek,mt8192-disp-mutex",
-         .data = &mt8192_mutex_driver_data},
-       { .compatible = "mediatek,mt8195-disp-mutex",
-         .data = &mt8195_mutex_driver_data},
-       { .compatible = "mediatek,mt8365-disp-mutex",
-         .data = &mt8365_mutex_driver_data},
-       {},
+       { .compatible = "mediatek,mt2701-disp-mutex", .data = &mt2701_mutex_driver_data },
+       { .compatible = "mediatek,mt2712-disp-mutex", .data = &mt2712_mutex_driver_data },
+       { .compatible = "mediatek,mt6795-disp-mutex", .data = &mt6795_mutex_driver_data },
+       { .compatible = "mediatek,mt8167-disp-mutex", .data = &mt8167_mutex_driver_data },
+       { .compatible = "mediatek,mt8173-disp-mutex", .data = &mt8173_mutex_driver_data },
+       { .compatible = "mediatek,mt8183-disp-mutex", .data = &mt8183_mutex_driver_data },
+       { .compatible = "mediatek,mt8186-disp-mutex", .data = &mt8186_mutex_driver_data },
+       { .compatible = "mediatek,mt8186-mdp3-mutex", .data = &mt8186_mdp_mutex_driver_data },
+       { .compatible = "mediatek,mt8188-disp-mutex", .data = &mt8188_mutex_driver_data },
+       { .compatible = "mediatek,mt8192-disp-mutex", .data = &mt8192_mutex_driver_data },
+       { .compatible = "mediatek,mt8195-disp-mutex", .data = &mt8195_mutex_driver_data },
+       { .compatible = "mediatek,mt8195-vpp-mutex",  .data = &mt8195_vpp_mutex_driver_data },
+       { .compatible = "mediatek,mt8365-disp-mutex", .data = &mt8365_mutex_driver_data },
+       { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, mutex_driver_dt_match);
 
@@ -957,19 +1055,7 @@ static struct platform_driver mtk_mutex_driver = {
                .of_match_table = mutex_driver_dt_match,
        },
 };
-
-static int __init mtk_mutex_init(void)
-{
-       return platform_driver_register(&mtk_mutex_driver);
-}
-
-static void __exit mtk_mutex_exit(void)
-{
-       platform_driver_unregister(&mtk_mutex_driver);
-}
-
-module_init(mtk_mutex_init);
-module_exit(mtk_mutex_exit);
+module_platform_driver(mtk_mutex_driver);
 
 MODULE_AUTHOR("Yongqiang Niu <yongqiang.niu@mediatek.com>");
 MODULE_DESCRIPTION("MediaTek SoC MUTEX driver");
index f26eb2f637d522e381f78a008b4a408e78a341b9..b9c96182a46a63a4be1d4127fae3923b79c4f4ea 100644 (file)
@@ -558,7 +558,7 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
        }
 
        /* Get thermal effect */
-       if (svsb->phase == SVSB_PHASE_MON) {
+       if (!IS_ERR_OR_NULL(svsb->tzd)) {
                ret = thermal_zone_get_temp(svsb->tzd, &tzone_temp);
                if (ret || (svsb->temp > SVSB_TEMP_UPPER_BOUND &&
                            svsb->temp < SVSB_TEMP_LOWER_BOUND)) {
@@ -573,7 +573,8 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
                        temp_voffset += svsb->tzone_ltemp_voffset;
 
                /* 2-line bank update all opp volts when running mon mode */
-               if (svsb->type == SVSB_HIGH || svsb->type == SVSB_LOW) {
+               if (svsb->phase == SVSB_PHASE_MON && (svsb->type == SVSB_HIGH ||
+                                                     svsb->type == SVSB_LOW)) {
                        opp_start = 0;
                        opp_stop = svsb->opp_count;
                }
@@ -589,11 +590,6 @@ static int svs_adjust_pm_opp_volts(struct svs_bank *svsb)
                        /* do nothing */
                        goto unlock_mutex;
                case SVSB_PHASE_INIT02:
-                       svsb_volt = max(svsb->volt[i], svsb->vmin);
-                       opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
-                                                            svsb->volt_step,
-                                                            svsb->volt_base);
-                       break;
                case SVSB_PHASE_MON:
                        svsb_volt = max(svsb->volt[i] + temp_voffset, svsb->vmin);
                        opp_volt = svs_bank_volt_to_opp_volt(svsb_volt,
@@ -624,6 +620,25 @@ unlock_mutex:
        return ret;
 }
 
+static void svs_bank_disable_and_restore_default_volts(struct svs_platform *svsp,
+                                                      struct svs_bank *svsb)
+{
+       unsigned long flags;
+
+       if (svsb->mode_support == SVSB_MODE_ALL_DISABLE)
+               return;
+
+       spin_lock_irqsave(&svs_lock, flags);
+       svsp->pbank = svsb;
+       svs_switch_bank(svsp);
+       svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
+       svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
+       spin_unlock_irqrestore(&svs_lock, flags);
+
+       svsb->phase = SVSB_PHASE_ERROR;
+       svs_adjust_pm_opp_volts(svsb);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int svs_dump_debug_show(struct seq_file *m, void *p)
 {
@@ -700,7 +715,6 @@ static ssize_t svs_enable_debug_write(struct file *filp,
 {
        struct svs_bank *svsb = file_inode(filp)->i_private;
        struct svs_platform *svsp = dev_get_drvdata(svsb->dev);
-       unsigned long flags;
        int enabled, ret;
        char *buf = NULL;
 
@@ -716,16 +730,8 @@ static ssize_t svs_enable_debug_write(struct file *filp,
                return ret;
 
        if (!enabled) {
-               spin_lock_irqsave(&svs_lock, flags);
-               svsp->pbank = svsb;
+               svs_bank_disable_and_restore_default_volts(svsp, svsb);
                svsb->mode_support = SVSB_MODE_ALL_DISABLE;
-               svs_switch_bank(svsp);
-               svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
-               svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
-               spin_unlock_irqrestore(&svs_lock, flags);
-
-               svsb->phase = SVSB_PHASE_ERROR;
-               svs_adjust_pm_opp_volts(svsb);
        }
 
        kfree(buf);
@@ -1508,16 +1514,7 @@ static int svs_init02(struct svs_platform *svsp)
 out_of_init02:
        for (idx = 0; idx < svsp->bank_max; idx++) {
                svsb = &svsp->banks[idx];
-
-               spin_lock_irqsave(&svs_lock, flags);
-               svsp->pbank = svsb;
-               svs_switch_bank(svsp);
-               svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
-               svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
-               spin_unlock_irqrestore(&svs_lock, flags);
-
-               svsb->phase = SVSB_PHASE_ERROR;
-               svs_adjust_pm_opp_volts(svsb);
+               svs_bank_disable_and_restore_default_volts(svsp, svsb);
        }
 
        return ret;
@@ -1563,23 +1560,12 @@ static int svs_suspend(struct device *dev)
 {
        struct svs_platform *svsp = dev_get_drvdata(dev);
        struct svs_bank *svsb;
-       unsigned long flags;
        int ret;
        u32 idx;
 
        for (idx = 0; idx < svsp->bank_max; idx++) {
                svsb = &svsp->banks[idx];
-
-               /* This might wait for svs_isr() process */
-               spin_lock_irqsave(&svs_lock, flags);
-               svsp->pbank = svsb;
-               svs_switch_bank(svsp);
-               svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
-               svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
-               spin_unlock_irqrestore(&svs_lock, flags);
-
-               svsb->phase = SVSB_PHASE_ERROR;
-               svs_adjust_pm_opp_volts(svsb);
+               svs_bank_disable_and_restore_default_volts(svsp, svsb);
        }
 
        ret = reset_control_assert(svsp->rst);
@@ -1693,7 +1679,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
                        }
                }
 
-               if (svsb->mode_support & SVSB_MODE_MON) {
+               if (!IS_ERR_OR_NULL(svsb->tzone_name)) {
                        svsb->tzd = thermal_zone_get_zone_by_name(svsb->tzone_name);
                        if (IS_ERR(svsb->tzd)) {
                                dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
@@ -1729,26 +1715,28 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
        return 0;
 }
 
-static int svs_thermal_efuse_get_data(struct svs_platform *svsp)
+static int svs_get_efuse_data(struct svs_platform *svsp,
+                             const char *nvmem_cell_name,
+                             u32 **svsp_efuse, size_t *svsp_efuse_max)
 {
        struct nvmem_cell *cell;
 
-       /* Thermal efuse parsing */
-       cell = nvmem_cell_get(svsp->dev, "t-calibration-data");
-       if (IS_ERR_OR_NULL(cell)) {
-               dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", PTR_ERR(cell));
+       cell = nvmem_cell_get(svsp->dev, nvmem_cell_name);
+       if (IS_ERR(cell)) {
+               dev_err(svsp->dev, "no \"%s\"? %ld\n",
+                       nvmem_cell_name, PTR_ERR(cell));
                return PTR_ERR(cell);
        }
 
-       svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max);
-       if (IS_ERR(svsp->tefuse)) {
-               dev_err(svsp->dev, "cannot read thermal efuse: %ld\n",
-                       PTR_ERR(svsp->tefuse));
+       *svsp_efuse = nvmem_cell_read(cell, svsp_efuse_max);
+       if (IS_ERR(*svsp_efuse)) {
+               dev_err(svsp->dev, "cannot read \"%s\" efuse: %ld\n",
+                       nvmem_cell_name, PTR_ERR(*svsp_efuse));
                nvmem_cell_put(cell);
-               return PTR_ERR(svsp->tefuse);
+               return PTR_ERR(*svsp_efuse);
        }
 
-       svsp->tefuse_max /= sizeof(u32);
+       *svsp_efuse_max /= sizeof(u32);
        nvmem_cell_put(cell);
 
        return 0;
@@ -1796,7 +1784,8 @@ static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
                svsb->vmax += svsb->dvt_fixed;
        }
 
-       ret = svs_thermal_efuse_get_data(svsp);
+       ret = svs_get_efuse_data(svsp, "t-calibration-data",
+                                &svsp->tefuse, &svsp->tefuse_max);
        if (ret)
                return false;
 
@@ -1901,7 +1890,8 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
                }
        }
 
-       ret = svs_thermal_efuse_get_data(svsp);
+       ret = svs_get_efuse_data(svsp, "t-calibration-data",
+                                &svsp->tefuse, &svsp->tefuse_max);
        if (ret)
                return false;
 
@@ -2003,32 +1993,6 @@ remove_mt8183_svsb_mon_mode:
        return true;
 }
 
-static bool svs_is_efuse_data_correct(struct svs_platform *svsp)
-{
-       struct nvmem_cell *cell;
-
-       /* Get svs efuse by nvmem */
-       cell = nvmem_cell_get(svsp->dev, "svs-calibration-data");
-       if (IS_ERR(cell)) {
-               dev_err(svsp->dev, "no \"svs-calibration-data\"? %ld\n",
-                       PTR_ERR(cell));
-               return false;
-       }
-
-       svsp->efuse = nvmem_cell_read(cell, &svsp->efuse_max);
-       if (IS_ERR(svsp->efuse)) {
-               dev_err(svsp->dev, "cannot read svs efuse: %ld\n",
-                       PTR_ERR(svsp->efuse));
-               nvmem_cell_put(cell);
-               return false;
-       }
-
-       svsp->efuse_max /= sizeof(u32);
-       nvmem_cell_put(cell);
-
-       return true;
-}
-
 static struct device *svs_get_subsys_device(struct svs_platform *svsp,
                                            const char *node_name)
 {
@@ -2059,11 +2023,6 @@ static struct device *svs_add_device_link(struct svs_platform *svsp,
        struct device *dev;
        struct device_link *sup_link;
 
-       if (!node_name) {
-               dev_err(svsp->dev, "node name cannot be null\n");
-               return ERR_PTR(-EINVAL);
-       }
-
        dev = svs_get_subsys_device(svsp, node_name);
        if (IS_ERR(dev))
                return dev;
@@ -2159,6 +2118,7 @@ static struct svs_bank svs_mt8192_banks[] = {
                .type                   = SVSB_LOW,
                .set_freq_pct           = svs_set_bank_freq_pct_v3,
                .get_volts              = svs_get_bank_volts_v3,
+               .tzone_name             = "gpu1",
                .volt_flags             = SVSB_REMOVE_DVTFIXED_VOLT,
                .mode_support           = SVSB_MODE_INIT02,
                .opp_count              = MAX_OPP_ENTRIES,
@@ -2176,6 +2136,10 @@ static struct svs_bank svs_mt8192_banks[] = {
                .core_sel               = 0x0fff0100,
                .int_st                 = BIT(0),
                .ctl0                   = 0x00540003,
+               .tzone_htemp            = 85000,
+               .tzone_htemp_voffset    = 0,
+               .tzone_ltemp            = 25000,
+               .tzone_ltemp_voffset    = 7,
        },
        {
                .sw_id                  = SVSB_GPU,
@@ -2364,8 +2328,9 @@ static int svs_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       if (!svs_is_efuse_data_correct(svsp)) {
-               dev_notice(svsp->dev, "efuse data isn't correct\n");
+       ret = svs_get_efuse_data(svsp, "svs-calibration-data",
+                                &svsp->efuse, &svsp->efuse_max);
+       if (ret) {
                ret = -EPERM;
                goto svs_probe_free_efuse;
        }
@@ -2373,19 +2338,19 @@ static int svs_probe(struct platform_device *pdev)
        if (!svsp_data->efuse_parsing(svsp)) {
                dev_err(svsp->dev, "efuse data parsing failed\n");
                ret = -EPERM;
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        ret = svs_bank_resource_setup(svsp);
        if (ret) {
                dev_err(svsp->dev, "svs bank resource setup fail: %d\n", ret);
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        svsp_irq = platform_get_irq(pdev, 0);
        if (svsp_irq < 0) {
                ret = svsp_irq;
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        svsp->main_clk = devm_clk_get(svsp->dev, "main");
@@ -2393,13 +2358,13 @@ static int svs_probe(struct platform_device *pdev)
                dev_err(svsp->dev, "failed to get clock: %ld\n",
                        PTR_ERR(svsp->main_clk));
                ret = PTR_ERR(svsp->main_clk);
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        ret = clk_prepare_enable(svsp->main_clk);
        if (ret) {
                dev_err(svsp->dev, "cannot enable main clk: %d\n", ret);
-               goto svs_probe_free_resource;
+               goto svs_probe_free_tefuse;
        }
 
        svsp->base = of_iomap(svsp->dev->of_node, 0);
@@ -2439,7 +2404,7 @@ svs_probe_iounmap:
 svs_probe_clk_disable:
        clk_disable_unprepare(svsp->main_clk);
 
-svs_probe_free_resource:
+svs_probe_free_tefuse:
        if (!IS_ERR_OR_NULL(svsp->tefuse))
                kfree(svsp->tefuse);
 
index 6e20207b57567b457b624849d14ceaee9865be90..216d9f4ea0ce936cec3e6a7da9bc99bef7e81cd5 100644 (file)
 #include <linux/slab.h>
 #include <linux/kref.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
 #include <linux/mailbox_client.h>
 #include <linux/platform_device.h>
 #include <soc/microchip/mpfs.h>
 
+/*
+ * This timeout must be long, as some services (example: image authentication)
+ * take significant time to complete
+ */
+#define MPFS_SYS_CTRL_TIMEOUT_MS 30000
+
 static DEFINE_MUTEX(transaction_lock);
 
 struct mpfs_sys_controller {
@@ -28,35 +35,47 @@ struct mpfs_sys_controller {
 
 int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg)
 {
-       int ret, err;
+       unsigned long timeout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
+       int ret;
 
-       err = mutex_lock_interruptible(&transaction_lock);
-       if (err)
-               return err;
+       ret = mutex_lock_interruptible(&transaction_lock);
+       if (ret)
+               return ret;
 
        reinit_completion(&sys_controller->c);
 
        ret = mbox_send_message(sys_controller->chan, msg);
-       if (ret >= 0) {
-               if (wait_for_completion_timeout(&sys_controller->c, HZ)) {
-                       ret = 0;
-               } else {
-                       ret = -ETIMEDOUT;
-                       dev_warn(sys_controller->client.dev,
-                                "MPFS sys controller transaction timeout\n");
-               }
+       if (ret < 0) {
+               dev_warn(sys_controller->client.dev, "MPFS sys controller service timeout\n");
+               goto out;
+       }
+
+       /*
+        * Unfortunately, the system controller will only deliver an interrupt
+        * if a service succeeds. mbox_send_message() will block until the busy
+        * flag is gone. If the busy flag is gone but no interrupt has arrived
+        * to trigger the rx callback then the service can be deemed to have
+        * failed.
+        * The caller can then interrogate msg::response::resp_status to
+        * determine the cause of the failure.
+        * mbox_send_message() returns positive integers in the success path, so
+        * ret needs to be cleared if we do get an interrupt.
+        */
+       if (!wait_for_completion_timeout(&sys_controller->c, timeout)) {
+               ret = -EBADMSG;
+               dev_warn(sys_controller->client.dev, "MPFS sys controller service failed\n");
        } else {
-               dev_err(sys_controller->client.dev,
-                       "mpfs sys controller transaction returned %d\n", ret);
+               ret = 0;
        }
 
+out:
        mutex_unlock(&transaction_lock);
 
        return ret;
 }
 EXPORT_SYMBOL(mpfs_blocking_transaction);
 
-static void rx_callback(struct mbox_client *client, void *msg)
+static void mpfs_sys_controller_rx_callback(struct mbox_client *client, void *msg)
 {
        struct mpfs_sys_controller *sys_controller =
                container_of(client, struct mpfs_sys_controller, client);
@@ -66,8 +85,8 @@ static void rx_callback(struct mbox_client *client, void *msg)
 
 static void mpfs_sys_controller_delete(struct kref *kref)
 {
-       struct mpfs_sys_controller *sys_controller = container_of(kref, struct mpfs_sys_controller,
-                                              consumers);
+       struct mpfs_sys_controller *sys_controller =
+               container_of(kref, struct mpfs_sys_controller, consumers);
 
        mbox_free_channel(sys_controller->chan);
        kfree(sys_controller);
@@ -102,8 +121,9 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        sys_controller->client.dev = dev;
-       sys_controller->client.rx_callback = rx_callback;
+       sys_controller->client.rx_callback = mpfs_sys_controller_rx_callback;
        sys_controller->client.tx_block = 1U;
+       sys_controller->client.tx_tout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
 
        sys_controller->chan = mbox_request_channel(&sys_controller->client, 0);
        if (IS_ERR(sys_controller->chan)) {
index a8f283086a2191b675f06509bd6fd688f89e25ac..a491718f8064f9b0c347e9851e75a7d8cf6fd246 100644 (file)
@@ -72,7 +72,7 @@ config QCOM_LLCC
 
 config QCOM_KRYO_L2_ACCESSORS
        bool
-       depends on ARCH_QCOM && ARM64 || COMPILE_TEST
+       depends on (ARCH_QCOM || COMPILE_TEST) && ARM64
 
 config QCOM_MDT_LOADER
        tristate
@@ -275,4 +275,8 @@ config QCOM_ICC_BWMON
          the fixed bandwidth votes from cpufreq (CPU nodes) thus achieve high
          memory throughput even with lower CPU frequencies.
 
+config QCOM_INLINE_CRYPTO_ENGINE
+       tristate
+       select QCOM_SCM
+
 endmenu
index 6e88da899f602c303b91ea5b6965916a8985e74f..0f43a88b4894e4675b7e456a08d906890c538829 100644 (file)
@@ -32,3 +32,4 @@ obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
 obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
 obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) +=        kryo-l2-accessors.o
 obj-$(CONFIG_QCOM_ICC_BWMON)   += icc-bwmon.o
+obj-$(CONFIG_QCOM_INLINE_CRYPTO_ENGINE)        += ice.o
index d07be3700db607a93a46708b13ac5466ad98022a..fd58c5b698978765d3213b8689d7db4dab39d415 100644 (file)
 /* Internal sampling clock frequency */
 #define HW_TIMER_HZ                            19200000
 
-#define BWMON_V4_GLOBAL_IRQ_CLEAR              0x008
-#define BWMON_V4_GLOBAL_IRQ_ENABLE             0x00c
+#define BWMON_V4_GLOBAL_IRQ_CLEAR              0x108
+#define BWMON_V4_GLOBAL_IRQ_ENABLE             0x10c
 /*
  * All values here and further are matching regmap fields, so without absolute
  * register offsets.
  */
 #define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE      BIT(0)
 
+/*
+ * Starting with SDM845, the BWMON4 register space has changed a bit:
+ * the global registers were jammed into the beginning of the monitor region.
+ * To keep the proper offsets, one would have to map <GLOBAL_BASE 0x200> and
+ * <GLOBAL_BASE+0x100 0x300>, which is straight up wrong.
+ * To facilitate for that, while allowing the older, arguably more proper
+ * implementations to work, offset the global registers by -0x100 to avoid
+ * having to map half of the global registers twice.
+ */
+#define BWMON_V4_845_OFFSET                    0x100
+#define BWMON_V4_GLOBAL_IRQ_CLEAR_845          (BWMON_V4_GLOBAL_IRQ_CLEAR - BWMON_V4_845_OFFSET)
+#define BWMON_V4_GLOBAL_IRQ_ENABLE_845         (BWMON_V4_GLOBAL_IRQ_ENABLE - BWMON_V4_845_OFFSET)
+
 #define BWMON_V4_IRQ_STATUS                    0x100
 #define BWMON_V4_IRQ_CLEAR                     0x108
 
 #define BWMON_NEEDS_FORCE_CLEAR                        BIT(1)
 
 enum bwmon_fields {
+       /* Global region fields, keep them at the top */
        F_GLOBAL_IRQ_CLEAR,
        F_GLOBAL_IRQ_ENABLE,
-       F_IRQ_STATUS,
+       F_NUM_GLOBAL_FIELDS,
+
+       /* Monitor region fields */
+       F_IRQ_STATUS = F_NUM_GLOBAL_FIELDS,
        F_IRQ_CLEAR,
        F_IRQ_ENABLE,
        F_ENABLE,
@@ -157,6 +174,9 @@ struct icc_bwmon_data {
 
        const struct regmap_config *regmap_cfg;
        const struct reg_field *regmap_fields;
+
+       const struct regmap_config *global_regmap_cfg;
+       const struct reg_field *global_regmap_fields;
 };
 
 struct icc_bwmon {
@@ -164,8 +184,8 @@ struct icc_bwmon {
        const struct icc_bwmon_data *data;
        int irq;
 
-       struct regmap *regmap;
        struct regmap_field *regs[F_NUM_FIELDS];
+       struct regmap_field *global_regs[F_NUM_GLOBAL_FIELDS];
 
        unsigned int max_bw_kbps;
        unsigned int min_bw_kbps;
@@ -175,8 +195,8 @@ struct icc_bwmon {
 
 /* BWMON v4 */
 static const struct reg_field msm8998_bwmon_reg_fields[] = {
-       [F_GLOBAL_IRQ_CLEAR]    = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
-       [F_GLOBAL_IRQ_ENABLE]   = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
+       [F_GLOBAL_IRQ_CLEAR]    = {},
+       [F_GLOBAL_IRQ_ENABLE]   = {},
        [F_IRQ_STATUS]          = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
        [F_IRQ_CLEAR]           = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
        [F_IRQ_ENABLE]          = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
@@ -202,7 +222,6 @@ static const struct reg_field msm8998_bwmon_reg_fields[] = {
 };
 
 static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] = {
-       regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
        regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
        regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
 };
@@ -222,16 +241,33 @@ static const struct regmap_access_table msm8998_bwmon_reg_volatile_table = {
        .n_yes_ranges   = ARRAY_SIZE(msm8998_bwmon_reg_volatile_ranges),
 };
 
+static const struct reg_field msm8998_bwmon_global_reg_fields[] = {
+       [F_GLOBAL_IRQ_CLEAR]    = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
+       [F_GLOBAL_IRQ_ENABLE]   = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
+};
+
+static const struct regmap_range msm8998_bwmon_global_reg_noread_ranges[] = {
+       regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
+};
+
+static const struct regmap_access_table msm8998_bwmon_global_reg_read_table = {
+       .no_ranges      = msm8998_bwmon_global_reg_noread_ranges,
+       .n_no_ranges    = ARRAY_SIZE(msm8998_bwmon_global_reg_noread_ranges),
+};
+
 /*
  * Fill the cache for non-readable registers only as rest does not really
  * matter and can be read from the device.
  */
 static const struct reg_default msm8998_bwmon_reg_defaults[] = {
-       { BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
        { BWMON_V4_IRQ_CLEAR, 0x0 },
        { BWMON_V4_CLEAR, 0x0 },
 };
 
+static const struct reg_default msm8998_bwmon_global_reg_defaults[] = {
+       { BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
+};
+
 static const struct regmap_config msm8998_bwmon_regmap_cfg = {
        .reg_bits               = 32,
        .reg_stride             = 4,
@@ -252,6 +288,93 @@ static const struct regmap_config msm8998_bwmon_regmap_cfg = {
        .cache_type             = REGCACHE_RBTREE,
 };
 
+static const struct regmap_config msm8998_bwmon_global_regmap_cfg = {
+       .reg_bits               = 32,
+       .reg_stride             = 4,
+       .val_bits               = 32,
+       /*
+        * No concurrent access expected - driver has one interrupt handler,
+        * regmap is not shared, no driver or user-space API.
+        */
+       .disable_locking        = true,
+       .rd_table               = &msm8998_bwmon_global_reg_read_table,
+       .reg_defaults           = msm8998_bwmon_global_reg_defaults,
+       .num_reg_defaults       = ARRAY_SIZE(msm8998_bwmon_global_reg_defaults),
+       /*
+        * Cache is necessary for using regmap fields with non-readable
+        * registers.
+        */
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static const struct reg_field sdm845_cpu_bwmon_reg_fields[] = {
+       [F_GLOBAL_IRQ_CLEAR]    = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR_845, 0, 0),
+       [F_GLOBAL_IRQ_ENABLE]   = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE_845, 0, 0),
+       [F_IRQ_STATUS]          = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
+       [F_IRQ_CLEAR]           = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
+       [F_IRQ_ENABLE]          = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
+       /* F_ENABLE covers entire register to disable other features */
+       [F_ENABLE]              = REG_FIELD(BWMON_V4_ENABLE, 0, 31),
+       [F_CLEAR]               = REG_FIELD(BWMON_V4_CLEAR, 0, 1),
+       [F_SAMPLE_WINDOW]       = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23),
+       [F_THRESHOLD_HIGH]      = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11),
+       [F_THRESHOLD_MED]       = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11),
+       [F_THRESHOLD_LOW]       = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11),
+       [F_ZONE_ACTIONS_ZONE0]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7),
+       [F_ZONE_ACTIONS_ZONE1]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15),
+       [F_ZONE_ACTIONS_ZONE2]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23),
+       [F_ZONE_ACTIONS_ZONE3]  = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31),
+       [F_THRESHOLD_COUNT_ZONE0]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7),
+       [F_THRESHOLD_COUNT_ZONE1]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15),
+       [F_THRESHOLD_COUNT_ZONE2]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23),
+       [F_THRESHOLD_COUNT_ZONE3]       = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31),
+       [F_ZONE0_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11),
+       [F_ZONE1_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11),
+       [F_ZONE2_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11),
+       [F_ZONE3_MAX]           = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11),
+};
+
+static const struct regmap_range sdm845_cpu_bwmon_reg_noread_ranges[] = {
+       regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR_845, BWMON_V4_GLOBAL_IRQ_CLEAR_845),
+       regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
+       regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
+};
+
+static const struct regmap_access_table sdm845_cpu_bwmon_reg_read_table = {
+       .no_ranges      = sdm845_cpu_bwmon_reg_noread_ranges,
+       .n_no_ranges    = ARRAY_SIZE(sdm845_cpu_bwmon_reg_noread_ranges),
+};
+
+/*
+ * Fill the cache for non-readable registers only as rest does not really
+ * matter and can be read from the device.
+ */
+static const struct reg_default sdm845_cpu_bwmon_reg_defaults[] = {
+       { BWMON_V4_GLOBAL_IRQ_CLEAR_845, 0x0 },
+       { BWMON_V4_IRQ_CLEAR, 0x0 },
+       { BWMON_V4_CLEAR, 0x0 },
+};
+
+static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg = {
+       .reg_bits               = 32,
+       .reg_stride             = 4,
+       .val_bits               = 32,
+       /*
+        * No concurrent access expected - driver has one interrupt handler,
+        * regmap is not shared, no driver or user-space API.
+        */
+       .disable_locking        = true,
+       .rd_table               = &sdm845_cpu_bwmon_reg_read_table,
+       .volatile_table         = &msm8998_bwmon_reg_volatile_table,
+       .reg_defaults           = sdm845_cpu_bwmon_reg_defaults,
+       .num_reg_defaults       = ARRAY_SIZE(sdm845_cpu_bwmon_reg_defaults),
+       /*
+        * Cache is necessary for using regmap fields with non-readable
+        * registers.
+        */
+       .cache_type             = REGCACHE_RBTREE,
+};
+
 /* BWMON v5 */
 static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = {
        [F_GLOBAL_IRQ_CLEAR]    = {},
@@ -350,6 +473,13 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
 
 static void bwmon_clear_irq(struct icc_bwmon *bwmon)
 {
+       struct regmap_field *global_irq_clr;
+
+       if (bwmon->data->global_regmap_fields)
+               global_irq_clr = bwmon->global_regs[F_GLOBAL_IRQ_CLEAR];
+       else
+               global_irq_clr = bwmon->regs[F_GLOBAL_IRQ_CLEAR];
+
        /*
         * Clear zone and global interrupts. The order and barriers are
         * important. Quoting downstream Qualcomm msm-4.9 tree:
@@ -370,15 +500,22 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon)
        if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
                regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0);
        if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
-               regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR],
+               regmap_field_force_write(global_irq_clr,
                                         BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
 }
 
 static void bwmon_disable(struct icc_bwmon *bwmon)
 {
+       struct regmap_field *global_irq_en;
+
+       if (bwmon->data->global_regmap_fields)
+               global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE];
+       else
+               global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE];
+
        /* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
        if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
-               regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0);
+               regmap_field_write(global_irq_en, 0x0);
        regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0);
 
        /*
@@ -390,10 +527,18 @@ static void bwmon_disable(struct icc_bwmon *bwmon)
 
 static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
 {
+       struct regmap_field *global_irq_en;
+
+       if (bwmon->data->global_regmap_fields)
+               global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE];
+       else
+               global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE];
+
        /* Enable interrupts */
        if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
-               regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE],
+               regmap_field_write(global_irq_en,
                                   BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
+
        regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable);
 
        /* Enable bwmon */
@@ -556,7 +701,9 @@ static int bwmon_init_regmap(struct platform_device *pdev,
        struct device *dev = &pdev->dev;
        void __iomem *base;
        struct regmap *map;
+       int ret;
 
+       /* Map the monitor base */
        base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(base))
                return dev_err_probe(dev, PTR_ERR(base),
@@ -567,12 +714,35 @@ static int bwmon_init_regmap(struct platform_device *pdev,
                return dev_err_probe(dev, PTR_ERR(map),
                                     "failed to initialize regmap\n");
 
+       BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_global_reg_fields) != F_NUM_GLOBAL_FIELDS);
        BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
+       BUILD_BUG_ON(ARRAY_SIZE(sdm845_cpu_bwmon_reg_fields) != F_NUM_FIELDS);
        BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
 
-       return devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
+       ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
                                           bwmon->data->regmap_fields,
                                           F_NUM_FIELDS);
+       if (ret)
+               return ret;
+
+       if (bwmon->data->global_regmap_cfg) {
+               /* Map the global base, if separate */
+               base = devm_platform_ioremap_resource(pdev, 1);
+               if (IS_ERR(base))
+                       return dev_err_probe(dev, PTR_ERR(base),
+                                            "failed to map bwmon global registers\n");
+
+               map = devm_regmap_init_mmio(dev, base, bwmon->data->global_regmap_cfg);
+               if (IS_ERR(map))
+                       return dev_err_probe(dev, PTR_ERR(map),
+                                            "failed to initialize global regmap\n");
+
+               ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->global_regs,
+                                                  bwmon->data->global_regmap_fields,
+                                                  F_NUM_GLOBAL_FIELDS);
+       }
+
+       return ret;
 }
 
 static int bwmon_probe(struct platform_device *pdev)
@@ -645,6 +815,21 @@ static const struct icc_bwmon_data msm8998_bwmon_data = {
        .quirks = BWMON_HAS_GLOBAL_IRQ,
        .regmap_fields = msm8998_bwmon_reg_fields,
        .regmap_cfg = &msm8998_bwmon_regmap_cfg,
+       .global_regmap_fields = msm8998_bwmon_global_reg_fields,
+       .global_regmap_cfg = &msm8998_bwmon_global_regmap_cfg,
+};
+
+static const struct icc_bwmon_data sdm845_cpu_bwmon_data = {
+       .sample_ms = 4,
+       .count_unit_kb = 64,
+       .default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
+       .default_medbw_kbps = 512 * 1024, /* 512 MBps */
+       .default_lowbw_kbps = 0,
+       .zone1_thres_count = 16,
+       .zone3_thres_count = 1,
+       .quirks = BWMON_HAS_GLOBAL_IRQ,
+       .regmap_fields = sdm845_cpu_bwmon_reg_fields,
+       .regmap_cfg = &sdm845_cpu_bwmon_regmap_cfg,
 };
 
 static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
@@ -673,16 +858,18 @@ static const struct icc_bwmon_data sc7280_llcc_bwmon_data = {
 };
 
 static const struct of_device_id bwmon_of_match[] = {
-       {
-               .compatible = "qcom,msm8998-bwmon",
-               .data = &msm8998_bwmon_data
-       }, {
-               .compatible = "qcom,sdm845-llcc-bwmon",
-               .data = &sdm845_llcc_bwmon_data
-       }, {
-               .compatible = "qcom,sc7280-llcc-bwmon",
-               .data = &sc7280_llcc_bwmon_data
-       },
+       /* BWMONv4, separate monitor and global register spaces */
+       { .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
+       /* BWMONv4, unified register space */
+       { .compatible = "qcom,sdm845-bwmon", .data = &sdm845_cpu_bwmon_data },
+       /* BWMONv5 */
+       { .compatible = "qcom,sdm845-llcc-bwmon", .data = &sdm845_llcc_bwmon_data },
+       { .compatible = "qcom,sc7280-llcc-bwmon", .data = &sc7280_llcc_bwmon_data },
+
+       /* Compatibles kept for legacy reasons */
+       { .compatible = "qcom,sc7280-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
+       { .compatible = "qcom,sc8280xp-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
+       { .compatible = "qcom,sm8550-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
        {}
 };
 MODULE_DEVICE_TABLE(of, bwmon_of_match);
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
new file mode 100644 (file)
index 0000000..a6123ea
--- /dev/null
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Qualcomm ICE (Inline Crypto Engine) support.
+ *
+ * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019, Google LLC
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/of_platform.h>
+
+#include <linux/firmware/qcom/qcom_scm.h>
+
+#include <soc/qcom/ice.h>
+
+#define AES_256_XTS_KEY_SIZE                   64
+
+/* QCOM ICE registers */
+#define QCOM_ICE_REG_VERSION                   0x0008
+#define QCOM_ICE_REG_FUSE_SETTING              0x0010
+#define QCOM_ICE_REG_BIST_STATUS               0x0070
+#define QCOM_ICE_REG_ADVANCED_CONTROL          0x1000
+
+/* BIST ("built-in self-test") status flags */
+#define QCOM_ICE_BIST_STATUS_MASK              GENMASK(31, 28)
+
+#define QCOM_ICE_FUSE_SETTING_MASK             0x1
+#define QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK    0x2
+#define QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK    0x4
+
+#define qcom_ice_writel(engine, val, reg)      \
+       writel((val), (engine)->base + (reg))
+
+#define qcom_ice_readl(engine, reg)    \
+       readl((engine)->base + (reg))
+
+struct qcom_ice {
+       struct device *dev;
+       void __iomem *base;
+       struct device_link *link;
+
+       struct clk *core_clk;
+};
+
+static bool qcom_ice_check_supported(struct qcom_ice *ice)
+{
+       u32 regval = qcom_ice_readl(ice, QCOM_ICE_REG_VERSION);
+       struct device *dev = ice->dev;
+       int major = FIELD_GET(GENMASK(31, 24), regval);
+       int minor = FIELD_GET(GENMASK(23, 16), regval);
+       int step = FIELD_GET(GENMASK(15, 0), regval);
+
+       /* For now this driver only supports ICE version 3 and 4. */
+       if (major != 3 && major != 4) {
+               dev_warn(dev, "Unsupported ICE version: v%d.%d.%d\n",
+                        major, minor, step);
+               return false;
+       }
+
+       dev_info(dev, "Found QC Inline Crypto Engine (ICE) v%d.%d.%d\n",
+                major, minor, step);
+
+       /* If fuses are blown, ICE might not work in the standard way. */
+       regval = qcom_ice_readl(ice, QCOM_ICE_REG_FUSE_SETTING);
+       if (regval & (QCOM_ICE_FUSE_SETTING_MASK |
+                     QCOM_ICE_FORCE_HW_KEY0_SETTING_MASK |
+                     QCOM_ICE_FORCE_HW_KEY1_SETTING_MASK)) {
+               dev_warn(dev, "Fuses are blown; ICE is unusable!\n");
+               return false;
+       }
+
+       return true;
+}
+
+static void qcom_ice_low_power_mode_enable(struct qcom_ice *ice)
+{
+       u32 regval;
+
+       regval = qcom_ice_readl(ice, QCOM_ICE_REG_ADVANCED_CONTROL);
+
+       /* Enable low power mode sequence */
+       regval |= 0x7000;
+       qcom_ice_writel(ice, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
+}
+
+static void qcom_ice_optimization_enable(struct qcom_ice *ice)
+{
+       u32 regval;
+
+       /* ICE Optimizations Enable Sequence */
+       regval = qcom_ice_readl(ice, QCOM_ICE_REG_ADVANCED_CONTROL);
+       regval |= 0xd807100;
+       /* ICE HPG requires delay before writing */
+       udelay(5);
+       qcom_ice_writel(ice, regval, QCOM_ICE_REG_ADVANCED_CONTROL);
+       udelay(5);
+}
+
+/*
+ * Wait until the ICE BIST (built-in self-test) has completed.
+ *
+ * This may be necessary before ICE can be used.
+ * Note that we don't really care whether the BIST passed or failed;
+ * we really just want to make sure that it isn't still running. This is
+ * because (a) the BIST is a FIPS compliance thing that never fails in
+ * practice, (b) ICE is documented to reject crypto requests if the BIST
+ * fails, so we needn't do it in software too, and (c) properly testing
+ * storage encryption requires testing the full storage stack anyway,
+ * and not relying on hardware-level self-tests.
+ */
+static int qcom_ice_wait_bist_status(struct qcom_ice *ice)
+{
+       u32 regval;
+       int err;
+
+       err = readl_poll_timeout(ice->base + QCOM_ICE_REG_BIST_STATUS,
+                                regval, !(regval & QCOM_ICE_BIST_STATUS_MASK),
+                                50, 5000);
+       if (err)
+               dev_err(ice->dev, "Timed out waiting for ICE self-test to complete\n");
+
+       return err;
+}
+
+int qcom_ice_enable(struct qcom_ice *ice)
+{
+       qcom_ice_low_power_mode_enable(ice);
+       qcom_ice_optimization_enable(ice);
+
+       return qcom_ice_wait_bist_status(ice);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_enable);
+
+int qcom_ice_resume(struct qcom_ice *ice)
+{
+       struct device *dev = ice->dev;
+       int err;
+
+       err = clk_prepare_enable(ice->core_clk);
+       if (err) {
+               dev_err(dev, "failed to enable core clock (%d)\n",
+                       err);
+               return err;
+       }
+
+       return qcom_ice_wait_bist_status(ice);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_resume);
+
+int qcom_ice_suspend(struct qcom_ice *ice)
+{
+       clk_disable_unprepare(ice->core_clk);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_suspend);
+
+int qcom_ice_program_key(struct qcom_ice *ice,
+                        u8 algorithm_id, u8 key_size,
+                        const u8 crypto_key[], u8 data_unit_size,
+                        int slot)
+{
+       struct device *dev = ice->dev;
+       union {
+               u8 bytes[AES_256_XTS_KEY_SIZE];
+               u32 words[AES_256_XTS_KEY_SIZE / sizeof(u32)];
+       } key;
+       int i;
+       int err;
+
+       /* Only AES-256-XTS has been tested so far. */
+       if (algorithm_id != QCOM_ICE_CRYPTO_ALG_AES_XTS ||
+           key_size != QCOM_ICE_CRYPTO_KEY_SIZE_256) {
+               dev_err_ratelimited(dev,
+                                   "Unhandled crypto capability; algorithm_id=%d, key_size=%d\n",
+                                   algorithm_id, key_size);
+               return -EINVAL;
+       }
+
+       memcpy(key.bytes, crypto_key, AES_256_XTS_KEY_SIZE);
+
+       /* The SCM call requires that the key words are encoded in big endian */
+       for (i = 0; i < ARRAY_SIZE(key.words); i++)
+               __cpu_to_be32s(&key.words[i]);
+
+       err = qcom_scm_ice_set_key(slot, key.bytes, AES_256_XTS_KEY_SIZE,
+                                  QCOM_SCM_ICE_CIPHER_AES_256_XTS,
+                                  data_unit_size);
+
+       memzero_explicit(&key, sizeof(key));
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(qcom_ice_program_key);
+
+int qcom_ice_evict_key(struct qcom_ice *ice, int slot)
+{
+       return qcom_scm_ice_invalidate_key(slot);
+}
+EXPORT_SYMBOL_GPL(qcom_ice_evict_key);
+
+static struct qcom_ice *qcom_ice_create(struct device *dev,
+                                       void __iomem *base)
+{
+       struct qcom_ice *engine;
+
+       if (!qcom_scm_is_available())
+               return ERR_PTR(-EPROBE_DEFER);
+
+       if (!qcom_scm_ice_available()) {
+               dev_warn(dev, "ICE SCM interface not found\n");
+               return NULL;
+       }
+
+       engine = devm_kzalloc(dev, sizeof(*engine), GFP_KERNEL);
+       if (!engine)
+               return ERR_PTR(-ENOMEM);
+
+       engine->dev = dev;
+       engine->base = base;
+
+       /*
+        * Legacy DT binding uses different clk names for each consumer,
+        * so lets try those first. If none of those are a match, it means
+        * the we only have one clock and it is part of the dedicated DT node.
+        * Also, enable the clock before we check what HW version the driver
+        * supports.
+        */
+       engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_optional_enabled(dev, "ice");
+       if (!engine->core_clk)
+               engine->core_clk = devm_clk_get_enabled(dev, NULL);
+       if (IS_ERR(engine->core_clk))
+               return ERR_CAST(engine->core_clk);
+
+       if (!qcom_ice_check_supported(engine))
+               return ERR_PTR(-EOPNOTSUPP);
+
+       dev_dbg(dev, "Registered Qualcomm Inline Crypto Engine\n");
+
+       return engine;
+}
+
+/**
+ * of_qcom_ice_get() - get an ICE instance from a DT node
+ * @dev: device pointer for the consumer device
+ *
+ * This function will provide an ICE instance either by creating one for the
+ * consumer device if its DT node provides the 'ice' reg range and the 'ice'
+ * clock (for legacy DT style). On the other hand, if consumer provides a
+ * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
+ * be created and so this function will return that instead.
+ *
+ * Return: ICE pointer on success, NULL if there is no ICE data provided by the
+ * consumer or ERR_PTR() on error.
+ */
+struct qcom_ice *of_qcom_ice_get(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct qcom_ice *ice;
+       struct device_node *node;
+       struct resource *res;
+       void __iomem *base;
+
+       if (!dev || !dev->of_node)
+               return ERR_PTR(-ENODEV);
+
+       /*
+        * In order to support legacy style devicetree bindings, we need
+        * to create the ICE instance using the consumer device and the reg
+        * range called 'ice' it provides.
+        */
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice");
+       if (res) {
+               base = devm_ioremap_resource(&pdev->dev, res);
+               if (IS_ERR(base))
+                       return ERR_CAST(base);
+
+               /* create ICE instance using consumer dev */
+               return qcom_ice_create(&pdev->dev, base);
+       }
+
+       /*
+        * If the consumer node does not provider an 'ice' reg range
+        * (legacy DT binding), then it must at least provide a phandle
+        * to the ICE devicetree node, otherwise ICE is not supported.
+        */
+       node = of_parse_phandle(dev->of_node, "qcom,ice", 0);
+       if (!node)
+               return NULL;
+
+       pdev = of_find_device_by_node(node);
+       if (!pdev) {
+               dev_err(dev, "Cannot find device node %s\n", node->name);
+               ice = ERR_PTR(-EPROBE_DEFER);
+               goto out;
+       }
+
+       ice = platform_get_drvdata(pdev);
+       if (!ice) {
+               dev_err(dev, "Cannot get ice instance from %s\n",
+                       dev_name(&pdev->dev));
+               platform_device_put(pdev);
+               ice = ERR_PTR(-EPROBE_DEFER);
+               goto out;
+       }
+
+       ice->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
+       if (!ice->link) {
+               dev_err(&pdev->dev,
+                       "Failed to create device link to consumer %s\n",
+                       dev_name(dev));
+               platform_device_put(pdev);
+               ice = ERR_PTR(-EINVAL);
+       }
+
+out:
+       of_node_put(node);
+
+       return ice;
+}
+EXPORT_SYMBOL_GPL(of_qcom_ice_get);
+
+static int qcom_ice_probe(struct platform_device *pdev)
+{
+       struct qcom_ice *engine;
+       void __iomem *base;
+
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base)) {
+               dev_warn(&pdev->dev, "ICE registers not found\n");
+               return PTR_ERR(base);
+       }
+
+       engine = qcom_ice_create(&pdev->dev, base);
+       if (IS_ERR(engine))
+               return PTR_ERR(engine);
+
+       platform_set_drvdata(pdev, engine);
+
+       return 0;
+}
+
+static const struct of_device_id qcom_ice_of_match_table[] = {
+       { .compatible = "qcom,inline-crypto-engine" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, qcom_ice_of_match_table);
+
+static struct platform_driver qcom_ice_driver = {
+       .probe  = qcom_ice_probe,
+       .driver = {
+               .name = "qcom-ice",
+               .of_match_table = qcom_ice_of_match_table,
+       },
+};
+
+module_platform_driver(qcom_ice_driver);
+
+MODULE_DESCRIPTION("Qualcomm Inline Crypto Engine driver");
+MODULE_LICENSE("GPL");
index 23ce2f78c4ed4c5e003e3ffeb022e1a1e20a0f1e..67c19ed2219a6d35d0c6927c8b65c81c9c961f92 100644 (file)
@@ -62,8 +62,6 @@
 #define LLCC_TRP_WRSC_CACHEABLE_EN    0x21f2c
 #define LLCC_TRP_ALGO_CFG8           0x21f30
 
-#define BANK_OFFSET_STRIDE           0x80000
-
 #define LLCC_VERSION_2_0_0_0          0x02000000
 #define LLCC_VERSION_2_1_0_0          0x02010000
 #define LLCC_VERSION_4_1_0_0          0x04010000
@@ -122,10 +120,11 @@ struct llcc_slice_config {
 
 struct qcom_llcc_config {
        const struct llcc_slice_config *sct_data;
-       int size;
-       bool need_llcc_cfg;
        const u32 *reg_offset;
        const struct llcc_edac_reg_offset *edac_reg_offset;
+       int size;
+       bool need_llcc_cfg;
+       bool no_edac;
 };
 
 enum llcc_reg_offset {
@@ -191,9 +190,9 @@ static const struct llcc_slice_config sc8280xp_data[] = {
        { LLCC_CVP,      28, 512,  3, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
        { LLCC_APTCM,    30, 1024, 3, 1, 0x0,   0x1, 1, 0, 0, 1, 0, 0 },
        { LLCC_WRCACHE,  31, 1024, 1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
-       { LLCC_CVPFW,    32, 512,  1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
-       { LLCC_CPUSS1,   33, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
-       { LLCC_CPUHWT,   36, 512,  1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
+       { LLCC_CVPFW,    17, 512,  1, 0, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+       { LLCC_CPUSS1,   3, 2048, 1, 1, 0xfff, 0x0, 0, 0, 0, 1, 0, 0 },
+       { LLCC_CPUHWT,   5, 512,  1, 1, 0xfff, 0x0, 0, 0, 0, 0, 1, 0 },
 };
 
 static const struct llcc_slice_config sdm845_data[] =  {
@@ -227,6 +226,14 @@ static const struct llcc_slice_config sm6350_data[] =  {
        { LLCC_MODPE,    29,  64, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0 },
 };
 
+static const struct llcc_slice_config sm7150_data[] =  {
+       { LLCC_CPUSS,    1,  512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 1 },
+       { LLCC_MDM,      8,  128, 2, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+       { LLCC_GPUHTW,   11, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
+       { LLCC_GPU,      12, 256, 1, 1, 0xF, 0x0, 0, 0, 0, 1, 0 },
+       { LLCC_NPU,      23, 512, 1, 0, 0xF, 0x0, 0, 0, 0, 1, 0 },
+};
+
 static const struct llcc_slice_config sm8150_data[] =  {
        {  LLCC_CPUSS,    1, 3072, 1, 1, 0xFFF, 0x0,   0, 0, 0, 1, 1 },
        {  LLCC_VIDSC0,   2, 512,  2, 1, 0xFFF, 0x0,   0, 0, 0, 1, 0 },
@@ -454,6 +461,7 @@ static const struct qcom_llcc_config sdm845_cfg = {
        .need_llcc_cfg  = false,
        .reg_offset     = llcc_v1_reg_offset,
        .edac_reg_offset = &llcc_v1_edac_reg_offset,
+       .no_edac        = true,
 };
 
 static const struct qcom_llcc_config sm6350_cfg = {
@@ -464,6 +472,14 @@ static const struct qcom_llcc_config sm6350_cfg = {
        .edac_reg_offset = &llcc_v1_edac_reg_offset,
 };
 
+static const struct qcom_llcc_config sm7150_cfg = {
+       .sct_data       = sm7150_data,
+       .size           = ARRAY_SIZE(sm7150_data),
+       .need_llcc_cfg  = true,
+       .reg_offset     = llcc_v1_reg_offset,
+       .edac_reg_offset = &llcc_v1_edac_reg_offset,
+};
+
 static const struct qcom_llcc_config sm8150_cfg = {
        .sct_data       = sm8150_data,
        .size           = ARRAY_SIZE(sm8150_data),
@@ -898,8 +914,8 @@ static int qcom_llcc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
-               const char *name)
+static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, u8 index,
+                                         const char *name)
 {
        void __iomem *base;
        struct regmap_config llcc_regmap_config = {
@@ -909,7 +925,7 @@ static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev,
                .fast_io = true,
        };
 
-       base = devm_platform_ioremap_resource_byname(pdev, name);
+       base = devm_platform_ioremap_resource(pdev, index);
        if (IS_ERR(base))
                return ERR_CAST(base);
 
@@ -927,6 +943,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
        const struct llcc_slice_config *llcc_cfg;
        u32 sz;
        u32 version;
+       struct regmap *regmap;
 
        drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
        if (!drv_data) {
@@ -934,21 +951,51 @@ static int qcom_llcc_probe(struct platform_device *pdev)
                goto err;
        }
 
-       drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base");
-       if (IS_ERR(drv_data->regmap)) {
-               ret = PTR_ERR(drv_data->regmap);
+       /* Initialize the first LLCC bank regmap */
+       regmap = qcom_llcc_init_mmio(pdev, 0, "llcc0_base");
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               goto err;
+       }
+
+       cfg = of_device_get_match_data(&pdev->dev);
+
+       ret = regmap_read(regmap, cfg->reg_offset[LLCC_COMMON_STATUS0], &num_banks);
+       if (ret)
+               goto err;
+
+       num_banks &= LLCC_LB_CNT_MASK;
+       num_banks >>= LLCC_LB_CNT_SHIFT;
+       drv_data->num_banks = num_banks;
+
+       drv_data->regmaps = devm_kcalloc(dev, num_banks, sizeof(*drv_data->regmaps), GFP_KERNEL);
+       if (!drv_data->regmaps) {
+               ret = -ENOMEM;
                goto err;
        }
 
-       drv_data->bcast_regmap =
-               qcom_llcc_init_mmio(pdev, "llcc_broadcast_base");
+       drv_data->regmaps[0] = regmap;
+
+       /* Initialize rest of LLCC bank regmaps */
+       for (i = 1; i < num_banks; i++) {
+               char *base = kasprintf(GFP_KERNEL, "llcc%d_base", i);
+
+               drv_data->regmaps[i] = qcom_llcc_init_mmio(pdev, i, base);
+               if (IS_ERR(drv_data->regmaps[i])) {
+                       ret = PTR_ERR(drv_data->regmaps[i]);
+                       kfree(base);
+                       goto err;
+               }
+
+               kfree(base);
+       }
+
+       drv_data->bcast_regmap = qcom_llcc_init_mmio(pdev, i, "llcc_broadcast_base");
        if (IS_ERR(drv_data->bcast_regmap)) {
                ret = PTR_ERR(drv_data->bcast_regmap);
                goto err;
        }
 
-       cfg = of_device_get_match_data(&pdev->dev);
-
        /* Extract version of the IP */
        ret = regmap_read(drv_data->bcast_regmap, cfg->reg_offset[LLCC_COMMON_HW_INFO],
                          &version);
@@ -957,15 +1004,6 @@ static int qcom_llcc_probe(struct platform_device *pdev)
 
        drv_data->version = version;
 
-       ret = regmap_read(drv_data->regmap, cfg->reg_offset[LLCC_COMMON_STATUS0],
-                         &num_banks);
-       if (ret)
-               goto err;
-
-       num_banks &= LLCC_LB_CNT_MASK;
-       num_banks >>= LLCC_LB_CNT_SHIFT;
-       drv_data->num_banks = num_banks;
-
        llcc_cfg = cfg->sct_data;
        sz = cfg->size;
 
@@ -973,16 +1011,6 @@ static int qcom_llcc_probe(struct platform_device *pdev)
                if (llcc_cfg[i].slice_id > drv_data->max_slices)
                        drv_data->max_slices = llcc_cfg[i].slice_id;
 
-       drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
-                                                       GFP_KERNEL);
-       if (!drv_data->offsets) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       for (i = 0; i < num_banks; i++)
-               drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
-
        drv_data->bitmap = devm_bitmap_zalloc(dev, drv_data->max_slices,
                                              GFP_KERNEL);
        if (!drv_data->bitmap) {
@@ -1001,7 +1029,14 @@ static int qcom_llcc_probe(struct platform_device *pdev)
                goto err;
 
        drv_data->ecc_irq = platform_get_irq_optional(pdev, 0);
-       if (drv_data->ecc_irq >= 0) {
+
+       /*
+        * On some platforms, the access to EDAC registers will be locked by
+        * the bootloader. So probing the EDAC driver will result in a crash.
+        * Hence, disable the creation of EDAC platform device for the
+        * problematic platforms.
+        */
+       if (!cfg->no_edac) {
                llcc_edac = platform_device_register_data(&pdev->dev,
                                                "qcom_llcc_edac", -1, drv_data,
                                                sizeof(*drv_data));
@@ -1022,6 +1057,7 @@ static const struct of_device_id qcom_llcc_of_match[] = {
        { .compatible = "qcom,sc8280xp-llcc", .data = &sc8280xp_cfg },
        { .compatible = "qcom,sdm845-llcc", .data = &sdm845_cfg },
        { .compatible = "qcom,sm6350-llcc", .data = &sm6350_cfg },
+       { .compatible = "qcom,sm7150-llcc", .data = &sm7150_cfg },
        { .compatible = "qcom,sm8150-llcc", .data = &sm8150_cfg },
        { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg },
        { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg },
index bb3fb57abcc6561ff1933a3066e86c3c48fd8b58..8bf95df0a56ac9f26cf741740d22af40005a0fdc 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2022, Linaro Ltd
  */
 #include <linux/auxiliary_bus.h>
+#include <linux/of_device.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/rpmsg.h>
 #include <linux/soc/qcom/pdr.h>
 #include <linux/soc/qcom/pmic_glink.h>
 
+enum {
+       PMIC_GLINK_CLIENT_BATT = 0,
+       PMIC_GLINK_CLIENT_ALTMODE,
+       PMIC_GLINK_CLIENT_UCSI,
+};
+
+#define PMIC_GLINK_CLIENT_DEFAULT      (BIT(PMIC_GLINK_CLIENT_BATT) |  \
+                                        BIT(PMIC_GLINK_CLIENT_ALTMODE))
+
 struct pmic_glink {
        struct device *dev;
        struct pdr_handle *pdr;
 
        struct rpmsg_endpoint *ept;
 
+       unsigned long client_mask;
+
        struct auxiliary_device altmode_aux;
        struct auxiliary_device ps_aux;
        struct auxiliary_device ucsi_aux;
@@ -233,6 +245,7 @@ static struct rpmsg_driver pmic_glink_rpmsg_driver = {
 
 static int pmic_glink_probe(struct platform_device *pdev)
 {
+       const unsigned long *match_data;
        struct pdr_service *service;
        struct pmic_glink *pg;
        int ret;
@@ -249,12 +262,27 @@ static int pmic_glink_probe(struct platform_device *pdev)
        mutex_init(&pg->client_lock);
        mutex_init(&pg->state_lock);
 
-       ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode");
-       if (ret)
-               return ret;
-       ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply");
-       if (ret)
-               goto out_release_altmode_aux;
+       match_data = (unsigned long *)of_device_get_match_data(&pdev->dev);
+       if (match_data)
+               pg->client_mask = *match_data;
+       else
+               pg->client_mask = PMIC_GLINK_CLIENT_DEFAULT;
+
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI)) {
+               ret = pmic_glink_add_aux_device(pg, &pg->ucsi_aux, "ucsi");
+               if (ret)
+                       return ret;
+       }
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE)) {
+               ret = pmic_glink_add_aux_device(pg, &pg->altmode_aux, "altmode");
+               if (ret)
+                       goto out_release_ucsi_aux;
+       }
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT)) {
+               ret = pmic_glink_add_aux_device(pg, &pg->ps_aux, "power-supply");
+               if (ret)
+                       goto out_release_altmode_aux;
+       }
 
        pg->pdr = pdr_handle_alloc(pmic_glink_pdr_callback, pg);
        if (IS_ERR(pg->pdr)) {
@@ -278,9 +306,14 @@ static int pmic_glink_probe(struct platform_device *pdev)
 out_release_pdr_handle:
        pdr_handle_release(pg->pdr);
 out_release_aux_devices:
-       pmic_glink_del_aux_device(pg, &pg->ps_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
+               pmic_glink_del_aux_device(pg, &pg->ps_aux);
 out_release_altmode_aux:
-       pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
+               pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+out_release_ucsi_aux:
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
+               pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
 
        return ret;
 }
@@ -291,8 +324,12 @@ static int pmic_glink_remove(struct platform_device *pdev)
 
        pdr_handle_release(pg->pdr);
 
-       pmic_glink_del_aux_device(pg, &pg->ps_aux);
-       pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_BATT))
+               pmic_glink_del_aux_device(pg, &pg->ps_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_ALTMODE))
+               pmic_glink_del_aux_device(pg, &pg->altmode_aux);
+       if (pg->client_mask & BIT(PMIC_GLINK_CLIENT_UCSI))
+               pmic_glink_del_aux_device(pg, &pg->ucsi_aux);
 
        mutex_lock(&__pmic_glink_lock);
        __pmic_glink = NULL;
@@ -301,8 +338,14 @@ static int pmic_glink_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* Do not handle altmode for now on those platforms */
+static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
+                                                          BIT(PMIC_GLINK_CLIENT_UCSI);
+
 static const struct of_device_id pmic_glink_of_match[] = {
-       { .compatible = "qcom,pmic-glink", },
+       { .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
+       { .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
+       { .compatible = "qcom,pmic-glink" },
        {}
 };
 MODULE_DEVICE_TABLE(of, pmic_glink_of_match);
index 18c856056475ce04ef05919367be1fa91b07b7c9..e376c32cc16eb0cfd55d077ec67f34575d1e31bd 100644 (file)
@@ -395,7 +395,7 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
                return -ENOMEM;
 
        for_each_available_child_of_node(np, child) {
-               if (!of_find_property(child, "#cooling-cells", NULL))
+               if (!of_property_present(child, "#cooling-cells"))
                        continue;
                ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
                                             child);
index 290bdefbf28aa148013e5a7304ae8672b6e4e3f1..f1742e5bddb9238465af5ed6e449dc46f331f348 100644 (file)
@@ -114,7 +114,7 @@ struct gsbi_info {
        struct regmap *tcsr;
 };
 
-static const struct of_device_id tcsr_dt_match[] = {
+static const struct of_device_id tcsr_dt_match[] __maybe_unused = {
        { .compatible = "qcom,tcsr-ipq8064", .data = &config_ipq8064},
        { .compatible = "qcom,tcsr-apq8064", .data = &config_apq8064},
        { .compatible = "qcom,tcsr-msm8960", .data = &config_msm8960},
index 2d3ee22b924943c33d41cc6b11f9a79ed0206512..0d31377f178d5c69cd886554b999c010ca71830d 100644 (file)
@@ -31,7 +31,7 @@ struct qcom_rmtfs_mem {
 
        unsigned int client_id;
 
-       unsigned int perms;
+       u64 perms;
 };
 
 static ssize_t qcom_rmtfs_mem_show(struct device *dev,
@@ -176,7 +176,8 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
        struct reserved_mem *rmem;
        struct qcom_rmtfs_mem *rmtfs_mem;
        u32 client_id;
-       u32 num_vmids, vmid[NUM_MAX_VMIDS];
+       u32 vmid[NUM_MAX_VMIDS];
+       int num_vmids;
        int ret, i;
 
        rmem = of_reserved_mem_lookup(node);
@@ -228,8 +229,11 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
        }
 
        num_vmids = of_property_count_u32_elems(node, "qcom,vmid");
-       if (num_vmids < 0) {
-               dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", ret);
+       if (num_vmids == -EINVAL) {
+               /* qcom,vmid is optional */
+               num_vmids = 0;
+       } else if (num_vmids < 0) {
+               dev_err(&pdev->dev, "failed to count qcom,vmid elements: %d\n", num_vmids);
                goto remove_cdev;
        } else if (num_vmids > NUM_MAX_VMIDS) {
                dev_warn(&pdev->dev,
index 0f8b2249f889479d0ee4e31b32c9101307104203..f93544f6d7961a01e18858f9b8cfee42f3da5645 100644 (file)
@@ -1073,7 +1073,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
        drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT);
        drv->ver.minor >>= MINOR_VER_SHIFT;
 
-       if (drv->ver.major == 3 && drv->ver.minor == 0)
+       if (drv->ver.major == 3 && drv->ver.minor >= 0)
                drv->regs = rpmh_rsc_reg_offset_ver_3_0;
        else
                drv->regs = rpmh_rsc_reg_offset_ver_2_7;
index 337b1ad1cd3bfecd4119dd417a4676655f9ee7bf..f8397dcb146cf79069282ec62d1cb2d0f7121684 100644 (file)
 
 #define MAX_CORNER_RPMPD_STATE 6
 
-#define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key,    \
-                         r_id)                                         \
-       static struct rpmpd _platform##_##_active;                      \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .peer = &_platform##_##_active,                         \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_##r_key,                                     \
-       };                                                              \
-       static struct rpmpd _platform##_##_active = {                   \
-               .pd = { .name = #_active, },                            \
-               .peer = &_platform##_##_name,                           \
-               .active_only = true,                                    \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_##r_key,                                     \
-       }
-
-#define DEFINE_RPMPD_CORNER(_platform, _name, r_type, r_id)            \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_CORNER,                                      \
-       }
-
-#define DEFINE_RPMPD_LEVEL(_platform, _name, r_type, r_id)             \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_LEVEL,                                       \
-       }
-
-#define DEFINE_RPMPD_VFC(_platform, _name, r_type, r_id)               \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_FLOOR_CORNER,                                \
-       }
-
-#define DEFINE_RPMPD_VFL(_platform, _name, r_type, r_id)               \
-       static struct rpmpd _platform##_##_name = {                     \
-               .pd = { .name = #_name, },                              \
-               .res_type = RPMPD_##r_type,                             \
-               .res_id = r_id,                                         \
-               .key = KEY_FLOOR_LEVEL,                                 \
-       }
-
 struct rpmpd_req {
        __le32 key;
        __le32 nbytes;
@@ -99,6 +48,7 @@ struct rpmpd_req {
 
 struct rpmpd {
        struct generic_pm_domain pd;
+       struct generic_pm_domain *parent;
        struct rpmpd *peer;
        const bool active_only;
        unsigned int corner;
@@ -118,19 +68,459 @@ struct rpmpd_desc {
 
 static DEFINE_MUTEX(rpmpd_lock);
 
-/* mdm9607 RPM Power Domains */
-DEFINE_RPMPD_PAIR(mdm9607, vddcx, vddcx_ao, SMPA, LEVEL, 3);
-DEFINE_RPMPD_VFL(mdm9607, vddcx_vfl, SMPA, 3);
+/* CX */
+static struct rpmpd cx_rwcx0_lvl_ao;
+static struct rpmpd cx_rwcx0_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_rwcx0_lvl_ao,
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_rwcx0_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_rwcx0_lvl,
+       .active_only = true,
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s1a_corner_ao;
+static struct rpmpd cx_s1a_corner = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s1a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s1a_corner_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s1a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_corner_ao;
+static struct rpmpd cx_s2a_corner = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s2a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_corner_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s2a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd cx_s2a_lvl_ao;
+static struct rpmpd cx_s2a_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s2a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s2a_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s2a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s3a_lvl_ao;
+static struct rpmpd cx_s3a_lvl = {
+       .pd = { .name = "cx", },
+       .peer = &cx_s3a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_s3a_lvl_ao = {
+       .pd = { .name = "cx_ao", },
+       .peer = &cx_s3a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd cx_rwcx0_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_RWCX,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_rwsc2_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 2,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_s1a_vfc = {
+       .pd = { .name = "cx_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd cx_s2a_vfc = {
+       .pd = { .name = "cx_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd cx_s2a_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd cx_s3a_vfl = {
+       .pd = { .name = "cx_vfl", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 3,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* G(F)X */
+static struct rpmpd gfx_s2b_corner = {
+       .pd = { .name = "gfx", },
+       .res_type = RPMPD_SMPB,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd gfx_s2b_vfc = {
+       .pd = { .name = "gfx_vfc", },
+       .res_type = RPMPD_SMPB,
+       .res_id = 2,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd mx_rwmx0_lvl;
+static struct rpmpd gx_rwgx0_lvl_ao;
+static struct rpmpd gx_rwgx0_lvl = {
+       .pd = { .name = "gx", },
+       .peer = &gx_rwgx0_lvl_ao,
+       .res_type = RPMPD_RWGX,
+       .parent = &mx_rwmx0_lvl.pd,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao;
+static struct rpmpd gx_rwgx0_lvl_ao = {
+       .pd = { .name = "gx_ao", },
+       .peer = &gx_rwgx0_lvl,
+       .parent = &mx_rwmx0_lvl_ao.pd,
+       .active_only = true,
+       .res_type = RPMPD_RWGX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+/* MX */
+static struct rpmpd mx_l3a_corner_ao;
+static struct rpmpd mx_l3a_corner = {
+       .pd = { .name = "mx", },
+       .peer = &mx_l3a_corner_ao,
+       .res_type = RPMPD_LDOA,
+       .res_id = 3,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_l3a_corner_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_l3a_corner,
+       .active_only = true,
+       .res_type = RPMPD_LDOA,
+       .res_id = 3,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_l12a_lvl_ao;
+static struct rpmpd mx_l12a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_l12a_lvl_ao,
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_l12a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_l12a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s2a_corner_ao;
+static struct rpmpd mx_s2a_corner = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s2a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_s2a_corner_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s2a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 2,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao;
+static struct rpmpd mx_rwmx0_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_rwmx0_lvl_ao,
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_rwmx0_lvl,
+       .active_only = true,
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s6a_lvl_ao;
+static struct rpmpd mx_s6a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s6a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 6,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s6a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s6a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 6,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s7a_lvl_ao;
+static struct rpmpd mx_s7a_lvl = {
+       .pd = { .name = "mx", },
+       .peer = &mx_s7a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 7,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_s7a_lvl_ao = {
+       .pd = { .name = "mx_ao", },
+       .peer = &mx_s7a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 7,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd mx_l12a_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 12,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd mx_rwmx0_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_RWMX,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd mx_rwsm6_vfl = {
+       .pd = { .name = "mx_vfl", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 6,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* MD */
+static struct rpmpd md_s1a_corner_ao;
+static struct rpmpd md_s1a_corner = {
+       .pd = { .name = "md", },
+       .peer = &md_s1a_corner_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd md_s1a_corner_ao = {
+       .pd = { .name = "md_ao", },
+       .peer = &md_s1a_corner,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd md_s1a_lvl_ao;
+static struct rpmpd md_s1a_lvl = {
+       .pd = { .name = "md", },
+       .peer = &md_s1a_lvl_ao,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd md_s1a_lvl_ao = {
+       .pd = { .name = "md_ao", },
+       .peer = &md_s1a_lvl,
+       .active_only = true,
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd md_s1a_vfc = {
+       .pd = { .name = "md_vfc", },
+       .res_type = RPMPD_SMPA,
+       .res_id = 1,
+       .key = KEY_FLOOR_CORNER,
+};
+
+/* LPI_CX */
+static struct rpmpd lpi_cx_rwlc0_lvl = {
+       .pd = { .name = "lpi_cx", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd lpi_cx_rwlc0_vfl = {
+       .pd = { .name = "lpi_cx_vfl", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* LPI_MX */
+static struct rpmpd lpi_mx_rwlm0_lvl = {
+       .pd = { .name = "lpi_mx", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd lpi_mx_rwlm0_vfl = {
+       .pd = { .name = "lpi_mx_vfl", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* SSC_CX */
+static struct rpmpd ssc_cx_l26a_corner = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 26,
+       .key = KEY_CORNER,
+};
+
+static struct rpmpd ssc_cx_rwlc0_lvl = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_cx_rwsc0_lvl = {
+       .pd = { .name = "ssc_cx", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_cx_l26a_vfc = {
+       .pd = { .name = "ssc_cx_vfc", },
+       .res_type = RPMPD_LDOA,
+       .res_id = 26,
+       .key = KEY_FLOOR_CORNER,
+};
+
+static struct rpmpd ssc_cx_rwlc0_vfl = {
+       .pd = { .name = "ssc_cx_vfl", },
+       .res_type = RPMPD_RWLC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd ssc_cx_rwsc0_vfl = {
+       .pd = { .name = "ssc_cx_vfl", },
+       .res_type = RPMPD_RWSC,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+/* SSC_MX */
+static struct rpmpd ssc_mx_rwlm0_lvl = {
+       .pd = { .name = "ssc_mx", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwsm0_lvl = {
+       .pd = { .name = "ssc_mx", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 0,
+       .key = KEY_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwlm0_vfl = {
+       .pd = { .name = "ssc_mx_vfl", },
+       .res_type = RPMPD_RWLM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
+
+static struct rpmpd ssc_mx_rwsm0_vfl = {
+       .pd = { .name = "ssc_mx_vfl", },
+       .res_type = RPMPD_RWSM,
+       .res_id = 0,
+       .key = KEY_FLOOR_LEVEL,
+};
 
-DEFINE_RPMPD_PAIR(mdm9607, vddmx, vddmx_ao, LDOA, LEVEL, 12);
-DEFINE_RPMPD_VFL(mdm9607, vddmx_vfl, LDOA, 12);
 static struct rpmpd *mdm9607_rpmpds[] = {
-       [MDM9607_VDDCX] =       &mdm9607_vddcx,
-       [MDM9607_VDDCX_AO] =    &mdm9607_vddcx_ao,
-       [MDM9607_VDDCX_VFL] =   &mdm9607_vddcx_vfl,
-       [MDM9607_VDDMX] =       &mdm9607_vddmx,
-       [MDM9607_VDDMX_AO] =    &mdm9607_vddmx_ao,
-       [MDM9607_VDDMX_VFL] =   &mdm9607_vddmx_vfl,
+       [MDM9607_VDDCX] =       &cx_s3a_lvl,
+       [MDM9607_VDDCX_AO] =    &cx_s3a_lvl_ao,
+       [MDM9607_VDDCX_VFL] =   &cx_s3a_vfl,
+       [MDM9607_VDDMX] =       &mx_l12a_lvl,
+       [MDM9607_VDDMX_AO] =    &mx_l12a_lvl_ao,
+       [MDM9607_VDDMX_VFL] =   &mx_l12a_vfl,
 };
 
 static const struct rpmpd_desc mdm9607_desc = {
@@ -139,14 +529,10 @@ static const struct rpmpd_desc mdm9607_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO,
 };
 
-/* msm8226 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8226, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_VFC(msm8226, vddcx_vfc, SMPA, 1);
-
 static struct rpmpd *msm8226_rpmpds[] = {
-       [MSM8226_VDDCX] =       &msm8226_vddcx,
-       [MSM8226_VDDCX_AO] =    &msm8226_vddcx_ao,
-       [MSM8226_VDDCX_VFC] =   &msm8226_vddcx_vfc,
+       [MSM8226_VDDCX] =       &cx_s1a_corner,
+       [MSM8226_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8226_VDDCX_VFC] =   &cx_s1a_vfc,
 };
 
 static const struct rpmpd_desc msm8226_desc = {
@@ -155,24 +541,15 @@ static const struct rpmpd_desc msm8226_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8939 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8939, vddmd, vddmd_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_VFC(msm8939, vddmd_vfc, SMPA, 1);
-
-DEFINE_RPMPD_PAIR(msm8939, vddcx, vddcx_ao, SMPA, CORNER, 2);
-DEFINE_RPMPD_VFC(msm8939, vddcx_vfc, SMPA, 2);
-
-DEFINE_RPMPD_PAIR(msm8939, vddmx, vddmx_ao, LDOA, CORNER, 3);
-
 static struct rpmpd *msm8939_rpmpds[] = {
-       [MSM8939_VDDMDCX] =     &msm8939_vddmd,
-       [MSM8939_VDDMDCX_AO] =  &msm8939_vddmd_ao,
-       [MSM8939_VDDMDCX_VFC] = &msm8939_vddmd_vfc,
-       [MSM8939_VDDCX] =       &msm8939_vddcx,
-       [MSM8939_VDDCX_AO] =    &msm8939_vddcx_ao,
-       [MSM8939_VDDCX_VFC] =   &msm8939_vddcx_vfc,
-       [MSM8939_VDDMX] =       &msm8939_vddmx,
-       [MSM8939_VDDMX_AO] =    &msm8939_vddmx_ao,
+       [MSM8939_VDDMDCX] =     &md_s1a_corner,
+       [MSM8939_VDDMDCX_AO] =  &md_s1a_corner_ao,
+       [MSM8939_VDDMDCX_VFC] = &md_s1a_vfc,
+       [MSM8939_VDDCX] =       &cx_s2a_corner,
+       [MSM8939_VDDCX_AO] =    &cx_s2a_corner_ao,
+       [MSM8939_VDDCX_VFC] =   &cx_s2a_vfc,
+       [MSM8939_VDDMX] =       &mx_l3a_corner,
+       [MSM8939_VDDMX_AO] =    &mx_l3a_corner_ao,
 };
 
 static const struct rpmpd_desc msm8939_desc = {
@@ -181,18 +558,12 @@ static const struct rpmpd_desc msm8939_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8916 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3);
-
-DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1);
-
 static struct rpmpd *msm8916_rpmpds[] = {
-       [MSM8916_VDDCX] =       &msm8916_vddcx,
-       [MSM8916_VDDCX_AO] =    &msm8916_vddcx_ao,
-       [MSM8916_VDDCX_VFC] =   &msm8916_vddcx_vfc,
-       [MSM8916_VDDMX] =       &msm8916_vddmx,
-       [MSM8916_VDDMX_AO] =    &msm8916_vddmx_ao,
+       [MSM8916_VDDCX] =       &cx_s1a_corner,
+       [MSM8916_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8916_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8916_VDDMX] =       &mx_l3a_corner,
+       [MSM8916_VDDMX_AO] =    &mx_l3a_corner_ao,
 };
 
 static const struct rpmpd_desc msm8916_desc = {
@@ -201,21 +572,14 @@ static const struct rpmpd_desc msm8916_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8953 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8953, vddmd, vddmd_ao, SMPA, LEVEL, 1);
-DEFINE_RPMPD_PAIR(msm8953, vddcx, vddcx_ao, SMPA, LEVEL, 2);
-DEFINE_RPMPD_PAIR(msm8953, vddmx, vddmx_ao, SMPA, LEVEL, 7);
-
-DEFINE_RPMPD_VFL(msm8953, vddcx_vfl, SMPA, 2);
-
 static struct rpmpd *msm8953_rpmpds[] = {
-       [MSM8953_VDDMD] =       &msm8953_vddmd,
-       [MSM8953_VDDMD_AO] =    &msm8953_vddmd_ao,
-       [MSM8953_VDDCX] =       &msm8953_vddcx,
-       [MSM8953_VDDCX_AO] =    &msm8953_vddcx_ao,
-       [MSM8953_VDDCX_VFL] =   &msm8953_vddcx_vfl,
-       [MSM8953_VDDMX] =       &msm8953_vddmx,
-       [MSM8953_VDDMX_AO] =    &msm8953_vddmx_ao,
+       [MSM8953_VDDMD] =       &md_s1a_lvl,
+       [MSM8953_VDDMD_AO] =    &md_s1a_lvl_ao,
+       [MSM8953_VDDCX] =       &cx_s2a_lvl,
+       [MSM8953_VDDCX_AO] =    &cx_s2a_lvl_ao,
+       [MSM8953_VDDCX_VFL] =   &cx_s2a_vfl,
+       [MSM8953_VDDMX] =       &mx_s7a_lvl,
+       [MSM8953_VDDMX_AO] =    &mx_s7a_lvl_ao,
 };
 
 static const struct rpmpd_desc msm8953_desc = {
@@ -224,20 +588,13 @@ static const struct rpmpd_desc msm8953_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO,
 };
 
-/* msm8976 RPM Power Domains */
-DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2);
-DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6);
-
-DEFINE_RPMPD_VFL(msm8976, vddcx_vfl, RWSC, 2);
-DEFINE_RPMPD_VFL(msm8976, vddmx_vfl, RWSM, 6);
-
 static struct rpmpd *msm8976_rpmpds[] = {
-       [MSM8976_VDDCX] =       &msm8976_vddcx,
-       [MSM8976_VDDCX_AO] =    &msm8976_vddcx_ao,
-       [MSM8976_VDDCX_VFL] =   &msm8976_vddcx_vfl,
-       [MSM8976_VDDMX] =       &msm8976_vddmx,
-       [MSM8976_VDDMX_AO] =    &msm8976_vddmx_ao,
-       [MSM8976_VDDMX_VFL] =   &msm8976_vddmx_vfl,
+       [MSM8976_VDDCX] =       &cx_s2a_lvl,
+       [MSM8976_VDDCX_AO] =    &cx_s2a_lvl_ao,
+       [MSM8976_VDDCX_VFL] =   &cx_rwsc2_vfl,
+       [MSM8976_VDDMX] =       &mx_s6a_lvl,
+       [MSM8976_VDDMX_AO] =    &mx_s6a_lvl_ao,
+       [MSM8976_VDDMX_VFL] =   &mx_rwsm6_vfl,
 };
 
 static const struct rpmpd_desc msm8976_desc = {
@@ -246,23 +603,16 @@ static const struct rpmpd_desc msm8976_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO_HIGH,
 };
 
-/* msm8994 RPM Power domains */
-DEFINE_RPMPD_PAIR(msm8994, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_PAIR(msm8994, vddmx, vddmx_ao, SMPA, CORNER, 2);
-/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
-DEFINE_RPMPD_CORNER(msm8994, vddgfx, SMPB, 2);
-
-DEFINE_RPMPD_VFC(msm8994, vddcx_vfc, SMPA, 1);
-DEFINE_RPMPD_VFC(msm8994, vddgfx_vfc, SMPB, 2);
-
 static struct rpmpd *msm8994_rpmpds[] = {
-       [MSM8994_VDDCX] =       &msm8994_vddcx,
-       [MSM8994_VDDCX_AO] =    &msm8994_vddcx_ao,
-       [MSM8994_VDDCX_VFC] =   &msm8994_vddcx_vfc,
-       [MSM8994_VDDMX] =       &msm8994_vddmx,
-       [MSM8994_VDDMX_AO] =    &msm8994_vddmx_ao,
-       [MSM8994_VDDGFX] =      &msm8994_vddgfx,
-       [MSM8994_VDDGFX_VFC] =  &msm8994_vddgfx_vfc,
+       [MSM8994_VDDCX] =       &cx_s1a_corner,
+       [MSM8994_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8994_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8994_VDDMX] =       &mx_s2a_corner,
+       [MSM8994_VDDMX_AO] =    &mx_s2a_corner_ao,
+
+       /* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
+       [MSM8994_VDDGFX] =      &gfx_s2b_corner,
+       [MSM8994_VDDGFX_VFC] =  &gfx_s2b_vfc,
 };
 
 static const struct rpmpd_desc msm8994_desc = {
@@ -271,22 +621,14 @@ static const struct rpmpd_desc msm8994_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8996 RPM Power domains */
-DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1);
-DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2);
-DEFINE_RPMPD_CORNER(msm8996, vddsscx, LDOA, 26);
-
-DEFINE_RPMPD_VFC(msm8996, vddcx_vfc, SMPA, 1);
-DEFINE_RPMPD_VFC(msm8996, vddsscx_vfc, LDOA, 26);
-
 static struct rpmpd *msm8996_rpmpds[] = {
-       [MSM8996_VDDCX] =       &msm8996_vddcx,
-       [MSM8996_VDDCX_AO] =    &msm8996_vddcx_ao,
-       [MSM8996_VDDCX_VFC] =   &msm8996_vddcx_vfc,
-       [MSM8996_VDDMX] =       &msm8996_vddmx,
-       [MSM8996_VDDMX_AO] =    &msm8996_vddmx_ao,
-       [MSM8996_VDDSSCX] =     &msm8996_vddsscx,
-       [MSM8996_VDDSSCX_VFC] = &msm8996_vddsscx_vfc,
+       [MSM8996_VDDCX] =       &cx_s1a_corner,
+       [MSM8996_VDDCX_AO] =    &cx_s1a_corner_ao,
+       [MSM8996_VDDCX_VFC] =   &cx_s1a_vfc,
+       [MSM8996_VDDMX] =       &mx_s2a_corner,
+       [MSM8996_VDDMX_AO] =    &mx_s2a_corner_ao,
+       [MSM8996_VDDSSCX] =     &ssc_cx_l26a_corner,
+       [MSM8996_VDDSSCX_VFC] = &ssc_cx_l26a_vfc,
 };
 
 static const struct rpmpd_desc msm8996_desc = {
@@ -295,30 +637,17 @@ static const struct rpmpd_desc msm8996_desc = {
        .max_state = MAX_CORNER_RPMPD_STATE,
 };
 
-/* msm8998 RPM Power domains */
-DEFINE_RPMPD_PAIR(msm8998, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(msm8998, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(msm8998, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(msm8998, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(msm8998, vdd_ssccx, RWSC, 0);
-DEFINE_RPMPD_VFL(msm8998, vdd_ssccx_vfl, RWSC, 0);
-
-DEFINE_RPMPD_LEVEL(msm8998, vdd_sscmx, RWSM, 0);
-DEFINE_RPMPD_VFL(msm8998, vdd_sscmx_vfl, RWSM, 0);
-
 static struct rpmpd *msm8998_rpmpds[] = {
-       [MSM8998_VDDCX] =               &msm8998_vddcx,
-       [MSM8998_VDDCX_AO] =            &msm8998_vddcx_ao,
-       [MSM8998_VDDCX_VFL] =           &msm8998_vddcx_vfl,
-       [MSM8998_VDDMX] =               &msm8998_vddmx,
-       [MSM8998_VDDMX_AO] =            &msm8998_vddmx_ao,
-       [MSM8998_VDDMX_VFL] =           &msm8998_vddmx_vfl,
-       [MSM8998_SSCCX] =               &msm8998_vdd_ssccx,
-       [MSM8998_SSCCX_VFL] =           &msm8998_vdd_ssccx_vfl,
-       [MSM8998_SSCMX] =               &msm8998_vdd_sscmx,
-       [MSM8998_SSCMX_VFL] =           &msm8998_vdd_sscmx_vfl,
+       [MSM8998_VDDCX] =       &cx_rwcx0_lvl,
+       [MSM8998_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
+       [MSM8998_VDDCX_VFL] =   &cx_rwcx0_vfl,
+       [MSM8998_VDDMX] =       &mx_rwmx0_lvl,
+       [MSM8998_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
+       [MSM8998_VDDMX_VFL] =   &mx_rwmx0_vfl,
+       [MSM8998_SSCCX] =       &ssc_cx_rwsc0_lvl,
+       [MSM8998_SSCCX_VFL] =   &ssc_cx_rwsc0_vfl,
+       [MSM8998_SSCMX] =       &ssc_mx_rwsm0_lvl,
+       [MSM8998_SSCMX_VFL] =   &ssc_mx_rwsm0_vfl,
 };
 
 static const struct rpmpd_desc msm8998_desc = {
@@ -327,24 +656,14 @@ static const struct rpmpd_desc msm8998_desc = {
        .max_state = RPM_SMD_LEVEL_BINNING,
 };
 
-/* qcs404 RPM Power domains */
-DEFINE_RPMPD_PAIR(qcs404, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(qcs404, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(qcs404, vdd_lpicx, RWLC, 0);
-DEFINE_RPMPD_VFL(qcs404, vdd_lpicx_vfl, RWLC, 0);
-
-DEFINE_RPMPD_LEVEL(qcs404, vdd_lpimx, RWLM, 0);
-DEFINE_RPMPD_VFL(qcs404, vdd_lpimx_vfl, RWLM, 0);
-
 static struct rpmpd *qcs404_rpmpds[] = {
-       [QCS404_VDDMX] = &qcs404_vddmx,
-       [QCS404_VDDMX_AO] = &qcs404_vddmx_ao,
-       [QCS404_VDDMX_VFL] = &qcs404_vddmx_vfl,
-       [QCS404_LPICX] = &qcs404_vdd_lpicx,
-       [QCS404_LPICX_VFL] = &qcs404_vdd_lpicx_vfl,
-       [QCS404_LPIMX] = &qcs404_vdd_lpimx,
-       [QCS404_LPIMX_VFL] = &qcs404_vdd_lpimx_vfl,
+       [QCS404_VDDMX] =        &mx_rwmx0_lvl,
+       [QCS404_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [QCS404_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [QCS404_LPICX] =        &lpi_cx_rwlc0_lvl,
+       [QCS404_LPICX_VFL] =    &lpi_cx_rwlc0_vfl,
+       [QCS404_LPIMX] =        &lpi_mx_rwlm0_lvl,
+       [QCS404_LPIMX_VFL] =    &lpi_mx_rwlm0_vfl,
 };
 
 static const struct rpmpd_desc qcs404_desc = {
@@ -353,30 +672,17 @@ static const struct rpmpd_desc qcs404_desc = {
        .max_state = RPM_SMD_LEVEL_BINNING,
 };
 
-/* sdm660 RPM Power domains */
-DEFINE_RPMPD_PAIR(sdm660, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sdm660, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(sdm660, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sdm660, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(sdm660, vdd_ssccx, RWLC, 0);
-DEFINE_RPMPD_VFL(sdm660, vdd_ssccx_vfl, RWLC, 0);
-
-DEFINE_RPMPD_LEVEL(sdm660, vdd_sscmx, RWLM, 0);
-DEFINE_RPMPD_VFL(sdm660, vdd_sscmx_vfl, RWLM, 0);
-
 static struct rpmpd *sdm660_rpmpds[] = {
-       [SDM660_VDDCX] =                &sdm660_vddcx,
-       [SDM660_VDDCX_AO] =             &sdm660_vddcx_ao,
-       [SDM660_VDDCX_VFL] =            &sdm660_vddcx_vfl,
-       [SDM660_VDDMX] =                &sdm660_vddmx,
-       [SDM660_VDDMX_AO] =             &sdm660_vddmx_ao,
-       [SDM660_VDDMX_VFL] =            &sdm660_vddmx_vfl,
-       [SDM660_SSCCX] =                &sdm660_vdd_ssccx,
-       [SDM660_SSCCX_VFL] =            &sdm660_vdd_ssccx_vfl,
-       [SDM660_SSCMX] =                &sdm660_vdd_sscmx,
-       [SDM660_SSCMX_VFL] =            &sdm660_vdd_sscmx_vfl,
+       [SDM660_VDDCX] =        &cx_rwcx0_lvl,
+       [SDM660_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SDM660_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SDM660_VDDMX] =        &mx_rwmx0_lvl,
+       [SDM660_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SDM660_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SDM660_SSCCX] =        &ssc_cx_rwlc0_lvl,
+       [SDM660_SSCCX_VFL] =    &ssc_cx_rwlc0_vfl,
+       [SDM660_SSCMX] =        &ssc_mx_rwlm0_lvl,
+       [SDM660_SSCMX_VFL] =    &ssc_mx_rwlm0_vfl,
 };
 
 static const struct rpmpd_desc sdm660_desc = {
@@ -385,25 +691,15 @@ static const struct rpmpd_desc sdm660_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO,
 };
 
-/* sm4250/6115 RPM Power domains */
-DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
-
-DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
-DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
-
 static struct rpmpd *sm6115_rpmpds[] = {
-       [SM6115_VDDCX] =                &sm6115_vddcx,
-       [SM6115_VDDCX_AO] =             &sm6115_vddcx_ao,
-       [SM6115_VDDCX_VFL] =            &sm6115_vddcx_vfl,
-       [SM6115_VDDMX] =                &sm6115_vddmx,
-       [SM6115_VDDMX_AO] =             &sm6115_vddmx_ao,
-       [SM6115_VDDMX_VFL] =            &sm6115_vddmx_vfl,
-       [SM6115_VDD_LPI_CX] =           &sm6115_vdd_lpi_cx,
-       [SM6115_VDD_LPI_MX] =           &sm6115_vdd_lpi_mx,
+       [SM6115_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6115_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6115_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6115_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6115_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6115_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SM6115_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
+       [SM6115_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
 };
 
 static const struct rpmpd_desc sm6115_desc = {
@@ -412,20 +708,13 @@ static const struct rpmpd_desc sm6115_desc = {
        .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
 };
 
-/* sm6125 RPM Power domains */
-DEFINE_RPMPD_PAIR(sm6125, vddcx, vddcx_ao, RWCX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6125, vddcx_vfl, RWCX, 0);
-
-DEFINE_RPMPD_PAIR(sm6125, vddmx, vddmx_ao, RWMX, LEVEL, 0);
-DEFINE_RPMPD_VFL(sm6125, vddmx_vfl, RWMX, 0);
-
 static struct rpmpd *sm6125_rpmpds[] = {
-       [SM6125_VDDCX] =                &sm6125_vddcx,
-       [SM6125_VDDCX_AO] =             &sm6125_vddcx_ao,
-       [SM6125_VDDCX_VFL] =            &sm6125_vddcx_vfl,
-       [SM6125_VDDMX] =                &sm6125_vddmx,
-       [SM6125_VDDMX_AO] =             &sm6125_vddmx_ao,
-       [SM6125_VDDMX_VFL] =            &sm6125_vddmx_vfl,
+       [SM6125_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6125_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6125_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6125_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6125_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6125_VDDMX_VFL] =    &mx_rwmx0_vfl,
 };
 
 static const struct rpmpd_desc sm6125_desc = {
@@ -434,18 +723,17 @@ static const struct rpmpd_desc sm6125_desc = {
        .max_state = RPM_SMD_LEVEL_BINNING,
 };
 
-DEFINE_RPMPD_PAIR(sm6375, vddgx, vddgx_ao, RWGX, LEVEL, 0);
 static struct rpmpd *sm6375_rpmpds[] = {
-       [SM6375_VDDCX] = &sm6125_vddcx,
-       [SM6375_VDDCX_AO] = &sm6125_vddcx_ao,
-       [SM6375_VDDCX_VFL] = &sm6125_vddcx_vfl,
-       [SM6375_VDDMX] = &sm6125_vddmx,
-       [SM6375_VDDMX_AO] = &sm6125_vddmx_ao,
-       [SM6375_VDDMX_VFL] = &sm6125_vddmx_vfl,
-       [SM6375_VDDGX] = &sm6375_vddgx,
-       [SM6375_VDDGX_AO] = &sm6375_vddgx_ao,
-       [SM6375_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
-       [SM6375_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
+       [SM6375_VDDCX] =        &cx_rwcx0_lvl,
+       [SM6375_VDDCX_AO] =     &cx_rwcx0_lvl_ao,
+       [SM6375_VDDCX_VFL] =    &cx_rwcx0_vfl,
+       [SM6375_VDDMX] =        &mx_rwmx0_lvl,
+       [SM6375_VDDMX_AO] =     &mx_rwmx0_lvl_ao,
+       [SM6375_VDDMX_VFL] =    &mx_rwmx0_vfl,
+       [SM6375_VDDGX] =        &gx_rwgx0_lvl,
+       [SM6375_VDDGX_AO] =     &gx_rwgx0_lvl_ao,
+       [SM6375_VDD_LPI_CX] =   &lpi_cx_rwlc0_lvl,
+       [SM6375_VDD_LPI_MX] =   &lpi_mx_rwlm0_lvl,
 };
 
 static const struct rpmpd_desc sm6375_desc = {
@@ -455,14 +743,14 @@ static const struct rpmpd_desc sm6375_desc = {
 };
 
 static struct rpmpd *qcm2290_rpmpds[] = {
-       [QCM2290_VDDCX] = &sm6115_vddcx,
-       [QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
-       [QCM2290_VDDCX_VFL] = &sm6115_vddcx_vfl,
-       [QCM2290_VDDMX] = &sm6115_vddmx,
-       [QCM2290_VDDMX_AO] = &sm6115_vddmx_ao,
-       [QCM2290_VDDMX_VFL] = &sm6115_vddmx_vfl,
-       [QCM2290_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
-       [QCM2290_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
+       [QCM2290_VDDCX] =       &cx_rwcx0_lvl,
+       [QCM2290_VDDCX_AO] =    &cx_rwcx0_lvl_ao,
+       [QCM2290_VDDCX_VFL] =   &cx_rwcx0_vfl,
+       [QCM2290_VDDMX] =       &mx_rwmx0_lvl,
+       [QCM2290_VDDMX_AO] =    &mx_rwmx0_lvl_ao,
+       [QCM2290_VDDMX_VFL] =   &mx_rwmx0_vfl,
+       [QCM2290_VDD_LPI_CX] =  &lpi_cx_rwlc0_lvl,
+       [QCM2290_VDD_LPI_MX] =  &lpi_mx_rwlm0_lvl,
 };
 
 static const struct rpmpd_desc qcm2290_desc = {
@@ -673,6 +961,15 @@ static int rpmpd_probe(struct platform_device *pdev)
                data->domains[i] = &rpmpds[i]->pd;
        }
 
+       /* Add subdomains */
+       for (i = 0; i < num; i++) {
+               if (!rpmpds[i])
+                       continue;
+
+               if (rpmpds[i]->parent)
+                       pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
+       }
+
        return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
 }
 
index 523627d5d3981424adf9d53ed4251f6d3f3d8e91..0c1aa809cc4e3af206fa7cd639139b8450bbcb27 100644 (file)
@@ -113,7 +113,7 @@ int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
        if (WARN_ON(size >= 256))
                return -EINVAL;
 
-       pkt = kmalloc(size, GFP_KERNEL);
+       pkt = kmalloc(size, GFP_ATOMIC);
        if (!pkt)
                return -ENOMEM;
 
index 4f163d62942c1aa580bb54786a6430aa55f6b3f6..6be7ea93c78cfe01777df0fb6f558f90a8f933d8 100644 (file)
@@ -85,7 +85,7 @@
 #define SMEM_GLOBAL_HOST       0xfffe
 
 /* Max number of processors/hosts in a system */
-#define SMEM_HOST_COUNT                15
+#define SMEM_HOST_COUNT                20
 
 /**
   * struct smem_proc_comm - proc_comm communication struct (legacy)
@@ -1045,7 +1045,7 @@ static int qcom_smem_probe(struct platform_device *pdev)
        int i;
 
        num_regions = 1;
-       if (of_find_property(pdev->dev.of_node, "qcom,rpm-msg-ram", NULL))
+       if (of_property_present(pdev->dev.of_node, "qcom,rpm-msg-ram"))
                num_regions++;
 
        array_size = num_regions * sizeof(struct smem_region);
index 3e8994d6110e68ddaa1fcc4a59c8eb4f0b7c62de..c58cfff64856e2b8f27af204ab971820429818cb 100644 (file)
@@ -452,11 +452,10 @@ static int smsm_get_size_info(struct qcom_smsm *smsm)
        } *info;
 
        info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SIZE_INFO, &size);
-       if (IS_ERR(info) && PTR_ERR(info) != -ENOENT) {
-               if (PTR_ERR(info) != -EPROBE_DEFER)
-                       dev_err(smsm->dev, "unable to retrieve smsm size info\n");
-               return PTR_ERR(info);
-       } else if (IS_ERR(info) || size != sizeof(*info)) {
+       if (IS_ERR(info) && PTR_ERR(info) != -ENOENT)
+               return dev_err_probe(smsm->dev, PTR_ERR(info),
+                                    "unable to retrieve smsm size info\n");
+       else if (IS_ERR(info) || size != sizeof(*info)) {
                dev_warn(smsm->dev, "no smsm size info, using defaults\n");
                smsm->num_entries = SMSM_DEFAULT_NUM_ENTRIES;
                smsm->num_hosts = SMSM_DEFAULT_NUM_HOSTS;
@@ -510,7 +509,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        for_each_child_of_node(pdev->dev.of_node, local_node) {
-               if (of_find_property(local_node, "#qcom,smem-state-cells", NULL))
+               if (of_property_present(local_node, "#qcom,smem-state-cells"))
                        break;
        }
        if (!local_node) {
index e9012ca1a87b0ead74bbbd3686a07c1391683a42..c2e4a57dd6665c7f9736f4762e1519c9b2da5222 100644 (file)
@@ -109,15 +109,20 @@ static const char *const pmic_models[] = {
        [32] = "PM8150B",
        [33] = "PMK8002",
        [36] = "PM8009",
+       [37] = "PMI632",
        [38] = "PM8150C",
+       [40] = "PM6150",
        [41] = "SMB2351",
+       [44] = "PM8008",
        [45] = "PM6125",
+       [46] = "PM7250B",
        [47] = "PMK8350",
        [48] = "PM8350",
        [49] = "PM8350C",
        [50] = "PM8350B",
        [51] = "PMR735A",
        [52] = "PMR735B",
+       [55] = "PM2250",
        [58] = "PM8450",
        [65] = "PM8010",
 };
@@ -405,6 +410,7 @@ static const struct soc_id soc_id[] = {
        { qcom_board_id(SA8155) },
        { qcom_board_id(SDA439) },
        { qcom_board_id(SDA429) },
+       { qcom_board_id(SM7150) },
        { qcom_board_id(IPQ8070) },
        { qcom_board_id(IPQ8071) },
        { qcom_board_id(QM215) },
@@ -426,6 +432,7 @@ static const struct soc_id soc_id[] = {
        { qcom_board_id(QCM2150) },
        { qcom_board_id(SDA429W) },
        { qcom_board_id(SM8350) },
+       { qcom_board_id(QCM2290) },
        { qcom_board_id(SM6115) },
        { qcom_board_id(SC8280XP) },
        { qcom_board_id(IPQ6005) },
@@ -441,7 +448,16 @@ static const struct soc_id soc_id[] = {
        { qcom_board_id(SC7280) },
        { qcom_board_id(SC7180P) },
        { qcom_board_id(SM6375) },
+       { qcom_board_id(IPQ9514) },
+       { qcom_board_id(IPQ9550) },
+       { qcom_board_id(IPQ9554) },
+       { qcom_board_id(IPQ9570) },
+       { qcom_board_id(IPQ9574) },
        { qcom_board_id(SM8550) },
+       { qcom_board_id(IPQ9510) },
+       { qcom_board_id(QRB4210) },
+       { qcom_board_id(QRB2210) },
+       { qcom_board_id(SA8775P) },
        { qcom_board_id(QRU1000) },
        { qcom_board_id(QDU1000) },
        { qcom_board_id(QDU1010) },
index 4e8b51ba226614ef1a1e91b47c8a4d249ceff9ac..de31589ed05404a83771d020c0ace184c66efc29 100644 (file)
@@ -206,13 +206,6 @@ config ARCH_R8A77990
          This enables support for the Renesas R-Car E3 SoC.
          This includes different gradings like R-Car E3e.
 
-config ARCH_R8A77950
-       bool "ARM64 Platform support for R-Car H3 ES1.x"
-       select ARCH_RCAR_GEN3
-       select SYSC_R8A7795
-       help
-         This enables support for the Renesas R-Car H3 SoC (revision 1.x).
-
 config ARCH_R8A77951
        bool "ARM64 Platform support for R-Car H3 ES2.0+"
        select ARCH_RCAR_GEN3
index c83bdbdabb64dfe1ac3406b1ef1bf6e9e811e9ce..452cee8d68bee7d04e7acbee6bd90dab457c77c3 100644 (file)
@@ -131,7 +131,7 @@ static struct platform_driver rzv2m_pwc_driver = {
        .probe = rzv2m_pwc_probe,
        .driver = {
                .name = "rzv2m_pwc",
-               .of_match_table = of_match_ptr(rzv2m_pwc_of_match),
+               .of_match_table = rzv2m_pwc_of_match,
        },
 };
 module_platform_driver(rzv2m_pwc_driver);
index 91074411b8cfe48f555ec22ccf36bacbb95ca54b..cbe1ff0fc58393e4d9d6e0ed6030c13119755540 100644 (file)
@@ -38,8 +38,6 @@ static struct rcar_sysc_area r8a7795_areas[] __initdata = {
        { "a3vp",       0x340, 0, R8A7795_PD_A3VP,      R8A7795_PD_ALWAYS_ON },
        { "cr7",        0x240, 0, R8A7795_PD_CR7,       R8A7795_PD_ALWAYS_ON },
        { "a3vc",       0x380, 0, R8A7795_PD_A3VC,      R8A7795_PD_ALWAYS_ON },
-       /* A2VC0 exists on ES1.x only */
-       { "a2vc0",      0x3c0, 0, R8A7795_PD_A2VC0,     R8A7795_PD_A3VC },
        { "a2vc1",      0x3c0, 1, R8A7795_PD_A2VC1,     R8A7795_PD_A3VC },
        { "3dg-a",      0x100, 0, R8A7795_PD_3DG_A,     R8A7795_PD_ALWAYS_ON },
        { "3dg-b",      0x100, 1, R8A7795_PD_3DG_B,     R8A7795_PD_3DG_A },
@@ -54,14 +52,10 @@ static struct rcar_sysc_area r8a7795_areas[] __initdata = {
         * Fixups for R-Car H3 revisions
         */
 
-#define HAS_A2VC0      BIT(0)          /* Power domain A2VC0 is present */
 #define NO_EXTMASK     BIT(1)          /* Missing SYSCEXTMASK register */
 
 static const struct soc_device_attribute r8a7795_quirks_match[] __initconst = {
        {
-               .soc_id = "r8a7795", .revision = "ES1.*",
-               .data = (void *)(HAS_A2VC0 | NO_EXTMASK),
-       }, {
                .soc_id = "r8a7795", .revision = "ES2.*",
                .data = (void *)(NO_EXTMASK),
        },
@@ -77,10 +71,6 @@ static int __init r8a7795_sysc_init(void)
        if (attr)
                quirks = (uintptr_t)attr->data;
 
-       if (!(quirks & HAS_A2VC0))
-               rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
-                                 R8A7795_PD_A2VC0);
-
        if (quirks & NO_EXTMASK)
                r8a7795_sysc_info.extmask_val = 0;
 
index 468ebce1ea88bf61ed364e173279da63ae0dbde0..42af7c09f743340626fc43d7116f5ec890b00fb4 100644 (file)
@@ -269,7 +269,7 @@ static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
 };
 
 
-static const struct of_device_id renesas_socs[] __initconst = {
+static const struct of_device_id renesas_socs[] __initconst __maybe_unused = {
 #ifdef CONFIG_ARCH_R7S72100
        { .compatible = "renesas,r7s72100",     .data = &soc_rz_a1h },
 #endif
@@ -330,10 +330,8 @@ static const struct of_device_id renesas_socs[] __initconst = {
 #ifdef CONFIG_ARCH_R8A7794
        { .compatible = "renesas,r8a7794",      .data = &soc_rcar_e2 },
 #endif
-#if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951)
-       { .compatible = "renesas,r8a7795",      .data = &soc_rcar_h3 },
-#endif
 #ifdef CONFIG_ARCH_R8A77951
+       { .compatible = "renesas,r8a7795",      .data = &soc_rcar_h3 },
        { .compatible = "renesas,r8a779m0",     .data = &soc_rcar_h3 },
        { .compatible = "renesas,r8a779m1",     .data = &soc_rcar_h3 },
        { .compatible = "renesas,r8a779m8",     .data = &soc_rcar_h3 },
@@ -375,20 +373,20 @@ static const struct of_device_id renesas_socs[] __initconst = {
 #ifdef CONFIG_ARCH_R8A779G0
        { .compatible = "renesas,r8a779g0",     .data = &soc_rcar_v4h },
 #endif
-#if defined(CONFIG_ARCH_R9A07G043)
+#ifdef CONFIG_ARCH_R9A07G043
 #ifdef CONFIG_RISCV
        { .compatible = "renesas,r9a07g043",    .data = &soc_rz_five },
 #else
        { .compatible = "renesas,r9a07g043",    .data = &soc_rz_g2ul },
 #endif
 #endif
-#if defined(CONFIG_ARCH_R9A07G044)
+#ifdef CONFIG_ARCH_R9A07G044
        { .compatible = "renesas,r9a07g044",    .data = &soc_rz_g2l },
 #endif
-#if defined(CONFIG_ARCH_R9A07G054)
+#ifdef CONFIG_ARCH_R9A07G054
        { .compatible = "renesas,r9a07g054",    .data = &soc_rz_v2l },
 #endif
-#if defined(CONFIG_ARCH_R9A09G011)
+#ifdef CONFIG_ARCH_R9A09G011
        { .compatible = "renesas,r9a09g011",    .data = &soc_rz_v2m },
 #endif
 #ifdef CONFIG_ARCH_SH73A0
@@ -471,8 +469,11 @@ static int __init renesas_soc_init(void)
        }
 
        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-       if (!soc_dev_attr)
+       if (!soc_dev_attr) {
+               if (chipid)
+                       iounmap(chipid);
                return -ENOMEM;
+       }
 
        np = of_find_node_by_path("/");
        of_property_read_string(np, "model", &soc_dev_attr->machine);
index 204e6135180b919c240f859901d7dc23df7a63b1..728ebac98e14a5cca82555c57b353783b434c370 100644 (file)
@@ -343,7 +343,7 @@ static int __init rmobile_init_pm_domains(void)
                        break;
                }
 
-               fwnode_dev_initialized(&np->fwnode, true);
+               fwnode_dev_initialized(of_fwnode_handle(np), true);
        }
 
        put_special_pds();
index d90e4a264b6f6bfa4ada206c7a7f14bde14856a3..1734da357ca21b249740e089698275507ea98a8a 100644 (file)
@@ -82,7 +82,7 @@ static int sunxi_mbus_notifier(struct notifier_block *nb,
         * Older DTs or SoCs who are not clearly understood need to set
         * that DMA offset though.
         */
-       if (of_find_property(dev->of_node, "interconnects", NULL))
+       if (of_property_present(dev->of_node, "interconnects"))
                return NOTIFY_DONE;
 
        ret = dma_direct_set_offset(dev, PHYS_OFFSET, 0, SZ_4G);
index f09918c5904230a3e10581610f95064f36e0cad3..4c4864cd2342a4b57f7e7a5ac9d8ecdbba9d0259 100644 (file)
@@ -424,4 +424,3 @@ builtin_platform_driver_probe(sunxi_sram_driver, sunxi_sram_probe);
 
 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
 MODULE_DESCRIPTION("Allwinner sunXi SRAM Controller Driver");
-MODULE_LICENSE("GPL");
index a8566b9dd8de4f8179b25763999930d28009c0ab..bd96204a68ee3d035156ba39dae0ba8d0f9c1da7 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/version.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/tegra-cbb.h>
 
index d4112b683f00fdfa1b422a926e41100ebb7dcdb3..54d7ce05c6367da53872f72fd75e65aa69235fcc 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/version.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/tegra-cbb.h>
 
@@ -2191,7 +2190,6 @@ MODULE_DEVICE_TABLE(of, tegra194_cbb_match);
 static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node *np)
 {
        struct tegra_cbb *entry;
-       struct resource res;
        unsigned long flags;
        unsigned int i;
        int err;
@@ -2211,8 +2209,7 @@ static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node
        spin_unlock_irqrestore(&cbb_lock, flags);
 
        if (!cbb->bridges) {
-               while (of_address_to_resource(np, cbb->num_bridges, &res) == 0)
-                       cbb->num_bridges++;
+               cbb->num_bridges = of_address_count(np);
 
                cbb->bridges = devm_kcalloc(cbb->base.dev, cbb->num_bridges,
                                            sizeof(*cbb->bridges), GFP_KERNEL);
@@ -2359,4 +2356,3 @@ module_exit(tegra194_cbb_exit);
 
 MODULE_AUTHOR("Sumit Gupta <sumitg@nvidia.com>");
 MODULE_DESCRIPTION("Control Backbone error handling driver for Tegra194");
-MODULE_LICENSE("GPL");
index f33d094e5ea60c28501b960f0952b05ed5a84303..5d16161b2566ec38d39d6d0303b9ed2c500457bd 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/version.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/tegra-cbb.h>
 
@@ -1174,11 +1173,6 @@ static int tegra234_cbb_probe(struct platform_device *pdev)
        return tegra_cbb_register(&cbb->base);
 }
 
-static int tegra234_cbb_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
 static int __maybe_unused tegra234_cbb_resume_noirq(struct device *dev)
 {
        struct tegra234_cbb *cbb = dev_get_drvdata(dev);
@@ -1196,7 +1190,6 @@ static const struct dev_pm_ops tegra234_cbb_pm = {
 
 static struct platform_driver tegra234_cbb_driver = {
        .probe = tegra234_cbb_probe,
-       .remove = tegra234_cbb_remove,
        .driver = {
                .name = "tegra234-cbb",
                .of_match_table = tegra234_cbb_dt_ids,
@@ -1218,4 +1211,3 @@ static void __exit tegra234_cbb_exit(void)
 module_exit(tegra234_cbb_exit);
 
 MODULE_DESCRIPTION("Control Backbone 2.0 error handling driver for Tegra234");
-MODULE_LICENSE("GPL");
index 5db919d96aba5811f53cb94e532d57693e8374ec..221202db33130c47db456cd0fcfc29b0f7efb48b 100644 (file)
@@ -156,10 +156,8 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
 static int tegra_flowctrl_probe(struct platform_device *pdev)
 {
        void __iomem *base = tegra_flowctrl_base;
-       struct resource *res;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
+       tegra_flowctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(tegra_flowctrl_base))
                return PTR_ERR(tegra_flowctrl_base);
 
index f02953f793e9e2df6681c28aa7728cbb8a2cd1d2..d7a37f5d45270e405f04ed81b78ae5473279018e 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2013-2022, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2013-2023, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #include <linux/clk.h>
@@ -166,7 +166,7 @@ static int tegra_fuse_probe(struct platform_device *pdev)
        nvmem.nkeepout = fuse->soc->num_keepouts;
        nvmem.type = NVMEM_TYPE_OTP;
        nvmem.read_only = true;
-       nvmem.root_only = true;
+       nvmem.root_only = false;
        nvmem.reg_read = tegra_fuse_read;
        nvmem.size = fuse->soc->info->size;
        nvmem.word_size = 4;
index cf4cfbf9f7c5a691fd095e7f7184465ef6e669fb..5d17799524c901ca74ce27828e29c46ce01ac5b7 100644 (file)
@@ -3,7 +3,7 @@
  * drivers/soc/tegra/pmc.c
  *
  * Copyright (c) 2010 Google, Inc
- * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
  *
  * Author:
  *     Colin Cross <ccross@google.com>
 /* Tegra186 and later */
 #define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
 #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
+#define WAKE_AOWAKE_CNTRL_SR_CAPTURE_EN (1 << 1)
 #define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2))
 #define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2))
 #define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2))
 #define WAKE_AOWAKE_CTRL 0x4f4
 #define  WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
 
+#define SW_WAKE_ID             83 /* wake83 */
+
 /* for secure PMC */
 #define TEGRA_SMC_PMC          0xc2fffe00
 #define  TEGRA_SMC_PMC_READ    0xaa
@@ -355,6 +358,7 @@ struct tegra_pmc_soc {
        void (*setup_irq_polarity)(struct tegra_pmc *pmc,
                                   struct device_node *np,
                                   bool invert);
+       void (*set_wake_filters)(struct tegra_pmc *pmc);
        int (*irq_set_wake)(struct irq_data *data, unsigned int on);
        int (*irq_set_type)(struct irq_data *data, unsigned int type);
        int (*powergate_set)(struct tegra_pmc *pmc, unsigned int id,
@@ -2416,6 +2420,17 @@ static int tegra210_pmc_irq_set_type(struct irq_data *data, unsigned int type)
        return 0;
 }
 
+static void tegra186_pmc_set_wake_filters(struct tegra_pmc *pmc)
+{
+       u32 value;
+
+       /* SW Wake (wake83) needs SR_CAPTURE filter to be enabled */
+       value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(SW_WAKE_ID));
+       value |= WAKE_AOWAKE_CNTRL_SR_CAPTURE_EN;
+       writel(value, pmc->wake + WAKE_AOWAKE_CNTRL(SW_WAKE_ID));
+       dev_dbg(pmc->dev, "WAKE_AOWAKE_CNTRL_83 = 0x%x\n", value);
+}
+
 static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
 {
        struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
@@ -3042,6 +3057,10 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, pmc);
        tegra_pm_init_suspend();
 
+       /* Some wakes require specific filter configuration */
+       if (pmc->soc->set_wake_filters)
+               pmc->soc->set_wake_filters(pmc);
+
        return 0;
 
 cleanup_powergates:
@@ -3938,6 +3957,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
        .regs = &tegra186_pmc_regs,
        .init = tegra186_pmc_init,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .set_wake_filters = tegra186_pmc_set_wake_filters,
        .irq_set_wake = tegra186_pmc_irq_set_wake,
        .irq_set_type = tegra186_pmc_irq_set_type,
        .reset_sources = tegra186_reset_sources,
@@ -4122,6 +4142,7 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = {
        .regs = &tegra194_pmc_regs,
        .init = tegra186_pmc_init,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .set_wake_filters = tegra186_pmc_set_wake_filters,
        .irq_set_wake = tegra186_pmc_irq_set_wake,
        .irq_set_type = tegra186_pmc_irq_set_type,
        .reset_sources = tegra194_reset_sources,
@@ -4225,7 +4246,9 @@ static const char * const tegra234_reset_sources[] = {
 };
 
 static const struct tegra_wake_event tegra234_wake_events[] = {
+       TEGRA_WAKE_IRQ("pmu", 24, 209),
        TEGRA_WAKE_GPIO("power", 29, 1, TEGRA234_AON_GPIO(EE, 4)),
+       TEGRA_WAKE_GPIO("mgbe", 56, 0, TEGRA234_MAIN_GPIO(Y, 3)),
        TEGRA_WAKE_IRQ("rtc", 73, 10),
 };
 
@@ -4247,6 +4270,7 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = {
        .regs = &tegra234_pmc_regs,
        .init = tegra186_pmc_init,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .set_wake_filters = tegra186_pmc_set_wake_filters,
        .irq_set_wake = tegra186_pmc_irq_set_wake,
        .irq_set_type = tegra186_pmc_irq_set_type,
        .reset_sources = tegra234_reset_sources,
index 8eaf50d0b6af8e61944b139583f53eb3b1022a90..179ed895c2796b3516647c0024e2e2b5b681eeb3 100644 (file)
@@ -286,7 +286,7 @@ remove:
                tegra_powergate_remove(powergate);
        }
 
-       kfree(genpd->domains);
+       kfree(domains);
        return err;
 }
 
index e01e4d815230af3bccfaad03c96414480db06f3d..8f131368a758621cb6f76eb6e3d26ba7d49f28cb 100644 (file)
@@ -406,6 +406,11 @@ static int k3_dmaring_request_dual_ring(struct k3_ringacc *ringacc, int fwd_id,
 
        mutex_lock(&ringacc->req_lock);
 
+       if (!try_module_get(ringacc->dev->driver->owner)) {
+               ret = -EINVAL;
+               goto err_module_get;
+       }
+
        if (test_bit(fwd_id, ringacc->rings_inuse)) {
                ret = -EBUSY;
                goto error;
@@ -421,6 +426,8 @@ static int k3_dmaring_request_dual_ring(struct k3_ringacc *ringacc, int fwd_id,
        return 0;
 
 error:
+       module_put(ringacc->dev->driver->owner);
+err_module_get:
        mutex_unlock(&ringacc->req_lock);
        return ret;
 }
index d15764e19d968c6eba8dab9f7a4e1155c86c02e8..ad97e08a25f6924816391ee657a4cb5c408c4ba4 100644 (file)
@@ -43,6 +43,7 @@ static const struct k3_soc_id {
        { 0xBB38, "AM64X" },
        { 0xBB75, "J721S2"},
        { 0xBB7E, "AM62X" },
+       { 0xBB80, "J784S4" },
        { 0xBB8D, "AM62AX" },
 };
 
index 84afebd355befc560496837f4f06559ef5316b1e..0fbc37cd5123106c475eb605d489dff6e743e72f 100644 (file)
@@ -666,8 +666,8 @@ static int dma_init(struct device_node *cloud, struct device_node *dma_node)
        dma->rx_priority = DMA_PRIO_DEFAULT;
        dma->tx_priority = DMA_PRIO_DEFAULT;
 
-       dma->enable_all = (of_get_property(node, "ti,enable-all", NULL) != NULL);
-       dma->loopback   = (of_get_property(node, "ti,loop-back",  NULL) != NULL);
+       dma->enable_all = of_property_read_bool(node, "ti,enable-all");
+       dma->loopback   = of_property_read_bool(node, "ti,loop-back");
 
        ret = of_property_read_u32(node, "ti,rx-retry-timeout", &timeout);
        if (ret < 0) {
index fde66e28e046a4aa97897ecf3ee72c09703aaf56..3d388646ed43c359f3d2dd0f8ef538f0818a7bd2 100644 (file)
@@ -521,7 +521,7 @@ int knav_init_acc_range(struct knav_device *kdev,
 
        info->pdsp = pdsp;
        channels = range->num_queues;
-       if (of_get_property(node, "multi-queue", NULL)) {
+       if (of_property_read_bool(node, "multi-queue")) {
                range->flags |= RANGE_MULTI_QUEUE;
                channels = 1;
                if (range->queue_base & (32 - 1)) {
index 8fb76908be7044bfab5ed7bee1ba3974df442d91..0f252c2549ba3148f478412a2a0a3d740b64faf2 100644 (file)
@@ -1264,10 +1264,10 @@ static int knav_setup_queue_range(struct knav_device *kdev,
        if (range->num_irqs)
                range->flags |= RANGE_HAS_IRQ;
 
-       if (of_get_property(node, "qalloc-by-id", NULL))
+       if (of_property_read_bool(node, "qalloc-by-id"))
                range->flags |= RANGE_RESERVED;
 
-       if (of_get_property(node, "accumulator", NULL)) {
+       if (of_property_present(node, "accumulator")) {
                ret = knav_init_acc_range(kdev, node, range);
                if (ret < 0) {
                        devm_kfree(dev, range);
index 913b964374a444092623bf31b309ebf90be368f4..ecd9a8bdd7c0afe43542813d954e59a0158cdd50 100644 (file)
@@ -684,7 +684,7 @@ static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
        const char *name;
        int error;
 
-       if (!of_find_property(dev->of_node, "#power-domain-cells", NULL))
+       if (!of_property_present(dev->of_node, "#power-domain-cells"))
                return 0;
 
        of_node_put(dev->of_node);
index ce09c42eaed259df492ccc51b7d5542531435259..f04c21157904bb4a8b901f1373accb22aa540c9d 100644 (file)
@@ -527,7 +527,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
 
        ret = am33xx_pm_alloc_sram();
        if (ret)
-               return ret;
+               goto err_wkup_m3_ipc_put;
 
        ret = am33xx_pm_rtc_setup();
        if (ret)
@@ -572,13 +572,14 @@ err_pm_runtime_put:
        pm_runtime_put_sync(dev);
 err_pm_runtime_disable:
        pm_runtime_disable(dev);
-       wkup_m3_ipc_put(m3_ipc);
 err_unsetup_rtc:
        iounmap(rtc_base_virt);
        clk_put(rtc_fck);
 err_free_sram:
        am33xx_pm_free_sram();
        pm33xx_dev = NULL;
+err_wkup_m3_ipc_put:
+       wkup_m3_ipc_put(m3_ipc);
        return ret;
 }
 
index 9d9496e0a94c9e59635a8d435fe02a6ebadf095c..da7898239a46ae238b7038551f6573f5ab0ac8f3 100644 (file)
@@ -937,21 +937,8 @@ err_list_del:
 
 static int omap_sr_remove(struct platform_device *pdev)
 {
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
        struct device *dev = &pdev->dev;
-       struct omap_sr *sr_info;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               return -EINVAL;
-       }
-
-       sr_info = _sr_lookup(pdata->voltdm);
-       if (IS_ERR(sr_info)) {
-               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
-                       __func__);
-               return PTR_ERR(sr_info);
-       }
+       struct omap_sr *sr_info = platform_get_drvdata(pdev);
 
        if (sr_info->autocomp_active)
                sr_stop_vddautocomp(sr_info);
@@ -965,20 +952,7 @@ static int omap_sr_remove(struct platform_device *pdev)
 
 static void omap_sr_shutdown(struct platform_device *pdev)
 {
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
-       struct omap_sr *sr_info;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               return;
-       }
-
-       sr_info = _sr_lookup(pdata->voltdm);
-       if (IS_ERR(sr_info)) {
-               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
-                       __func__);
-               return;
-       }
+       struct omap_sr *sr_info = platform_get_drvdata(pdev);
 
        if (sr_info->autocomp_active)
                sr_stop_vddautocomp(sr_info);
index 343c58ed58961044e03d304eeb5596a4a40bac8d..c9197912ec249dfe8acf65421725153f121b858e 100644 (file)
@@ -615,7 +615,6 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
        int irq, ret, temp;
        phandle rproc_phandle;
        struct rproc *m3_rproc;
-       struct resource *res;
        struct task_struct *task;
        struct wkup_m3_ipc *m3_ipc;
        struct device_node *np = dev->of_node;
@@ -624,8 +623,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
        if (!m3_ipc)
                return -ENOMEM;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       m3_ipc->ipc_mem_base = devm_ioremap_resource(dev, res);
+       m3_ipc->ipc_mem_base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(m3_ipc->ipc_mem_base))
                return PTR_ERR(m3_ipc->ipc_mem_base);
 
@@ -681,7 +679,7 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
                        dev_warn(dev, "Invalid VTT GPIO(%d) pin\n", temp);
        }
 
-       if (of_find_property(np, "ti,set-io-isolation", NULL))
+       if (of_property_read_bool(np, "ti,set-io-isolation"))
                wkup_m3_set_io_isolation(m3_ipc);
 
        ret = of_property_read_string(np, "firmware-name",
index bd87d3c92dd335f03c49a7f40b234c61f9cff579..69347b6bf60cdbd44a5e5a9bac8efa66cac0c0a3 100644 (file)
@@ -632,7 +632,7 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(dev, "Failed to request irq\n");
 
-               return ret;
+               goto err_irq;
        }
 
        ret = rockchip_sfc_init(sfc);
index 44b85a8d47f112f795fb0a8a46397daff7999bcf..7bc14fb309a69970ea92902e4f1ec88b32a41e8c 100644 (file)
@@ -4456,6 +4456,11 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
                        return NOTIFY_OK;
                }
 
+               /*
+                * Clear the flag before adding the device so that fw_devlink
+                * doesn't skip adding consumers to this device.
+                */
+               rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
                spi = of_register_spi_device(ctlr, rd->dn);
                put_device(&ctlr->dev);
 
index 297dc62bca2986f014c4b4060c95d112a807fe7d..372d64756ed64b10c3dd9096aa20886320837ff9 100644 (file)
@@ -267,35 +267,34 @@ int amdtee_open_session(struct tee_context *ctx,
                goto out;
        }
 
+       /* Open session with loaded TA */
+       handle_open_session(arg, &session_info, param);
+       if (arg->ret != TEEC_SUCCESS) {
+               pr_err("open_session failed %d\n", arg->ret);
+               handle_unload_ta(ta_handle);
+               kref_put(&sess->refcount, destroy_session);
+               goto out;
+       }
+
        /* Find an empty session index for the given TA */
        spin_lock(&sess->lock);
        i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);
-       if (i < TEE_NUM_SESSIONS)
+       if (i < TEE_NUM_SESSIONS) {
+               sess->session_info[i] = session_info;
+               set_session_id(ta_handle, i, &arg->session);
                set_bit(i, sess->sess_mask);
+       }
        spin_unlock(&sess->lock);
 
        if (i >= TEE_NUM_SESSIONS) {
                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
+               handle_close_session(ta_handle, session_info);
                handle_unload_ta(ta_handle);
                kref_put(&sess->refcount, destroy_session);
                rc = -ENOMEM;
                goto out;
        }
 
-       /* Open session with loaded TA */
-       handle_open_session(arg, &session_info, param);
-       if (arg->ret != TEEC_SUCCESS) {
-               pr_err("open_session failed %d\n", arg->ret);
-               spin_lock(&sess->lock);
-               clear_bit(i, sess->sess_mask);
-               spin_unlock(&sess->lock);
-               handle_unload_ta(ta_handle);
-               kref_put(&sess->refcount, destroy_session);
-               goto out;
-       }
-
-       sess->session_info[i] = session_info;
-       set_session_id(ta_handle, i, &arg->session);
 out:
        free_pages((u64)ta, get_order(ta_size));
        return rc;
index f121c224e682b0cffccfb49cab1209fd6b2ce536..70898bbd58095951744b8fd0a566ebd9249b8daf 100644 (file)
@@ -7,3 +7,20 @@ config OPTEE
        help
          This implements the OP-TEE Trusted Execution Environment (TEE)
          driver.
+
+config OPTEE_INSECURE_LOAD_IMAGE
+       bool "Load OP-TEE image as firmware"
+       default n
+       depends on OPTEE && ARM64
+       help
+         This loads the BL32 image for OP-TEE as firmware when the driver is
+         probed. This returns -EPROBE_DEFER until the firmware is loadable from
+         the filesystem which is determined by checking the system_state until
+         it is in SYSTEM_RUNNING. This also requires enabling the corresponding
+         option in Trusted Firmware for Arm. The documentation there explains
+         the security threat associated with enabling this as well as
+         mitigations at the firmware and platform level.
+         https://trustedfirmware-a.readthedocs.io/en/latest/threat_model/threat_model.html
+
+         Additional documentation on kernel security risks are at
+         Documentation/staging/tee.rst.
index 290b1bb0e9cd724fe51188154aef53da808cfbd1..df5fb5410b722a1be0f50996bbbb1582806c50c2 100644 (file)
@@ -488,7 +488,7 @@ static bool is_normal_memory(pgprot_t p)
 #elif defined(CONFIG_ARM64)
        return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
 #else
-#error "Unuspported architecture"
+#error "Unsupported architecture"
 #endif
 }
 
index 70e9cc2ee96b08fa44708b1c1b8547968b003612..e8840a82b98356d21b791cc8f2b305aa9f086fb1 100644 (file)
@@ -241,11 +241,23 @@ struct optee_msg_arg {
  * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
  * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
  * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
+ *
+ * In the case where the OP-TEE image is loaded by the kernel, this will
+ * initially return an alternate UID to reflect that we are communicating with
+ * the TF-A image loading service at that time instead of OP-TEE. That UID is:
+ * a3fbeab1-1246-315d-c7c4-06b9c03cbea4.
+ * Represented in 4 32-bit words in OPTEE_MSG_IMAGE_LOAD_UID_0,
+ * OPTEE_MSG_IMAGE_LOAD_UID_1, OPTEE_MSG_IMAGE_LOAD_UID_2,
+ * OPTEE_MSG_IMAGE_LOAD_UID_3.
  */
 #define OPTEE_MSG_UID_0                        0x384fb3e0
 #define OPTEE_MSG_UID_1                        0xe7f811e3
 #define OPTEE_MSG_UID_2                        0xaf630002
 #define OPTEE_MSG_UID_3                        0xa5d5c51b
+#define OPTEE_MSG_IMAGE_LOAD_UID_0     0xa3fbeab1
+#define OPTEE_MSG_IMAGE_LOAD_UID_1     0x1246315d
+#define OPTEE_MSG_IMAGE_LOAD_UID_2     0xc7c406b9
+#define OPTEE_MSG_IMAGE_LOAD_UID_3     0xc03cbea4
 #define OPTEE_MSG_FUNCID_CALLS_UID     0xFF01
 
 /*
index 04ae58892608c6b7e2627b156030fb39a3c5b5a2..72685ee0d53f881cbaa8116fec69f465d81f7ca9 100644 (file)
@@ -94,11 +94,35 @@ struct optee_supp {
        struct completion reqs_c;
 };
 
+/*
+ * struct optee_pcpu - per cpu notif private struct passed to work functions
+ * @optee              optee device reference
+ */
+struct optee_pcpu {
+       struct optee *optee;
+};
+
+/*
+ * struct optee_smc - optee smc communication struct
+ * @invoke_fn          handler function to invoke secure monitor
+ * @memremaped_shm     virtual address of memory in shared memory pool
+ * @sec_caps:          secure world capabilities defined by
+ *                     OPTEE_SMC_SEC_CAP_* in optee_smc.h
+ * @notif_irq          interrupt used as async notification by OP-TEE or 0
+ * @optee_pcpu         per_cpu optee instance for per cpu work or NULL
+ * @notif_pcpu_wq      workqueue for per cpu asynchronous notification or NULL
+ * @notif_pcpu_work    work for per cpu asynchronous notification
+ * @notif_cpuhp_state   CPU hotplug state assigned for pcpu interrupt management
+ */
 struct optee_smc {
        optee_invoke_fn *invoke_fn;
        void *memremaped_shm;
        u32 sec_caps;
        unsigned int notif_irq;
+       struct optee_pcpu __percpu *optee_pcpu;
+       struct workqueue_struct *notif_pcpu_wq;
+       struct work_struct notif_pcpu_work;
+       unsigned int notif_cpuhp_state;
 };
 
 /**
index 73b5e7760d102d9e1424dbcece28557c0281c6f0..7d9fa426505ba524f59b541a2059feaa3104b8e0 100644 (file)
@@ -104,6 +104,30 @@ struct optee_smc_call_get_os_revision_result {
        unsigned long reserved1;
 };
 
+/*
+ * Load Trusted OS from optee/tee.bin in the Linux firmware.
+ *
+ * WARNING: Use this cautiously as it could lead to insecure loading of the
+ * Trusted OS.
+ * This SMC instructs EL3 to load a binary and execute it as the Trusted OS.
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_CALL_LOAD_IMAGE
+ * a1 Upper 32bit of a 64bit size for the payload
+ * a2 Lower 32bit of a 64bit size for the payload
+ * a3 Upper 32bit of the physical address for the payload
+ * a4 Lower 32bit of the physical address for the payload
+ *
+ * The payload is in the OP-TEE image format.
+ *
+ * Returns result in a0, 0 on success and an error code otherwise.
+ */
+#define OPTEE_SMC_FUNCID_LOAD_IMAGE 2
+#define OPTEE_SMC_CALL_LOAD_IMAGE \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+                          OPTEE_SMC_FUNCID_LOAD_IMAGE)
+
 /*
  * Call with struct optee_msg_arg as argument
  *
index a1c1fa1a9c28a7374337dc571a5a28db575f2317..49702cb08f4fb3a56f28f3bd9f643268b68cba1f 100644 (file)
@@ -7,10 +7,13 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/arm-smccc.h>
+#include <linux/cpuhotplug.h>
 #include <linux/errno.h>
+#include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irqdomain.h>
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/of.h>
  */
 #define OPTEE_MIN_STATIC_POOL_ALIGN    9 /* 512 bytes aligned */
 
+/* SMC ABI considers at most a single TEE firmware */
+static unsigned int pcpu_irq_num;
+
+static int optee_cpuhp_enable_pcpu_irq(unsigned int cpu)
+{
+       enable_percpu_irq(pcpu_irq_num, IRQ_TYPE_NONE);
+
+       return 0;
+}
+
+static int optee_cpuhp_disable_pcpu_irq(unsigned int cpu)
+{
+       disable_percpu_irq(pcpu_irq_num);
+
+       return 0;
+}
+
 /*
  * 1. Convert between struct tee_param and struct optee_msg_param
  *
@@ -991,9 +1011,8 @@ static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid,
        return res.a1;
 }
 
-static irqreturn_t notif_irq_handler(int irq, void *dev_id)
+static irqreturn_t irq_handler(struct optee *optee)
 {
-       struct optee *optee = dev_id;
        bool do_bottom_half = false;
        bool value_valid;
        bool value_pending;
@@ -1016,6 +1035,13 @@ static irqreturn_t notif_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t notif_irq_handler(int irq, void *dev_id)
+{
+       struct optee *optee = dev_id;
+
+       return irq_handler(optee);
+}
+
 static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
 {
        struct optee *optee = dev_id;
@@ -1025,7 +1051,7 @@ static irqreturn_t notif_irq_thread_fn(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
+static int init_irq(struct optee *optee, u_int irq)
 {
        int rc;
 
@@ -1040,12 +1066,103 @@ static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
        return 0;
 }
 
+static irqreturn_t notif_pcpu_irq_handler(int irq, void *dev_id)
+{
+       struct optee_pcpu *pcpu = dev_id;
+       struct optee *optee = pcpu->optee;
+
+       if (irq_handler(optee) == IRQ_WAKE_THREAD)
+               queue_work(optee->smc.notif_pcpu_wq,
+                          &optee->smc.notif_pcpu_work);
+
+       return IRQ_HANDLED;
+}
+
+static void notif_pcpu_irq_work_fn(struct work_struct *work)
+{
+       struct optee_smc *optee_smc = container_of(work, struct optee_smc,
+                                                  notif_pcpu_work);
+       struct optee *optee = container_of(optee_smc, struct optee, smc);
+
+       optee_smc_do_bottom_half(optee->ctx);
+}
+
+static int init_pcpu_irq(struct optee *optee, u_int irq)
+{
+       struct optee_pcpu __percpu *optee_pcpu;
+       int cpu, rc;
+
+       optee_pcpu = alloc_percpu(struct optee_pcpu);
+       if (!optee_pcpu)
+               return -ENOMEM;
+
+       for_each_present_cpu(cpu)
+               per_cpu_ptr(optee_pcpu, cpu)->optee = optee;
+
+       rc = request_percpu_irq(irq, notif_pcpu_irq_handler,
+                               "optee_pcpu_notification", optee_pcpu);
+       if (rc)
+               goto err_free_pcpu;
+
+       INIT_WORK(&optee->smc.notif_pcpu_work, notif_pcpu_irq_work_fn);
+       optee->smc.notif_pcpu_wq = create_workqueue("optee_pcpu_notification");
+       if (!optee->smc.notif_pcpu_wq) {
+               rc = -EINVAL;
+               goto err_free_pcpu_irq;
+       }
+
+       optee->smc.optee_pcpu = optee_pcpu;
+       optee->smc.notif_irq = irq;
+
+       pcpu_irq_num = irq;
+       rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "optee/pcpu-notif:starting",
+                              optee_cpuhp_enable_pcpu_irq,
+                              optee_cpuhp_disable_pcpu_irq);
+       if (!rc)
+               rc = -EINVAL;
+       if (rc < 0)
+               goto err_free_pcpu_irq;
+
+       optee->smc.notif_cpuhp_state = rc;
+
+       return 0;
+
+err_free_pcpu_irq:
+       free_percpu_irq(irq, optee_pcpu);
+err_free_pcpu:
+       free_percpu(optee_pcpu);
+
+       return rc;
+}
+
+static int optee_smc_notif_init_irq(struct optee *optee, u_int irq)
+{
+       if (irq_is_percpu_devid(irq))
+               return init_pcpu_irq(optee, irq);
+       else
+               return init_irq(optee, irq);
+}
+
+static void uninit_pcpu_irq(struct optee *optee)
+{
+       cpuhp_remove_state(optee->smc.notif_cpuhp_state);
+
+       destroy_workqueue(optee->smc.notif_pcpu_wq);
+
+       free_percpu_irq(optee->smc.notif_irq, optee->smc.optee_pcpu);
+       free_percpu(optee->smc.optee_pcpu);
+}
+
 static void optee_smc_notif_uninit_irq(struct optee *optee)
 {
        if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_ASYNC_NOTIF) {
                optee_smc_stop_async_notif(optee->ctx);
                if (optee->smc.notif_irq) {
-                       free_irq(optee->smc.notif_irq, optee);
+                       if (irq_is_percpu_devid(optee->smc.notif_irq))
+                               uninit_pcpu_irq(optee);
+                       else
+                               free_irq(optee->smc.notif_irq, optee);
+
                        irq_dispose_mapping(optee->smc.notif_irq);
                }
        }
@@ -1149,6 +1266,22 @@ static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
        return false;
 }
 
+#ifdef CONFIG_OPTEE_INSECURE_LOAD_IMAGE
+static bool optee_msg_api_uid_is_optee_image_load(optee_invoke_fn *invoke_fn)
+{
+       struct arm_smccc_res res;
+
+       invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       if (res.a0 == OPTEE_MSG_IMAGE_LOAD_UID_0 &&
+           res.a1 == OPTEE_MSG_IMAGE_LOAD_UID_1 &&
+           res.a2 == OPTEE_MSG_IMAGE_LOAD_UID_2 &&
+           res.a3 == OPTEE_MSG_IMAGE_LOAD_UID_3)
+               return true;
+       return false;
+}
+#endif
+
 static void optee_msg_get_os_revision(optee_invoke_fn *invoke_fn)
 {
        union {
@@ -1354,6 +1487,120 @@ static void optee_shutdown(struct platform_device *pdev)
                optee_disable_shm_cache(optee);
 }
 
+#ifdef CONFIG_OPTEE_INSECURE_LOAD_IMAGE
+
+#define OPTEE_FW_IMAGE "optee/tee.bin"
+
+static optee_invoke_fn *cpuhp_invoke_fn;
+
+static int optee_cpuhp_probe(unsigned int cpu)
+{
+       /*
+        * Invoking a call on a CPU will cause OP-TEE to perform the required
+        * setup for that CPU. Just invoke the call to get the UID since that
+        * has no side effects.
+        */
+       if (optee_msg_api_uid_is_optee_api(cpuhp_invoke_fn))
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int optee_load_fw(struct platform_device *pdev,
+                        optee_invoke_fn *invoke_fn)
+{
+       const struct firmware *fw = NULL;
+       struct arm_smccc_res res;
+       phys_addr_t data_pa;
+       u8 *data_buf = NULL;
+       u64 data_size;
+       u32 data_pa_high, data_pa_low;
+       u32 data_size_high, data_size_low;
+       int rc;
+       int hp_state;
+
+       if (!optee_msg_api_uid_is_optee_image_load(invoke_fn))
+               return 0;
+
+       rc = request_firmware(&fw, OPTEE_FW_IMAGE, &pdev->dev);
+       if (rc) {
+               /*
+                * The firmware in the rootfs will not be accessible until we
+                * are in the SYSTEM_RUNNING state, so return EPROBE_DEFER until
+                * that point.
+                */
+               if (system_state < SYSTEM_RUNNING)
+                       return -EPROBE_DEFER;
+               goto fw_err;
+       }
+
+       data_size = fw->size;
+       /*
+        * This uses the GFP_DMA flag to ensure we are allocated memory in the
+        * 32-bit space since TF-A cannot map memory beyond the 32-bit boundary.
+        */
+       data_buf = kmalloc(fw->size, GFP_KERNEL | GFP_DMA);
+       if (!data_buf) {
+               rc = -ENOMEM;
+               goto fw_err;
+       }
+       memcpy(data_buf, fw->data, fw->size);
+       data_pa = virt_to_phys(data_buf);
+       reg_pair_from_64(&data_pa_high, &data_pa_low, data_pa);
+       reg_pair_from_64(&data_size_high, &data_size_low, data_size);
+       goto fw_load;
+
+fw_err:
+       pr_warn("image loading failed\n");
+       data_pa_high = 0;
+       data_pa_low = 0;
+       data_size_high = 0;
+       data_size_low = 0;
+
+fw_load:
+       /*
+        * Always invoke the SMC, even if loading the image fails, to indicate
+        * to EL3 that we have passed the point where it should allow invoking
+        * this SMC.
+        */
+       pr_warn("OP-TEE image loaded from kernel, this can be insecure");
+       invoke_fn(OPTEE_SMC_CALL_LOAD_IMAGE, data_size_high, data_size_low,
+                 data_pa_high, data_pa_low, 0, 0, 0, &res);
+       if (!rc)
+               rc = res.a0;
+       if (fw)
+               release_firmware(fw);
+       kfree(data_buf);
+
+       if (!rc) {
+               /*
+                * We need to initialize OP-TEE on all other running cores as
+                * well. Any cores that aren't running yet will get initialized
+                * when they are brought up by the power management functions in
+                * TF-A which are registered by the OP-TEE SPD. Due to that we
+                * can un-register the callback right after registering it.
+                */
+               cpuhp_invoke_fn = invoke_fn;
+               hp_state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "optee:probe",
+                                            optee_cpuhp_probe, NULL);
+               if (hp_state < 0) {
+                       pr_warn("Failed with CPU hotplug setup for OP-TEE");
+                       return -EINVAL;
+               }
+               cpuhp_remove_state(hp_state);
+               cpuhp_invoke_fn = NULL;
+       }
+
+       return rc;
+}
+#else
+static inline int optee_load_fw(struct platform_device *pdev,
+                               optee_invoke_fn *invoke_fn)
+{
+       return 0;
+}
+#endif
+
 static int optee_probe(struct platform_device *pdev)
 {
        optee_invoke_fn *invoke_fn;
@@ -1372,6 +1619,10 @@ static int optee_probe(struct platform_device *pdev)
        if (IS_ERR(invoke_fn))
                return PTR_ERR(invoke_fn);
 
+       rc = optee_load_fw(pdev, invoke_fn);
+       if (rc)
+               return rc;
+
        if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
                pr_warn("api uid mismatch\n");
                return -EINVAL;
index b1c6231defad7a5ebf939e44466717f7e5645f6e..673cf035949483eba11bc9067d4303fd7eced52f 100644 (file)
@@ -32,7 +32,7 @@ static int shm_get_kernel_pages(unsigned long start, size_t page_count,
                         is_kmap_addr((void *)start)))
                return -EINVAL;
 
-       page = virt_to_page(start);
+       page = virt_to_page((void *)start);
        for (n = 0; n < page_count; n++) {
                pages[n] = page + n;
                get_page(pages[n]);
index 90526f46c9b1104d5d0f28c76cf5e500741ba75c..d71ee50e7878f6c2dbb0b9ac84c1dd631f1b9c8c 100644 (file)
@@ -153,7 +153,6 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp
                cancel_delayed_work_sync(&pci_info->work);
                proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0);
                proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_THRES_0, 0);
-               thermal_zone_device_disable(tzd);
                pci_info->stored_thres = 0;
                return 0;
        }
index c7ba5680cd483abd5c3196b7db2ca68abcb6f644..91fc7e239497165d6cf5a91eed20f8810d9c4903 100644 (file)
@@ -235,6 +235,12 @@ static int max_idle_set(const char *arg, const struct kernel_param *kp)
                goto skip_limit_set;
        }
 
+       if (!cpumask_available(idle_injection_cpu_mask)) {
+               ret = allocate_copy_idle_injection_mask(cpu_present_mask);
+               if (ret)
+                       goto skip_limit_set;
+       }
+
        if (check_invalid(idle_injection_cpu_mask, new_max_idle)) {
                ret = -EINVAL;
                goto skip_limit_set;
@@ -791,7 +797,8 @@ static int __init powerclamp_init(void)
                return retval;
 
        mutex_lock(&powerclamp_lock);
-       retval = allocate_copy_idle_injection_mask(cpu_present_mask);
+       if (!cpumask_available(idle_injection_cpu_mask))
+               retval = allocate_copy_idle_injection_mask(cpu_present_mask);
        mutex_unlock(&powerclamp_lock);
 
        if (retval)
index 2e22bb82b7389e740c70dc66de24351372861bf0..e69868e868eb9e9abd0a2e826dbf75913605b4bc 100644 (file)
@@ -193,8 +193,67 @@ static const struct attribute_group thermal_attr_group = {
 #define THERM_THROT_POLL_INTERVAL      HZ
 #define THERM_STATUS_PROCHOT_LOG       BIT(1)
 
-#define THERM_STATUS_CLEAR_CORE_MASK (BIT(1) | BIT(3) | BIT(5) | BIT(7) | BIT(9) | BIT(11) | BIT(13) | BIT(15))
-#define THERM_STATUS_CLEAR_PKG_MASK  (BIT(1) | BIT(3) | BIT(5) | BIT(7) | BIT(9) | BIT(11))
+static u64 therm_intr_core_clear_mask;
+static u64 therm_intr_pkg_clear_mask;
+
+static void thermal_intr_init_core_clear_mask(void)
+{
+       if (therm_intr_core_clear_mask)
+               return;
+
+       /*
+        * Reference: Intel SDM  Volume 4
+        * "Table 2-2. IA-32 Architectural MSRs", MSR 0x19C
+        * IA32_THERM_STATUS.
+        */
+
+       /*
+        * Bit 1, 3, 5: CPUID.01H:EDX[22] = 1. This driver will not
+        * enable interrupts, when 0 as it checks for X86_FEATURE_ACPI.
+        */
+       therm_intr_core_clear_mask = (BIT(1) | BIT(3) | BIT(5));
+
+       /*
+        * Bit 7 and 9: Thermal Threshold #1 and #2 log
+        * If CPUID.01H:ECX[8] = 1
+        */
+       if (boot_cpu_has(X86_FEATURE_TM2))
+               therm_intr_core_clear_mask |= (BIT(7) | BIT(9));
+
+       /* Bit 11: Power Limitation log (R/WC0) If CPUID.06H:EAX[4] = 1 */
+       if (boot_cpu_has(X86_FEATURE_PLN))
+               therm_intr_core_clear_mask |= BIT(11);
+
+       /*
+        * Bit 13: Current Limit log (R/WC0) If CPUID.06H:EAX[7] = 1
+        * Bit 15: Cross Domain Limit log (R/WC0) If CPUID.06H:EAX[7] = 1
+        */
+       if (boot_cpu_has(X86_FEATURE_HWP))
+               therm_intr_core_clear_mask |= (BIT(13) | BIT(15));
+}
+
+static void thermal_intr_init_pkg_clear_mask(void)
+{
+       if (therm_intr_pkg_clear_mask)
+               return;
+
+       /*
+        * Reference: Intel SDM  Volume 4
+        * "Table 2-2. IA-32 Architectural MSRs", MSR 0x1B1
+        * IA32_PACKAGE_THERM_STATUS.
+        */
+
+       /* All bits except BIT 26 depend on CPUID.06H: EAX[6] = 1 */
+       if (boot_cpu_has(X86_FEATURE_PTS))
+               therm_intr_pkg_clear_mask = (BIT(1) | BIT(3) | BIT(5) | BIT(7) | BIT(9) | BIT(11));
+
+       /*
+        * Intel SDM Volume 2A: Thermal and Power Management Leaf
+        * Bit 26: CPUID.06H: EAX[19] = 1
+        */
+       if (boot_cpu_has(X86_FEATURE_HFI))
+               therm_intr_pkg_clear_mask |= BIT(26);
+}
 
 /*
  * Clear the bits in package thermal status register for bit = 1
@@ -207,13 +266,10 @@ void thermal_clear_package_intr_status(int level, u64 bit_mask)
 
        if (level == CORE_LEVEL) {
                msr  = MSR_IA32_THERM_STATUS;
-               msr_val = THERM_STATUS_CLEAR_CORE_MASK;
+               msr_val = therm_intr_core_clear_mask;
        } else {
                msr  = MSR_IA32_PACKAGE_THERM_STATUS;
-               msr_val = THERM_STATUS_CLEAR_PKG_MASK;
-               if (boot_cpu_has(X86_FEATURE_HFI))
-                       msr_val |= BIT(26);
-
+               msr_val = therm_intr_pkg_clear_mask;
        }
 
        msr_val &= ~bit_mask;
@@ -708,6 +764,9 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
        h = THERMAL_APIC_VECTOR | APIC_DM_FIXED | APIC_LVT_MASKED;
        apic_write(APIC_LVTTHMR, h);
 
+       thermal_intr_init_core_clear_mask();
+       thermal_intr_init_pkg_clear_mask();
+
        rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
        if (cpu_has(c, X86_FEATURE_PLN) && !int_pln_enable)
                wrmsr(MSR_IA32_THERM_INTERRUPT,
index 55679fd86505d762ea05ec68028e1a500aec0b5d..566df4522b8853fb89d965d994353c6c0d603671 100644 (file)
@@ -613,6 +613,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
        struct thermal_instance *pos;
        struct thermal_zone_device *pos1;
        struct thermal_cooling_device *pos2;
+       bool upper_no_limit;
        int result;
 
        if (trip >= tz->num_trips || trip < 0)
@@ -632,7 +633,13 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 
        /* lower default 0, upper default max_state */
        lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
-       upper = upper == THERMAL_NO_LIMIT ? cdev->max_state : upper;
+
+       if (upper == THERMAL_NO_LIMIT) {
+               upper = cdev->max_state;
+               upper_no_limit = true;
+       } else {
+               upper_no_limit = false;
+       }
 
        if (lower > upper || upper > cdev->max_state)
                return -EINVAL;
@@ -644,6 +651,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
        dev->cdev = cdev;
        dev->trip = trip;
        dev->upper = upper;
+       dev->upper_no_limit = upper_no_limit;
        dev->lower = lower;
        dev->target = THERMAL_NO_TARGET;
        dev->weight = weight;
@@ -1045,6 +1053,91 @@ devm_thermal_of_cooling_device_register(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_thermal_of_cooling_device_register);
 
+static bool thermal_cooling_device_present(struct thermal_cooling_device *cdev)
+{
+       struct thermal_cooling_device *pos = NULL;
+
+       list_for_each_entry(pos, &thermal_cdev_list, node) {
+               if (pos == cdev)
+                       return true;
+       }
+
+       return false;
+}
+
+/**
+ * thermal_cooling_device_update - Update a cooling device object
+ * @cdev: Target cooling device.
+ *
+ * Update @cdev to reflect a change of the underlying hardware or platform.
+ *
+ * Must be called when the maximum cooling state of @cdev becomes invalid and so
+ * its .get_max_state() callback needs to be run to produce the new maximum
+ * cooling state value.
+ */
+void thermal_cooling_device_update(struct thermal_cooling_device *cdev)
+{
+       struct thermal_instance *ti;
+       unsigned long state;
+
+       if (IS_ERR_OR_NULL(cdev))
+               return;
+
+       /*
+        * Hold thermal_list_lock throughout the update to prevent the device
+        * from going away while being updated.
+        */
+       mutex_lock(&thermal_list_lock);
+
+       if (!thermal_cooling_device_present(cdev))
+               goto unlock_list;
+
+       /*
+        * Update under the cdev lock to prevent the state from being set beyond
+        * the new limit concurrently.
+        */
+       mutex_lock(&cdev->lock);
+
+       if (cdev->ops->get_max_state(cdev, &cdev->max_state))
+               goto unlock;
+
+       thermal_cooling_device_stats_reinit(cdev);
+
+       list_for_each_entry(ti, &cdev->thermal_instances, cdev_node) {
+               if (ti->upper == cdev->max_state)
+                       continue;
+
+               if (ti->upper < cdev->max_state) {
+                       if (ti->upper_no_limit)
+                               ti->upper = cdev->max_state;
+
+                       continue;
+               }
+
+               ti->upper = cdev->max_state;
+               if (ti->lower > ti->upper)
+                       ti->lower = ti->upper;
+
+               if (ti->target == THERMAL_NO_TARGET)
+                       continue;
+
+               if (ti->target > ti->upper)
+                       ti->target = ti->upper;
+       }
+
+       if (cdev->ops->get_cur_state(cdev, &state) || state > cdev->max_state)
+               goto unlock;
+
+       thermal_cooling_device_stats_update(cdev, state);
+
+unlock:
+       mutex_unlock(&cdev->lock);
+
+unlock_list:
+       mutex_unlock(&thermal_list_lock);
+}
+EXPORT_SYMBOL_GPL(thermal_cooling_device_update);
+
 static void __unbind(struct thermal_zone_device *tz, int mask,
                     struct thermal_cooling_device *cdev)
 {
@@ -1067,20 +1160,17 @@ void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
        int i;
        const struct thermal_zone_params *tzp;
        struct thermal_zone_device *tz;
-       struct thermal_cooling_device *pos = NULL;
 
        if (!cdev)
                return;
 
        mutex_lock(&thermal_list_lock);
-       list_for_each_entry(pos, &thermal_cdev_list, node)
-               if (pos == cdev)
-                       break;
-       if (pos != cdev) {
-               /* thermal cooling device not found */
+
+       if (!thermal_cooling_device_present(cdev)) {
                mutex_unlock(&thermal_list_lock);
                return;
        }
+
        list_del(&cdev->node);
 
        /* Unbind all thermal zones associated with 'this' cdev */
@@ -1309,7 +1399,7 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
                struct thermal_trip trip;
 
                result = thermal_zone_get_trip(tz, count, &trip);
-               if (result)
+               if (result || !trip.temperature)
                        set_bit(count, &tz->trips_disabled);
        }
 
index 7af54382e915172975bd63079f3a5cf23de8d1fc..3d4a787c6b28a0baf7197726058708a5a7b830af 100644 (file)
@@ -101,6 +101,7 @@ struct thermal_instance {
        struct list_head tz_node; /* node in tz->thermal_instances */
        struct list_head cdev_node; /* node in cdev->thermal_instances */
        unsigned int weight; /* The weight of the cooling device */
+       bool upper_no_limit;
 };
 
 #define to_thermal_zone(_dev) \
@@ -127,6 +128,7 @@ int thermal_zone_create_device_groups(struct thermal_zone_device *, int);
 void thermal_zone_destroy_device_groups(struct thermal_zone_device *);
 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *);
 void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev);
+void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev);
 /* used only at binding time */
 ssize_t trip_point_show(struct device *, struct device_attribute *, char *);
 ssize_t weight_show(struct device *, struct device_attribute *, char *);
index cef860deaf912db0b264a14e71ffff0bff3eee52..6c20c9f90a05acb777b13019fa341fcb80e69320 100644 (file)
@@ -685,6 +685,8 @@ void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
 {
        struct cooling_dev_stats *stats = cdev->stats;
 
+       lockdep_assert_held(&cdev->lock);
+
        if (!stats)
                return;
 
@@ -706,13 +708,22 @@ static ssize_t total_trans_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
-       int ret;
+       struct cooling_dev_stats *stats;
+       int ret = 0;
+
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats)
+               goto unlock;
 
        spin_lock(&stats->lock);
        ret = sprintf(buf, "%u\n", stats->total_trans);
        spin_unlock(&stats->lock);
 
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return ret;
 }
 
@@ -721,11 +732,18 @@ time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
                      char *buf)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
+       struct cooling_dev_stats *stats;
        ssize_t len = 0;
        int i;
 
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats)
+               goto unlock;
+
        spin_lock(&stats->lock);
+
        update_time_in_state(stats);
 
        for (i = 0; i <= cdev->max_state; i++) {
@@ -734,6 +752,9 @@ time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
        }
        spin_unlock(&stats->lock);
 
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return len;
 }
 
@@ -742,8 +763,16 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
            size_t count)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
-       int i, states = cdev->max_state + 1;
+       struct cooling_dev_stats *stats;
+       int i, states;
+
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats)
+               goto unlock;
+
+       states = cdev->max_state + 1;
 
        spin_lock(&stats->lock);
 
@@ -757,6 +786,9 @@ reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
 
        spin_unlock(&stats->lock);
 
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return count;
 }
 
@@ -764,10 +796,18 @@ static ssize_t trans_table_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
        struct thermal_cooling_device *cdev = to_cooling_device(dev);
-       struct cooling_dev_stats *stats = cdev->stats;
+       struct cooling_dev_stats *stats;
        ssize_t len = 0;
        int i, j;
 
+       mutex_lock(&cdev->lock);
+
+       stats = cdev->stats;
+       if (!stats) {
+               len = -ENODATA;
+               goto unlock;
+       }
+
        len += snprintf(buf + len, PAGE_SIZE - len, " From  :    To\n");
        len += snprintf(buf + len, PAGE_SIZE - len, "       : ");
        for (i = 0; i <= cdev->max_state; i++) {
@@ -775,8 +815,10 @@ static ssize_t trans_table_show(struct device *dev,
                        break;
                len += snprintf(buf + len, PAGE_SIZE - len, "state%2u  ", i);
        }
-       if (len >= PAGE_SIZE)
-               return PAGE_SIZE;
+       if (len >= PAGE_SIZE) {
+               len = PAGE_SIZE;
+               goto unlock;
+       }
 
        len += snprintf(buf + len, PAGE_SIZE - len, "\n");
 
@@ -799,8 +841,12 @@ static ssize_t trans_table_show(struct device *dev,
 
        if (len >= PAGE_SIZE) {
                pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n");
-               return -EFBIG;
+               len = -EFBIG;
        }
+
+unlock:
+       mutex_unlock(&cdev->lock);
+
        return len;
 }
 
@@ -879,6 +925,14 @@ void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
        cooling_device_stats_destroy(cdev);
 }
 
+void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev)
+{
+       lockdep_assert_held(&cdev->lock);
+
+       cooling_device_stats_destroy(cdev);
+       cooling_device_stats_setup(cdev);
+}
+
 /* these helper will be used only at the time of bindig */
 ssize_t
 trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
index 4339e706cc3a12ad455b01ab4a0e99898c06c9aa..f92ad71ef9831fa3611134c764af3af68b1c4582 100644 (file)
@@ -942,7 +942,8 @@ static void margining_port_remove(struct tb_port *port)
 
        snprintf(dir_name, sizeof(dir_name), "port%d", port->port);
        parent = debugfs_lookup(dir_name, port->sw->debugfs_dir);
-       debugfs_remove_recursive(debugfs_lookup("margining", parent));
+       if (parent)
+               debugfs_remove_recursive(debugfs_lookup("margining", parent));
 
        kfree(port->usb4->margining);
        port->usb4->margining = NULL;
@@ -967,19 +968,18 @@ static void margining_switch_init(struct tb_switch *sw)
 
 static void margining_switch_remove(struct tb_switch *sw)
 {
+       struct tb_port *upstream, *downstream;
        struct tb_switch *parent_sw;
-       struct tb_port *downstream;
        u64 route = tb_route(sw);
 
        if (!route)
                return;
 
-       /*
-        * Upstream is removed with the router itself but we need to
-        * remove the downstream port margining directory.
-        */
+       upstream = tb_upstream_port(sw);
        parent_sw = tb_switch_parent(sw);
        downstream = tb_port_at(route, parent_sw);
+
+       margining_port_remove(upstream);
        margining_port_remove(downstream);
 }
 
index 4dce2edd86ea0f9a4d223f2f6047e8a7db03d42e..cfebec107f3fc8a437718c376045cd4d8d734171 100644 (file)
@@ -46,7 +46,7 @@
 #define QUIRK_AUTO_CLEAR_INT   BIT(0)
 #define QUIRK_E2E              BIT(1)
 
-static int ring_interrupt_index(struct tb_ring *ring)
+static int ring_interrupt_index(const struct tb_ring *ring)
 {
        int bit = ring->hop;
        if (!ring->is_tx)
@@ -63,13 +63,14 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
 {
        int reg = REG_RING_INTERRUPT_BASE +
                  ring_interrupt_index(ring) / 32 * 4;
-       int bit = ring_interrupt_index(ring) & 31;
-       int mask = 1 << bit;
+       int interrupt_bit = ring_interrupt_index(ring) & 31;
+       int mask = 1 << interrupt_bit;
        u32 old, new;
 
        if (ring->irq > 0) {
                u32 step, shift, ivr, misc;
                void __iomem *ivr_base;
+               int auto_clear_bit;
                int index;
 
                if (ring->is_tx)
@@ -77,18 +78,25 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
                else
                        index = ring->hop + ring->nhi->hop_count;
 
-               if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT) {
-                       /*
-                        * Ask the hardware to clear interrupt status
-                        * bits automatically since we already know
-                        * which interrupt was triggered.
-                        */
-                       misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
-                       if (!(misc & REG_DMA_MISC_INT_AUTO_CLEAR)) {
-                               misc |= REG_DMA_MISC_INT_AUTO_CLEAR;
-                               iowrite32(misc, ring->nhi->iobase + REG_DMA_MISC);
-                       }
-               }
+               /*
+                * Intel routers support a bit that isn't part of
+                * the USB4 spec to ask the hardware to clear
+                * interrupt status bits automatically since
+                * we already know which interrupt was triggered.
+                *
+                * Other routers explicitly disable auto-clear
+                * to prevent conditions that may occur where two
+                * MSIX interrupts are simultaneously active and
+                * reading the register clears both of them.
+                */
+               misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
+               if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT)
+                       auto_clear_bit = REG_DMA_MISC_INT_AUTO_CLEAR;
+               else
+                       auto_clear_bit = REG_DMA_MISC_DISABLE_AUTO_CLEAR;
+               if (!(misc & auto_clear_bit))
+                       iowrite32(misc | auto_clear_bit,
+                                 ring->nhi->iobase + REG_DMA_MISC);
 
                ivr_base = ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE;
                step = index / REG_INT_VEC_ALLOC_REGS * REG_INT_VEC_ALLOC_BITS;
@@ -108,7 +116,7 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active)
 
        dev_dbg(&ring->nhi->pdev->dev,
                "%s interrupt at register %#x bit %d (%#x -> %#x)\n",
-               active ? "enabling" : "disabling", reg, bit, old, new);
+               active ? "enabling" : "disabling", reg, interrupt_bit, old, new);
 
        if (new == old)
                dev_WARN(&ring->nhi->pdev->dev,
@@ -393,14 +401,17 @@ EXPORT_SYMBOL_GPL(tb_ring_poll_complete);
 
 static void ring_clear_msix(const struct tb_ring *ring)
 {
+       int bit;
+
        if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT)
                return;
 
+       bit = ring_interrupt_index(ring) & 31;
        if (ring->is_tx)
-               ioread32(ring->nhi->iobase + REG_RING_NOTIFY_BASE);
+               iowrite32(BIT(bit), ring->nhi->iobase + REG_RING_INT_CLEAR);
        else
-               ioread32(ring->nhi->iobase + REG_RING_NOTIFY_BASE +
-                        4 * (ring->nhi->hop_count / 32));
+               iowrite32(BIT(bit), ring->nhi->iobase + REG_RING_INT_CLEAR +
+                         4 * (ring->nhi->hop_count / 32));
 }
 
 static irqreturn_t ring_msix(int irq, void *data)
index 0d4970dcef842f7c8841ad933ef36940c8d5ed24..faef165a919ccda93a00fea018151210f68aec1b 100644 (file)
@@ -77,12 +77,13 @@ struct ring_desc {
 
 /*
  * three bitfields: tx, rx, rx overflow
- * Every bitfield contains one bit for every hop (REG_HOP_COUNT). Registers are
- * cleared on read. New interrupts are fired only after ALL registers have been
+ * Every bitfield contains one bit for every hop (REG_HOP_COUNT).
+ * New interrupts are fired only after ALL registers have been
  * read (even those containing only disabled rings).
  */
 #define REG_RING_NOTIFY_BASE   0x37800
 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32)
+#define REG_RING_INT_CLEAR     0x37808
 
 /*
  * two bitfields: rx, tx
@@ -105,6 +106,7 @@ struct ring_desc {
 
 #define REG_DMA_MISC                   0x39864
 #define REG_DMA_MISC_INT_AUTO_CLEAR     BIT(2)
+#define REG_DMA_MISC_DISABLE_AUTO_CLEAR        BIT(17)
 
 #define REG_INMAIL_DATA                        0x39900
 
index b5f2ec79c4d6e53e20266aff1ee7c57d9008669f..1157b8869bcca1da217285202b74b53bea2bf703 100644 (file)
@@ -20,6 +20,25 @@ static void quirk_dp_credit_allocation(struct tb_switch *sw)
        }
 }
 
+static void quirk_clx_disable(struct tb_switch *sw)
+{
+       sw->quirks |= QUIRK_NO_CLX;
+       tb_sw_dbg(sw, "disabling CL states\n");
+}
+
+static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
+{
+       struct tb_port *port;
+
+       tb_switch_for_each_port(sw, port) {
+               if (!tb_port_is_usb3_down(port))
+                       continue;
+               port->max_bw = 16376;
+               tb_port_dbg(port, "USB3 maximum bandwidth limited to %u Mb/s\n",
+                           port->max_bw);
+       }
+}
+
 struct tb_quirk {
        u16 hw_vendor_id;
        u16 hw_device_id;
@@ -37,6 +56,31 @@ static const struct tb_quirk tb_quirks[] = {
         * DP buffers.
         */
        { 0x8087, 0x0b26, 0x0000, 0x0000, quirk_dp_credit_allocation },
+       /*
+        * Limit the maximum USB3 bandwidth for the following Intel USB4
+        * host routers due to a hardware issue.
+        */
+       { 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_ADL_NHI1, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_RPL_NHI1, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_MTL_M_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI0, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       { 0x8087, PCI_DEVICE_ID_INTEL_MTL_P_NHI1, 0x0000, 0x0000,
+                 quirk_usb3_maximum_bandwidth },
+       /*
+        * CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms.
+        */
+       { 0x0438, 0x0208, 0x0000, 0x0000, quirk_clx_disable },
+       { 0x0438, 0x0209, 0x0000, 0x0000, quirk_clx_disable },
+       { 0x0438, 0x020a, 0x0000, 0x0000, quirk_clx_disable },
+       { 0x0438, 0x020b, 0x0000, 0x0000, quirk_clx_disable },
 };
 
 /**
index 56008eb91e2e448b9d584c318d6bc55c9af00a5b..9cc28197dbc45f7e6912ac43fc01d40fe5a80027 100644 (file)
@@ -187,6 +187,22 @@ static ssize_t nvm_authenticate_show(struct device *dev,
        return ret;
 }
 
+static void tb_retimer_set_inbound_sbtx(struct tb_port *port)
+{
+       int i;
+
+       for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
+               usb4_port_retimer_set_inbound_sbtx(port, i);
+}
+
+static void tb_retimer_unset_inbound_sbtx(struct tb_port *port)
+{
+       int i;
+
+       for (i = TB_MAX_RETIMER_INDEX; i >= 1; i--)
+               usb4_port_retimer_unset_inbound_sbtx(port, i);
+}
+
 static ssize_t nvm_authenticate_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t count)
 {
@@ -213,6 +229,7 @@ static ssize_t nvm_authenticate_store(struct device *dev,
        rt->auth_status = 0;
 
        if (val) {
+               tb_retimer_set_inbound_sbtx(rt->port);
                if (val == AUTHENTICATE_ONLY) {
                        ret = tb_retimer_nvm_authenticate(rt, true);
                } else {
@@ -232,6 +249,7 @@ static ssize_t nvm_authenticate_store(struct device *dev,
        }
 
 exit_unlock:
+       tb_retimer_unset_inbound_sbtx(rt->port);
        mutex_unlock(&rt->tb->lock);
 exit_rpm:
        pm_runtime_mark_last_busy(&rt->dev);
@@ -440,8 +458,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
         * Enable sideband channel for each retimer. We can do this
         * regardless whether there is device connected or not.
         */
-       for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++)
-               usb4_port_retimer_set_inbound_sbtx(port, i);
+       tb_retimer_set_inbound_sbtx(port);
 
        /*
         * Before doing anything else, read the authentication status.
@@ -464,6 +481,8 @@ int tb_retimer_scan(struct tb_port *port, bool add)
                        break;
        }
 
+       tb_retimer_unset_inbound_sbtx(port);
+
        if (!last_idx)
                return 0;
 
index 5185cf3e4d978f0216ea8f8cd3327c3fc0be32ef..f37a4320f10a528393b8a10f320103b8565b124d 100644 (file)
@@ -20,6 +20,7 @@ enum usb4_sb_opcode {
        USB4_SB_OPCODE_ROUTER_OFFLINE = 0x4e45534c,             /* "LSEN" */
        USB4_SB_OPCODE_ENUMERATE_RETIMERS = 0x4d554e45,         /* "ENUM" */
        USB4_SB_OPCODE_SET_INBOUND_SBTX = 0x5055534c,           /* "LSUP" */
+       USB4_SB_OPCODE_UNSET_INBOUND_SBTX = 0x50555355,         /* "USUP" */
        USB4_SB_OPCODE_QUERY_LAST_RETIMER = 0x5453414c,         /* "LAST" */
        USB4_SB_OPCODE_GET_NVM_SECTOR_SIZE = 0x53534e47,        /* "GNSS" */
        USB4_SB_OPCODE_NVM_SET_OFFSET = 0x53504f42,             /* "BOPS" */
index 3370e18ba05f9348c37ec526bbd7641f2673225b..da373ac38285c6a1b35c8ed035689306fc9c045c 100644 (file)
@@ -2968,8 +2968,6 @@ int tb_switch_add(struct tb_switch *sw)
                        dev_warn(&sw->dev, "reading DROM failed: %d\n", ret);
                tb_sw_dbg(sw, "uid: %#llx\n", sw->uid);
 
-               tb_check_quirks(sw);
-
                ret = tb_switch_set_uuid(sw);
                if (ret) {
                        dev_err(&sw->dev, "failed to set UUID\n");
@@ -2988,6 +2986,8 @@ int tb_switch_add(struct tb_switch *sw)
                        }
                }
 
+               tb_check_quirks(sw);
+
                tb_switch_default_link_ports(sw);
 
                ret = tb_switch_update_link_attributes(sw);
index cbb20a2773462ab892c2e4e242becbe3085dc0bf..275ff5219a3a3ae79a69b0548aab891bc1824aa1 100644 (file)
 #define NVM_MAX_SIZE           SZ_512K
 #define NVM_DATA_DWORDS                16
 
+/* Keep link controller awake during update */
+#define QUIRK_FORCE_POWER_LINK_CONTROLLER              BIT(0)
+/* Disable CLx if not supported */
+#define QUIRK_NO_CLX                                   BIT(1)
+
 /**
  * struct tb_nvm - Structure holding NVM information
  * @dev: Owner of the NVM
@@ -267,6 +272,8 @@ struct tb_bandwidth_group {
  * @group: Bandwidth allocation group the adapter is assigned to. Only
  *        used for DP IN adapters for now.
  * @group_list: The adapter is linked to the group's list of ports through this
+ * @max_bw: Maximum possible bandwidth through this adapter if set to
+ *         non-zero.
  *
  * In USB4 terminology this structure represents an adapter (protocol or
  * lane adapter).
@@ -294,6 +301,7 @@ struct tb_port {
        unsigned int dma_credits;
        struct tb_bandwidth_group *group;
        struct list_head group_list;
+       unsigned int max_bw;
 };
 
 /**
@@ -1019,6 +1027,9 @@ static inline bool tb_switch_is_clx_enabled(const struct tb_switch *sw,
  */
 static inline bool tb_switch_is_clx_supported(const struct tb_switch *sw)
 {
+       if (sw->quirks & QUIRK_NO_CLX)
+               return false;
+
        return tb_switch_is_usb4(sw) || tb_switch_is_titan_ridge(sw);
 }
 
@@ -1234,6 +1245,7 @@ int usb4_port_sw_margin(struct tb_port *port, unsigned int lanes, bool timing,
 int usb4_port_sw_margin_errors(struct tb_port *port, u32 *errors);
 
 int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index);
+int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index);
 int usb4_port_retimer_read(struct tb_port *port, u8 index, u8 reg, void *buf,
                           u8 size);
 int usb4_port_retimer_write(struct tb_port *port, u8 index, u8 reg,
@@ -1291,9 +1303,6 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port);
 void usb4_port_device_remove(struct usb4_port *usb4);
 int usb4_port_device_resume(struct usb4_port *usb4);
 
-/* Keep link controller awake during update */
-#define QUIRK_FORCE_POWER_LINK_CONTROLLER              BIT(0)
-
 void tb_check_quirks(struct tb_switch *sw);
 
 #ifdef CONFIG_ACPI
index 1e5e9c147a310da3627f38f11296d0345e7f529c..a0996cb2893c8693cfc08fd2e0bf71966b04a34a 100644 (file)
@@ -1578,6 +1578,20 @@ int usb4_port_retimer_set_inbound_sbtx(struct tb_port *port, u8 index)
                                    500);
 }
 
+/**
+ * usb4_port_retimer_unset_inbound_sbtx() - Disable sideband channel transactions
+ * @port: USB4 port
+ * @index: Retimer index
+ *
+ * Disables sideband channel transations on SBTX. The reverse of
+ * usb4_port_retimer_set_inbound_sbtx().
+ */
+int usb4_port_retimer_unset_inbound_sbtx(struct tb_port *port, u8 index)
+{
+       return usb4_port_retimer_op(port, index,
+                                   USB4_SB_OPCODE_UNSET_INBOUND_SBTX, 500);
+}
+
 /**
  * usb4_port_retimer_read() - Read from retimer sideband registers
  * @port: USB4 port
@@ -1868,6 +1882,15 @@ int usb4_port_retimer_nvm_read(struct tb_port *port, u8 index,
                                usb4_port_retimer_nvm_read_block, &info);
 }
 
+static inline unsigned int
+usb4_usb3_port_max_bandwidth(const struct tb_port *port, unsigned int bw)
+{
+       /* Take the possible bandwidth limitation into account */
+       if (port->max_bw)
+               return min(bw, port->max_bw);
+       return bw;
+}
+
 /**
  * usb4_usb3_port_max_link_rate() - Maximum support USB3 link rate
  * @port: USB3 adapter port
@@ -1889,7 +1912,9 @@ int usb4_usb3_port_max_link_rate(struct tb_port *port)
                return ret;
 
        lr = (val & ADP_USB3_CS_4_MSLR_MASK) >> ADP_USB3_CS_4_MSLR_SHIFT;
-       return lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000;
+       ret = lr == ADP_USB3_CS_4_MSLR_20G ? 20000 : 10000;
+
+       return usb4_usb3_port_max_bandwidth(port, ret);
 }
 
 /**
@@ -1916,7 +1941,9 @@ int usb4_usb3_port_actual_link_rate(struct tb_port *port)
                return 0;
 
        lr = val & ADP_USB3_CS_4_ALR_MASK;
-       return lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000;
+       ret = lr == ADP_USB3_CS_4_ALR_20G ? 20000 : 10000;
+
+       return usb4_usb3_port_max_bandwidth(port, ret);
 }
 
 static int usb4_usb3_port_cm_request(struct tb_port *port, bool request)
@@ -2067,18 +2094,30 @@ static int usb4_usb3_port_write_allocated_bandwidth(struct tb_port *port,
                                                    int downstream_bw)
 {
        u32 val, ubw, dbw, scale;
-       int ret;
+       int ret, max_bw;
 
-       /* Read the used scale, hardware default is 0 */
-       ret = tb_port_read(port, &scale, TB_CFG_PORT,
-                          port->cap_adap + ADP_USB3_CS_3, 1);
+       /* Figure out suitable scale */
+       scale = 0;
+       max_bw = max(upstream_bw, downstream_bw);
+       while (scale < 64) {
+               if (mbps_to_usb3_bw(max_bw, scale) < 4096)
+                       break;
+               scale++;
+       }
+
+       if (WARN_ON(scale >= 64))
+               return -EINVAL;
+
+       ret = tb_port_write(port, &scale, TB_CFG_PORT,
+                           port->cap_adap + ADP_USB3_CS_3, 1);
        if (ret)
                return ret;
 
-       scale &= ADP_USB3_CS_3_SCALE_MASK;
        ubw = mbps_to_usb3_bw(upstream_bw, scale);
        dbw = mbps_to_usb3_bw(downstream_bw, scale);
 
+       tb_port_dbg(port, "scaled bandwidth %u/%u, scale %u\n", ubw, dbw, scale);
+
        ret = tb_port_read(port, &val, TB_CFG_PORT,
                           port->cap_adap + ADP_USB3_CS_2, 1);
        if (ret)
index 5bddb2f5e93185eca993595dd0c44f7cc7d1ec46..98764e740c07830495dc5d3532e08d3b40a9ee7b 100644 (file)
@@ -43,6 +43,7 @@ struct xencons_info {
        int irq;
        int vtermno;
        grant_ref_t gntref;
+       spinlock_t ring_lock;
 };
 
 static LIST_HEAD(xenconsoles);
@@ -89,12 +90,15 @@ static int __write_console(struct xencons_info *xencons,
        XENCONS_RING_IDX cons, prod;
        struct xencons_interface *intf = xencons->intf;
        int sent = 0;
+       unsigned long flags;
 
+       spin_lock_irqsave(&xencons->ring_lock, flags);
        cons = intf->out_cons;
        prod = intf->out_prod;
        mb();                   /* update queue values before going on */
 
        if ((prod - cons) > sizeof(intf->out)) {
+               spin_unlock_irqrestore(&xencons->ring_lock, flags);
                pr_err_once("xencons: Illegal ring page indices");
                return -EINVAL;
        }
@@ -104,6 +108,7 @@ static int __write_console(struct xencons_info *xencons,
 
        wmb();                  /* write ring before updating pointer */
        intf->out_prod = prod;
+       spin_unlock_irqrestore(&xencons->ring_lock, flags);
 
        if (sent)
                notify_daemon(xencons);
@@ -146,16 +151,19 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
        int recv = 0;
        struct xencons_info *xencons = vtermno_to_xencons(vtermno);
        unsigned int eoiflag = 0;
+       unsigned long flags;
 
        if (xencons == NULL)
                return -EINVAL;
        intf = xencons->intf;
 
+       spin_lock_irqsave(&xencons->ring_lock, flags);
        cons = intf->in_cons;
        prod = intf->in_prod;
        mb();                   /* get pointers before reading ring */
 
        if ((prod - cons) > sizeof(intf->in)) {
+               spin_unlock_irqrestore(&xencons->ring_lock, flags);
                pr_err_once("xencons: Illegal ring page indices");
                return -EINVAL;
        }
@@ -179,10 +187,13 @@ static int domU_read_console(uint32_t vtermno, char *buf, int len)
                xencons->out_cons = intf->out_cons;
                xencons->out_cons_same = 0;
        }
+       if (!recv && xencons->out_cons_same++ > 1) {
+               eoiflag = XEN_EOI_FLAG_SPURIOUS;
+       }
+       spin_unlock_irqrestore(&xencons->ring_lock, flags);
+
        if (recv) {
                notify_daemon(xencons);
-       } else if (xencons->out_cons_same++ > 1) {
-               eoiflag = XEN_EOI_FLAG_SPURIOUS;
        }
 
        xen_irq_lateeoi(xencons->irq, eoiflag);
@@ -239,6 +250,7 @@ static int xen_hvm_console_init(void)
                info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
                if (!info)
                        return -ENOMEM;
+               spin_lock_init(&info->ring_lock);
        } else if (info->intf != NULL) {
                /* already configured */
                return 0;
@@ -275,6 +287,7 @@ err:
 
 static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
 {
+       spin_lock_init(&info->ring_lock);
        info->evtchn = xen_start_info->console.domU.evtchn;
        /* GFN == MFN for PV guest */
        info->intf = gfn_to_virt(xen_start_info->console.domU.mfn);
@@ -325,6 +338,7 @@ static int xen_initial_domain_console_init(void)
                info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
                if (!info)
                        return -ENOMEM;
+               spin_lock_init(&info->ring_lock);
        }
 
        info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
@@ -482,6 +496,7 @@ static int xencons_probe(struct xenbus_device *dev,
        info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
+       spin_lock_init(&info->ring_lock);
        dev_set_drvdata(&dev->dev, info);
        info->xbdev = dev;
        info->vtermno = xenbus_devid_to_vtermno(devid);
index aa80de3a819478e83b20839bce704c615afcf9b4..678014253b7b2642147d5ffe5b6367d0727f1a59 100644 (file)
@@ -534,7 +534,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
                if (!serdev)
                        continue;
 
-               serdev->dev.of_node = node;
+               device_set_node(&serdev->dev, of_fwnode_handle(node));
 
                err = serdev_device_add(serdev);
                if (err) {
index f8e99995eee911de69ceb5eb8d95dec876cb1acd..d94c3811a8f7af310528a36df2dd99fd28256c69 100644 (file)
@@ -106,8 +106,8 @@ static int serial8250_em_probe(struct platform_device *pdev)
        memset(&up, 0, sizeof(up));
        up.port.mapbase = regs->start;
        up.port.irq = irq;
-       up.port.type = PORT_UNKNOWN;
-       up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
+       up.port.type = PORT_16750;
+       up.port.flags = UPF_FIXED_PORT | UPF_IOREMAP | UPF_FIXED_TYPE;
        up.port.dev = &pdev->dev;
        up.port.private_data = priv;
 
index 8aad15622a2e5c869b94dfec762f98185e1d785e..8adfaa183f778d4a6f8cf21098025b2dac886691 100644 (file)
@@ -34,7 +34,7 @@ int fsl8250_handle_irq(struct uart_port *port)
 
        iir = port->serial_in(port, UART_IIR);
        if (iir & UART_IIR_NO_INT) {
-               spin_unlock(&up->port.lock);
+               spin_unlock_irqrestore(&up->port.lock, flags);
                return 0;
        }
 
@@ -42,7 +42,7 @@ int fsl8250_handle_irq(struct uart_port *port)
        if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
                up->lsr_saved_flags &= ~UART_LSR_BI;
                port->serial_in(port, UART_RX);
-               spin_unlock(&up->port.lock);
+               spin_unlock_irqrestore(&up->port.lock, flags);
                return 1;
        }
 
index fa43df05342bd5f72741c93172aa16659039c206..3ba9c8b93ae6c56510af4ee3bb07ec6e3e0bd6f3 100644 (file)
@@ -1903,6 +1903,17 @@ EXPORT_SYMBOL_GPL(serial8250_modem_status);
 static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)
 {
        switch (iir & 0x3f) {
+       case UART_IIR_THRI:
+               /*
+                * Postpone DMA or not decision to IIR_RDI or IIR_RX_TIMEOUT
+                * because it's impossible to do an informed decision about
+                * that with IIR_THRI.
+                *
+                * This also fixes one known DMA Rx corruption issue where
+                * DR is asserted but DMA Rx only gets a corrupted zero byte
+                * (too early DR?).
+                */
+               return false;
        case UART_IIR_RDI:
                if (!up->dma->rx_running)
                        break;
index 978dc196c29bea32ca85477337667f2449ec4fde..5313aa31930f4ec4ea8f798a03f8c08066b86b36 100644 (file)
@@ -257,8 +257,9 @@ config SERIAL_8250_ASPEED_VUART
        tristate "Aspeed Virtual UART"
        depends on SERIAL_8250
        depends on OF
-       depends on REGMAP && MFD_SYSCON
+       depends on MFD_SYSCON
        depends on ARCH_ASPEED || COMPILE_TEST
+       select REGMAP
        help
          If you want to use the virtual UART (VUART) device on Aspeed
          BMC platforms, enable this option. This enables the 16550A-
@@ -299,7 +300,6 @@ config SERIAL_8250_PCI1XXXX
        tristate "Microchip 8250 based serial port"
        depends on SERIAL_8250 && PCI
        select SERIAL_8250_PCILIB
-       default SERIAL_8250
        help
         Select this option if you have a setup with Microchip PCIe
         Switch with serial port enabled and wish to enable 8250
index 625358f44419743ffbc3d1663d1aae455df119b6..0072892ca7fc9df89a104270d1e35924cbe00746 100644 (file)
@@ -1313,7 +1313,7 @@ config SERIAL_FSL_LPUART
 
 config SERIAL_FSL_LPUART_CONSOLE
        bool "Console on Freescale lpuart serial port"
-       depends on SERIAL_FSL_LPUART
+       depends on SERIAL_FSL_LPUART=y
        select SERIAL_CORE_CONSOLE
        select SERIAL_EARLYCON
        help
index e945f41b93d4384b573c0ffe279da5c50c187ba1..074bfed57fc9e26c9c6db931ee89468d77f37a19 100644 (file)
@@ -858,11 +858,17 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port)
                        struct lpuart_port, port);
        unsigned long stat = lpuart32_read(port, UARTSTAT);
        unsigned long sfifo = lpuart32_read(port, UARTFIFO);
+       unsigned long ctrl = lpuart32_read(port, UARTCTRL);
 
        if (sport->dma_tx_in_progress)
                return 0;
 
-       if (stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT)
+       /*
+        * LPUART Transmission Complete Flag may never be set while queuing a break
+        * character, so avoid checking for transmission complete when UARTCTRL_SBK
+        * is asserted.
+        */
+       if ((stat & UARTSTAT_TC && sfifo & UARTFIFO_TXEMPT) || ctrl & UARTCTRL_SBK)
                return TIOCSER_TEMT;
 
        return 0;
@@ -1354,6 +1360,7 @@ static void lpuart_dma_rx_free(struct uart_port *port)
        struct dma_chan *chan = sport->dma_rx_chan;
 
        dmaengine_terminate_sync(chan);
+       del_timer_sync(&sport->lpuart_timer);
        dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);
        kfree(sport->rx_ring.buf);
        sport->rx_ring.tail = 0;
@@ -1813,7 +1820,6 @@ static int lpuart32_startup(struct uart_port *port)
 static void lpuart_dma_shutdown(struct lpuart_port *sport)
 {
        if (sport->lpuart_dma_rx_use) {
-               del_timer_sync(&sport->lpuart_timer);
                lpuart_dma_rx_free(&sport->port);
                sport->lpuart_dma_rx_use = false;
        }
@@ -1973,10 +1979,8 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,
         * Since timer function acqures sport->port.lock, need to stop before
         * acquring same lock because otherwise del_timer_sync() can deadlock.
         */
-       if (old && sport->lpuart_dma_rx_use) {
-               del_timer_sync(&sport->lpuart_timer);
+       if (old && sport->lpuart_dma_rx_use)
                lpuart_dma_rx_free(&sport->port);
-       }
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
@@ -2210,10 +2214,8 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
         * Since timer function acqures sport->port.lock, need to stop before
         * acquring same lock because otherwise del_timer_sync() can deadlock.
         */
-       if (old && sport->lpuart_dma_rx_use) {
-               del_timer_sync(&sport->lpuart_timer);
+       if (old && sport->lpuart_dma_rx_use)
                lpuart_dma_rx_free(&sport->port);
-       }
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
@@ -2240,9 +2242,15 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
        /* update the per-port timeout */
        uart_update_timeout(port, termios->c_cflag, baud);
 
-       /* wait transmit engin complete */
-       lpuart32_write(&sport->port, 0, UARTMODIR);
-       lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
+       /*
+        * LPUART Transmission Complete Flag may never be set while queuing a break
+        * character, so skip waiting for transmission complete when UARTCTRL_SBK is
+        * asserted.
+        */
+       if (!(old_ctrl & UARTCTRL_SBK)) {
+               lpuart32_write(&sport->port, 0, UARTMODIR);
+               lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
+       }
 
        /* disable transmit and receive */
        lpuart32_write(&sport->port, old_ctrl & ~(UARTCTRL_TE | UARTCTRL_RE),
@@ -2940,7 +2948,7 @@ static bool lpuart_uport_is_active(struct lpuart_port *sport)
        tty = tty_port_tty_get(port);
        if (tty) {
                tty_dev = tty->dev;
-               may_wake = device_may_wakeup(tty_dev);
+               may_wake = tty_dev && device_may_wakeup(tty_dev);
                tty_kref_put(tty);
        }
 
@@ -3014,7 +3022,6 @@ static int lpuart_suspend(struct device *dev)
                         * cannot resume as expected, hence gracefully release the
                         * Rx DMA path before suspend and start Rx DMA path on resume.
                         */
-                       del_timer_sync(&sport->lpuart_timer);
                        lpuart_dma_rx_free(&sport->port);
 
                        /* Disable Rx DMA to use UART port as wakeup source */
index d69592e5e2ec581743d1c155c8ad469453a701d4..28fbc927a546574e6d4559063034f629caffd9ed 100644 (file)
@@ -596,7 +596,7 @@ static void qcom_geni_serial_stop_tx_dma(struct uart_port *uport)
        if (!qcom_geni_serial_main_active(uport))
                return;
 
-       if (port->rx_dma_addr) {
+       if (port->tx_dma_addr) {
                geni_se_tx_dma_unprep(&port->se, port->tx_dma_addr,
                                      port->tx_remaining);
                port->tx_dma_addr = 0;
@@ -631,9 +631,8 @@ static void qcom_geni_serial_start_tx_dma(struct uart_port *uport)
        if (port->tx_dma_addr)
                return;
 
-       xmit_size = uart_circ_chars_pending(xmit);
-       if (xmit_size < WAKEUP_CHARS)
-               uart_write_wakeup(uport);
+       if (uart_circ_empty(xmit))
+               return;
 
        xmit_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 
@@ -1070,6 +1069,10 @@ static int setup_fifos(struct qcom_geni_serial_port *port)
 static void qcom_geni_serial_shutdown(struct uart_port *uport)
 {
        disable_irq(uport->irq);
+
+       if (uart_console(uport))
+               return;
+
        qcom_geni_serial_stop_tx(uport);
        qcom_geni_serial_stop_rx(uport);
 }
index 7bd0807209299bba3f6c7af65a8d7f492d71e7de..caa09a0c48f45d0c72d99e8d22b04aa30b2af317 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/ioport.h>
 #include <linux/ktime.h>
 #include <linux/major.h>
+#include <linux/minmax.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/of.h>
@@ -2864,6 +2865,13 @@ static int sci_init_single(struct platform_device *dev,
                        sci_port->irqs[i] = platform_get_irq(dev, i);
        }
 
+       /*
+        * The fourth interrupt on SCI port is transmit end interrupt, so
+        * shuffle the interrupts.
+        */
+       if (p->type == PORT_SCI)
+               swap(sci_port->irqs[SCIx_BRI_IRQ], sci_port->irqs[SCIx_TEI_IRQ]);
+
        /* The SCI generates several interrupts. They can be muxed together or
         * connected to different interrupt lines. In the muxed case only one
         * interrupt resource is specified as there is only one interrupt ID.
@@ -2929,7 +2937,7 @@ static int sci_init_single(struct platform_device *dev,
        port->flags             = UPF_FIXED_PORT | UPF_BOOT_AUTOCONF | p->flags;
        port->fifosize          = sci_port->params->fifosize;
 
-       if (port->type == PORT_SCI) {
+       if (port->type == PORT_SCI && !dev->dev.of_node) {
                if (sci_port->reg_size >= 0x20)
                        port->regshift = 2;
                else
index 57a5c23b51d47429c4c1d2d5a7a80d16beb2b75b..3c2ea9c098f7c4b36f1687f1b4834fe7de0a3e28 100644 (file)
@@ -4545,6 +4545,9 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
        int c;
        unsigned int vpitch = op->op == KD_FONT_OP_GET_TALL ? op->height : 32;
 
+       if (vpitch > max_font_height)
+               return -EINVAL;
+
        if (op->data) {
                font.data = kvmalloc(max_font_size, GFP_KERNEL);
                if (!font.data)
index 05eac965ee2759ccef20c3120727a5acb3fac94e..70b112038792aed022a9d3441ca862e3e42fdff3 100644 (file)
@@ -1409,13 +1409,6 @@ static int ufshcd_devfreq_target(struct device *dev,
        struct ufs_clk_info *clki;
        unsigned long irq_flags;
 
-       /*
-        * Skip devfreq if UFS initialization is not finished.
-        * Otherwise ufs could be in a inconsistent state.
-        */
-       if (!smp_load_acquire(&hba->logical_unit_scan_finished))
-               return 0;
-
        if (!ufshcd_is_clkscaling_supported(hba))
                return -EINVAL;
 
@@ -1500,7 +1493,7 @@ start_window:
        scaling->window_start_t = curr_t;
        scaling->tot_busy_t = 0;
 
-       if (hba->outstanding_reqs) {
+       if (scaling->active_reqs) {
                scaling->busy_start_t = curr_t;
                scaling->is_busy_started = true;
        } else {
@@ -2118,7 +2111,7 @@ static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba)
 
        spin_lock_irqsave(hba->host->host_lock, flags);
        hba->clk_scaling.active_reqs--;
-       if (!hba->outstanding_reqs && scaling->is_busy_started) {
+       if (!scaling->active_reqs && scaling->is_busy_started) {
                scaling->tot_busy_t += ktime_to_us(ktime_sub(ktime_get(),
                                        scaling->busy_start_t));
                scaling->busy_start_t = 0;
@@ -8399,6 +8392,22 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
        if (ret)
                goto out;
 
+       /* Initialize devfreq after UFS device is detected */
+       if (ufshcd_is_clkscaling_supported(hba)) {
+               memcpy(&hba->clk_scaling.saved_pwr_info.info,
+                       &hba->pwr_info,
+                       sizeof(struct ufs_pa_layer_attr));
+               hba->clk_scaling.saved_pwr_info.is_valid = true;
+               hba->clk_scaling.is_allowed = true;
+
+               ret = ufshcd_devfreq_init(hba);
+               if (ret)
+                       goto out;
+
+               hba->clk_scaling.is_enabled = true;
+               ufshcd_init_clk_scaling_sysfs(hba);
+       }
+
        ufs_bsg_probe(hba);
        ufshpb_init(hba);
        scsi_scan_host(hba->host);
@@ -8670,12 +8679,6 @@ out:
        if (ret) {
                pm_runtime_put_sync(hba->dev);
                ufshcd_hba_exit(hba);
-       } else {
-               /*
-                * Make sure that when reader code sees UFS initialization has finished,
-                * all initialization steps have really been executed.
-                */
-               smp_store_release(&hba->logical_unit_scan_finished, true);
        }
 }
 
@@ -10316,30 +10319,12 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
         */
        ufshcd_set_ufs_dev_active(hba);
 
-       /* Initialize devfreq */
-       if (ufshcd_is_clkscaling_supported(hba)) {
-               memcpy(&hba->clk_scaling.saved_pwr_info.info,
-                       &hba->pwr_info,
-                       sizeof(struct ufs_pa_layer_attr));
-               hba->clk_scaling.saved_pwr_info.is_valid = true;
-               hba->clk_scaling.is_allowed = true;
-
-               err = ufshcd_devfreq_init(hba);
-               if (err)
-                       goto rpm_put_sync;
-
-               hba->clk_scaling.is_enabled = true;
-               ufshcd_init_clk_scaling_sysfs(hba);
-       }
-
        async_schedule(ufshcd_async_scan, hba);
        ufs_sysfs_add_nodes(hba->dev);
 
        device_enable_async_suspend(dev);
        return 0;
 
-rpm_put_sync:
-       pm_runtime_put_sync(dev);
 free_tmf_queue:
        blk_mq_destroy_queue(hba->tmf_queue);
        blk_put_queue(hba->tmf_queue);
index deeea618ba33beccc840169a2ae85d1f6a8445d8..1f6320d98a76ba37b03e928c9ae965c9d5a01272 100644 (file)
@@ -60,6 +60,11 @@ static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev)
                        return NULL;
        }
 
+       if (func->devfn != PCI_DEV_FN_HOST_DEVICE &&
+           func->devfn != PCI_DEV_FN_OTG) {
+               return NULL;
+       }
+
        return func;
 }
 
index 9b8325f824992ad7829a12bb880304dcffe0e024..f317d3c84781082d00d27f13481a5f759e7d1515 100644 (file)
@@ -403,20 +403,6 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
        case USB_REQ_SET_ISOCH_DELAY:
                ret = cdnsp_ep0_set_isoch_delay(pdev, ctrl);
                break;
-       case USB_REQ_SET_INTERFACE:
-               /*
-                * Add request into pending list to block sending status stage
-                * by libcomposite.
-                */
-               list_add_tail(&pdev->ep0_preq.list,
-                             &pdev->ep0_preq.pep->pending_list);
-
-               ret = cdnsp_ep0_delegate_req(pdev, ctrl);
-               if (ret == -EBUSY)
-                       ret = 0;
-
-               list_del(&pdev->ep0_preq.list);
-               break;
        default:
                ret = cdnsp_ep0_delegate_req(pdev, ctrl);
                break;
@@ -428,7 +414,7 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
 void cdnsp_setup_analyze(struct cdnsp_device *pdev)
 {
        struct usb_ctrlrequest *ctrl = &pdev->setup;
-       int ret = 0;
+       int ret = -EINVAL;
        u16 len;
 
        trace_cdnsp_ctrl_req(ctrl);
@@ -438,7 +424,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
 
        if (pdev->gadget.state == USB_STATE_NOTATTACHED) {
                dev_err(pdev->dev, "ERR: Setup detected in unattached state\n");
-               ret = -EINVAL;
                goto out;
        }
 
@@ -474,9 +459,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
        else
                ret = cdnsp_ep0_delegate_req(pdev, ctrl);
 
-       if (!len)
-               pdev->ep0_stage = CDNSP_STATUS_STAGE;
-
        if (ret == USB_GADGET_DELAYED_STATUS) {
                trace_cdnsp_ep0_status_stage("delayed");
                return;
@@ -484,6 +466,6 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
 out:
        if (ret < 0)
                cdnsp_ep0_stall(pdev);
-       else if (pdev->ep0_stage == CDNSP_STATUS_STAGE)
+       else if (!len && pdev->ep0_stage != CDNSP_STATUS_STAGE)
                cdnsp_status_stage(pdev);
 }
index efd54ed918b9701e6f765408f298391219ffca3e..7b151f5af3ccb82ceb37c0a71a7c63da677d3d7b 100644 (file)
 #define PLAT_DRIVER_NAME       "cdns-usbssp"
 
 #define CDNS_VENDOR_ID         0x17cd
-#define CDNS_DEVICE_ID         0x0100
+#define CDNS_DEVICE_ID         0x0200
+#define CDNS_DRD_ID            0x0100
 #define CDNS_DRD_IF            (PCI_CLASS_SERIAL_USB << 8 | 0x80)
 
 static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
 {
-       struct pci_dev *func;
-
        /*
         * Gets the second function.
-        * It's little tricky, but this platform has two function.
-        * The fist keeps resources for Host/Device while the second
-        * keeps resources for DRD/OTG.
+        * Platform has two function. The fist keeps resources for
+        * Host/Device while the secon keeps resources for DRD/OTG.
         */
-       func = pci_get_device(pdev->vendor, pdev->device, NULL);
-       if (!func)
-               return NULL;
+       if (pdev->device == CDNS_DEVICE_ID)
+               return  pci_get_device(pdev->vendor, CDNS_DRD_ID, NULL);
+       else if (pdev->device == CDNS_DRD_ID)
+               return pci_get_device(pdev->vendor, CDNS_DEVICE_ID, NULL);
 
-       if (func->devfn == pdev->devfn) {
-               func = pci_get_device(pdev->vendor, pdev->device, func);
-               if (!func)
-                       return NULL;
-       }
-
-       return func;
+       return NULL;
 }
 
 static int cdnsp_pci_probe(struct pci_dev *pdev,
@@ -230,6 +223,8 @@ static const struct pci_device_id cdnsp_pci_ids[] = {
          PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID },
        { PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
          CDNS_DRD_IF, PCI_ANY_ID },
+       { PCI_VENDOR_ID_CDNS, CDNS_DRD_ID, PCI_ANY_ID, PCI_ANY_ID,
+         CDNS_DRD_IF, PCI_ANY_ID },
        { 0, }
 };
 
index 005c67cb3afb72cadc171d73cc5c25887a7939b3..f210b7489fd5b8ff825905da38c87674ce5a87a0 100644 (file)
@@ -208,6 +208,7 @@ struct hw_bank {
  * @in_lpm: if the core in low power mode
  * @wakeup_int: if wakeup interrupt occur
  * @rev: The revision number for controller
+ * @mutex: protect code from concorrent running when doing role switch
  */
 struct ci_hdrc {
        struct device                   *dev;
@@ -260,6 +261,7 @@ struct ci_hdrc {
        bool                            in_lpm;
        bool                            wakeup_int;
        enum ci_revision                rev;
+       struct mutex                    mutex;
 };
 
 static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
index 27c601296130e23f5b3d740d2b2944ccb2bbe586..281fc51720cea2ab9d0d63b486fb38c6c4f4ebfc 100644 (file)
@@ -984,9 +984,16 @@ static ssize_t role_store(struct device *dev,
                             strlen(ci->roles[role]->name)))
                        break;
 
-       if (role == CI_ROLE_END || role == ci->role)
+       if (role == CI_ROLE_END)
                return -EINVAL;
 
+       mutex_lock(&ci->mutex);
+
+       if (role == ci->role) {
+               mutex_unlock(&ci->mutex);
+               return n;
+       }
+
        pm_runtime_get_sync(dev);
        disable_irq(ci->irq);
        ci_role_stop(ci);
@@ -995,6 +1002,7 @@ static ssize_t role_store(struct device *dev,
                ci_handle_vbus_change(ci);
        enable_irq(ci->irq);
        pm_runtime_put_sync(dev);
+       mutex_unlock(&ci->mutex);
 
        return (ret == 0) ? n : ret;
 }
@@ -1030,6 +1038,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        spin_lock_init(&ci->lock);
+       mutex_init(&ci->mutex);
        ci->dev = dev;
        ci->platdata = dev_get_platdata(dev);
        ci->imx28_write_fix = !!(ci->platdata->flags &
index 622c3b68aa1e6a4bf55370d42ab4d3768eb478d8..f5490f2a5b6bca6b725c596d7536c2b548547d4b 100644 (file)
@@ -167,8 +167,10 @@ static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
 
 void ci_handle_id_switch(struct ci_hdrc *ci)
 {
-       enum ci_role role = ci_otg_role(ci);
+       enum ci_role role;
 
+       mutex_lock(&ci->mutex);
+       role = ci_otg_role(ci);
        if (role != ci->role) {
                dev_dbg(ci->dev, "switching from %s to %s\n",
                        ci_role(ci)->name, ci->roles[role]->name);
@@ -198,6 +200,7 @@ void ci_handle_id_switch(struct ci_hdrc *ci)
                if (role == CI_ROLE_GADGET)
                        ci_handle_vbus_change(ci);
        }
+       mutex_unlock(&ci->mutex);
 }
 /**
  * ci_otg_work - perform otg (vbus/id) event handle
index d8d6493bc4576ba767d0c13b0255592cbece1595..a8605b02115b1c3d0c6038c1dbb72e0e9ab3bac9 100644 (file)
@@ -35,7 +35,8 @@ static void dwc2_ovr_init(struct dwc2_hsotg *hsotg)
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
-       dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST));
+       dwc2_force_mode(hsotg, (hsotg->dr_mode == USB_DR_MODE_HOST) ||
+                               (hsotg->role_sw_default_mode == USB_DR_MODE_HOST));
 }
 
 static int dwc2_ovr_avalid(struct dwc2_hsotg *hsotg, bool valid)
index 62fa6378d2d73c63365e22ef0ea916517372a589..8b15742d9e8aa03301c41a7192207b33dd1a7293 100644 (file)
@@ -4549,8 +4549,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
        hsotg->gadget.dev.of_node = hsotg->dev->of_node;
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
-       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL ||
-           (hsotg->dr_mode == USB_DR_MODE_OTG && dwc2_is_device_mode(hsotg))) {
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
                ret = dwc2_lowlevel_hw_enable(hsotg);
                if (ret)
                        goto err;
@@ -4612,8 +4611,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
        if (!IS_ERR_OR_NULL(hsotg->uphy))
                otg_set_peripheral(hsotg->uphy->otg, NULL);
 
-       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL ||
-           (hsotg->dr_mode == USB_DR_MODE_OTG && dwc2_is_device_mode(hsotg)))
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
                dwc2_lowlevel_hw_disable(hsotg);
 
        return 0;
index 23ef759968231a80bab5e78cdf3217d7771298fc..d1589ba7d322dc6ccf8427ab29c131059c4ee80a 100644 (file)
@@ -91,13 +91,6 @@ static int dwc2_get_dr_mode(struct dwc2_hsotg *hsotg)
        return 0;
 }
 
-static void __dwc2_disable_regulators(void *data)
-{
-       struct dwc2_hsotg *hsotg = data;
-
-       regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-}
-
 static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
 {
        struct platform_device *pdev = to_platform_device(hsotg->dev);
@@ -108,11 +101,6 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
        if (ret)
                return ret;
 
-       ret = devm_add_action_or_reset(&pdev->dev,
-                                      __dwc2_disable_regulators, hsotg);
-       if (ret)
-               return ret;
-
        if (hsotg->clk) {
                ret = clk_prepare_enable(hsotg->clk);
                if (ret)
@@ -168,7 +156,7 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
        if (hsotg->clk)
                clk_disable_unprepare(hsotg->clk);
 
-       return 0;
+       return regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
 }
 
 /**
@@ -576,8 +564,7 @@ static int dwc2_driver_probe(struct platform_device *dev)
        dwc2_debugfs_init(hsotg);
 
        /* Gadget code manages lowlevel hw on its own */
-       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL ||
-           (hsotg->dr_mode == USB_DR_MODE_OTG && dwc2_is_device_mode(hsotg)))
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
                dwc2_lowlevel_hw_disable(hsotg);
 
 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
@@ -608,7 +595,7 @@ error_init:
        if (hsotg->params.activate_stm_id_vb_detection)
                regulator_disable(hsotg->usb33d);
 error:
-       if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL)
+       if (hsotg->ll_hw_enabled)
                dwc2_lowlevel_hw_disable(hsotg);
        return retval;
 }
index 582ebd9cf9c2e1ed4867404203efe8c9a0e11254..4743e918dcafa96aea30b238ca24d44c36745448 100644 (file)
@@ -1098,7 +1098,7 @@ struct dwc3_scratchpad_array {
  *                     change quirk.
  * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate
  *                     check during HS transmit.
- * @resume-hs-terminations: Set if we enable quirk for fixing improper crc
+ * @resume_hs_terminations: Set if we enable quirk for fixing improper crc
  *                     generation after resume from suspend.
  * @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed
  *                     instances in park mode.
index a23ddbb81979502ace7b66e93ea3b0c5f269ec5e..560793545362afc0ee105f54a086a87b003fbe46 100644 (file)
@@ -49,6 +49,7 @@
 #define PCI_DEVICE_ID_INTEL_RPLS               0x7a61
 #define PCI_DEVICE_ID_INTEL_MTLM               0x7eb1
 #define PCI_DEVICE_ID_INTEL_MTLP               0x7ec1
+#define PCI_DEVICE_ID_INTEL_MTLS               0x7f6f
 #define PCI_DEVICE_ID_INTEL_MTL                        0x7e7e
 #define PCI_DEVICE_ID_INTEL_TGL                        0x9a15
 #define PCI_DEVICE_ID_AMD_MR                   0x163a
@@ -474,6 +475,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLP),
          (kernel_ulong_t) &dwc3_pci_intel_swnode, },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTLS),
+         (kernel_ulong_t) &dwc3_pci_intel_swnode, },
+
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MTL),
          (kernel_ulong_t) &dwc3_pci_intel_swnode, },
 
index 3c63fa97a680041f7345b1f6aadddda4e6207a2b..cf5b4f49c3ed8241fdf34d5ebd9ae15d78c14e89 100644 (file)
@@ -1699,6 +1699,7 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
  */
 static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
 {
+       struct dwc3 *dwc = dep->dwc;
        struct dwc3_gadget_ep_cmd_params params;
        u32 cmd;
        int ret;
@@ -1722,10 +1723,13 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
 
-       if (!interrupt)
+       if (!interrupt) {
+               if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A))
+                       mdelay(1);
                dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-       else if (!ret)
+       } else if (!ret) {
                dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+       }
 
        dep->flags &= ~DWC3_EP_DELAY_STOP;
        return ret;
@@ -3774,7 +3778,11 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
         * enabled, the EndTransfer command will have completed upon
         * returning from this function.
         *
-        * This mode is NOT available on the DWC_usb31 IP.
+        * This mode is NOT available on the DWC_usb31 IP.  In this
+        * case, if the IOC bit is not set, then delay by 1ms
+        * after issuing the EndTransfer command.  This allows for the
+        * controller to handle the command completely before DWC3
+        * remove requests attempts to unmap USB request buffers.
         */
 
        __dwc3_stop_active_transfer(dep, force, interrupt);
index fa7dd6cf014d7b093da3fea48aee1a6981e9157e..5377d873c08eb6fb57895e1fe127f8b0fa16b68e 100644 (file)
@@ -2079,10 +2079,9 @@ unknown:
                                sizeof(url_descriptor->URL)
                                - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_offset);
 
-                       if (ctrl->wLength < WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH
-                                           + landing_page_length)
-                               landing_page_length = ctrl->wLength
-                                       - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_offset;
+                       if (w_length < WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_length)
+                               landing_page_length = w_length
+                               - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + landing_page_offset;
 
                        memcpy(url_descriptor->URL,
                                cdev->landing_page + landing_page_offset,
index ddfc537c7526b2256dd4a17f85daab0d8b1f739d..56cdfb2e42113eb27b29e2f675a104d84503c737 100644 (file)
@@ -1251,7 +1251,7 @@ static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to)
        p->kiocb = kiocb;
        if (p->aio) {
                p->to_free = dup_iter(&p->data, to, GFP_KERNEL);
-               if (!p->to_free) {
+               if (!iter_is_ubuf(&p->data) && !p->to_free) {
                        kfree(p);
                        return -ENOMEM;
                }
index c1f62e91b012634498bb7b299e59a018c28076d6..4a42574b4a7feb9ecc230889fe66f85e3c5ab8ea 100644 (file)
@@ -1422,7 +1422,7 @@ void g_audio_cleanup(struct g_audio *g_audio)
        uac = g_audio->uac;
        card = uac->card;
        if (card)
-               snd_card_free(card);
+               snd_card_free_when_closed(card);
 
        kfree(uac->p_prm.reqs);
        kfree(uac->c_prm.reqs);
index d605bc2e7e8fd43dd0725e221e22786d96e22bfd..28249d0bf0629fa73acb9c8b9c963fad52b0b619 100644 (file)
@@ -614,7 +614,7 @@ ep_read_iter(struct kiocb *iocb, struct iov_iter *to)
                if (!priv)
                        goto fail;
                priv->to_free = dup_iter(&priv->to, to, GFP_KERNEL);
-               if (!priv->to_free) {
+               if (!iter_is_ubuf(&priv->to) && !priv->to_free) {
                        kfree(priv);
                        goto fail;
                }
index fb988e4ea9244e160e7b2af6aabf01901b9b4d63..6db07ca419c317488e4c0918a39d2d3e6f6a5865 100644 (file)
@@ -771,12 +771,11 @@ static struct pci_driver xhci_pci_driver = {
        /* suspend and resume implemented later */
 
        .shutdown =     usb_hcd_pci_shutdown,
-       .driver = {
 #ifdef CONFIG_PM
-               .pm = &usb_hcd_pci_pm_ops,
-#endif
-               .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+       .driver = {
+               .pm = &usb_hcd_pci_pm_ops
        },
+#endif
 };
 
 static int __init xhci_pci_init(void)
index 1ff22f675930c41c7eb4383d5430441455ce9063..a88c39e525c235521d1583ca2807aced1bc96259 100644 (file)
@@ -1360,6 +1360,9 @@ static void tegra_xhci_id_work(struct work_struct *work)
 
        mutex_unlock(&tegra->lock);
 
+       tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(tegra->padctl,
+                                                                   tegra->otg_usb2_port);
+
        if (tegra->host_mode) {
                /* switch to host mode */
                if (tegra->otg_usb3_port >= 0) {
@@ -1474,9 +1477,6 @@ static int tegra_xhci_id_notify(struct notifier_block *nb,
        }
 
        tegra->otg_usb2_port = tegra_xusb_get_usb2_port(tegra, usbphy);
-       tegra->otg_usb3_port = tegra_xusb_padctl_get_usb3_companion(
-                                                       tegra->padctl,
-                                                       tegra->otg_usb2_port);
 
        tegra->host_mode = (usbphy->last_event == USB_EVENT_ID) ? true : false;
 
index 6183ce8574b1abcec88b35a5261601af8a72fc58..6307bae9cddffdf775786d976b28b7eadd8d0078 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/iommu.h>
 #include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/log2.h>
@@ -228,6 +229,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
 static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
 {
        struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+       struct iommu_domain *domain;
        int err, i;
        u64 val;
        u32 intrs;
@@ -246,7 +248,9 @@ static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
         * an iommu. Doing anything when there is no iommu is definitely
         * unsafe...
         */
-       if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !device_iommu_mapped(dev))
+       domain = iommu_get_domain_for_dev(dev);
+       if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !domain ||
+           domain->type == IOMMU_DOMAIN_IDENTITY)
                return;
 
        xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n");
@@ -4438,6 +4442,7 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
 
        if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
                spin_unlock_irqrestore(&xhci->lock, flags);
+               xhci_free_command(xhci, command);
                return 0;
        }
 
index 5402e4b7267b9957f0f6300099f20ccc50398944..12fc6eb67c3bf23a253ee1f48667499021d830d7 100644 (file)
@@ -410,6 +410,7 @@ static const struct usb_device_id onboard_hub_id_table[] = {
        { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 */
        { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 */
        { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */
+       { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */
        { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */
index 0a943a1546490293c3342609dd960f71cf046b50..aca5f50eb0da77f471816219d1e0d37ad57589cc 100644 (file)
@@ -36,6 +36,7 @@ static const struct onboard_hub_pdata vialab_vl817_data = {
 
 static const struct of_device_id onboard_hub_match[] = {
        { .compatible = "usb424,2514", .data = &microchip_usb424_data, },
+       { .compatible = "usb424,2517", .data = &microchip_usb424_data, },
        { .compatible = "usb451,8140", .data = &ti_tusb8041_data, },
        { .compatible = "usb451,8142", .data = &ti_tusb8041_data, },
        { .compatible = "usb5e3,608", .data = &genesys_gl850g_data, },
index 832ad592b7ef3bed8411922c9fec294591ea0756..cdea1bff3b708b819d58be6265fd0d8f617bd8b3 100644 (file)
@@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
        { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */
        { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
+       { USB_DEVICE(0x10C4, 0x82AA) }, /* Silicon Labs IFS-USB-DATACABLE used with Quint UPS */
        { USB_DEVICE(0x10C4, 0x82EF) }, /* CESINEL FALCO 6105 AC Power Supply */
        { USB_DEVICE(0x10C4, 0x82F1) }, /* CESINEL MEDCAL EFD Earth Fault Detector */
        { USB_DEVICE(0x10C4, 0x82F2) }, /* CESINEL MEDCAL ST Network Analyzer */
index e6d8d9b35ad0e2186a961746d9eaaed736d96a31..f31cc3c763299d4dc7affd31e7aa94c025841029 100644 (file)
@@ -1198,6 +1198,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0900, 0xff, 0, 0), /* RM500U-CN */
+         .driver_info = ZLP },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
@@ -1300,6 +1302,14 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(1) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff),    /* Telit FN990 (PCIe) */
          .driver_info = RSVD(0) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff),    /* Telit FE990 (rmnet) */
+         .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff),    /* Telit FE990 (MBIM) */
+         .driver_info = NCTRL(0) | RSVD(1) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1082, 0xff),    /* Telit FE990 (RNDIS) */
+         .driver_info = NCTRL(2) | RSVD(3) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff),    /* Telit FE990 (ECM) */
+         .driver_info = NCTRL(0) | RSVD(1) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
index c7b763d6d102394aba9080cfc104db9cb2b3c9c3..1f8c9b16a0fb850de066b2d1c071ff933fa4f4bf 100644 (file)
@@ -111,6 +111,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_BROKEN_FUA),
 
+/* Reported by: Yaroslav Furman <yaro330@gmail.com> */
+UNUSUAL_DEV(0x152d, 0x0583, 0x0000, 0x9999,
+               "JMicron",
+               "JMS583Gen 2",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_REPORT_OPCODES),
+
 /* Reported-by: Thinh Nguyen <thinhn@synopsys.com> */
 UNUSUAL_DEV(0x154b, 0xf00b, 0x0000, 0x9999,
                "PNY",
index 662cd043b50ea68468b7c5fc672364848ed2e749..8f3e884222adef512a424e16623ad3cad8565143 100644 (file)
@@ -112,8 +112,12 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
                if (dp->data.status & DP_STATUS_PREFER_MULTI_FUNC &&
                    pin_assign & DP_PIN_ASSIGN_MULTI_FUNC_MASK)
                        pin_assign &= DP_PIN_ASSIGN_MULTI_FUNC_MASK;
-               else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK)
+               else if (pin_assign & DP_PIN_ASSIGN_DP_ONLY_MASK) {
                        pin_assign &= DP_PIN_ASSIGN_DP_ONLY_MASK;
+                       /* Default to pin assign C if available */
+                       if (pin_assign & BIT(DP_PIN_ASSIGN_C))
+                               pin_assign = BIT(DP_PIN_ASSIGN_C);
+               }
 
                if (!pin_assign)
                        return -EINVAL;
index a0d943d785800fbbdb36a2cc5f206b5841697d64..1ee774c263f08c06ea87f28dcca1a83ef614e279 100644 (file)
@@ -1445,10 +1445,18 @@ static int tcpm_ams_start(struct tcpm_port *port, enum tcpm_ams ams)
 static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
                           const u32 *data, int cnt)
 {
+       u32 vdo_hdr = port->vdo_data[0];
+
        WARN_ON(!mutex_is_locked(&port->lock));
 
-       /* Make sure we are not still processing a previous VDM packet */
-       WARN_ON(port->vdm_state > VDM_STATE_DONE);
+       /* If is sending discover_identity, handle received message first */
+       if (PD_VDO_SVDM(vdo_hdr) && PD_VDO_CMD(vdo_hdr) == CMD_DISCOVER_IDENT) {
+               port->send_discover = true;
+               mod_send_discover_delayed_work(port, SEND_DISCOVER_RETRY_MS);
+       } else {
+               /* Make sure we are not still processing a previous VDM packet */
+               WARN_ON(port->vdm_state > VDM_STATE_DONE);
+       }
 
        port->vdo_count = cnt + 1;
        port->vdo_data[0] = header;
@@ -1948,11 +1956,13 @@ static void vdm_run_state_machine(struct tcpm_port *port)
                        switch (PD_VDO_CMD(vdo_hdr)) {
                        case CMD_DISCOVER_IDENT:
                                res = tcpm_ams_start(port, DISCOVER_IDENTITY);
-                               if (res == 0)
+                               if (res == 0) {
                                        port->send_discover = false;
-                               else if (res == -EAGAIN)
+                               } else if (res == -EAGAIN) {
+                                       port->vdo_data[0] = 0;
                                        mod_send_discover_delayed_work(port,
                                                                       SEND_DISCOVER_RETRY_MS);
+                               }
                                break;
                        case CMD_DISCOVER_SVID:
                                res = tcpm_ams_start(port, DISCOVER_SVIDS);
@@ -2035,6 +2045,7 @@ static void vdm_run_state_machine(struct tcpm_port *port)
                        unsigned long timeout;
 
                        port->vdm_retries = 0;
+                       port->vdo_data[0] = 0;
                        port->vdm_state = VDM_STATE_BUSY;
                        timeout = vdm_ready_timeout(vdo_hdr);
                        mod_vdm_delayed_work(port, timeout);
@@ -4570,6 +4581,9 @@ static void run_state_machine(struct tcpm_port *port)
        case SOFT_RESET:
                port->message_id = 0;
                port->rx_msgid = -1;
+               /* remove existing capabilities */
+               usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+               port->partner_source_caps = NULL;
                tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
                tcpm_ams_finish(port);
                if (port->pwr_role == TYPEC_SOURCE) {
@@ -4589,6 +4603,9 @@ static void run_state_machine(struct tcpm_port *port)
        case SOFT_RESET_SEND:
                port->message_id = 0;
                port->rx_msgid = -1;
+               /* remove existing capabilities */
+               usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+               port->partner_source_caps = NULL;
                if (tcpm_pd_send_control(port, PD_CTRL_SOFT_RESET))
                        tcpm_set_state_cond(port, hard_reset_state(port), 0);
                else
@@ -4718,6 +4735,9 @@ static void run_state_machine(struct tcpm_port *port)
                tcpm_set_state(port, SNK_STARTUP, 0);
                break;
        case PR_SWAP_SNK_SRC_SINK_OFF:
+               /* will be source, remove existing capabilities */
+               usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+               port->partner_source_caps = NULL;
                /*
                 * Prevent vbus discharge circuit from turning on during PR_SWAP
                 * as this is not a disconnect.
index f632350f6dcb2ad43bf4faa6509ce1d917c654b4..8d1baf28df55c90e3f3bf2078ee6373134ddcfc6 100644 (file)
@@ -1125,12 +1125,11 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
        return NULL;
 }
 
-static int ucsi_register_port(struct ucsi *ucsi, int index)
+static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
 {
        struct usb_power_delivery_desc desc = { ucsi->cap.pd_version};
        struct usb_power_delivery_capabilities_desc pd_caps;
        struct usb_power_delivery_capabilities *pd_cap;
-       struct ucsi_connector *con = &ucsi->connector[index];
        struct typec_capability *cap = &con->typec_cap;
        enum typec_accessory *accessory = cap->accessory;
        enum usb_role u_role = USB_ROLE_NONE;
@@ -1151,7 +1150,6 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
        init_completion(&con->complete);
        mutex_init(&con->lock);
        INIT_LIST_HEAD(&con->partner_tasks);
-       con->num = index + 1;
        con->ucsi = ucsi;
 
        cap->fwnode = ucsi_find_fwnode(con);
@@ -1328,8 +1326,8 @@ out_unlock:
  */
 static int ucsi_init(struct ucsi *ucsi)
 {
-       struct ucsi_connector *con;
-       u64 command;
+       struct ucsi_connector *con, *connector;
+       u64 command, ntfy;
        int ret;
        int i;
 
@@ -1341,8 +1339,8 @@ static int ucsi_init(struct ucsi *ucsi)
        }
 
        /* Enable basic notifications */
-       ucsi->ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
-       command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
+       ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR;
+       command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
        ret = ucsi_send_command(ucsi, command, NULL, 0);
        if (ret < 0)
                goto err_reset;
@@ -1359,31 +1357,33 @@ static int ucsi_init(struct ucsi *ucsi)
        }
 
        /* Allocate the connectors. Released in ucsi_unregister() */
-       ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1,
-                                 sizeof(*ucsi->connector), GFP_KERNEL);
-       if (!ucsi->connector) {
+       connector = kcalloc(ucsi->cap.num_connectors + 1, sizeof(*connector), GFP_KERNEL);
+       if (!connector) {
                ret = -ENOMEM;
                goto err_reset;
        }
 
        /* Register all connectors */
        for (i = 0; i < ucsi->cap.num_connectors; i++) {
-               ret = ucsi_register_port(ucsi, i);
+               connector[i].num = i + 1;
+               ret = ucsi_register_port(ucsi, &connector[i]);
                if (ret)
                        goto err_unregister;
        }
 
        /* Enable all notifications */
-       ucsi->ntfy = UCSI_ENABLE_NTFY_ALL;
-       command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
+       ntfy = UCSI_ENABLE_NTFY_ALL;
+       command = UCSI_SET_NOTIFICATION_ENABLE | ntfy;
        ret = ucsi_send_command(ucsi, command, NULL, 0);
        if (ret < 0)
                goto err_unregister;
 
+       ucsi->connector = connector;
+       ucsi->ntfy = ntfy;
        return 0;
 
 err_unregister:
-       for (con = ucsi->connector; con->port; con++) {
+       for (con = connector; con->port; con++) {
                ucsi_unregister_partner(con);
                ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
                ucsi_unregister_port_psy(con);
@@ -1399,10 +1399,7 @@ err_unregister:
                typec_unregister_port(con->port);
                con->port = NULL;
        }
-
-       kfree(ucsi->connector);
-       ucsi->connector = NULL;
-
+       kfree(connector);
 err_reset:
        memset(&ucsi->cap, 0, sizeof(ucsi->cap));
        ucsi_reset_ppm(ucsi);
index ce0c8ef80c04343d2d674579283cddfc567c3e85..62206a6b8ea75019e1ec767146a1a1d35e5e5b90 100644 (file)
@@ -78,7 +78,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
        if (ret)
                goto out_clear_bit;
 
-       if (!wait_for_completion_timeout(&ua->complete, HZ))
+       if (!wait_for_completion_timeout(&ua->complete, 5 * HZ))
                ret = -ETIMEDOUT;
 
 out_clear_bit:
index 058fbe28107e9e2740c698ad862a1b1b747c8cc1..25fc4120b618de16483ae2bd89af9bb866206bcd 100644 (file)
@@ -96,6 +96,7 @@ struct mlx5_vdpa_dev {
        struct mlx5_control_vq cvq;
        struct workqueue_struct *wq;
        unsigned int group2asid[MLX5_VDPA_NUMVQ_GROUPS];
+       bool suspended;
 };
 
 int mlx5_vdpa_alloc_pd(struct mlx5_vdpa_dev *dev, u32 *pdn, u16 uid);
index 3a0e721aef05fb419ca84c604ed29c79f8e84da8..195963b82b636340d4a1b73e15e25a6c5face806 100644 (file)
@@ -2438,7 +2438,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev,
        if (err)
                goto err_mr;
 
-       if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
+       if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK) || mvdev->suspended)
                goto err_mr;
 
        restore_channels_info(ndev);
@@ -2467,10 +2467,11 @@ static int setup_driver(struct mlx5_vdpa_dev *mvdev)
                err = 0;
                goto out;
        }
+       mlx5_vdpa_add_debugfs(ndev);
        err = setup_virtqueues(mvdev);
        if (err) {
                mlx5_vdpa_warn(mvdev, "setup_virtqueues\n");
-               goto out;
+               goto err_setup;
        }
 
        err = create_rqt(ndev);
@@ -2500,6 +2501,8 @@ err_tir:
        destroy_rqt(ndev);
 err_rqt:
        teardown_virtqueues(ndev);
+err_setup:
+       mlx5_vdpa_remove_debugfs(ndev->debugfs);
 out:
        return err;
 }
@@ -2513,6 +2516,8 @@ static void teardown_driver(struct mlx5_vdpa_net *ndev)
        if (!ndev->setup)
                return;
 
+       mlx5_vdpa_remove_debugfs(ndev->debugfs);
+       ndev->debugfs = NULL;
        teardown_steering(ndev);
        destroy_tir(ndev);
        destroy_rqt(ndev);
@@ -2606,6 +2611,7 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev)
        clear_vqs_ready(ndev);
        mlx5_vdpa_destroy_mr(&ndev->mvdev);
        ndev->mvdev.status = 0;
+       ndev->mvdev.suspended = false;
        ndev->cur_num_vqs = 0;
        ndev->mvdev.cvq.received_desc = 0;
        ndev->mvdev.cvq.completed_desc = 0;
@@ -2852,6 +2858,8 @@ static int mlx5_vdpa_suspend(struct vdpa_device *vdev)
        struct mlx5_vdpa_virtqueue *mvq;
        int i;
 
+       mlx5_vdpa_info(mvdev, "suspending device\n");
+
        down_write(&ndev->reslock);
        ndev->nb_registered = false;
        mlx5_notifier_unregister(mvdev->mdev, &ndev->nb);
@@ -2861,6 +2869,7 @@ static int mlx5_vdpa_suspend(struct vdpa_device *vdev)
                suspend_vq(ndev, mvq);
        }
        mlx5_vdpa_cvq_suspend(mvdev);
+       mvdev->suspended = true;
        up_write(&ndev->reslock);
        return 0;
 }
@@ -3257,7 +3266,6 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
        if (err)
                goto err_reg;
 
-       mlx5_vdpa_add_debugfs(ndev);
        mgtdev->ndev = ndev;
        return 0;
 
index 6a0a658146269a5d1c218d88747f4a6186060869..eea23c630f7c08d3abc33ef463529bde775e64b8 100644 (file)
@@ -68,6 +68,17 @@ static void vdpasim_queue_ready(struct vdpasim *vdpasim, unsigned int idx)
                          (uintptr_t)vq->device_addr);
 
        vq->vring.last_avail_idx = last_avail_idx;
+
+       /*
+        * Since vdpa_sim does not support receive inflight descriptors as a
+        * destination of a migration, let's set both avail_idx and used_idx
+        * the same at vq start.  This is how vhost-user works in a
+        * VHOST_SET_VRING_BASE call.
+        *
+        * Although the simple fix is to set last_used_idx at
+        * vdpasim_set_vq_state, it would be reset at vdpasim_queue_ready.
+        */
+       vq->vring.last_used_idx = last_avail_idx;
        vq->vring.notify = vdpasim_vq_notify;
 }
 
index 862f405362de27dc3ca88eefa3d3ac334a154fa5..dfe2ce34180356e408cb129a9ce0be77461bd64d 100644 (file)
@@ -466,16 +466,21 @@ static int vdpasim_net_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
 
        vdpasim_net_setup_config(simdev, config);
 
-       ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_NET_VQ_NUM);
-       if (ret)
-               goto reg_err;
-
        net = sim_to_net(simdev);
 
        u64_stats_init(&net->tx_stats.syncp);
        u64_stats_init(&net->rx_stats.syncp);
        u64_stats_init(&net->cq_stats.syncp);
 
+       /*
+        * Initialization must be completed before this call, since it can
+        * connect the device to the vDPA bus, so requests can arrive after
+        * this call.
+        */
+       ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_NET_VQ_NUM);
+       if (ret)
+               goto reg_err;
+
        return 0;
 
 reg_err:
index 8fe267ca3e76f2483501030aa838b9773321bac6..281287fae89f137e18e09d5c259115f3af1fcb4f 100644 (file)
@@ -645,8 +645,8 @@ static void vp_vdpa_remove(struct pci_dev *pdev)
        struct virtio_pci_modern_device *mdev = NULL;
 
        mdev = vp_vdpa_mgtdev->mdev;
-       vp_modern_remove(mdev);
        vdpa_mgmtdev_unregister(&vp_vdpa_mgtdev->mgtdev);
+       vp_modern_remove(mdev);
        kfree(vp_vdpa_mgtdev->mgtdev.id_table);
        kfree(mdev);
        kfree(vp_vdpa_mgtdev);
index e897537a9e8ad7e26238eee6c8bd90ab3fbaf6b6..d95fd382814c8f28ba4db8d78170e97441992cc9 100644 (file)
@@ -442,16 +442,10 @@ static long mlx5vf_precopy_ioctl(struct file *filp, unsigned int cmd,
        if (migf->pre_copy_initial_bytes > *pos) {
                info.initial_bytes = migf->pre_copy_initial_bytes - *pos;
        } else {
-               buf = mlx5vf_get_data_buff_from_pos(migf, *pos, &end_of_data);
-               if (buf) {
-                       info.dirty_bytes = buf->start_pos + buf->length - *pos;
-               } else {
-                       if (!end_of_data) {
-                               ret = -EINVAL;
-                               goto err_migf_unlock;
-                       }
-                       info.dirty_bytes = inc_length;
-               }
+               info.dirty_bytes = migf->max_pos - *pos;
+               if (!info.dirty_bytes)
+                       end_of_data = true;
+               info.dirty_bytes += inc_length;
        }
 
        if (!end_of_data || !inc_length) {
index 587fbae0618213ea5399a2cf0bf7f55cd8ed558b..b455d9ab6f3d9c989ca10f37efd1fbebbcae665b 100644 (file)
@@ -13,9 +13,14 @@ config VHOST_RING
          This option is selected by any driver which needs to access
          the host side of a virtio ring.
 
+config VHOST_TASK
+       bool
+       default n
+
 config VHOST
        tristate
        select VHOST_IOTLB
+       select VHOST_TASK
        help
          This option is selected by any driver which needs to access
          the core of vhost.
index b244e7c0f514ca3efdb676b771a4457780a2b7a2..e68f7d226bc9ff9482a8842c7e32dc5ba598236e 100644 (file)
@@ -125,7 +125,6 @@ struct vhost_scsi_tpg {
        struct se_portal_group se_tpg;
        /* Pointer back to vhost_scsi, protected by tv_tpg_mutex */
        struct vhost_scsi *vhost_scsi;
-       struct list_head tmf_queue;
 };
 
 struct vhost_scsi_tport {
@@ -206,10 +205,8 @@ struct vhost_scsi {
 
 struct vhost_scsi_tmf {
        struct vhost_work vwork;
-       struct vhost_scsi_tpg *tpg;
        struct vhost_scsi *vhost;
        struct vhost_scsi_virtqueue *svq;
-       struct list_head queue_entry;
 
        struct se_cmd se_cmd;
        u8 scsi_resp;
@@ -352,12 +349,9 @@ static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd)
 
 static void vhost_scsi_release_tmf_res(struct vhost_scsi_tmf *tmf)
 {
-       struct vhost_scsi_tpg *tpg = tmf->tpg;
        struct vhost_scsi_inflight *inflight = tmf->inflight;
 
-       mutex_lock(&tpg->tv_tpg_mutex);
-       list_add_tail(&tpg->tmf_queue, &tmf->queue_entry);
-       mutex_unlock(&tpg->tv_tpg_mutex);
+       kfree(tmf);
        vhost_scsi_put_inflight(inflight);
 }
 
@@ -671,7 +665,7 @@ vhost_scsi_calc_sgls(struct iov_iter *iter, size_t bytes, int max_sgls)
 {
        int sgl_count = 0;
 
-       if (!iter || !iter->iov) {
+       if (!iter || !iter_iov(iter)) {
                pr_err("%s: iter->iov is NULL, but expected bytes: %zu"
                       " present\n", __func__, bytes);
                return -EINVAL;
@@ -1194,19 +1188,11 @@ vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg,
                goto send_reject;
        }
 
-       mutex_lock(&tpg->tv_tpg_mutex);
-       if (list_empty(&tpg->tmf_queue)) {
-               pr_err("Missing reserve TMF. Could not handle LUN RESET.\n");
-               mutex_unlock(&tpg->tv_tpg_mutex);
+       tmf = kzalloc(sizeof(*tmf), GFP_KERNEL);
+       if (!tmf)
                goto send_reject;
-       }
-
-       tmf = list_first_entry(&tpg->tmf_queue, struct vhost_scsi_tmf,
-                              queue_entry);
-       list_del_init(&tmf->queue_entry);
-       mutex_unlock(&tpg->tv_tpg_mutex);
 
-       tmf->tpg = tpg;
+       vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work);
        tmf->vhost = vs;
        tmf->svq = svq;
        tmf->resp_iov = vq->iov[vc->out];
@@ -1658,7 +1644,10 @@ undepend:
        for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
                tpg = vs_tpg[i];
                if (tpg) {
+                       mutex_lock(&tpg->tv_tpg_mutex);
+                       tpg->vhost_scsi = NULL;
                        tpg->tv_tpg_vhost_count--;
+                       mutex_unlock(&tpg->tv_tpg_mutex);
                        target_undepend_item(&tpg->se_tpg.tpg_group.cg_item);
                }
        }
@@ -2032,19 +2021,11 @@ static int vhost_scsi_port_link(struct se_portal_group *se_tpg,
 {
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
-       struct vhost_scsi_tmf *tmf;
-
-       tmf = kzalloc(sizeof(*tmf), GFP_KERNEL);
-       if (!tmf)
-               return -ENOMEM;
-       INIT_LIST_HEAD(&tmf->queue_entry);
-       vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work);
 
        mutex_lock(&vhost_scsi_mutex);
 
        mutex_lock(&tpg->tv_tpg_mutex);
        tpg->tv_tpg_port_count++;
-       list_add_tail(&tmf->queue_entry, &tpg->tmf_queue);
        mutex_unlock(&tpg->tv_tpg_mutex);
 
        vhost_scsi_hotplug(tpg, lun);
@@ -2059,16 +2040,11 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
 {
        struct vhost_scsi_tpg *tpg = container_of(se_tpg,
                                struct vhost_scsi_tpg, se_tpg);
-       struct vhost_scsi_tmf *tmf;
 
        mutex_lock(&vhost_scsi_mutex);
 
        mutex_lock(&tpg->tv_tpg_mutex);
        tpg->tv_tpg_port_count--;
-       tmf = list_first_entry(&tpg->tmf_queue, struct vhost_scsi_tmf,
-                              queue_entry);
-       list_del(&tmf->queue_entry);
-       kfree(tmf);
        mutex_unlock(&tpg->tv_tpg_mutex);
 
        vhost_scsi_hotunplug(tpg, lun);
@@ -2329,7 +2305,6 @@ vhost_scsi_make_tpg(struct se_wwn *wwn, const char *name)
        }
        mutex_init(&tpg->tv_tpg_mutex);
        INIT_LIST_HEAD(&tpg->tv_tpg_list);
-       INIT_LIST_HEAD(&tpg->tmf_queue);
        tpg->tport = tport;
        tpg->tport_tpgt = tpgt;
 
index dc12dbd5b43ba6045078e621afd035e0b7946e8c..7be9d9d8f01c819d60e309ec1d6a83e46e03bf21 100644 (file)
@@ -1169,6 +1169,7 @@ static int vhost_vdpa_alloc_domain(struct vhost_vdpa *v)
 
 err_attach:
        iommu_domain_free(v->domain);
+       v->domain = NULL;
        return ret;
 }
 
@@ -1213,6 +1214,7 @@ static void vhost_vdpa_cleanup(struct vhost_vdpa *v)
                        vhost_vdpa_remove_as(v, asid);
        }
 
+       vhost_vdpa_free_domain(v);
        vhost_dev_cleanup(&v->vdev);
        kfree(v->vdev.vqs);
 }
@@ -1285,7 +1287,6 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
        vhost_vdpa_clean_irq(v);
        vhost_vdpa_reset(v);
        vhost_dev_stop(&v->vdev);
-       vhost_vdpa_free_domain(v);
        vhost_vdpa_config_put(v);
        vhost_vdpa_cleanup(v);
        mutex_unlock(&d->mutex);
index f11bdbe4c2c5ff712bd4fa929e77e8723a63c239..6d07b42833be4093b7c6a6f4b738e1b4ef800db9 100644 (file)
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/kthread.h>
-#include <linux/cgroup.h>
 #include <linux/module.h>
 #include <linux/sort.h>
 #include <linux/sched/mm.h>
 #include <linux/sched/signal.h>
+#include <linux/sched/vhost_task.h>
 #include <linux/interval_tree_generic.h>
 #include <linux/nospec.h>
 #include <linux/kcov.h>
@@ -255,8 +255,8 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
                 * sure it was not in the list.
                 * test_and_set_bit() implies a memory barrier.
                 */
-               llist_add(&work->node, &dev->work_list);
-               wake_up_process(dev->worker);
+               llist_add(&work->node, &dev->worker->work_list);
+               wake_up_process(dev->worker->vtsk->task);
        }
 }
 EXPORT_SYMBOL_GPL(vhost_work_queue);
@@ -264,7 +264,7 @@ EXPORT_SYMBOL_GPL(vhost_work_queue);
 /* A lockless hint for busy polling code to exit the loop */
 bool vhost_has_work(struct vhost_dev *dev)
 {
-       return !llist_empty(&dev->work_list);
+       return dev->worker && !llist_empty(&dev->worker->work_list);
 }
 EXPORT_SYMBOL_GPL(vhost_has_work);
 
@@ -335,22 +335,20 @@ static void vhost_vq_reset(struct vhost_dev *dev,
 
 static int vhost_worker(void *data)
 {
-       struct vhost_dev *dev = data;
+       struct vhost_worker *worker = data;
        struct vhost_work *work, *work_next;
        struct llist_node *node;
 
-       kthread_use_mm(dev->mm);
-
        for (;;) {
                /* mb paired w/ kthread_stop */
                set_current_state(TASK_INTERRUPTIBLE);
 
-               if (kthread_should_stop()) {
+               if (vhost_task_should_stop(worker->vtsk)) {
                        __set_current_state(TASK_RUNNING);
                        break;
                }
 
-               node = llist_del_all(&dev->work_list);
+               node = llist_del_all(&worker->work_list);
                if (!node)
                        schedule();
 
@@ -360,14 +358,14 @@ static int vhost_worker(void *data)
                llist_for_each_entry_safe(work, work_next, node, node) {
                        clear_bit(VHOST_WORK_QUEUED, &work->flags);
                        __set_current_state(TASK_RUNNING);
-                       kcov_remote_start_common(dev->kcov_handle);
+                       kcov_remote_start_common(worker->kcov_handle);
                        work->fn(work);
                        kcov_remote_stop();
                        if (need_resched())
                                schedule();
                }
        }
-       kthread_unuse_mm(dev->mm);
+
        return 0;
 }
 
@@ -479,7 +477,6 @@ void vhost_dev_init(struct vhost_dev *dev,
        dev->byte_weight = byte_weight;
        dev->use_worker = use_worker;
        dev->msg_handler = msg_handler;
-       init_llist_head(&dev->work_list);
        init_waitqueue_head(&dev->wait);
        INIT_LIST_HEAD(&dev->read_list);
        INIT_LIST_HEAD(&dev->pending_list);
@@ -509,31 +506,6 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
 }
 EXPORT_SYMBOL_GPL(vhost_dev_check_owner);
 
-struct vhost_attach_cgroups_struct {
-       struct vhost_work work;
-       struct task_struct *owner;
-       int ret;
-};
-
-static void vhost_attach_cgroups_work(struct vhost_work *work)
-{
-       struct vhost_attach_cgroups_struct *s;
-
-       s = container_of(work, struct vhost_attach_cgroups_struct, work);
-       s->ret = cgroup_attach_task_all(s->owner, current);
-}
-
-static int vhost_attach_cgroups(struct vhost_dev *dev)
-{
-       struct vhost_attach_cgroups_struct attach;
-
-       attach.owner = current;
-       vhost_work_init(&attach.work, vhost_attach_cgroups_work);
-       vhost_work_queue(dev, &attach.work);
-       vhost_dev_flush(dev);
-       return attach.ret;
-}
-
 /* Caller should have device mutex */
 bool vhost_dev_has_owner(struct vhost_dev *dev)
 {
@@ -571,10 +543,54 @@ static void vhost_detach_mm(struct vhost_dev *dev)
        dev->mm = NULL;
 }
 
+static void vhost_worker_free(struct vhost_dev *dev)
+{
+       struct vhost_worker *worker = dev->worker;
+
+       if (!worker)
+               return;
+
+       dev->worker = NULL;
+       WARN_ON(!llist_empty(&worker->work_list));
+       vhost_task_stop(worker->vtsk);
+       kfree(worker);
+}
+
+static int vhost_worker_create(struct vhost_dev *dev)
+{
+       struct vhost_worker *worker;
+       struct vhost_task *vtsk;
+       char name[TASK_COMM_LEN];
+       int ret;
+
+       worker = kzalloc(sizeof(*worker), GFP_KERNEL_ACCOUNT);
+       if (!worker)
+               return -ENOMEM;
+
+       dev->worker = worker;
+       worker->kcov_handle = kcov_common_handle();
+       init_llist_head(&worker->work_list);
+       snprintf(name, sizeof(name), "vhost-%d", current->pid);
+
+       vtsk = vhost_task_create(vhost_worker, worker, name);
+       if (!vtsk) {
+               ret = -ENOMEM;
+               goto free_worker;
+       }
+
+       worker->vtsk = vtsk;
+       vhost_task_start(vtsk);
+       return 0;
+
+free_worker:
+       kfree(worker);
+       dev->worker = NULL;
+       return ret;
+}
+
 /* Caller should have device mutex */
 long vhost_dev_set_owner(struct vhost_dev *dev)
 {
-       struct task_struct *worker;
        int err;
 
        /* Is there an owner already? */
@@ -585,36 +601,21 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
 
        vhost_attach_mm(dev);
 
-       dev->kcov_handle = kcov_common_handle();
        if (dev->use_worker) {
-               worker = kthread_create(vhost_worker, dev,
-                                       "vhost-%d", current->pid);
-               if (IS_ERR(worker)) {
-                       err = PTR_ERR(worker);
-                       goto err_worker;
-               }
-
-               dev->worker = worker;
-               wake_up_process(worker); /* avoid contributing to loadavg */
-
-               err = vhost_attach_cgroups(dev);
+               err = vhost_worker_create(dev);
                if (err)
-                       goto err_cgroup;
+                       goto err_worker;
        }
 
        err = vhost_dev_alloc_iovecs(dev);
        if (err)
-               goto err_cgroup;
+               goto err_iovecs;
 
        return 0;
-err_cgroup:
-       if (dev->worker) {
-               kthread_stop(dev->worker);
-               dev->worker = NULL;
-       }
+err_iovecs:
+       vhost_worker_free(dev);
 err_worker:
        vhost_detach_mm(dev);
-       dev->kcov_handle = 0;
 err_mm:
        return err;
 }
@@ -705,12 +706,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
        dev->iotlb = NULL;
        vhost_clear_msg(dev);
        wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM);
-       WARN_ON(!llist_empty(&dev->work_list));
-       if (dev->worker) {
-               kthread_stop(dev->worker);
-               dev->worker = NULL;
-               dev->kcov_handle = 0;
-       }
+       vhost_worker_free(dev);
        vhost_detach_mm(dev);
 }
 EXPORT_SYMBOL_GPL(vhost_dev_cleanup);
@@ -1831,7 +1827,7 @@ EXPORT_SYMBOL_GPL(vhost_dev_ioctl);
 
 /* TODO: This is really inefficient.  We need something like get_user()
  * (instruction directly accesses the data, with an exception table entry
- * returning -EFAULT). See Documentation/x86/exception-tables.rst.
+ * returning -EFAULT). See Documentation/arch/x86/exception-tables.rst.
  */
 static int set_bit_to_user(int nr, void __user *addr)
 {
index 1647b750169c79363b8e9ea3ac9c667d0af6af69..0308638cdeeebef46ca0ad98994eb8c6edd803f4 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/irqbypass.h>
 
 struct vhost_work;
+struct vhost_task;
 typedef void (*vhost_work_fn_t)(struct vhost_work *work);
 
 #define VHOST_WORK_QUEUED 1
@@ -25,6 +26,12 @@ struct vhost_work {
        unsigned long           flags;
 };
 
+struct vhost_worker {
+       struct vhost_task       *vtsk;
+       struct llist_head       work_list;
+       u64                     kcov_handle;
+};
+
 /* Poll a file (eventfd or socket) */
 /* Note: there's nothing vhost specific about this structure. */
 struct vhost_poll {
@@ -147,8 +154,7 @@ struct vhost_dev {
        struct vhost_virtqueue **vqs;
        int nvqs;
        struct eventfd_ctx *log_ctx;
-       struct llist_head work_list;
-       struct task_struct *worker;
+       struct vhost_worker *worker;
        struct vhost_iotlb *umem;
        struct vhost_iotlb *iotlb;
        spinlock_t iotlb_lock;
@@ -158,7 +164,6 @@ struct vhost_dev {
        int iov_limit;
        int weight;
        int byte_weight;
-       u64 kcov_handle;
        bool use_worker;
        int (*msg_handler)(struct vhost_dev *dev, u32 asid,
                           struct vhost_iotlb_msg *msg);
index f65c96d1394d3257a93dfc1b1ad82bb3432cf4ed..e45338227be6e03e102b2cf06a95d5afffa21d13 100644 (file)
@@ -854,7 +854,7 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
        board->caps = CLCD_CAP_ALL;
        board->check = clcdfb_check;
        board->decode = clcdfb_decode;
-       if (of_find_property(node, "memory-region", NULL)) {
+       if (of_property_present(node, "memory-region")) {
                board->setup = clcdfb_of_vram_setup;
                board->mmap = clcdfb_of_vram_mmap;
                board->remove = clcdfb_of_vram_remove;
index 81c3154544287763a30ff522e05bdc6305e51f21..b6b22fa4a8a01360095c3549dc63800f6dd0ddf9 100644 (file)
@@ -1040,6 +1040,9 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
        u32 pixclock;
        int screen_size, plane;
 
+       if (!var->pixclock)
+               return -EINVAL;
+
        plane = fbdev->plane;
 
        /* Make sure that the mode respect all LCD controller and
index 6403ae07970d6cbd7110f7b781627d628e69fd83..9cbadcd18b256c4ff0e525f7d09867d377d1028f 100644 (file)
@@ -306,7 +306,7 @@ static int bw2_probe(struct platform_device *op)
        if (!par->regs)
                goto out_release_fb;
 
-       if (!of_find_property(dp, "width", NULL)) {
+       if (!of_property_present(dp, "width")) {
                err = bw2_do_default_mode(par, info, &linebytes);
                if (err)
                        goto out_unmap_regs;
index bdcc3f6ab6665b6b31984f0e05b0c0bf4e594695..3a37fff4df3664df0ddf608f2908298a7bd3aa84 100644 (file)
@@ -393,7 +393,7 @@ static int cg3_probe(struct platform_device *op)
 
        cg3_blank(FB_BLANK_UNBLANK, info);
 
-       if (!of_find_property(dp, "width", NULL)) {
+       if (!of_property_present(dp, "width")) {
                err = cg3_do_default_mode(par);
                if (err)
                        goto out_unmap_screen;
index cc37ec3f8fc1f466af20402ff1254f1e780fcaff..7799d52a651f3273a8280f36e1c9174d15c50d52 100644 (file)
@@ -358,16 +358,21 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
        if (rc)
                return rc;
 
-       if (pci_enable_device(dp) < 0) {
+       rc = pci_enable_device(dp);
+       if (rc < 0) {
                dev_err(&dp->dev, "Cannot enable PCI device\n");
                goto err_out;
        }
 
-       if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
+       if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) {
+               rc = -ENODEV;
                goto err_disable;
+       }
        addr = pci_resource_start(dp, 0);
-       if (addr == 0)
+       if (addr == 0) {
+               rc = -ENODEV;
                goto err_disable;
+       }
 
        p = framebuffer_alloc(0, &dp->dev);
        if (p == NULL) {
@@ -417,7 +422,8 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
 
        init_chips(p, addr);
 
-       if (register_framebuffer(p) < 0) {
+       rc = register_framebuffer(p);
+       if (rc < 0) {
                dev_err(&dp->dev,"C&T 65550 framebuffer failed to register\n");
                goto err_unmap;
        }
index 45c75ff01eca4d938a496f0d37cc46d165aa717e..c8bfc608bd9c11ea61d48d3373abaa61e669d5b4 100644 (file)
@@ -238,8 +238,7 @@ static int clps711x_fb_probe(struct platform_device *pdev)
        info->fix.mmio_start = res->start;
        info->fix.mmio_len = resource_size(res);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       info->screen_base = devm_ioremap_resource(dev, res);
+       info->screen_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
        if (IS_ERR(info->screen_base)) {
                ret = PTR_ERR(info->screen_base);
                goto out_fb_release;
index aa5f059d022271c3ffe879edbd2d5027b51c710a..274f5d0fa24714ab31a7a6fcb1aa1667bda78c8a 100644 (file)
@@ -305,17 +305,18 @@ void fb_deferred_io_open(struct fb_info *info,
                         struct inode *inode,
                         struct file *file)
 {
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
        file->f_mapping->a_ops = &fb_deferred_io_aops;
+       fbdefio->open_count++;
 }
 EXPORT_SYMBOL_GPL(fb_deferred_io_open);
 
-void fb_deferred_io_release(struct fb_info *info)
+static void fb_deferred_io_lastclose(struct fb_info *info)
 {
-       struct fb_deferred_io *fbdefio = info->fbdefio;
        struct page *page;
        int i;
 
-       BUG_ON(!fbdefio);
        cancel_delayed_work_sync(&info->deferred_work);
 
        /* clear out the mapping that we setup */
@@ -324,13 +325,21 @@ void fb_deferred_io_release(struct fb_info *info)
                page->mapping = NULL;
        }
 }
+
+void fb_deferred_io_release(struct fb_info *info)
+{
+       struct fb_deferred_io *fbdefio = info->fbdefio;
+
+       if (!--fbdefio->open_count)
+               fb_deferred_io_lastclose(info);
+}
 EXPORT_SYMBOL_GPL(fb_deferred_io_release);
 
 void fb_deferred_io_cleanup(struct fb_info *info)
 {
        struct fb_deferred_io *fbdefio = info->fbdefio;
 
-       fb_deferred_io_release(info);
+       fb_deferred_io_lastclose(info);
 
        kvfree(info->pagerefs);
        mutex_destroy(&fbdefio->lock);
index 0a2c47df01f402b2221777a2d5ba78e748ceb43c..eb565a10e5cda306fb3f12b837d57a311599fb95 100644 (file)
@@ -823,7 +823,7 @@ static int set_con2fb_map(int unit, int newidx, int user)
        int oldidx = con2fb_map[unit];
        struct fb_info *info = fbcon_registered_fb[newidx];
        struct fb_info *oldinfo = NULL;
-       int found, err = 0, show_logo;
+       int err = 0, show_logo;
 
        WARN_CONSOLE_UNLOCKED();
 
@@ -841,26 +841,26 @@ static int set_con2fb_map(int unit, int newidx, int user)
        if (oldidx != -1)
                oldinfo = fbcon_registered_fb[oldidx];
 
-       found = search_fb_in_map(newidx);
-
-       if (!err && !found) {
+       if (!search_fb_in_map(newidx)) {
                err = con2fb_acquire_newinfo(vc, info, unit);
-               if (!err)
-                       con2fb_map[unit] = newidx;
+               if (err)
+                       return err;
+
+               fbcon_add_cursor_work(info);
        }
 
+       con2fb_map[unit] = newidx;
+
        /*
         * If old fb is not mapped to any of the consoles,
         * fbcon should release it.
         */
-       if (!err && oldinfo && !search_fb_in_map(oldidx))
+       if (oldinfo && !search_fb_in_map(oldidx))
                con2fb_release_oldinfo(vc, oldinfo, info);
 
        show_logo = (fg_console == 0 && !user &&
                         logo_shown != FBCON_LOGO_DONTSHOW);
 
-       if (!found)
-               fbcon_add_cursor_work(info);
        con2fb_map_boot[unit] = newidx;
        con2fb_init_display(vc, info, unit, show_logo);
 
index 875541ff185bf365f2a046e55c2421d50790649a..3fd95a79e4c334674e2bd6fdcecda747cdcd6c8c 100644 (file)
@@ -1116,6 +1116,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
        case FBIOPUT_VSCREENINFO:
                if (copy_from_user(&var, argp, sizeof(var)))
                        return -EFAULT;
+               /* only for kernel-internal use */
+               var.activate &= ~FB_ACTIVATE_KD_TEXT;
                console_lock();
                lock_fb_info(info);
                ret = fbcon_modechange_possible(info, &var);
index 8130e9eee2b4b4151a202358d0ce9d69964530de..556d8b1a9e06aefd6ec34796d9a60963c733f956 100644 (file)
@@ -235,6 +235,9 @@ static void get_modedb(struct fb_videomode **modedb, unsigned int *size)
 
 static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+       if (!var->pixclock)
+               return -EINVAL;
+
        if (var->xres > 1920 || var->yres > 1440)
                return -EINVAL;
 
index 0a9e5067b201083be2b74654b7c60ea89b575d43..a81095b2b1ea592e6eaabc03f0f880d459e9e1fd 100644 (file)
@@ -1222,6 +1222,9 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
 
        dinfo = GET_DINFO(info);
 
+       if (!var->pixclock)
+               return -EINVAL;
+
        /* update the pitch */
        if (intelfbhw_validate_mode(dinfo, var) != 0)
                return -EINVAL;
index e60a276b4855dcddd06a6ffbe46220b161bba7d5..ea4ba3dfb96bb51d149c0e288286269bc1a1ad0f 100644 (file)
@@ -764,6 +764,8 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var,
        int pitch, err = 0;
 
        NVTRACE_ENTER();
+       if (!var->pixclock)
+               return -EINVAL;
 
        var->transp.offset = 0;
        var->transp.length = 0;
index f7ad6bc9d02d718e3c10818000554005f3978e49..b97d251d894b7a9100f76b1f0eff7d2f20694e69 100644 (file)
@@ -549,10 +549,10 @@ static void offb_init_nodriver(struct platform_device *parent, struct device_nod
        int foreign_endian = 0;
 
 #ifdef __BIG_ENDIAN
-       if (of_get_property(dp, "little-endian", NULL))
+       if (of_property_read_bool(dp, "little-endian"))
                foreign_endian = FBINFO_FOREIGN_ENDIAN;
 #else
-       if (of_get_property(dp, "big-endian", NULL))
+       if (of_property_read_bool(dp, "big-endian"))
                foreign_endian = FBINFO_FOREIGN_ENDIAN;
 #endif
 
index 504edb9c09dd832dbe097581f903196ddc668faf..6d5082c76919d9ba26e168c1c2ef99622e143e7d 100644 (file)
@@ -18,7 +18,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o
 
 lcds-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o
 lcds-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o
-lcds-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o
 
 lcds-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o
 
diff --git a/drivers/video/fbdev/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c
deleted file mode 100644 (file)
index 8168ba0..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * LCD panel support for the TI OMAP OSK board
- *
- * Copyright (C) 2004 Nokia Corporation
- * Author: Imre Deak <imre.deak@nokia.com>
- * Adapted for OSK by <dirk.behme@de.bosch.com>
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <linux/soc/ti/omap1-io.h>
-#include <linux/soc/ti/omap1-mux.h>
-
-#include "omapfb.h"
-
-static int osk_panel_enable(struct lcd_panel *panel)
-{
-       /* configure PWL pin */
-       omap_cfg_reg(PWL);
-
-       /* Enable PWL unit */
-       omap_writeb(0x01, OMAP_PWL_CLK_ENABLE);
-
-       /* Set PWL level */
-       omap_writeb(0xFF, OMAP_PWL_ENABLE);
-
-       /* set GPIO2 high (lcd power enabled) */
-       gpio_set_value(2, 1);
-
-       return 0;
-}
-
-static void osk_panel_disable(struct lcd_panel *panel)
-{
-       /* Set PWL level to zero */
-       omap_writeb(0x00, OMAP_PWL_ENABLE);
-
-       /* Disable PWL unit */
-       omap_writeb(0x00, OMAP_PWL_CLK_ENABLE);
-
-       /* set GPIO2 low */
-       gpio_set_value(2, 0);
-}
-
-static struct lcd_panel osk_panel = {
-       .name           = "osk",
-       .config         = OMAP_LCDC_PANEL_TFT,
-
-       .bpp            = 16,
-       .data_lines     = 16,
-       .x_res          = 240,
-       .y_res          = 320,
-       .pixel_clock    = 12500,
-       .hsw            = 40,
-       .hfp            = 40,
-       .hbp            = 72,
-       .vsw            = 1,
-       .vfp            = 1,
-       .vbp            = 0,
-       .pcd            = 12,
-
-       .enable         = osk_panel_enable,
-       .disable        = osk_panel_disable,
-};
-
-static int osk_panel_probe(struct platform_device *pdev)
-{
-       omapfb_register_panel(&osk_panel);
-       return 0;
-}
-
-static struct platform_driver osk_panel_driver = {
-       .probe          = osk_panel_probe,
-       .driver         = {
-               .name   = "lcd_osk",
-       },
-};
-
-module_platform_driver(osk_panel_driver);
-
-MODULE_AUTHOR("Imre Deak");
-MODULE_DESCRIPTION("LCD panel support for the TI OMAP OSK board");
-MODULE_LICENSE("GPL");
index 1f3df2055ff0d5670cc8b1b79a25937413f79a88..18736079843dca4b6fd92a4b46b9db7388abfa41 100644 (file)
@@ -544,19 +544,25 @@ static int set_fb_var(struct fb_info *fbi,
                var->yoffset = var->yres_virtual - var->yres;
 
        if (plane->color_mode == OMAPFB_COLOR_RGB444) {
-               var->red.offset   = 8; var->red.length   = 4;
-                                               var->red.msb_right   = 0;
-               var->green.offset = 4; var->green.length = 4;
-                                               var->green.msb_right = 0;
-               var->blue.offset  = 0; var->blue.length  = 4;
-                                               var->blue.msb_right  = 0;
+               var->red.offset         = 8;
+               var->red.length         = 4;
+               var->red.msb_right      = 0;
+               var->green.offset       = 4;
+               var->green.length       = 4;
+               var->green.msb_right    = 0;
+               var->blue.offset        = 0;
+               var->blue.length        = 4;
+               var->blue.msb_right     = 0;
        } else {
-               var->red.offset  = 11; var->red.length   = 5;
-                                               var->red.msb_right   = 0;
-               var->green.offset = 5;  var->green.length = 6;
-                                               var->green.msb_right = 0;
-               var->blue.offset = 0;  var->blue.length  = 5;
-                                               var->blue.msb_right  = 0;
+               var->red.offset         = 11;
+               var->red.length         = 5;
+               var->red.msb_right      = 0;
+               var->green.offset       = 5;
+               var->green.length       = 6;
+               var->green.msb_right    = 0;
+               var->blue.offset        = 0;
+               var->blue.length        = 5;
+               var->blue.msb_right     = 0;
        }
 
        var->height             = -1;
index 0ae0cab252d3d0460e8b713f37496a3235872357..09f719af0d0c914c9b62b52b3549fb2b98037101 100644 (file)
@@ -192,7 +192,7 @@ static int __init omapdss_boot_init(void)
        omapdss_walk_device(dss, true);
 
        for_each_available_child_of_node(dss, child) {
-               if (!of_find_property(child, "compatible", NULL))
+               if (!of_property_present(child, "compatible"))
                        continue;
 
                omapdss_walk_device(child, true);
index c3cd1e1cc01b497fe2eaf8b0d5f368790a4e76a9..d16729215423d0909620d72b39b036452304743b 100644 (file)
@@ -599,8 +599,7 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev)
        priv->misc_dev.fops     = &pxa3xx_gcu_miscdev_fops;
 
        /* handle IO resources */
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->mmio_base = devm_ioremap_resource(dev, r);
+       priv->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
        if (IS_ERR(priv->mmio_base))
                return PTR_ERR(priv->mmio_base);
 
index f743bfbde2a6cb02e98fde4bbee27ddb2cf7b452..1f3cbe723def139e1f5cea1614d6e09c72c82028 100644 (file)
@@ -1737,10 +1737,10 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
 
 #if defined(CONFIG_OF)
 #ifdef __BIG_ENDIAN
-       if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
+       if (of_property_read_bool(info->dev->parent->of_node, "little-endian"))
                fb->flags |= FBINFO_FOREIGN_ENDIAN;
 #else
-       if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
+       if (of_property_read_bool(info->dev->parent->of_node, "big-endian"))
                fb->flags |= FBINFO_FOREIGN_ENDIAN;
 #endif
 #endif
index 3feb6e40d56d8c8db1ba4699dde09465050e1ec8..ef8a4c5fc6875c55e180eea152e84e72c55c39d0 100644 (file)
@@ -921,6 +921,28 @@ SETUP_HCRX(struct stifb_info *fb)
 
 /* ------------------- driver specific functions --------------------------- */
 
+static int
+stifb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct stifb_info *fb = container_of(info, struct stifb_info, info);
+
+       if (var->xres != fb->info.var.xres ||
+           var->yres != fb->info.var.yres ||
+           var->bits_per_pixel != fb->info.var.bits_per_pixel)
+               return -EINVAL;
+
+       var->xres_virtual = var->xres;
+       var->yres_virtual = var->yres;
+       var->xoffset = 0;
+       var->yoffset = 0;
+       var->grayscale = fb->info.var.grayscale;
+       var->red.length = fb->info.var.red.length;
+       var->green.length = fb->info.var.green.length;
+       var->blue.length = fb->info.var.blue.length;
+
+       return 0;
+}
+
 static int
 stifb_setcolreg(u_int regno, u_int red, u_int green,
              u_int blue, u_int transp, struct fb_info *info)
@@ -1145,6 +1167,7 @@ stifb_init_display(struct stifb_info *fb)
 
 static const struct fb_ops stifb_ops = {
        .owner          = THIS_MODULE,
+       .fb_check_var   = stifb_check_var,
        .fb_setcolreg   = stifb_setcolreg,
        .fb_blank       = stifb_blank,
        .fb_fillrect    = stifb_fillrect,
@@ -1164,6 +1187,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        struct stifb_info *fb;
        struct fb_info *info;
        unsigned long sti_rom_address;
+       char modestr[32];
        char *dev_name;
        int bpp, xres, yres;
 
@@ -1342,6 +1366,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
        info->flags = FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
        info->pseudo_palette = &fb->pseudo_palette;
 
+       scnprintf(modestr, sizeof(modestr), "%dx%d-%d", xres, yres, bpp);
+       fb_find_mode(&info->var, info, modestr, NULL, 0, NULL, bpp);
+
        /* This has to be done !!! */
        if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0))
                goto out_err1;
index 01d87f53324d985452afb511f343d16ab67ec0dd..f2eaf6e7fff604de0a191939d53120a182e5c3b5 100644 (file)
@@ -379,8 +379,7 @@ static int tcx_probe(struct platform_device *op)
 
        spin_lock_init(&par->lock);
 
-       par->lowdepth =
-               (of_find_property(dp, "tcx-8-bit", NULL) != NULL);
+       par->lowdepth = of_property_read_bool(dp, "tcx-8-bit");
 
        sbusfb_fill_var(&info->var, dp, 8);
        info->var.red.length = 8;
index 14d37c49633c6b36819bda002333b4d63b199795..b44004880f0d1e25119ab9028aafc9acd0c61177 100644 (file)
@@ -173,6 +173,9 @@ tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        struct tga_par *par = (struct tga_par *)info->par;
 
+       if (!var->pixclock)
+               return -EINVAL;
+
        if (par->tga_type == TGA_TYPE_8PLANE) {
                if (var->bits_per_pixel != 8)
                        return -EINVAL;
index 8f4d674fa0d03892ea22bf3ecb8bd8f355890b03..96a6f7623e197396ed7231215df7df3d9ff1d8e7 100644 (file)
@@ -261,7 +261,6 @@ static const struct fb_ops wm8505fb_ops = {
 static int wm8505fb_probe(struct platform_device *pdev)
 {
        struct wm8505fb_info    *fbi;
-       struct resource *res;
        struct display_timings *disp_timing;
        void                    *addr;
        int ret;
@@ -299,8 +298,7 @@ static int wm8505fb_probe(struct platform_device *pdev)
        addr = addr + sizeof(struct wm8505fb_info);
        fbi->fb.pseudo_palette  = addr;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
+       fbi->regbase = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(fbi->regbase))
                return PTR_ERR(fbi->regbase);
 
index 1ac83900a21ccef301d2a0557549b610bbe46127..7911354827dc25042720884f408c11a98ae373bd 100644 (file)
@@ -273,8 +273,7 @@ static int xilinxfb_assign(struct platform_device *pdev,
        if (drvdata->flags & BUS_ACCESS_FLAG) {
                struct resource *res;
 
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               drvdata->regs = devm_ioremap_resource(&pdev->dev, res);
+               drvdata->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
                if (IS_ERR(drvdata->regs))
                        return PTR_ERR(drvdata->regs);
 
@@ -469,8 +468,7 @@ static int xilinxfb_of_probe(struct platform_device *pdev)
                pdata.yvirt = prop[1];
        }
 
-       if (of_find_property(pdev->dev.of_node, "rotate-display", NULL))
-               pdata.rotate_screen = 1;
+       pdata.rotate_screen = of_property_read_bool(pdev->dev.of_node, "rotate-display");
 
        platform_set_drvdata(pdev, drvdata);
        return xilinxfb_assign(pdev, drvdata, &pdata);
index 4718d7895f0b451e4a529a4e1fcce6a85ec5a4c5..ada5ef6e51b7a9f61159101b39e5c299b010e61a 100644 (file)
@@ -1,15 +1,9 @@
-
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  *  Convert a logo in ASCII PNM format to C source suitable for inclusion in
  *  the Linux kernel
  *
  *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
- *
- *  --------------------------------------------------------------------------
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of the Linux
- *  distribution for more details.
  */
 
 #include <ctype.h>
@@ -34,37 +28,37 @@ static FILE *out;
 #define LINUX_LOGO_GRAY256     4       /* 256 levels grayscale */
 
 static const char *logo_types[LINUX_LOGO_GRAY256+1] = {
-    [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
-    [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
-    [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
-    [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
+       [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
+       [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
+       [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
+       [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
 };
 
 #define MAX_LINUX_LOGO_COLORS  224
 
 struct color {
-    unsigned char red;
-    unsigned char green;
-    unsigned char blue;
+       unsigned char red;
+       unsigned char green;
+       unsigned char blue;
 };
 
 static const struct color clut_vga16[16] = {
-    { 0x00, 0x00, 0x00 },
-    { 0x00, 0x00, 0xaa },
-    { 0x00, 0xaa, 0x00 },
-    { 0x00, 0xaa, 0xaa },
-    { 0xaa, 0x00, 0x00 },
-    { 0xaa, 0x00, 0xaa },
-    { 0xaa, 0x55, 0x00 },
-    { 0xaa, 0xaa, 0xaa },
-    { 0x55, 0x55, 0x55 },
-    { 0x55, 0x55, 0xff },
-    { 0x55, 0xff, 0x55 },
-    { 0x55, 0xff, 0xff },
-    { 0xff, 0x55, 0x55 },
-    { 0xff, 0x55, 0xff },
-    { 0xff, 0xff, 0x55 },
-    { 0xff, 0xff, 0xff },
+       { 0x00, 0x00, 0x00 },
+       { 0x00, 0x00, 0xaa },
+       { 0x00, 0xaa, 0x00 },
+       { 0x00, 0xaa, 0xaa },
+       { 0xaa, 0x00, 0x00 },
+       { 0xaa, 0x00, 0xaa },
+       { 0xaa, 0x55, 0x00 },
+       { 0xaa, 0xaa, 0xaa },
+       { 0x55, 0x55, 0x55 },
+       { 0x55, 0x55, 0xff },
+       { 0x55, 0xff, 0x55 },
+       { 0x55, 0xff, 0xff },
+       { 0xff, 0x55, 0x55 },
+       { 0xff, 0x55, 0xff },
+       { 0xff, 0xff, 0x55 },
+       { 0xff, 0xff, 0xff },
 };
 
 
@@ -77,438 +71,440 @@ static unsigned int logo_clutsize;
 static int is_plain_pbm = 0;
 
 static void die(const char *fmt, ...)
-    __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2)));
-static void usage(void) __attribute ((noreturn));
+__attribute__((noreturn)) __attribute((format (printf, 1, 2)));
+static void usage(void) __attribute((noreturn));
 
 
 static unsigned int get_number(FILE *fp)
 {
-    int c, val;
-
-    /* Skip leading whitespace */
-    do {
-       c = fgetc(fp);
-       if (c == EOF)
-           die("%s: end of file\n", filename);
-       if (c == '#') {
-           /* Ignore comments 'till end of line */
-           do {
+       int c, val;
+
+       /* Skip leading whitespace */
+       do {
                c = fgetc(fp);
                if (c == EOF)
-                   die("%s: end of file\n", filename);
-           } while (c != '\n');
+                       die("%s: end of file\n", filename);
+               if (c == '#') {
+                       /* Ignore comments 'till end of line */
+                       do {
+                               c = fgetc(fp);
+                               if (c == EOF)
+                                       die("%s: end of file\n", filename);
+                       } while (c != '\n');
+               }
+       } while (isspace(c));
+
+       /* Parse decimal number */
+       val = 0;
+       while (isdigit(c)) {
+               val = 10*val+c-'0';
+               /* some PBM are 'broken'; GiMP for example exports a PBM without space
+                * between the digits. This is Ok cause we know a PBM can only have a '1'
+                * or a '0' for the digit.
+                */
+               if (is_plain_pbm)
+                       break;
+               c = fgetc(fp);
+               if (c == EOF)
+                       die("%s: end of file\n", filename);
        }
-    } while (isspace(c));
-
-    /* Parse decimal number */
-    val = 0;
-    while (isdigit(c)) {
-       val = 10*val+c-'0';
-       /* some PBM are 'broken'; GiMP for example exports a PBM without space
-        * between the digits. This is Ok cause we know a PBM can only have a '1'
-        * or a '0' for the digit. */
-       if (is_plain_pbm)
-               break;
-       c = fgetc(fp);
-       if (c == EOF)
-           die("%s: end of file\n", filename);
-    }
-    return val;
+       return val;
 }
 
 static unsigned int get_number255(FILE *fp, unsigned int maxval)
 {
-    unsigned int val = get_number(fp);
-    return (255*val+maxval/2)/maxval;
+       unsigned int val = get_number(fp);
+
+       return (255*val+maxval/2)/maxval;
 }
 
 static void read_image(void)
 {
-    FILE *fp;
-    unsigned int i, j;
-    int magic;
-    unsigned int maxval;
-
-    /* open image file */
-    fp = fopen(filename, "r");
-    if (!fp)
-       die("Cannot open file %s: %s\n", filename, strerror(errno));
-
-    /* check file type and read file header */
-    magic = fgetc(fp);
-    if (magic != 'P')
-       die("%s is not a PNM file\n", filename);
-    magic = fgetc(fp);
-    switch (magic) {
+       FILE *fp;
+       unsigned int i, j;
+       int magic;
+       unsigned int maxval;
+
+       /* open image file */
+       fp = fopen(filename, "r");
+       if (!fp)
+               die("Cannot open file %s: %s\n", filename, strerror(errno));
+
+       /* check file type and read file header */
+       magic = fgetc(fp);
+       if (magic != 'P')
+               die("%s is not a PNM file\n", filename);
+       magic = fgetc(fp);
+       switch (magic) {
        case '1':
        case '2':
        case '3':
-           /* Plain PBM/PGM/PPM */
-           break;
+               /* Plain PBM/PGM/PPM */
+               break;
 
        case '4':
        case '5':
        case '6':
-           /* Binary PBM/PGM/PPM */
-           die("%s: Binary PNM is not supported\n"
+               /* Binary PBM/PGM/PPM */
+               die("%s: Binary PNM is not supported\n"
                "Use pnmnoraw(1) to convert it to ASCII PNM\n", filename);
 
        default:
-           die("%s is not a PNM file\n", filename);
-    }
-    logo_width = get_number(fp);
-    logo_height = get_number(fp);
-
-    /* allocate image data */
-    logo_data = (struct color **)malloc(logo_height*sizeof(struct color *));
-    if (!logo_data)
-       die("%s\n", strerror(errno));
-    for (i = 0; i < logo_height; i++) {
-       logo_data[i] = malloc(logo_width*sizeof(struct color));
+               die("%s is not a PNM file\n", filename);
+       }
+       logo_width = get_number(fp);
+       logo_height = get_number(fp);
+
+       /* allocate image data */
+       logo_data = (struct color **)malloc(logo_height*sizeof(struct color *));
+       if (!logo_data)
+               die("%s\n", strerror(errno));
+       for (i = 0; i < logo_height; i++) {
+               logo_data[i] = malloc(logo_width*sizeof(struct color));
        if (!logo_data[i])
-           die("%s\n", strerror(errno));
-    }
+               die("%s\n", strerror(errno));
+       }
 
-    /* read image data */
-    switch (magic) {
+       /* read image data */
+       switch (magic) {
        case '1':
-           /* Plain PBM */
-           is_plain_pbm = 1;
-           for (i = 0; i < logo_height; i++)
-               for (j = 0; j < logo_width; j++)
-                   logo_data[i][j].red = logo_data[i][j].green =
-                       logo_data[i][j].blue = 255*(1-get_number(fp));
-           break;
+               /* Plain PBM */
+               is_plain_pbm = 1;
+               for (i = 0; i < logo_height; i++)
+                       for (j = 0; j < logo_width; j++)
+                               logo_data[i][j].red = logo_data[i][j].green =
+                                       logo_data[i][j].blue = 255*(1-get_number(fp));
+               break;
 
        case '2':
-           /* Plain PGM */
-           maxval = get_number(fp);
-           for (i = 0; i < logo_height; i++)
-               for (j = 0; j < logo_width; j++)
-                   logo_data[i][j].red = logo_data[i][j].green =
-                       logo_data[i][j].blue = get_number255(fp, maxval);
-           break;
+               /* Plain PGM */
+               maxval = get_number(fp);
+               for (i = 0; i < logo_height; i++)
+                       for (j = 0; j < logo_width; j++)
+                               logo_data[i][j].red = logo_data[i][j].green =
+                                       logo_data[i][j].blue = get_number255(fp, maxval);
+               break;
 
        case '3':
-           /* Plain PPM */
-           maxval = get_number(fp);
-           for (i = 0; i < logo_height; i++)
-               for (j = 0; j < logo_width; j++) {
-                   logo_data[i][j].red = get_number255(fp, maxval);
-                   logo_data[i][j].green = get_number255(fp, maxval);
-                   logo_data[i][j].blue = get_number255(fp, maxval);
-               }
-           break;
-    }
+               /* Plain PPM */
+               maxval = get_number(fp);
+               for (i = 0; i < logo_height; i++)
+                       for (j = 0; j < logo_width; j++) {
+                               logo_data[i][j].red = get_number255(fp, maxval);
+                               logo_data[i][j].green = get_number255(fp, maxval);
+                               logo_data[i][j].blue = get_number255(fp, maxval);
+                       }
+               break;
+       }
 
-    /* close file */
-    fclose(fp);
+       /* close file */
+       fclose(fp);
 }
 
 static inline int is_black(struct color c)
 {
-    return c.red == 0 && c.green == 0 && c.blue == 0;
+       return c.red == 0 && c.green == 0 && c.blue == 0;
 }
 
 static inline int is_white(struct color c)
 {
-    return c.red == 255 && c.green == 255 && c.blue == 255;
+       return c.red == 255 && c.green == 255 && c.blue == 255;
 }
 
 static inline int is_gray(struct color c)
 {
-    return c.red == c.green && c.red == c.blue;
+       return c.red == c.green && c.red == c.blue;
 }
 
 static inline int is_equal(struct color c1, struct color c2)
 {
-    return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
+       return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
 }
 
 static void write_header(void)
 {
-    /* open logo file */
-    if (outputname) {
-       out = fopen(outputname, "w");
-       if (!out)
-           die("Cannot create file %s: %s\n", outputname, strerror(errno));
-    } else {
-       out = stdout;
-    }
-
-    fputs("/*\n", out);
-    fputs(" *  DO NOT EDIT THIS FILE!\n", out);
-    fputs(" *\n", out);
-    fprintf(out, " *  It was automatically generated from %s\n", filename);
-    fputs(" *\n", out);
-    fprintf(out, " *  Linux logo %s\n", logoname);
-    fputs(" */\n\n", out);
-    fputs("#include <linux/linux_logo.h>\n\n", out);
-    fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
-           logoname);
+       /* open logo file */
+       if (outputname) {
+               out = fopen(outputname, "w");
+               if (!out)
+                       die("Cannot create file %s: %s\n", outputname, strerror(errno));
+       } else {
+               out = stdout;
+       }
+
+       fputs("/*\n", out);
+       fputs(" *  DO NOT EDIT THIS FILE!\n", out);
+       fputs(" *\n", out);
+       fprintf(out, " *  It was automatically generated from %s\n", filename);
+       fputs(" *\n", out);
+       fprintf(out, " *  Linux logo %s\n", logoname);
+       fputs(" */\n\n", out);
+       fputs("#include <linux/linux_logo.h>\n\n", out);
+       fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
+               logoname);
 }
 
 static void write_footer(void)
 {
-    fputs("\n};\n\n", out);
-    fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
-    fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
-    fprintf(out, "\t.width\t\t= %d,\n", logo_width);
-    fprintf(out, "\t.height\t\t= %d,\n", logo_height);
-    if (logo_type == LINUX_LOGO_CLUT224) {
-       fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize);
-       fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
-    }
-    fprintf(out, "\t.data\t\t= %s_data\n", logoname);
-    fputs("};\n\n", out);
-
-    /* close logo file */
-    if (outputname)
-       fclose(out);
+       fputs("\n};\n\n", out);
+       fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
+       fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
+       fprintf(out, "\t.width\t\t= %d,\n", logo_width);
+       fprintf(out, "\t.height\t\t= %d,\n", logo_height);
+       if (logo_type == LINUX_LOGO_CLUT224) {
+               fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize);
+               fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
+       }
+       fprintf(out, "\t.data\t\t= %s_data\n", logoname);
+       fputs("};\n\n", out);
+
+       /* close logo file */
+       if (outputname)
+               fclose(out);
 }
 
 static int write_hex_cnt;
 
 static void write_hex(unsigned char byte)
 {
-    if (write_hex_cnt % 12)
-       fprintf(out, ", 0x%02x", byte);
-    else if (write_hex_cnt)
-       fprintf(out, ",\n\t0x%02x", byte);
-    else
-       fprintf(out, "\t0x%02x", byte);
-    write_hex_cnt++;
+       if (write_hex_cnt % 12)
+               fprintf(out, ", 0x%02x", byte);
+       else if (write_hex_cnt)
+               fprintf(out, ",\n\t0x%02x", byte);
+       else
+               fprintf(out, "\t0x%02x", byte);
+       write_hex_cnt++;
 }
 
 static void write_logo_mono(void)
 {
-    unsigned int i, j;
-    unsigned char val, bit;
-
-    /* validate image */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++)
-           if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
-               die("Image must be monochrome\n");
-
-    /* write file header */
-    write_header();
-
-    /* write logo data */
-    for (i = 0; i < logo_height; i++) {
-       for (j = 0; j < logo_width;) {
-           for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
-               if (logo_data[i][j].red)
-                   val |= bit;
-           write_hex(val);
+       unsigned int i, j;
+       unsigned char val, bit;
+
+       /* validate image */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++)
+                       if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
+                               die("Image must be monochrome\n");
+
+       /* write file header */
+       write_header();
+
+       /* write logo data */
+       for (i = 0; i < logo_height; i++) {
+               for (j = 0; j < logo_width;) {
+                       for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
+                               if (logo_data[i][j].red)
+                                       val |= bit;
+                       write_hex(val);
+               }
        }
-    }
 
-    /* write logo structure and file footer */
-    write_footer();
+       /* write logo structure and file footer */
+       write_footer();
 }
 
 static void write_logo_vga16(void)
 {
-    unsigned int i, j, k;
-    unsigned char val;
-
-    /* validate image */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++) {
-           for (k = 0; k < 16; k++)
-               if (is_equal(logo_data[i][j], clut_vga16[k]))
-                   break;
-           if (k == 16)
-               die("Image must use the 16 console colors only\n"
-                   "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
-                   "of colors\n");
-       }
+       unsigned int i, j, k;
+       unsigned char val;
 
-    /* write file header */
-    write_header();
-
-    /* write logo data */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++) {
-           for (k = 0; k < 16; k++)
-               if (is_equal(logo_data[i][j], clut_vga16[k]))
-                   break;
-           val = k<<4;
-           if (++j < logo_width) {
-               for (k = 0; k < 16; k++)
-                   if (is_equal(logo_data[i][j], clut_vga16[k]))
-                       break;
-               val |= k;
-           }
-           write_hex(val);
-       }
+       /* validate image */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++) {
+                       for (k = 0; k < 16; k++)
+                               if (is_equal(logo_data[i][j], clut_vga16[k]))
+                                       break;
+                       if (k == 16)
+                               die("Image must use the 16 console colors only\n"
+                                   "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
+                                   "of colors\n");
+               }
 
-    /* write logo structure and file footer */
-    write_footer();
+       /* write file header */
+       write_header();
+
+       /* write logo data */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++) {
+                       for (k = 0; k < 16; k++)
+                               if (is_equal(logo_data[i][j], clut_vga16[k]))
+                                       break;
+                       val = k<<4;
+                       if (++j < logo_width) {
+                               for (k = 0; k < 16; k++)
+                                       if (is_equal(logo_data[i][j], clut_vga16[k]))
+                                               break;
+                               val |= k;
+                       }
+                       write_hex(val);
+               }
+
+       /* write logo structure and file footer */
+       write_footer();
 }
 
 static void write_logo_clut224(void)
 {
-    unsigned int i, j, k;
-
-    /* validate image */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++) {
-           for (k = 0; k < logo_clutsize; k++)
-               if (is_equal(logo_data[i][j], logo_clut[k]))
-                   break;
-           if (k == logo_clutsize) {
-               if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
-                   die("Image has more than %d colors\n"
-                       "Use ppmquant(1) to reduce the number of colors\n",
-                       MAX_LINUX_LOGO_COLORS);
-               logo_clut[logo_clutsize++] = logo_data[i][j];
-           }
-       }
+       unsigned int i, j, k;
 
-    /* write file header */
-    write_header();
+       /* validate image */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++) {
+                       for (k = 0; k < logo_clutsize; k++)
+                               if (is_equal(logo_data[i][j], logo_clut[k]))
+                                       break;
+                       if (k == logo_clutsize) {
+                               if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
+                                       die("Image has more than %d colors\n"
+                                           "Use ppmquant(1) to reduce the number of colors\n",
+                                           MAX_LINUX_LOGO_COLORS);
+                               logo_clut[logo_clutsize++] = logo_data[i][j];
+                       }
+               }
 
-    /* write logo data */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++) {
-           for (k = 0; k < logo_clutsize; k++)
-               if (is_equal(logo_data[i][j], logo_clut[k]))
-                   break;
-           write_hex(k+32);
+       /* write file header */
+       write_header();
+
+       /* write logo data */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++) {
+                       for (k = 0; k < logo_clutsize; k++)
+                               if (is_equal(logo_data[i][j], logo_clut[k]))
+                                       break;
+                       write_hex(k+32);
+               }
+       fputs("\n};\n\n", out);
+
+       /* write logo clut */
+       fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
+               logoname);
+       write_hex_cnt = 0;
+       for (i = 0; i < logo_clutsize; i++) {
+               write_hex(logo_clut[i].red);
+               write_hex(logo_clut[i].green);
+               write_hex(logo_clut[i].blue);
        }
-    fputs("\n};\n\n", out);
-
-    /* write logo clut */
-    fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
-           logoname);
-    write_hex_cnt = 0;
-    for (i = 0; i < logo_clutsize; i++) {
-       write_hex(logo_clut[i].red);
-       write_hex(logo_clut[i].green);
-       write_hex(logo_clut[i].blue);
-    }
-
-    /* write logo structure and file footer */
-    write_footer();
+
+       /* write logo structure and file footer */
+       write_footer();
 }
 
 static void write_logo_gray256(void)
 {
-    unsigned int i, j;
+       unsigned int i, j;
 
-    /* validate image */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++)
-           if (!is_gray(logo_data[i][j]))
-               die("Image must be grayscale\n");
+       /* validate image */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++)
+                       if (!is_gray(logo_data[i][j]))
+                               die("Image must be grayscale\n");
 
-    /* write file header */
-    write_header();
+       /* write file header */
+       write_header();
 
-    /* write logo data */
-    for (i = 0; i < logo_height; i++)
-       for (j = 0; j < logo_width; j++)
-           write_hex(logo_data[i][j].red);
+       /* write logo data */
+       for (i = 0; i < logo_height; i++)
+               for (j = 0; j < logo_width; j++)
+                       write_hex(logo_data[i][j].red);
 
-    /* write logo structure and file footer */
-    write_footer();
+       /* write logo structure and file footer */
+       write_footer();
 }
 
 static void die(const char *fmt, ...)
 {
-    va_list ap;
+       va_list ap;
 
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
 
-    exit(1);
+       exit(1);
 }
 
 static void usage(void)
 {
-    die("\n"
+       die("\n"
        "Usage: %s [options] <filename>\n"
        "\n"
        "Valid options:\n"
-       "    -h          : display this usage information\n"
-       "    -n <name>   : specify logo name (default: linux_logo)\n"
-       "    -o <output> : output to file <output> instead of stdout\n"
-       "    -t <type>   : specify logo type, one of\n"
-       "                      mono    : monochrome black/white\n"
-       "                      vga16   : 16 colors VGA text palette\n"
-       "                      clut224 : 224 colors (default)\n"
-       "                      gray256 : 256 levels grayscale\n"
+       "       -h                : display this usage information\n"
+       "       -n <name>   : specify logo name (default: linux_logo)\n"
+       "       -o <output> : output to file <output> instead of stdout\n"
+       "       -t <type>   : specify logo type, one of\n"
+       "                                         mono  : monochrome black/white\n"
+       "                                         vga16   : 16 colors VGA text palette\n"
+       "                                         clut224 : 224 colors (default)\n"
+       "                                         gray256 : 256 levels grayscale\n"
        "\n", programname);
 }
 
 int main(int argc, char *argv[])
 {
-    int opt;
+       int opt;
 
-    programname = argv[0];
+       programname = argv[0];
 
-    opterr = 0;
-    while (1) {
-       opt = getopt(argc, argv, "hn:o:t:");
-       if (opt == -1)
-           break;
+       opterr = 0;
+       while (1) {
+               opt = getopt(argc, argv, "hn:o:t:");
+               if (opt == -1)
+                       break;
 
-       switch (opt) {
-           case 'h':
-               usage();
-               break;
+               switch (opt) {
+               case 'h':
+                       usage();
+                       break;
 
-           case 'n':
-               logoname = optarg;
-               break;
+               case 'n':
+                       logoname = optarg;
+                       break;
 
-           case 'o':
-               outputname = optarg;
-               break;
+               case 'o':
+                       outputname = optarg;
+                       break;
 
-           case 't':
-               if (!strcmp(optarg, "mono"))
-                   logo_type = LINUX_LOGO_MONO;
-               else if (!strcmp(optarg, "vga16"))
-                   logo_type = LINUX_LOGO_VGA16;
-               else if (!strcmp(optarg, "clut224"))
-                   logo_type = LINUX_LOGO_CLUT224;
-               else if (!strcmp(optarg, "gray256"))
-                   logo_type = LINUX_LOGO_GRAY256;
-               else
-                   usage();
-               break;
+               case 't':
+                       if (!strcmp(optarg, "mono"))
+                               logo_type = LINUX_LOGO_MONO;
+                       else if (!strcmp(optarg, "vga16"))
+                               logo_type = LINUX_LOGO_VGA16;
+                       else if (!strcmp(optarg, "clut224"))
+                               logo_type = LINUX_LOGO_CLUT224;
+                       else if (!strcmp(optarg, "gray256"))
+                               logo_type = LINUX_LOGO_GRAY256;
+                       else
+                               usage();
+                       break;
 
-           default:
-               usage();
-               break;
+               default:
+                       usage();
+                       break;
+               }
        }
-    }
-    if (optind != argc-1)
-       usage();
+       if (optind != argc-1)
+               usage();
 
-    filename = argv[optind];
+       filename = argv[optind];
 
-    read_image();
-    switch (logo_type) {
+       read_image();
+       switch (logo_type) {
        case LINUX_LOGO_MONO:
-           write_logo_mono();
-           break;
+               write_logo_mono();
+               break;
 
        case LINUX_LOGO_VGA16:
-           write_logo_vga16();
-           break;
+               write_logo_vga16();
+               break;
 
        case LINUX_LOGO_CLUT224:
-           write_logo_clut224();
-           break;
+               write_logo_clut224();
+               break;
 
        case LINUX_LOGO_GRAY256:
-           write_logo_gray256();
-           break;
-    }
-    exit(0);
+               write_logo_gray256();
+               break;
+       }
+       exit(0);
 }
index 7b4e9009f33559fe04a11c17af5433715b625893..97dbe715e96adfab478a255354f731c1dfdd55ee 100644 (file)
@@ -31,6 +31,9 @@
 #define AAD_LEN                48
 #define MSG_HDR_VER    1
 
+#define SNP_REQ_MAX_RETRY_DURATION     (60*HZ)
+#define SNP_REQ_RETRY_DELAY            (2*HZ)
+
 struct snp_guest_crypto {
        struct crypto_aead *tfm;
        u8 *iv, *authtag;
@@ -43,7 +46,15 @@ struct snp_guest_dev {
 
        void *certs_data;
        struct snp_guest_crypto *crypto;
+       /* request and response are in unencrypted memory */
        struct snp_guest_msg *request, *response;
+
+       /*
+        * Avoid information leakage by double-buffering shared messages
+        * in fields that are in regular encrypted memory.
+        */
+       struct snp_guest_msg secret_request, secret_response;
+
        struct snp_secrets_page_layout *layout;
        struct snp_req_data input;
        u32 *os_area_msg_seqno;
@@ -263,14 +274,17 @@ static int dec_payload(struct snp_guest_dev *snp_dev, struct snp_guest_msg *msg,
 static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz)
 {
        struct snp_guest_crypto *crypto = snp_dev->crypto;
-       struct snp_guest_msg *resp = snp_dev->response;
-       struct snp_guest_msg *req = snp_dev->request;
+       struct snp_guest_msg *resp = &snp_dev->secret_response;
+       struct snp_guest_msg *req = &snp_dev->secret_request;
        struct snp_guest_msg_hdr *req_hdr = &req->hdr;
        struct snp_guest_msg_hdr *resp_hdr = &resp->hdr;
 
        dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n",
                resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz);
 
+       /* Copy response from shared memory to encrypted memory. */
+       memcpy(resp, snp_dev->response, sizeof(*resp));
+
        /* Verify that the sequence counter is incremented by 1 */
        if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1)))
                return -EBADMSG;
@@ -294,7 +308,7 @@ static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload,
 static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type,
                        void *payload, size_t sz)
 {
-       struct snp_guest_msg *req = snp_dev->request;
+       struct snp_guest_msg *req = &snp_dev->secret_request;
        struct snp_guest_msg_hdr *hdr = &req->hdr;
 
        memset(req, 0, sizeof(*req));
@@ -318,45 +332,40 @@ static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8
        return __enc_payload(snp_dev, req, payload, sz);
 }
 
-static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver,
-                               u8 type, void *req_buf, size_t req_sz, void *resp_buf,
-                               u32 resp_sz, __u64 *fw_err)
+static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code,
+                                 struct snp_guest_request_ioctl *rio)
 {
-       unsigned long err;
-       u64 seqno;
+       unsigned long req_start = jiffies;
+       unsigned int override_npages = 0;
+       u64 override_err = 0;
        int rc;
 
-       /* Get message sequence and verify that its a non-zero */
-       seqno = snp_get_msg_seqno(snp_dev);
-       if (!seqno)
-               return -EIO;
-
-       memset(snp_dev->response, 0, sizeof(struct snp_guest_msg));
-
-       /* Encrypt the userspace provided payload */
-       rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz);
-       if (rc)
-               return rc;
-
+retry_request:
        /*
         * Call firmware to process the request. In this function the encrypted
         * message enters shared memory with the host. So after this call the
         * sequence number must be incremented or the VMPCK must be deleted to
         * prevent reuse of the IV.
         */
-       rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
-
-       /*
-        * If the extended guest request fails due to having too small of a
-        * certificate data buffer, retry the same guest request without the
-        * extended data request in order to increment the sequence number
-        * and thus avoid IV reuse.
-        */
-       if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
-           err == SNP_GUEST_REQ_INVALID_LEN) {
-               const unsigned int certs_npages = snp_dev->input.data_npages;
+       rc = snp_issue_guest_request(exit_code, &snp_dev->input, rio);
+       switch (rc) {
+       case -ENOSPC:
+               /*
+                * If the extended guest request fails due to having too
+                * small of a certificate data buffer, retry the same
+                * guest request without the extended data request in
+                * order to increment the sequence number and thus avoid
+                * IV reuse.
+                */
+               override_npages = snp_dev->input.data_npages;
+               exit_code       = SVM_VMGEXIT_GUEST_REQUEST;
 
-               exit_code = SVM_VMGEXIT_GUEST_REQUEST;
+               /*
+                * Override the error to inform callers the given extended
+                * request buffer size was too small and give the caller the
+                * required buffer size.
+                */
+               override_err = SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN);
 
                /*
                 * If this call to the firmware succeeds, the sequence number can
@@ -366,15 +375,20 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
                 * of the VMPCK and the error code being propagated back to the
                 * user as an ioctl() return code.
                 */
-               rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+               goto retry_request;
 
-               /*
-                * Override the error to inform callers the given extended
-                * request buffer size was too small and give the caller the
-                * required buffer size.
-                */
-               err = SNP_GUEST_REQ_INVALID_LEN;
-               snp_dev->input.data_npages = certs_npages;
+       /*
+        * The host may return SNP_GUEST_VMM_ERR_BUSY if the request has been
+        * throttled. Retry in the driver to avoid returning and reusing the
+        * message sequence number on a different message.
+        */
+       case -EAGAIN:
+               if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) {
+                       rc = -ETIMEDOUT;
+                       break;
+               }
+               schedule_timeout_killable(SNP_REQ_RETRY_DELAY);
+               goto retry_request;
        }
 
        /*
@@ -385,38 +399,75 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
         */
        snp_inc_msg_seqno(snp_dev);
 
-       if (fw_err)
-               *fw_err = err;
+       if (override_err) {
+               rio->exitinfo2 = override_err;
+
+               /*
+                * If an extended guest request was issued and the supplied certificate
+                * buffer was not large enough, a standard guest request was issued to
+                * prevent IV reuse. If the standard request was successful, return -EIO
+                * back to the caller as would have originally been returned.
+                */
+               if (!rc && override_err == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN))
+                       rc = -EIO;
+       }
+
+       if (override_npages)
+               snp_dev->input.data_npages = override_npages;
+
+       return rc;
+}
+
+static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code,
+                               struct snp_guest_request_ioctl *rio, u8 type,
+                               void *req_buf, size_t req_sz, void *resp_buf,
+                               u32 resp_sz)
+{
+       u64 seqno;
+       int rc;
+
+       /* Get message sequence and verify that its a non-zero */
+       seqno = snp_get_msg_seqno(snp_dev);
+       if (!seqno)
+               return -EIO;
+
+       /* Clear shared memory's response for the host to populate. */
+       memset(snp_dev->response, 0, sizeof(struct snp_guest_msg));
+
+       /* Encrypt the userspace provided payload in snp_dev->secret_request. */
+       rc = enc_payload(snp_dev, seqno, rio->msg_version, type, req_buf, req_sz);
+       if (rc)
+               return rc;
 
        /*
-        * If an extended guest request was issued and the supplied certificate
-        * buffer was not large enough, a standard guest request was issued to
-        * prevent IV reuse. If the standard request was successful, return -EIO
-        * back to the caller as would have originally been returned.
+        * Write the fully encrypted request to the shared unencrypted
+        * request page.
         */
-       if (!rc && err == SNP_GUEST_REQ_INVALID_LEN)
-               return -EIO;
+       memcpy(snp_dev->request, &snp_dev->secret_request,
+              sizeof(snp_dev->secret_request));
 
+       rc = __handle_guest_request(snp_dev, exit_code, rio);
        if (rc) {
+               if (rc == -EIO &&
+                   rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN))
+                       return rc;
+
                dev_alert(snp_dev->dev,
-                         "Detected error from ASP request. rc: %d, fw_err: %llu\n",
-                         rc, *fw_err);
-               goto disable_vmpck;
+                         "Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n",
+                         rc, rio->exitinfo2);
+
+               snp_disable_vmpck(snp_dev);
+               return rc;
        }
 
        rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz);
        if (rc) {
-               dev_alert(snp_dev->dev,
-                         "Detected unexpected decode failure from ASP. rc: %d\n",
-                         rc);
-               goto disable_vmpck;
+               dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc);
+               snp_disable_vmpck(snp_dev);
+               return rc;
        }
 
        return 0;
-
-disable_vmpck:
-       snp_disable_vmpck(snp_dev);
-       return rc;
 }
 
 static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
@@ -444,9 +495,9 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
        if (!resp)
                return -ENOMEM;
 
-       rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version,
+       rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg,
                                  SNP_MSG_REPORT_REQ, &req, sizeof(req), resp->data,
-                                 resp_len, &arg->fw_err);
+                                 resp_len);
        if (rc)
                goto e_free;
 
@@ -484,9 +535,8 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
        if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req)))
                return -EFAULT;
 
-       rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version,
-                                 SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len,
-                                 &arg->fw_err);
+       rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg,
+                                 SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len);
        if (rc)
                return rc;
 
@@ -546,12 +596,12 @@ cmd:
                return -ENOMEM;
 
        snp_dev->input.data_npages = npages;
-       ret = handle_guest_request(snp_dev, SVM_VMGEXIT_EXT_GUEST_REQUEST, arg->msg_version,
+       ret = handle_guest_request(snp_dev, SVM_VMGEXIT_EXT_GUEST_REQUEST, arg,
                                   SNP_MSG_REPORT_REQ, &req.data,
-                                  sizeof(req.data), resp->data, resp_len, &arg->fw_err);
+                                  sizeof(req.data), resp->data, resp_len);
 
        /* If certs length is invalid then copy the returned length */
-       if (arg->fw_err == SNP_GUEST_REQ_INVALID_LEN) {
+       if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) {
                req.certs_len = snp_dev->input.data_npages << PAGE_SHIFT;
 
                if (copy_to_user((void __user *)arg->req_data, &req, sizeof(req)))
@@ -586,7 +636,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
        if (copy_from_user(&input, argp, sizeof(input)))
                return -EFAULT;
 
-       input.fw_err = 0xff;
+       input.exitinfo2 = 0xff;
 
        /* Message version must be non-zero */
        if (!input.msg_version)
@@ -617,7 +667,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
 
        mutex_unlock(&snp_cmd_mutex);
 
-       if (input.fw_err && copy_to_user(argp, &input, sizeof(input)))
+       if (input.exitinfo2 && copy_to_user(argp, &input, sizeof(input)))
                return -EFAULT;
 
        return ret;
@@ -703,6 +753,9 @@ static int __init sev_guest_probe(struct platform_device *pdev)
        void __iomem *mapping;
        int ret;
 
+       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+               return -ENODEV;
+
        if (!dev->platform_data)
                return -ENODEV;
 
index c6c73a33c44d556c0ac5ebf53d6b5e078bfb6dc5..b799bc759c15f4e988a858ed1f41c1d3b3b6d934 100644 (file)
@@ -64,7 +64,7 @@ static int xensyms_next_sym(struct xensyms *xs)
 
 static void *xensyms_start(struct seq_file *m, loff_t *pos)
 {
-       struct xensyms *xs = (struct xensyms *)m->private;
+       struct xensyms *xs = m->private;
 
        xs->op.u.symdata.symnum = *pos;
 
@@ -76,7 +76,7 @@ static void *xensyms_start(struct seq_file *m, loff_t *pos)
 
 static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos)
 {
-       struct xensyms *xs = (struct xensyms *)m->private;
+       struct xensyms *xs = m->private;
 
        xs->op.u.symdata.symnum = ++(*pos);
 
@@ -88,7 +88,7 @@ static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos)
 
 static int xensyms_show(struct seq_file *m, void *p)
 {
-       struct xensyms *xs = (struct xensyms *)m->private;
+       struct xensyms *xs = m->private;
        struct xenpf_symdata *symdata = &xs->op.u.symdata;
 
        seq_printf(m, "%016llx %c %s\n", symdata->address,
@@ -120,7 +120,7 @@ static int xensyms_open(struct inode *inode, struct file *file)
                return ret;
 
        m = file->private_data;
-       xs = (struct xensyms *)m->private;
+       xs = m->private;
 
        xs->namelen = XEN_KSYM_NAME_LEN + 1;
        xs->name = kzalloc(xs->namelen, GFP_KERNEL);
@@ -138,7 +138,7 @@ static int xensyms_open(struct inode *inode, struct file *file)
 static int xensyms_release(struct inode *inode, struct file *file)
 {
        struct seq_file *m = file->private_data;
-       struct xensyms *xs = (struct xensyms *)m->private;
+       struct xensyms *xs = m->private;
 
        kfree(xs->name);
        return seq_release_private(inode, file);
index 50f7f3f6b55e9a7853cc1f6e4d8d14238274379a..e00cf8109b3f31cb77ffb900b56ca67df480a791 100644 (file)
@@ -35,10 +35,12 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
                return retval;
        }
        if (attr_size > buffer_size) {
-               if (!buffer_size) /* request to get the attr_size */
-                       retval = attr_size;
-               else
+               if (buffer_size)
                        retval = -ERANGE;
+               else if (attr_size > SSIZE_MAX)
+                       retval = -EOVERFLOW;
+               else /* request to get the attr_size */
+                       retval = attr_size;
        } else {
                iov_iter_truncate(&to, attr_size);
                retval = p9_client_read(attr_fid, 0, &to, &err);
@@ -183,10 +185,6 @@ static struct xattr_handler v9fs_xattr_security_handler = {
 const struct xattr_handler *v9fs_xattr_handlers[] = {
        &v9fs_xattr_user_handler,
        &v9fs_xattr_trusted_handler,
-#ifdef CONFIG_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
 #ifdef CONFIG_9P_FS_SECURITY
        &v9fs_xattr_security_handler,
 #endif
index aca9ff7aed3331c31848cf6bf7480bd4b9e27187..d60dc1edb526885584bf62b74da1542e271a8f7d 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -47,6 +47,7 @@ int setattr_should_drop_sgid(struct mnt_idmap *idmap,
                return ATTR_KILL_SGID;
        return 0;
 }
+EXPORT_SYMBOL(setattr_should_drop_sgid);
 
 /**
  * setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
index 90e40d5ceccd15bca4b4c388d2dcc97d88f34b4c..e54f0884802a0cb2ac3592a71d348e80e5e01e62 100644 (file)
@@ -1921,8 +1921,7 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
        level = -1;
        ULIST_ITER_INIT(&uiter);
        while (1) {
-               bool is_shared;
-               bool cached;
+               const unsigned long prev_ref_count = ctx->refs.nnodes;
 
                walk_ctx.bytenr = bytenr;
                ret = find_parent_nodes(&walk_ctx, &shared);
@@ -1940,21 +1939,36 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
                ret = 0;
 
                /*
-                * If our data extent was not directly shared (without multiple
-                * reference items), than it might have a single reference item
-                * with a count > 1 for the same offset, which means there are 2
-                * (or more) file extent items that point to the data extent -
-                * this happens when a file extent item needs to be split and
-                * then one item gets moved to another leaf due to a b+tree leaf
-                * split when inserting some item. In this case the file extent
-                * items may be located in different leaves and therefore some
-                * of the leaves may be referenced through shared subtrees while
-                * others are not. Since our extent buffer cache only works for
-                * a single path (by far the most common case and simpler to
-                * deal with), we can not use it if we have multiple leaves
-                * (which implies multiple paths).
+                * More than one extent buffer (bytenr) may have been added to
+                * the ctx->refs ulist, in which case we have to check multiple
+                * tree paths in case the first one is not shared, so we can not
+                * use the path cache which is made for a single path. Multiple
+                * extent buffers at the current level happen when:
+                *
+                * 1) level -1, the data extent: If our data extent was not
+                *    directly shared (without multiple reference items), then
+                *    it might have a single reference item with a count > 1 for
+                *    the same offset, which means there are 2 (or more) file
+                *    extent items that point to the data extent - this happens
+                *    when a file extent item needs to be split and then one
+                *    item gets moved to another leaf due to a b+tree leaf split
+                *    when inserting some item. In this case the file extent
+                *    items may be located in different leaves and therefore
+                *    some of the leaves may be referenced through shared
+                *    subtrees while others are not. Since our extent buffer
+                *    cache only works for a single path (by far the most common
+                *    case and simpler to deal with), we can not use it if we
+                *    have multiple leaves (which implies multiple paths).
+                *
+                * 2) level >= 0, a tree node/leaf: We can have a mix of direct
+                *    and indirect references on a b+tree node/leaf, so we have
+                *    to check multiple paths, and the extent buffer (the
+                *    current bytenr) may be shared or not. One example is
+                *    during relocation as we may get a shared tree block ref
+                *    (direct ref) and a non-shared tree block ref (indirect
+                *    ref) for the same node/leaf.
                 */
-               if (level == -1 && ctx->refs.nnodes > 1)
+               if ((ctx->refs.nnodes - prev_ref_count) > 1)
                        ctx->use_path_cache = false;
 
                if (level >= 0)
@@ -1964,18 +1978,45 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
                if (!node)
                        break;
                bytenr = node->val;
-               level++;
-               cached = lookup_backref_shared_cache(ctx, root, bytenr, level,
-                                                    &is_shared);
-               if (cached) {
-                       ret = (is_shared ? 1 : 0);
-                       break;
+               if (ctx->use_path_cache) {
+                       bool is_shared;
+                       bool cached;
+
+                       level++;
+                       cached = lookup_backref_shared_cache(ctx, root, bytenr,
+                                                            level, &is_shared);
+                       if (cached) {
+                               ret = (is_shared ? 1 : 0);
+                               break;
+                       }
                }
                shared.share_count = 0;
                shared.have_delayed_delete_refs = false;
                cond_resched();
        }
 
+       /*
+        * If the path cache is disabled, then it means at some tree level we
+        * got multiple parents due to a mix of direct and indirect backrefs or
+        * multiple leaves with file extent items pointing to the same data
+        * extent. We have to invalidate the cache and cache only the sharedness
+        * result for the levels where we got only one node/reference.
+        */
+       if (!ctx->use_path_cache) {
+               int i = 0;
+
+               level--;
+               if (ret >= 0 && level >= 0) {
+                       bytenr = ctx->path_cache_entries[level].bytenr;
+                       ctx->use_path_cache = true;
+                       store_backref_shared_cache(ctx, root, bytenr, level, ret);
+                       i = level + 1;
+               }
+
+               for ( ; i < BTRFS_MAX_LEVEL; i++)
+                       ctx->path_cache_entries[i].bytenr = 0;
+       }
+
        /*
         * Cache the sharedness result for the data extent if we know our inode
         * has more than 1 file extent item that refers to the data extent.
index 0ef8b8926bfa7209a6e82145ee1c2b5f81b407c7..5fc670c27f8648d996016fe8da3f6fae658fdc78 100644 (file)
@@ -1175,14 +1175,8 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                        < block_group->zone_unusable);
                WARN_ON(block_group->space_info->disk_total
                        < block_group->length * factor);
-               WARN_ON(test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE,
-                                &block_group->runtime_flags) &&
-                       block_group->space_info->active_total_bytes
-                       < block_group->length);
        }
        block_group->space_info->total_bytes -= block_group->length;
-       if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags))
-               block_group->space_info->active_total_bytes -= block_group->length;
        block_group->space_info->bytes_readonly -=
                (block_group->length - block_group->zone_unusable);
        block_group->space_info->bytes_zone_unusable -=
@@ -3476,6 +3470,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
        spin_unlock(&info->delalloc_root_lock);
 
        while (total) {
+               struct btrfs_space_info *space_info;
                bool reclaim = false;
 
                cache = btrfs_lookup_block_group(info, bytenr);
@@ -3483,6 +3478,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                        ret = -ENOENT;
                        break;
                }
+               space_info = cache->space_info;
                factor = btrfs_bg_type_to_factor(cache->flags);
 
                /*
@@ -3497,7 +3493,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                byte_in_group = bytenr - cache->start;
                WARN_ON(byte_in_group > cache->length);
 
-               spin_lock(&cache->space_info->lock);
+               spin_lock(&space_info->lock);
                spin_lock(&cache->lock);
 
                if (btrfs_test_opt(info, SPACE_CACHE) &&
@@ -3510,24 +3506,24 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                        old_val += num_bytes;
                        cache->used = old_val;
                        cache->reserved -= num_bytes;
-                       cache->space_info->bytes_reserved -= num_bytes;
-                       cache->space_info->bytes_used += num_bytes;
-                       cache->space_info->disk_used += num_bytes * factor;
+                       space_info->bytes_reserved -= num_bytes;
+                       space_info->bytes_used += num_bytes;
+                       space_info->disk_used += num_bytes * factor;
                        spin_unlock(&cache->lock);
-                       spin_unlock(&cache->space_info->lock);
+                       spin_unlock(&space_info->lock);
                } else {
                        old_val -= num_bytes;
                        cache->used = old_val;
                        cache->pinned += num_bytes;
-                       btrfs_space_info_update_bytes_pinned(info,
-                                       cache->space_info, num_bytes);
-                       cache->space_info->bytes_used -= num_bytes;
-                       cache->space_info->disk_used -= num_bytes * factor;
+                       btrfs_space_info_update_bytes_pinned(info, space_info,
+                                                            num_bytes);
+                       space_info->bytes_used -= num_bytes;
+                       space_info->disk_used -= num_bytes * factor;
 
                        reclaim = should_reclaim_block_group(cache, num_bytes);
 
                        spin_unlock(&cache->lock);
-                       spin_unlock(&cache->space_info->lock);
+                       spin_unlock(&space_info->lock);
 
                        set_extent_dirty(&trans->transaction->pinned_extents,
                                         bytenr, bytenr + num_bytes - 1,
index 317aeff6c1dacce2b3432cf91bfdb7261da883a8..a6d77fe41e1a9eeb367322c03b26c5edef50e453 100644 (file)
 #define BTRFS_DISCARD_DELAY            (120ULL * NSEC_PER_SEC)
 #define BTRFS_DISCARD_UNUSED_DELAY     (10ULL * NSEC_PER_SEC)
 
-/* Target completion latency of discarding all discardable extents */
-#define BTRFS_DISCARD_TARGET_MSEC      (6 * 60 * 60UL * MSEC_PER_SEC)
 #define BTRFS_DISCARD_MIN_DELAY_MSEC   (1UL)
 #define BTRFS_DISCARD_MAX_DELAY_MSEC   (1000UL)
-#define BTRFS_DISCARD_MAX_IOPS         (10U)
+#define BTRFS_DISCARD_MAX_IOPS         (1000U)
 
 /* Monotonically decreasing minimum length filters after index 0 */
 static int discard_minlen[BTRFS_NR_DISCARD_LISTS] = {
@@ -577,6 +575,7 @@ void btrfs_discard_calc_delay(struct btrfs_discard_ctl *discard_ctl)
        s32 discardable_extents;
        s64 discardable_bytes;
        u32 iops_limit;
+       unsigned long min_delay = BTRFS_DISCARD_MIN_DELAY_MSEC;
        unsigned long delay;
 
        discardable_extents = atomic_read(&discard_ctl->discardable_extents);
@@ -607,13 +606,19 @@ void btrfs_discard_calc_delay(struct btrfs_discard_ctl *discard_ctl)
        }
 
        iops_limit = READ_ONCE(discard_ctl->iops_limit);
-       if (iops_limit)
+
+       if (iops_limit) {
                delay = MSEC_PER_SEC / iops_limit;
-       else
-               delay = BTRFS_DISCARD_TARGET_MSEC / discardable_extents;
+       } else {
+               /*
+                * Unset iops_limit means go as fast as possible, so allow a
+                * delay of 0.
+                */
+               delay = 0;
+               min_delay = 0;
+       }
 
-       delay = clamp(delay, BTRFS_DISCARD_MIN_DELAY_MSEC,
-                     BTRFS_DISCARD_MAX_DELAY_MSEC);
+       delay = clamp(delay, min_delay, BTRFS_DISCARD_MAX_DELAY_MSEC);
        discard_ctl->delay_ms = delay;
 
        spin_unlock(&discard_ctl->lock);
index b53f0e30ce2b3bbb2e40baa1163ee57e29e942b7..9e1596bb208db09ff69d441c9ca3330ea7b940c2 100644 (file)
@@ -2250,6 +2250,20 @@ static int btrfs_init_csum_hash(struct btrfs_fs_info *fs_info, u16 csum_type)
 
        fs_info->csum_shash = csum_shash;
 
+       /*
+        * Check if the checksum implementation is a fast accelerated one.
+        * As-is this is a bit of a hack and should be replaced once the csum
+        * implementations provide that information themselves.
+        */
+       switch (csum_type) {
+       case BTRFS_CSUM_TYPE_CRC32:
+               if (!strstr(crypto_shash_driver_name(csum_shash), "generic"))
+                       set_bit(BTRFS_FS_CSUM_IMPL_FAST, &fs_info->flags);
+               break;
+       default:
+               break;
+       }
+
        btrfs_info(fs_info, "using %s (%s) checksum algorithm",
                        btrfs_super_csum_name(csum_type),
                        crypto_shash_driver_name(csum_shash));
index 5cc5a1faaef5b571e81322b7b3699bf2017a591b..f649647392e0e47c62f030d5c59c74cf633e4fac 100644 (file)
@@ -3730,10 +3730,15 @@ static int check_direct_read(struct btrfs_fs_info *fs_info,
        if (!iter_is_iovec(iter))
                return 0;
 
-       for (seg = 0; seg < iter->nr_segs; seg++)
-               for (i = seg + 1; i < iter->nr_segs; i++)
-                       if (iter->iov[seg].iov_base == iter->iov[i].iov_base)
+       for (seg = 0; seg < iter->nr_segs; seg++) {
+               for (i = seg + 1; i < iter->nr_segs; i++) {
+                       const struct iovec *iov1 = iter_iov(iter) + seg;
+                       const struct iovec *iov2 = iter_iov(iter) + i;
+
+                       if (iov1->iov_base == iov2->iov_base)
                                return -EINVAL;
+               }
+       }
        return 0;
 }
 
index 0d250d052487cf04085e5b059e10be1810e7d654..d84cef89cdff522ab64931da108498d00637ea53 100644 (file)
@@ -2693,8 +2693,13 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
                bg_reclaim_threshold = READ_ONCE(sinfo->bg_reclaim_threshold);
 
        spin_lock(&ctl->tree_lock);
+       /* Count initial region as zone_unusable until it gets activated. */
        if (!used)
                to_free = size;
+       else if (initial &&
+                test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &block_group->fs_info->flags) &&
+                (block_group->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM)))
+               to_free = 0;
        else if (initial)
                to_free = block_group->zone_capacity;
        else if (offset >= block_group->alloc_offset)
@@ -2722,7 +2727,8 @@ static int __btrfs_add_free_space_zoned(struct btrfs_block_group *block_group,
        reclaimable_unusable = block_group->zone_unusable -
                               (block_group->length - block_group->zone_capacity);
        /* All the region is now unusable. Mark it as unused and reclaim */
-       if (block_group->zone_unusable == block_group->length) {
+       if (block_group->zone_unusable == block_group->length &&
+           block_group->alloc_offset) {
                btrfs_mark_bg_unused(block_group);
        } else if (bg_reclaim_threshold &&
                   reclaimable_unusable >=
index 4c477eae689148dd59c45514eb2069a073d08155..24cd492294086c1dfa02b59e61d5f4d311e99c30 100644 (file)
@@ -120,11 +120,8 @@ enum {
        /* Indicate that we want to commit the transaction. */
        BTRFS_FS_NEED_TRANS_COMMIT,
 
-       /*
-        * Indicate metadata over-commit is disabled. This is set when active
-        * zone tracking is needed.
-        */
-       BTRFS_FS_NO_OVERCOMMIT,
+       /* This is set when active zone tracking is needed. */
+       BTRFS_FS_ACTIVE_ZONE_TRACKING,
 
        /*
         * Indicate if we have some features changed, this is mostly for
index 6c18dc9a1831d03b7ec04c13ac6efc19a28d7a67..957e4d76a7b6578d59fd8f0b7d887e30d02c4e2b 100644 (file)
@@ -5421,8 +5421,13 @@ static int btrfs_inode_by_name(struct btrfs_inode *dir, struct dentry *dentry,
                return -ENOMEM;
 
        ret = fscrypt_setup_filename(&dir->vfs_inode, &dentry->d_name, 1, &fname);
-       if (ret)
+       if (ret < 0)
                goto out;
+       /*
+        * fscrypt_setup_filename() should never return a positive value, but
+        * gcc on sparc/parisc thinks it can, so assert that doesn't happen.
+        */
+       ASSERT(ret == 0);
 
        /* This needs to handle no-key deletions later on */
 
index a0ef1a1784c79be72102a5146c1d016633e6b46c..ba769a1eb87ab24e535576b37db26e50be58b02b 100644 (file)
@@ -3732,7 +3732,9 @@ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
        }
 
        /* update qgroup status and info */
+       mutex_lock(&fs_info->qgroup_ioctl_lock);
        err = btrfs_run_qgroups(trans);
+       mutex_unlock(&fs_info->qgroup_ioctl_lock);
        if (err < 0)
                btrfs_handle_fs_error(fs_info, err,
                                      "failed to update qgroup status and info");
index 52a7d2fa2284f89ae063ee436578337abdae2ee8..f41da7ac360d86767bd120900d89c1e1d3b82ab5 100644 (file)
@@ -2828,13 +2828,22 @@ cleanup:
 }
 
 /*
- * called from commit_transaction. Writes all changed qgroups to disk.
+ * Writes all changed qgroups to disk.
+ * Called by the transaction commit path and the qgroup assign ioctl.
  */
 int btrfs_run_qgroups(struct btrfs_trans_handle *trans)
 {
        struct btrfs_fs_info *fs_info = trans->fs_info;
        int ret = 0;
 
+       /*
+        * In case we are called from the qgroup assign ioctl, assert that we
+        * are holding the qgroup_ioctl_lock, otherwise we can race with a quota
+        * disable operation (ioctl) and access a freed quota root.
+        */
+       if (trans->transaction->state != TRANS_STATE_COMMIT_DOING)
+               lockdep_assert_held(&fs_info->qgroup_ioctl_lock);
+
        if (!fs_info->quota_root)
                return ret;
 
index 69c09508afb506ac8121caeae39fb2e7071362c0..3eecce86f63fc4e8d1cc96c6c7b09d84db076d1e 100644 (file)
@@ -308,8 +308,6 @@ void btrfs_add_bg_to_space_info(struct btrfs_fs_info *info,
        ASSERT(found);
        spin_lock(&found->lock);
        found->total_bytes += block_group->length;
-       if (test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags))
-               found->active_total_bytes += block_group->length;
        found->disk_total += block_group->length * factor;
        found->bytes_used += block_group->used;
        found->disk_used += block_group->used * factor;
@@ -379,22 +377,6 @@ static u64 calc_available_free_space(struct btrfs_fs_info *fs_info,
        return avail;
 }
 
-static inline u64 writable_total_bytes(struct btrfs_fs_info *fs_info,
-                                      struct btrfs_space_info *space_info)
-{
-       /*
-        * On regular filesystem, all total_bytes are always writable. On zoned
-        * filesystem, there may be a limitation imposed by max_active_zones.
-        * For metadata allocation, we cannot finish an existing active block
-        * group to avoid a deadlock. Thus, we need to consider only the active
-        * groups to be writable for metadata space.
-        */
-       if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
-               return space_info->total_bytes;
-
-       return space_info->active_total_bytes;
-}
-
 int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
                         struct btrfs_space_info *space_info, u64 bytes,
                         enum btrfs_reserve_flush_enum flush)
@@ -407,13 +389,13 @@ int btrfs_can_overcommit(struct btrfs_fs_info *fs_info,
                return 0;
 
        used = btrfs_space_info_used(space_info, true);
-       if (test_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags) &&
+       if (test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags) &&
            (space_info->flags & BTRFS_BLOCK_GROUP_METADATA))
                avail = 0;
        else
                avail = calc_available_free_space(fs_info, space_info, flush);
 
-       if (used + bytes < writable_total_bytes(fs_info, space_info) + avail)
+       if (used + bytes < space_info->total_bytes + avail)
                return 1;
        return 0;
 }
@@ -449,7 +431,7 @@ again:
                ticket = list_first_entry(head, struct reserve_ticket, list);
 
                /* Check and see if our ticket can be satisfied now. */
-               if ((used + ticket->bytes <= writable_total_bytes(fs_info, space_info)) ||
+               if ((used + ticket->bytes <= space_info->total_bytes) ||
                    btrfs_can_overcommit(fs_info, space_info, ticket->bytes,
                                         flush)) {
                        btrfs_space_info_update_bytes_may_use(fs_info,
@@ -829,7 +811,6 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
 {
        u64 used;
        u64 avail;
-       u64 total;
        u64 to_reclaim = space_info->reclaim_size;
 
        lockdep_assert_held(&space_info->lock);
@@ -844,9 +825,8 @@ btrfs_calc_reclaim_metadata_size(struct btrfs_fs_info *fs_info,
         * space.  If that's the case add in our overage so we make sure to put
         * appropriate pressure on the flushing state machine.
         */
-       total = writable_total_bytes(fs_info, space_info);
-       if (total + avail < used)
-               to_reclaim += used - (total + avail);
+       if (space_info->total_bytes + avail < used)
+               to_reclaim += used - (space_info->total_bytes + avail);
 
        return to_reclaim;
 }
@@ -856,11 +836,10 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
 {
        u64 global_rsv_size = fs_info->global_block_rsv.reserved;
        u64 ordered, delalloc;
-       u64 total = writable_total_bytes(fs_info, space_info);
        u64 thresh;
        u64 used;
 
-       thresh = mult_perc(total, 90);
+       thresh = mult_perc(space_info->total_bytes, 90);
 
        lockdep_assert_held(&space_info->lock);
 
@@ -923,8 +902,8 @@ static bool need_preemptive_reclaim(struct btrfs_fs_info *fs_info,
                                           BTRFS_RESERVE_FLUSH_ALL);
        used = space_info->bytes_used + space_info->bytes_reserved +
               space_info->bytes_readonly + global_rsv_size;
-       if (used < total)
-               thresh += total - used;
+       if (used < space_info->total_bytes)
+               thresh += space_info->total_bytes - used;
        thresh >>= space_info->clamp;
 
        used = space_info->bytes_pinned;
@@ -1651,7 +1630,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,
         * can_overcommit() to ensure we can overcommit to continue.
         */
        if (!pending_tickets &&
-           ((used + orig_bytes <= writable_total_bytes(fs_info, space_info)) ||
+           ((used + orig_bytes <= space_info->total_bytes) ||
             btrfs_can_overcommit(fs_info, space_info, orig_bytes, flush))) {
                btrfs_space_info_update_bytes_may_use(fs_info, space_info,
                                                      orig_bytes);
@@ -1665,8 +1644,7 @@ static int __reserve_bytes(struct btrfs_fs_info *fs_info,
         */
        if (ret && unlikely(flush == BTRFS_RESERVE_FLUSH_EMERGENCY)) {
                used = btrfs_space_info_used(space_info, false);
-               if (used + orig_bytes <=
-                   writable_total_bytes(fs_info, space_info)) {
+               if (used + orig_bytes <= space_info->total_bytes) {
                        btrfs_space_info_update_bytes_may_use(fs_info, space_info,
                                                              orig_bytes);
                        ret = 0;
index fc99ea2b0c34fc2187813dffc2a206577e65ee22..2033b71b18cece2b5ee1e35877d184e1d3ced1b2 100644 (file)
@@ -96,8 +96,6 @@ struct btrfs_space_info {
        u64 bytes_may_use;      /* number of bytes that may be used for
                                   delalloc/allocations */
        u64 bytes_readonly;     /* total bytes that are read only */
-       /* Total bytes in the space, but only accounts active block groups. */
-       u64 active_total_bytes;
        u64 bytes_zone_unusable;        /* total bytes that are unusable until
                                           resetting the device zone */
 
index 581845bc206ad28b403d52f7b8dc421982078222..366fb4cde14584b5c1477869c064364c4a1c03fa 100644 (file)
@@ -1516,8 +1516,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
                shrinker_debugfs_rename(&s->s_shrink, "sb-%s:%s", fs_type->name,
                                        s->s_id);
                btrfs_sb(s)->bdev_holder = fs_type;
-               if (!strstr(crc32c_impl(), "generic"))
-                       set_bit(BTRFS_FS_CSUM_IMPL_FAST, &fs_info->flags);
                error = btrfs_fill_super(s, fs_devices, data);
        }
        if (!error)
@@ -1631,6 +1629,8 @@ static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
        btrfs_workqueue_set_max(fs_info->hipri_workers, new_pool_size);
        btrfs_workqueue_set_max(fs_info->delalloc_workers, new_pool_size);
        btrfs_workqueue_set_max(fs_info->caching_workers, new_pool_size);
+       workqueue_set_max_active(fs_info->endio_workers, new_pool_size);
+       workqueue_set_max_active(fs_info->endio_meta_workers, new_pool_size);
        btrfs_workqueue_set_max(fs_info->endio_write_workers, new_pool_size);
        btrfs_workqueue_set_max(fs_info->endio_freespace_worker, new_pool_size);
        btrfs_workqueue_set_max(fs_info->delayed_workers, new_pool_size);
index 18329ebcb1cbffa0e3c98b9eaea654ec39529662..b8d5b1fa9a03b447b579d50a19c15810f231c79e 100644 (file)
@@ -2035,7 +2035,20 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
 
        if (current->journal_info == trans)
                current->journal_info = NULL;
-       btrfs_scrub_cancel(fs_info);
+
+       /*
+        * If relocation is running, we can't cancel scrub because that will
+        * result in a deadlock. Before relocating a block group, relocation
+        * pauses scrub, then starts and commits a transaction before unpausing
+        * scrub. If the transaction commit is being done by the relocation
+        * task or triggered by another task and the relocation task is waiting
+        * for the commit, and we end up here due to an error in the commit
+        * path, then calling btrfs_scrub_cancel() will deadlock, as we are
+        * asking for scrub to stop while having it asked to be paused higher
+        * above in relocation code.
+        */
+       if (!test_bit(BTRFS_FS_RELOC_RUNNING, &fs_info->flags))
+               btrfs_scrub_cancel(fs_info);
 
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
 }
index 7823168c08a6aa22466addc1472f0c4f3732529c..c6d59287040019a17ac4796f1f69f105a316178e 100644 (file)
@@ -1366,8 +1366,17 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
         * So, we need to add a special mount option to scan for
         * later supers, using BTRFS_SUPER_MIRROR_MAX instead
         */
-       flags |= FMODE_EXCL;
 
+       /*
+        * Avoid using flag |= FMODE_EXCL here, as the systemd-udev may
+        * initiate the device scan which may race with the user's mount
+        * or mkfs command, resulting in failure.
+        * Since the device scan is solely for reading purposes, there is
+        * no need for FMODE_EXCL. Additionally, the devices are read again
+        * during the mount process. It is ok to get some inconsistent
+        * values temporarily, as the device paths of the fsid are the only
+        * required information for assembling the volume.
+        */
        bdev = blkdev_get_by_path(path, flags, holder);
        if (IS_ERR(bdev))
                return ERR_CAST(bdev);
@@ -3266,8 +3275,15 @@ int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
        btrfs_scrub_pause(fs_info);
        ret = btrfs_relocate_block_group(fs_info, chunk_offset);
        btrfs_scrub_continue(fs_info);
-       if (ret)
+       if (ret) {
+               /*
+                * If we had a transaction abort, stop all running scrubs.
+                * See transaction.c:cleanup_transaction() why we do it here.
+                */
+               if (BTRFS_FS_ERROR(fs_info))
+                       btrfs_scrub_cancel(fs_info);
                return ret;
+       }
 
        block_group = btrfs_lookup_block_group(fs_info, chunk_offset);
        if (!block_group)
@@ -6363,7 +6379,8 @@ int __btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        ASSERT(op != BTRFS_MAP_DISCARD);
 
        em = btrfs_get_chunk_map(fs_info, logical, *length);
-       ASSERT(!IS_ERR(em));
+       if (IS_ERR(em))
+               return PTR_ERR(em);
 
        map = em->map_lookup;
        data_stripes = nr_data_stripes(map);
index 0ebeaf4e81f9329541f7e6b29457a69923d6e5d2..fc4b20c2688a060b38a9afee1f10d002f2489818 100644 (file)
@@ -444,10 +444,6 @@ static const struct xattr_handler btrfs_btrfs_xattr_handler = {
 
 const struct xattr_handler *btrfs_xattr_handlers[] = {
        &btrfs_security_xattr_handler,
-#ifdef CONFIG_BTRFS_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &btrfs_trusted_xattr_handler,
        &btrfs_user_xattr_handler,
        &btrfs_btrfs_xattr_handler,
index f95b2c94d6199a62194d785ffa3d427c0a3fa79b..45d04092f2f8cdadded5570b677738c9de74197a 100644 (file)
@@ -524,8 +524,7 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
                }
                atomic_set(&zone_info->active_zones_left,
                           max_active_zones - nactive);
-               /* Overcommit does not work well with active zone tacking. */
-               set_bit(BTRFS_FS_NO_OVERCOMMIT, &fs_info->flags);
+               set_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &fs_info->flags);
        }
 
        /* Validate superblock log */
@@ -1581,9 +1580,19 @@ void btrfs_calc_zone_unusable(struct btrfs_block_group *cache)
                return;
 
        WARN_ON(cache->bytes_super != 0);
-       unusable = (cache->alloc_offset - cache->used) +
-                  (cache->length - cache->zone_capacity);
-       free = cache->zone_capacity - cache->alloc_offset;
+
+       /* Check for block groups never get activated */
+       if (test_bit(BTRFS_FS_ACTIVE_ZONE_TRACKING, &cache->fs_info->flags) &&
+           cache->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM) &&
+           !test_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &cache->runtime_flags) &&
+           cache->alloc_offset == 0) {
+               unusable = cache->length;
+               free = 0;
+       } else {
+               unusable = (cache->alloc_offset - cache->used) +
+                          (cache->length - cache->zone_capacity);
+               free = cache->zone_capacity - cache->alloc_offset;
+       }
 
        /* We only need ->free_space in ALLOC_SEQ block groups */
        cache->cached = BTRFS_CACHE_FINISHED;
@@ -1902,7 +1911,11 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group)
 
        /* Successfully activated all the zones */
        set_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &block_group->runtime_flags);
-       space_info->active_total_bytes += block_group->length;
+       WARN_ON(block_group->alloc_offset != 0);
+       if (block_group->zone_unusable == block_group->length) {
+               block_group->zone_unusable = block_group->length - block_group->zone_capacity;
+               space_info->bytes_zone_unusable -= block_group->zone_capacity;
+       }
        spin_unlock(&block_group->lock);
        btrfs_try_granting_tickets(fs_info, space_info);
        spin_unlock(&space_info->lock);
@@ -2086,11 +2099,21 @@ bool btrfs_can_activate_zone(struct btrfs_fs_devices *fs_devices, u64 flags)
                if (!device->bdev)
                        continue;
 
-               if (!zinfo->max_active_zones ||
-                   atomic_read(&zinfo->active_zones_left)) {
+               if (!zinfo->max_active_zones) {
                        ret = true;
                        break;
                }
+
+               switch (flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+               case 0: /* single */
+                       ret = (atomic_read(&zinfo->active_zones_left) >= 1);
+                       break;
+               case BTRFS_BLOCK_GROUP_DUP:
+                       ret = (atomic_read(&zinfo->active_zones_left) >= 2);
+                       break;
+               }
+               if (ret)
+                       break;
        }
        mutex_unlock(&fs_info->chunk_mutex);
 
@@ -2256,7 +2279,7 @@ int btrfs_zone_finish_one_bg(struct btrfs_fs_info *fs_info)
                u64 avail;
 
                spin_lock(&block_group->lock);
-               if (block_group->reserved ||
+               if (block_group->reserved || block_group->alloc_offset == 0 ||
                    (block_group->flags & BTRFS_BLOCK_GROUP_SYSTEM)) {
                        spin_unlock(&block_group->lock);
                        continue;
@@ -2293,10 +2316,6 @@ int btrfs_zoned_activate_one_bg(struct btrfs_fs_info *fs_info,
        if (!btrfs_is_zoned(fs_info) || (space_info->flags & BTRFS_BLOCK_GROUP_DATA))
                return 0;
 
-       /* No more block groups to activate */
-       if (space_info->active_total_bytes == space_info->total_bytes)
-               return 0;
-
        for (;;) {
                int ret;
                bool need_finish = false;
index 9e1e2add541e07a593bcc743d73eb05ed51bfbd9..10390f53f3f529321dada7eec6593a27d0054ca4 100644 (file)
@@ -2581,7 +2581,7 @@ int block_truncate_page(struct address_space *mapping,
        struct inode *inode = mapping->host;
        struct page *page;
        struct buffer_head *bh;
-       int err;
+       int err = 0;
 
        blocksize = i_blocksize(inode);
        length = offset & (blocksize - 1);
@@ -2594,9 +2594,8 @@ int block_truncate_page(struct address_space *mapping,
        iblock = (sector_t)index << (PAGE_SHIFT - inode->i_blkbits);
        
        page = grab_cache_page(mapping, index);
-       err = -ENOMEM;
        if (!page)
-               goto out;
+               return -ENOMEM;
 
        if (!page_has_buffers(page))
                create_empty_buffers(page, blocksize, 0);
@@ -2610,7 +2609,6 @@ int block_truncate_page(struct address_space *mapping,
                pos += blocksize;
        }
 
-       err = 0;
        if (!buffer_mapped(bh)) {
                WARN_ON(bh->b_size != blocksize);
                err = get_block(inode, iblock, bh, 0);
@@ -2634,12 +2632,11 @@ int block_truncate_page(struct address_space *mapping,
 
        zero_user(page, offset, length);
        mark_buffer_dirty(bh);
-       err = 0;
 
 unlock:
        unlock_page(page);
        put_page(page);
-out:
+
        return err;
 }
 EXPORT_SYMBOL(block_truncate_page);
index f65b07cc33a2471d196d7c2e5bb650db822299e0..1fe1b62abebd135befe3ee67b2f1060ed30286f8 100644 (file)
@@ -1411,10 +1411,6 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
  * attributes are handled directly.
  */
 const struct xattr_handler *ceph_xattr_handlers[] = {
-#ifdef CONFIG_CEPH_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &ceph_other_xattr_handler,
        NULL,
 };
index 75d5e06306ea52d30038ffa4f2d7760bbcf346e0..bfc964b36c72ecaa9da088892be7349731b327dc 100644 (file)
@@ -99,6 +99,23 @@ path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path)
        return dentry;
 }
 
+static const char *path_no_prefix(struct cifs_sb_info *cifs_sb,
+                                 const char *path)
+{
+       size_t len = 0;
+
+       if (!*path)
+               return path;
+
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
+           cifs_sb->prepath) {
+               len = strlen(cifs_sb->prepath) + 1;
+               if (unlikely(len > strlen(path)))
+                       return ERR_PTR(-EINVAL);
+       }
+       return path + len;
+}
+
 /*
  * Open the and cache a directory handle.
  * If error then *cfid is not initialized.
@@ -125,6 +142,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
        struct dentry *dentry = NULL;
        struct cached_fid *cfid;
        struct cached_fids *cfids;
+       const char *npath;
 
        if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache ||
            is_smb1_server(tcon->ses->server))
@@ -160,6 +178,20 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
                return 0;
        }
 
+       /*
+        * Skip any prefix paths in @path as lookup_positive_unlocked() ends up
+        * calling ->lookup() which already adds those through
+        * build_path_from_dentry().  Also, do it earlier as we might reconnect
+        * below when trying to send compounded request and then potentially
+        * having a different prefix path (e.g. after DFS failover).
+        */
+       npath = path_no_prefix(cifs_sb, path);
+       if (IS_ERR(npath)) {
+               rc = PTR_ERR(npath);
+               kfree(utf16_path);
+               return rc;
+       }
+
        /*
         * We do not hold the lock for the open because in case
         * SMB2_open needs to reconnect.
@@ -184,6 +216,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
@@ -251,10 +284,10 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
                                (char *)&cfid->file_all_info))
                cfid->file_all_info_is_valid = true;
 
-       if (!path[0])
+       if (!npath[0])
                dentry = dget(cifs_sb->root);
        else {
-               dentry = path_to_dentry(cifs_sb, path);
+               dentry = path_to_dentry(cifs_sb, npath);
                if (IS_ERR(dentry)) {
                        rc = -ENOENT;
                        goto oshr_free;
index 1911f7016fa1d5e747681f6df06e75a27a6db199..e9c8c088d948ccb44fa110f64ab99729a50d1e2f 100644 (file)
@@ -176,7 +176,7 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
 
        seq_puts(m, "# Version:1\n");
        seq_puts(m, "# Format:\n");
-       seq_puts(m, "# <tree id> <persistent fid> <flags> <count> <pid> <uid>");
+       seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
 #ifdef CONFIG_CIFS_DEBUG2
        seq_printf(m, " <filename> <mid>\n");
 #else
@@ -189,8 +189,9 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
                                spin_lock(&tcon->open_file_lock);
                                list_for_each_entry(cfile, &tcon->openFileList, tlist) {
                                        seq_printf(m,
-                                               "0x%x 0x%llx 0x%x %d %d %d %pd",
+                                               "0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd",
                                                tcon->tid,
+                                               ses->Suid,
                                                cfile->fid.persistent_fid,
                                                cfile->f_flags,
                                                cfile->count,
@@ -216,6 +217,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
 {
        struct mid_q_entry *mid_entry;
        struct TCP_Server_Info *server;
+       struct TCP_Server_Info *chan_server;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
        struct cifs_server_iface *iface;
@@ -420,6 +422,11 @@ skip_rdma:
                                   from_kuid(&init_user_ns, ses->linux_uid),
                                   from_kuid(&init_user_ns, ses->cred_uid));
 
+                       if (ses->dfs_root_ses) {
+                               seq_printf(m, "\n\tDFS root session id: 0x%llx",
+                                          ses->dfs_root_ses->Suid);
+                       }
+
                        spin_lock(&ses->chan_lock);
                        if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0))
                                seq_puts(m, "\tPrimary channel: DISCONNECTED ");
@@ -469,23 +476,35 @@ skip_rdma:
                                        seq_puts(m, "\t\t[CONNECTED]\n");
                        }
                        spin_unlock(&ses->iface_lock);
+
+                       seq_puts(m, "\n\n\tMIDs: ");
+                       spin_lock(&ses->chan_lock);
+                       for (j = 0; j < ses->chan_count; j++) {
+                               chan_server = ses->chans[j].server;
+                               if (!chan_server)
+                                       continue;
+
+                               if (list_empty(&chan_server->pending_mid_q))
+                                       continue;
+
+                               seq_printf(m, "\n\tServer ConnectionId: 0x%llx",
+                                          chan_server->conn_id);
+                               spin_lock(&chan_server->mid_lock);
+                               list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) {
+                                       seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu",
+                                                  mid_entry->mid_state,
+                                                  le16_to_cpu(mid_entry->command),
+                                                  mid_entry->pid,
+                                                  mid_entry->callback_data,
+                                                  mid_entry->mid);
+                               }
+                               spin_unlock(&chan_server->mid_lock);
+                       }
+                       spin_unlock(&ses->chan_lock);
+                       seq_puts(m, "\n--\n");
                }
                if (i == 0)
                        seq_printf(m, "\n\t\t[NONE]");
-
-               seq_puts(m, "\n\n\tMIDs: ");
-               spin_lock(&server->mid_lock);
-               list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
-                       seq_printf(m, "\n\tState: %d com: %d pid:"
-                                       " %d cbdata: %p mid %llu\n",
-                                       mid_entry->mid_state,
-                                       le16_to_cpu(mid_entry->command),
-                                       mid_entry->pid,
-                                       mid_entry->callback_data,
-                                       mid_entry->mid);
-               }
-               spin_unlock(&server->mid_lock);
-               seq_printf(m, "\n--\n");
        }
        if (c == 0)
                seq_printf(m, "\n\t[NONE]");
index 2b1a8d55b4ec427dcd25ddad2439bd9a65f79c93..0329a907bdfe8acc709069d5bb165ddd1fdcdb72 100644 (file)
@@ -171,14 +171,13 @@ static struct vfsmount *cifs_dfs_do_automount(struct path *path)
                mnt = ERR_CAST(full_path);
                goto out;
        }
-
-       convert_delimiter(full_path, '/');
        cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
 
        tmp = *cur_ctx;
        tmp.source = full_path;
        tmp.leaf_fullpath = NULL;
        tmp.UNC = tmp.prepath = NULL;
+       tmp.dfs_root_ses = NULL;
 
        rc = smb3_fs_context_dup(ctx, &tmp);
        if (rc) {
index 013a4bd65280ce9d7341796e456f189eff255367..65175919228014001a7b5c0b0acc4df8c72ed8b2 100644 (file)
@@ -61,8 +61,6 @@ struct cifs_sb_info {
        /* only used when CIFS_MOUNT_USE_PREFIX_PATH is set */
        char *prepath;
 
-       /* randomly generated 128-bit number for indexing dfs mount groups in referral cache */
-       uuid_t dfs_mount_id;
        /*
         * Indicate whether serverino option was turned off later
         * (cifs_autodisable_serverino) in order to match new mounts.
index cbcf210d56e4863d705597175ee952100cb4c51e..ac9034fce409d27be6640a1fd1dbcea66c3abf32 100644 (file)
@@ -731,13 +731,16 @@ static void cifs_umount_begin(struct super_block *sb)
        spin_lock(&tcon->tc_lock);
        if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) {
                /* we have other mounts to same share or we have
-                  already tried to force umount this and woken up
+                  already tried to umount this and woken up
                   all waiting network requests, nothing to do */
                spin_unlock(&tcon->tc_lock);
                spin_unlock(&cifs_tcp_ses_lock);
                return;
-       } else if (tcon->tc_count == 1)
-               tcon->status = TID_EXITING;
+       }
+       /*
+        * can not set tcon->status to TID_EXITING yet since we don't know if umount -f will
+        * fail later (e.g. due to open files).  TID_EXITING will be set just before tdis req sent
+        */
        spin_unlock(&tcon->tc_lock);
        spin_unlock(&cifs_tcp_ses_lock);
 
index 71fe0a0a799265b677bb8d874de1f29d73ed105b..415176b2cf321ff2c270d410f47b04a310938a82 100644 (file)
@@ -124,7 +124,10 @@ extern const struct dentry_operations cifs_ci_dentry_ops;
 #ifdef CONFIG_CIFS_DFS_UPCALL
 extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
 #else
-#define cifs_dfs_d_automount NULL
+static inline struct vfsmount *cifs_dfs_d_automount(struct path *path)
+{
+       return ERR_PTR(-EREMOTE);
+}
 #endif
 
 /* Functions related to symlinks */
index a99883f16d9467d75dd167ada1d32b5a951a617d..08a73dcb778641bc4d313d34632bf06d9d3ed621 100644 (file)
@@ -1233,6 +1233,7 @@ struct cifs_tcon {
        /* BB add field for back pointer to sb struct(s)? */
 #ifdef CONFIG_CIFS_DFS_UPCALL
        struct list_head ulist; /* cache update list */
+       struct list_head dfs_ses_list;
 #endif
        struct delayed_work     query_interfaces; /* query interfaces workqueue job */
 };
@@ -1749,9 +1750,8 @@ struct cifs_mount_ctx {
        struct TCP_Server_Info *server;
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
-       struct cifs_ses *root_ses;
-       uuid_t mount_id;
        char *origin_fullpath, *leaf_fullpath;
+       struct list_head dfs_ses_list;
 };
 
 static inline void free_dfs_info_param(struct dfs_info3_param *param)
index a43c78396dd8815a9b972814bb599dafd2c4c456..9d963caec35c8d07f671aefca26ae1ee9a63a82d 100644 (file)
@@ -71,7 +71,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
        int rc;
        struct cifs_ses *ses;
        struct TCP_Server_Info *server;
-       struct nls_table *nls_codepage;
+       struct nls_table *nls_codepage = NULL;
 
        /*
         * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
@@ -86,13 +86,11 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
 
        /*
         * only tree disconnect, open, and write, (and ulogoff which does not
-        * have tcon) are allowed as we start force umount
+        * have tcon) are allowed as we start umount
         */
        spin_lock(&tcon->tc_lock);
        if (tcon->status == TID_EXITING) {
-               if (smb_command != SMB_COM_WRITE_ANDX &&
-                   smb_command != SMB_COM_OPEN_ANDX &&
-                   smb_command != SMB_COM_TREE_DISCONNECT) {
+               if (smb_command != SMB_COM_TREE_DISCONNECT) {
                        spin_unlock(&tcon->tc_lock);
                        cifs_dbg(FYI, "can not send cmd %d while umounting\n",
                                 smb_command);
@@ -101,6 +99,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
        }
        spin_unlock(&tcon->tc_lock);
 
+again:
        rc = cifs_wait_for_server_reconnect(server, tcon->retry);
        if (rc)
                return rc;
@@ -112,8 +111,7 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
        }
        spin_unlock(&ses->chan_lock);
 
-       nls_codepage = load_nls_default();
-
+       mutex_lock(&ses->session_mutex);
        /*
         * Recheck after acquire mutex. If another thread is negotiating
         * and the server never sends an answer the socket will be closed
@@ -122,29 +120,38 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
        spin_lock(&server->srv_lock);
        if (server->tcpStatus == CifsNeedReconnect) {
                spin_unlock(&server->srv_lock);
+               mutex_unlock(&ses->session_mutex);
+
+               if (tcon->retry)
+                       goto again;
                rc = -EHOSTDOWN;
                goto out;
        }
        spin_unlock(&server->srv_lock);
 
+       nls_codepage = load_nls_default();
+
        /*
         * need to prevent multiple threads trying to simultaneously
         * reconnect the same SMB session
         */
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       if (!cifs_chan_needs_reconnect(ses, server)) {
+       if (!cifs_chan_needs_reconnect(ses, server) &&
+           ses->ses_status == SES_GOOD) {
                spin_unlock(&ses->chan_lock);
+               spin_unlock(&ses->ses_lock);
 
                /* this means that we only need to tree connect */
                if (tcon->need_reconnect)
                        goto skip_sess_setup;
 
-               rc = -EHOSTDOWN;
+               mutex_unlock(&ses->session_mutex);
                goto out;
        }
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
-       mutex_lock(&ses->session_mutex);
        rc = cifs_negotiate_protocol(0, ses, server);
        if (!rc)
                rc = cifs_setup_session(0, ses, server, nls_codepage);
@@ -4375,8 +4382,13 @@ CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses,
                return -ENODEV;
 
 getDFSRetry:
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc, (void **) &pSMB,
-                     (void **) &pSMBr);
+       /*
+        * Use smb_init_no_reconnect() instead of smb_init() as
+        * CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
+        * causing an infinite recursion.
+        */
+       rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
+                                  (void **)&pSMB, (void **)&pSMBr);
        if (rc)
                return rc;
 
index 5233f14f0636ac0fa65ff1d1b058d186543ffada..1cbb9058799572686193dfa84925d0b03601d5ad 100644 (file)
@@ -212,31 +212,42 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
                        cifs_chan_update_iface(ses, server);
 
                spin_lock(&ses->chan_lock);
-               if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server))
-                       goto next_session;
+               if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) {
+                       spin_unlock(&ses->chan_lock);
+                       continue;
+               }
 
                if (mark_smb_session)
                        CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses);
                else
                        cifs_chan_set_need_reconnect(ses, server);
 
+               cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
+                        __func__, ses->chans_need_reconnect);
+
                /* If all channels need reconnect, then tcon needs reconnect */
-               if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses))
-                       goto next_session;
+               if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+                       spin_unlock(&ses->chan_lock);
+                       continue;
+               }
+               spin_unlock(&ses->chan_lock);
 
+               spin_lock(&ses->ses_lock);
                ses->ses_status = SES_NEED_RECON;
+               spin_unlock(&ses->ses_lock);
 
                list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
                        tcon->need_reconnect = true;
+                       spin_lock(&tcon->tc_lock);
                        tcon->status = TID_NEED_RECON;
+                       spin_unlock(&tcon->tc_lock);
                }
                if (ses->tcon_ipc) {
                        ses->tcon_ipc->need_reconnect = true;
+                       spin_lock(&ses->tcon_ipc->tc_lock);
                        ses->tcon_ipc->status = TID_NEED_RECON;
+                       spin_unlock(&ses->tcon_ipc->tc_lock);
                }
-
-next_session:
-               spin_unlock(&ses->chan_lock);
        }
        spin_unlock(&cifs_tcp_ses_lock);
 }
@@ -1721,7 +1732,7 @@ out_err:
        return ERR_PTR(rc);
 }
 
-/* this function must be called with ses_lock held */
+/* this function must be called with ses_lock and chan_lock held */
 static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
 {
        if (ctx->sectype != Unspecified &&
@@ -1732,12 +1743,8 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
         * If an existing session is limited to less channels than
         * requested, it should not be reused
         */
-       spin_lock(&ses->chan_lock);
-       if (ses->chan_max < ctx->max_channels) {
-               spin_unlock(&ses->chan_lock);
+       if (ses->chan_max < ctx->max_channels)
                return 0;
-       }
-       spin_unlock(&ses->chan_lock);
 
        switch (ses->sectype) {
        case Kerberos:
@@ -1865,10 +1872,13 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
                        spin_unlock(&ses->ses_lock);
                        continue;
                }
+               spin_lock(&ses->chan_lock);
                if (!match_session(ses, ctx)) {
+                       spin_unlock(&ses->chan_lock);
                        spin_unlock(&ses->ses_lock);
                        continue;
                }
+               spin_unlock(&ses->chan_lock);
                spin_unlock(&ses->ses_lock);
 
                ++ses->ses_count;
@@ -2229,6 +2239,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
         * need to lock before changing something in the session.
         */
        spin_lock(&cifs_tcp_ses_lock);
+       ses->dfs_root_ses = ctx->dfs_root_ses;
        list_add(&ses->smb_ses_list, &server->smb_ses_list);
        spin_unlock(&cifs_tcp_ses_lock);
 
@@ -2313,6 +2324,7 @@ cifs_put_tcon(struct cifs_tcon *tcon)
        WARN_ON(tcon->tc_count < 0);
 
        list_del_init(&tcon->tcon_list);
+       tcon->status = TID_EXITING;
        spin_unlock(&tcon->tc_lock);
        spin_unlock(&cifs_tcp_ses_lock);
 
@@ -2692,6 +2704,7 @@ cifs_match_super(struct super_block *sb, void *data)
 
        spin_lock(&tcp_srv->srv_lock);
        spin_lock(&ses->ses_lock);
+       spin_lock(&ses->chan_lock);
        spin_lock(&tcon->tc_lock);
        if (!match_server(tcp_srv, ctx, dfs_super_cmp) ||
            !match_session(ses, ctx) ||
@@ -2704,6 +2717,7 @@ cifs_match_super(struct super_block *sb, void *data)
        rc = compare_mount_options(sb, mnt_data);
 out:
        spin_unlock(&tcon->tc_lock);
+       spin_unlock(&ses->chan_lock);
        spin_unlock(&ses->ses_lock);
        spin_unlock(&tcp_srv->srv_lock);
 
@@ -3407,7 +3421,8 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
        bool isdfs;
        int rc;
 
-       uuid_gen(&mnt_ctx.mount_id);
+       INIT_LIST_HEAD(&mnt_ctx.dfs_ses_list);
+
        rc = dfs_mount_share(&mnt_ctx, &isdfs);
        if (rc)
                goto error;
@@ -3427,7 +3442,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
        kfree(cifs_sb->prepath);
        cifs_sb->prepath = ctx->prepath;
        ctx->prepath = NULL;
-       uuid_copy(&cifs_sb->dfs_mount_id, &mnt_ctx.mount_id);
 
 out:
        cifs_try_adding_channels(cifs_sb, mnt_ctx.ses);
@@ -3439,7 +3453,7 @@ out:
        return rc;
 
 error:
-       dfs_cache_put_refsrv_sessions(&mnt_ctx.mount_id);
+       dfs_put_root_smb_sessions(&mnt_ctx.dfs_ses_list);
        kfree(mnt_ctx.origin_fullpath);
        kfree(mnt_ctx.leaf_fullpath);
        cifs_mount_put_conns(&mnt_ctx);
@@ -3637,9 +3651,6 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
        spin_unlock(&cifs_sb->tlink_tree_lock);
 
        kfree(cifs_sb->prepath);
-#ifdef CONFIG_CIFS_DFS_UPCALL
-       dfs_cache_put_refsrv_sessions(&cifs_sb->dfs_mount_id);
-#endif
        call_rcu(&cifs_sb->rcu, delayed_free);
 }
 
@@ -3654,11 +3665,19 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
 
        /* only send once per connect */
        spin_lock(&server->srv_lock);
-       if (!server->ops->need_neg(server) ||
+       if (server->tcpStatus != CifsGood &&
+           server->tcpStatus != CifsNew &&
            server->tcpStatus != CifsNeedNegotiate) {
+               spin_unlock(&server->srv_lock);
+               return -EHOSTDOWN;
+       }
+
+       if (!server->ops->need_neg(server) &&
+           server->tcpStatus == CifsGood) {
                spin_unlock(&server->srv_lock);
                return 0;
        }
+
        server->tcpStatus = CifsInNegotiate;
        spin_unlock(&server->srv_lock);
 
@@ -3692,23 +3711,28 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
        bool is_binding = false;
 
        spin_lock(&ses->ses_lock);
+       cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n",
+                __func__, ses->chans_need_reconnect);
+
        if (ses->ses_status != SES_GOOD &&
            ses->ses_status != SES_NEW &&
            ses->ses_status != SES_NEED_RECON) {
                spin_unlock(&ses->ses_lock);
-               return 0;
+               return -EHOSTDOWN;
        }
 
        /* only send once per connect */
        spin_lock(&ses->chan_lock);
-       if (CIFS_ALL_CHANS_GOOD(ses) ||
-           cifs_chan_in_reconnect(ses, server)) {
+       if (CIFS_ALL_CHANS_GOOD(ses)) {
+               if (ses->ses_status == SES_NEED_RECON)
+                       ses->ses_status = SES_GOOD;
                spin_unlock(&ses->chan_lock);
                spin_unlock(&ses->ses_lock);
                return 0;
        }
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
+
        cifs_chan_set_in_reconnect(ses, server);
+       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
        spin_unlock(&ses->chan_lock);
 
        if (!is_binding)
@@ -4038,9 +4062,13 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
-       if (tcon->ses->ses_status != SES_GOOD ||
-           (tcon->status != TID_NEW &&
-           tcon->status != TID_NEED_TCON)) {
+       if (tcon->status != TID_NEW &&
+           tcon->status != TID_NEED_TCON) {
+               spin_unlock(&tcon->tc_lock);
+               return -EHOSTDOWN;
+       }
+
+       if (tcon->status == TID_GOOD) {
                spin_unlock(&tcon->tc_lock);
                return 0;
        }
index b64d20374b9c853d4402ef3f8617dbfa57921d94..3a11716b6e13eb4b724177265a343981b26143a4 100644 (file)
@@ -95,25 +95,31 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
        ctx->leaf_fullpath = (char *)full_path;
        rc = cifs_mount_get_session(mnt_ctx);
        ctx->leaf_fullpath = NULL;
-       if (!rc) {
-               struct cifs_ses *ses = mnt_ctx->ses;
 
-               mutex_lock(&ses->session_mutex);
-               ses->dfs_root_ses = mnt_ctx->root_ses;
-               mutex_unlock(&ses->session_mutex);
-       }
        return rc;
 }
 
-static void set_root_ses(struct cifs_mount_ctx *mnt_ctx)
+static int get_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
 {
-       if (mnt_ctx->ses) {
+       struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+       struct dfs_root_ses *root_ses;
+       struct cifs_ses *ses = mnt_ctx->ses;
+
+       if (ses) {
+               root_ses = kmalloc(sizeof(*root_ses), GFP_KERNEL);
+               if (!root_ses)
+                       return -ENOMEM;
+
+               INIT_LIST_HEAD(&root_ses->list);
+
                spin_lock(&cifs_tcp_ses_lock);
-               mnt_ctx->ses->ses_count++;
+               ses->ses_count++;
                spin_unlock(&cifs_tcp_ses_lock);
-               dfs_cache_add_refsrv_session(&mnt_ctx->mount_id, mnt_ctx->ses);
+               root_ses->ses = ses;
+               list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
        }
-       mnt_ctx->root_ses = mnt_ctx->ses;
+       ctx->dfs_root_ses = ses;
+       return 0;
 }
 
 static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, const char *full_path,
@@ -121,7 +127,8 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co
 {
        struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
        struct dfs_info3_param ref = {};
-       int rc;
+       bool is_refsrv = false;
+       int rc, rc2;
 
        rc = dfs_cache_get_tgt_referral(ref_path + 1, tit, &ref);
        if (rc)
@@ -136,8 +143,7 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co
        if (rc)
                goto out;
 
-       if (ref.flags & DFSREF_REFERRAL_SERVER)
-               set_root_ses(mnt_ctx);
+       is_refsrv = !!(ref.flags & DFSREF_REFERRAL_SERVER);
 
        rc = -EREMOTE;
        if (ref.flags & DFSREF_STORAGE_SERVER) {
@@ -146,13 +152,17 @@ static int get_dfs_conn(struct cifs_mount_ctx *mnt_ctx, const char *ref_path, co
                        goto out;
 
                /* some servers may not advertise referral capability under ref.flags */
-               if (!(ref.flags & DFSREF_REFERRAL_SERVER) &&
-                   is_tcon_dfs(mnt_ctx->tcon))
-                       set_root_ses(mnt_ctx);
+               is_refsrv |= is_tcon_dfs(mnt_ctx->tcon);
 
                rc = cifs_is_path_remote(mnt_ctx);
        }
 
+       if (rc == -EREMOTE && is_refsrv) {
+               rc2 = get_root_smb_session(mnt_ctx);
+               if (rc2)
+                       rc = rc2;
+       }
+
 out:
        free_dfs_info_param(&ref);
        return rc;
@@ -165,6 +175,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
        char *ref_path = NULL, *full_path = NULL;
        struct dfs_cache_tgt_iterator *tit;
        struct TCP_Server_Info *server;
+       struct cifs_tcon *tcon;
        char *origin_fullpath = NULL;
        int num_links = 0;
        int rc;
@@ -234,12 +245,22 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
 
        if (!rc) {
                server = mnt_ctx->server;
+               tcon = mnt_ctx->tcon;
 
                mutex_lock(&server->refpath_lock);
-               server->origin_fullpath = origin_fullpath;
-               server->current_fullpath = server->leaf_fullpath;
+               if (!server->origin_fullpath) {
+                       server->origin_fullpath = origin_fullpath;
+                       server->current_fullpath = server->leaf_fullpath;
+                       origin_fullpath = NULL;
+               }
                mutex_unlock(&server->refpath_lock);
-               origin_fullpath = NULL;
+
+               if (list_empty(&tcon->dfs_ses_list)) {
+                       list_replace_init(&mnt_ctx->dfs_ses_list,
+                                         &tcon->dfs_ses_list);
+               } else {
+                       dfs_put_root_smb_sessions(&mnt_ctx->dfs_ses_list);
+               }
        }
 
 out:
@@ -260,7 +281,7 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
        rc = get_session(mnt_ctx, NULL);
        if (rc)
                return rc;
-       mnt_ctx->root_ses = mnt_ctx->ses;
+       ctx->dfs_root_ses = mnt_ctx->ses;
        /*
         * If called with 'nodfs' mount option, then skip DFS resolving.  Otherwise unconditionally
         * try to get an DFS referral (even cached) to determine whether it is an DFS mount.
@@ -280,7 +301,9 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
        }
 
        *isdfs = true;
-       set_root_ses(mnt_ctx);
+       rc = get_root_smb_session(mnt_ctx);
+       if (rc)
+               return rc;
 
        return __dfs_mount_share(mnt_ctx);
 }
@@ -479,9 +502,13 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
 
        /* only send once per connect */
        spin_lock(&tcon->tc_lock);
-       if (tcon->ses->ses_status != SES_GOOD ||
-           (tcon->status != TID_NEW &&
-           tcon->status != TID_NEED_TCON)) {
+       if (tcon->status != TID_NEW &&
+           tcon->status != TID_NEED_TCON) {
+               spin_unlock(&tcon->tc_lock);
+               return -EHOSTDOWN;
+       }
+
+       if (tcon->status == TID_GOOD) {
                spin_unlock(&tcon->tc_lock);
                return 0;
        }
index 344bea6d8bab1e471444131b1841c4442e5ca657..0b8cbf721fff6ed6e9aac7c4f01239f039acefdf 100644 (file)
 #include "fs_context.h"
 #include "cifs_unicode.h"
 
+struct dfs_root_ses {
+       struct list_head list;
+       struct cifs_ses *ses;
+};
+
 int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_param *ref,
                              struct smb3_fs_context *ctx);
 int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs);
@@ -22,25 +27,51 @@ static inline char *dfs_get_path(struct cifs_sb_info *cifs_sb, const char *path)
 static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *path,
                                   struct dfs_info3_param *ref, struct dfs_cache_tgt_list *tl)
 {
+       struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
        struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
 
-       return dfs_cache_find(mnt_ctx->xid, mnt_ctx->root_ses, cifs_sb->local_nls,
+       return dfs_cache_find(mnt_ctx->xid, ctx->dfs_root_ses, cifs_sb->local_nls,
                              cifs_remap(cifs_sb), path, ref, tl);
 }
 
+/* Return DFS full path out of a dentry set for automount */
 static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
        struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
        struct TCP_Server_Info *server = tcon->ses->server;
+       size_t len;
+       char *s;
 
        if (unlikely(!server->origin_fullpath))
                return ERR_PTR(-EREMOTE);
 
-       return __build_path_from_dentry_optional_prefix(dentry, page,
-                                                       server->origin_fullpath,
-                                                       strlen(server->origin_fullpath),
-                                                       true);
+       s = dentry_path_raw(dentry, page, PATH_MAX);
+       if (IS_ERR(s))
+               return s;
+       /* for root, we want "" */
+       if (!s[1])
+               s++;
+
+       len = strlen(server->origin_fullpath);
+       if (s < (char *)page + len)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       s -= len;
+       memcpy(s, server->origin_fullpath, len);
+       convert_delimiter(s, '/');
+       return s;
+}
+
+static inline void dfs_put_root_smb_sessions(struct list_head *head)
+{
+       struct dfs_root_ses *root, *tmp;
+
+       list_for_each_entry_safe(root, tmp, head, list) {
+               list_del_init(&root->list);
+               cifs_put_smb_ses(root->ses);
+               kfree(root);
+       }
 }
 
 #endif /* _CIFS_DFS_H */
index ac86bd0ebd637bc2d1440c3f2858489ed27b5364..30cbdf8514a5969c8a2b862277b0544405d2a151 100644 (file)
@@ -49,17 +49,6 @@ struct cache_entry {
        struct cache_dfs_tgt *tgthint;
 };
 
-/* List of referral server sessions per dfs mount */
-struct mount_group {
-       struct list_head list;
-       uuid_t id;
-       struct cifs_ses *sessions[CACHE_MAX_ENTRIES];
-       int num_sessions;
-       spinlock_t lock;
-       struct list_head refresh_list;
-       struct kref refcount;
-};
-
 static struct kmem_cache *cache_slab __read_mostly;
 static struct workqueue_struct *dfscache_wq __read_mostly;
 
@@ -76,85 +65,10 @@ static atomic_t cache_count;
 static struct hlist_head cache_htable[CACHE_HTABLE_SIZE];
 static DECLARE_RWSEM(htable_rw_lock);
 
-static LIST_HEAD(mount_group_list);
-static DEFINE_MUTEX(mount_group_list_lock);
-
 static void refresh_cache_worker(struct work_struct *work);
 
 static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker);
 
-static void __mount_group_release(struct mount_group *mg)
-{
-       int i;
-
-       for (i = 0; i < mg->num_sessions; i++)
-               cifs_put_smb_ses(mg->sessions[i]);
-       kfree(mg);
-}
-
-static void mount_group_release(struct kref *kref)
-{
-       struct mount_group *mg = container_of(kref, struct mount_group, refcount);
-
-       mutex_lock(&mount_group_list_lock);
-       list_del(&mg->list);
-       mutex_unlock(&mount_group_list_lock);
-       __mount_group_release(mg);
-}
-
-static struct mount_group *find_mount_group_locked(const uuid_t *id)
-{
-       struct mount_group *mg;
-
-       list_for_each_entry(mg, &mount_group_list, list) {
-               if (uuid_equal(&mg->id, id))
-                       return mg;
-       }
-       return ERR_PTR(-ENOENT);
-}
-
-static struct mount_group *__get_mount_group_locked(const uuid_t *id)
-{
-       struct mount_group *mg;
-
-       mg = find_mount_group_locked(id);
-       if (!IS_ERR(mg))
-               return mg;
-
-       mg = kmalloc(sizeof(*mg), GFP_KERNEL);
-       if (!mg)
-               return ERR_PTR(-ENOMEM);
-       kref_init(&mg->refcount);
-       uuid_copy(&mg->id, id);
-       mg->num_sessions = 0;
-       spin_lock_init(&mg->lock);
-       list_add(&mg->list, &mount_group_list);
-       return mg;
-}
-
-static struct mount_group *get_mount_group(const uuid_t *id)
-{
-       struct mount_group *mg;
-
-       mutex_lock(&mount_group_list_lock);
-       mg = __get_mount_group_locked(id);
-       if (!IS_ERR(mg))
-               kref_get(&mg->refcount);
-       mutex_unlock(&mount_group_list_lock);
-
-       return mg;
-}
-
-static void free_mount_group_list(void)
-{
-       struct mount_group *mg, *tmp_mg;
-
-       list_for_each_entry_safe(mg, tmp_mg, &mount_group_list, list) {
-               list_del_init(&mg->list);
-               __mount_group_release(mg);
-       }
-}
-
 /**
  * dfs_cache_canonical_path - get a canonical DFS path
  *
@@ -704,7 +618,6 @@ void dfs_cache_destroy(void)
 {
        cancel_delayed_work_sync(&refresh_task);
        unload_nls(cache_cp);
-       free_mount_group_list();
        flush_cache_ents();
        kmem_cache_destroy(cache_slab);
        destroy_workqueue(dfscache_wq);
@@ -1111,54 +1024,6 @@ out_unlock:
        return rc;
 }
 
-/**
- * dfs_cache_add_refsrv_session - add SMB session of referral server
- *
- * @mount_id: mount group uuid to lookup.
- * @ses: reference counted SMB session of referral server.
- */
-void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses)
-{
-       struct mount_group *mg;
-
-       if (WARN_ON_ONCE(!mount_id || uuid_is_null(mount_id) || !ses))
-               return;
-
-       mg = get_mount_group(mount_id);
-       if (WARN_ON_ONCE(IS_ERR(mg)))
-               return;
-
-       spin_lock(&mg->lock);
-       if (mg->num_sessions < ARRAY_SIZE(mg->sessions))
-               mg->sessions[mg->num_sessions++] = ses;
-       spin_unlock(&mg->lock);
-       kref_put(&mg->refcount, mount_group_release);
-}
-
-/**
- * dfs_cache_put_refsrv_sessions - put all referral server sessions
- *
- * Put all SMB sessions from the given mount group id.
- *
- * @mount_id: mount group uuid to lookup.
- */
-void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id)
-{
-       struct mount_group *mg;
-
-       if (!mount_id || uuid_is_null(mount_id))
-               return;
-
-       mutex_lock(&mount_group_list_lock);
-       mg = find_mount_group_locked(mount_id);
-       if (IS_ERR(mg)) {
-               mutex_unlock(&mount_group_list_lock);
-               return;
-       }
-       mutex_unlock(&mount_group_list_lock);
-       kref_put(&mg->refcount, mount_group_release);
-}
-
 /* Extract share from DFS target and return a pointer to prefix path or NULL */
 static const char *parse_target_share(const char *target, char **share)
 {
@@ -1326,7 +1191,7 @@ static int __refresh_tcon(const char *path, struct cifs_tcon *tcon, bool force_r
        }
 
        spin_lock(&ipc->tc_lock);
-       if (ses->ses_status != SES_GOOD || ipc->status != TID_GOOD) {
+       if (ipc->status != TID_GOOD) {
                spin_unlock(&ipc->tc_lock);
                cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", __func__);
                goto out;
@@ -1384,11 +1249,6 @@ int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
                cifs_dbg(FYI, "%s: not a dfs mount\n", __func__);
                return 0;
        }
-
-       if (uuid_is_null(&cifs_sb->dfs_mount_id)) {
-               cifs_dbg(FYI, "%s: no dfs mount group id\n", __func__);
-               return -EINVAL;
-       }
        /*
         * After reconnecting to a different server, unique ids won't match anymore, so we disable
         * serverino. This prevents dentry revalidation to think the dentry are stale (ESTALE).
index be3b5a44cf82711a575e8efe70934f7e07109131..e0d39393035a99086c875324d8440f8fe03436ca 100644 (file)
@@ -40,8 +40,6 @@ int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iter
                               struct dfs_info3_param *ref);
 int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
                            char **prefix);
-void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id);
-void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses);
 char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap);
 int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb);
 
index 4d4a2d82636d2a359f785c41c5efca5ba5aa8504..b33d2e7b0f984490e9db987a535201de0fe79e1e 100644 (file)
@@ -174,13 +174,13 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
        struct list_head *tmp1;
 
        /* only send once per connect */
-       spin_lock(&tcon->ses->ses_lock);
-       if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) {
-               spin_unlock(&tcon->ses->ses_lock);
+       spin_lock(&tcon->tc_lock);
+       if (tcon->status != TID_NEED_RECON) {
+               spin_unlock(&tcon->tc_lock);
                return;
        }
        tcon->status = TID_IN_FILES_INVALIDATE;
-       spin_unlock(&tcon->ses->ses_lock);
+       spin_unlock(&tcon->tc_lock);
 
        /* list all files open on tree connection and mark them invalid */
        spin_lock(&tcon->open_file_lock);
@@ -4010,7 +4010,6 @@ static void
 collect_uncached_read_data(struct cifs_aio_ctx *ctx)
 {
        struct cifs_readdata *rdata, *tmp;
-       struct iov_iter *to = &ctx->iter;
        struct cifs_sb_info *cifs_sb;
        int rc;
 
@@ -4076,9 +4075,6 @@ again:
                kref_put(&rdata->refcount, cifs_readdata_release);
        }
 
-       if (!ctx->direct_io)
-               ctx->total_len = ctx->len - iov_iter_count(to);
-
        /* mask nodata case */
        if (rc == -ENODATA)
                rc = 0;
index 6d13f8207e96a146a44860538cfaf1045924b4b2..ace11a1a7c8abc07e9df9ec7e9fbf2bd61455e1c 100644 (file)
@@ -441,13 +441,14 @@ out:
  * but there are some bugs that prevent rename from working if there are
  * multiple delimiters.
  *
- * Returns a sanitized duplicate of @path. The caller is responsible for
- * cleaning up the original.
+ * Returns a sanitized duplicate of @path. @gfp indicates the GFP_* flags
+ * for kstrdup.
+ * The caller is responsible for freeing the original.
  */
 #define IS_DELIM(c) ((c) == '/' || (c) == '\\')
-static char *sanitize_path(char *path)
+char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)
 {
-       char *cursor1 = path, *cursor2 = path;
+       char *cursor1 = prepath, *cursor2 = prepath;
 
        /* skip all prepended delimiters */
        while (IS_DELIM(*cursor1))
@@ -469,7 +470,7 @@ static char *sanitize_path(char *path)
                cursor2--;
 
        *(cursor2) = '\0';
-       return kstrdup(path, GFP_KERNEL);
+       return kstrdup(prepath, gfp);
 }
 
 /*
@@ -531,7 +532,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
        if (!*pos)
                return 0;
 
-       ctx->prepath = sanitize_path(pos);
+       ctx->prepath = cifs_sanitize_prepath(pos, GFP_KERNEL);
        if (!ctx->prepath)
                return -ENOMEM;
 
index 44cb5639ed3ba3502db464c887526c3c0b0ec58a..f4eaf855890222924c99a92f693f131b0c69cde7 100644 (file)
@@ -265,6 +265,7 @@ struct smb3_fs_context {
        bool rootfs:1; /* if it's a SMB root file system */
        bool witness:1; /* use witness protocol */
        char *leaf_fullpath;
+       struct cifs_ses *dfs_root_ses;
 };
 
 extern const struct fs_parameter_spec smb3_fs_parameters[];
@@ -285,5 +286,8 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
  * max deferred close timeout (jiffies) - 2^30
  */
 #define SMB3_MAX_DCLOSETIMEO (1 << 30)
-#define SMB3_DEF_DCLOSETIMEO (5 * HZ) /* Can increase later, other clients use larger */
+#define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */
+
+extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
+
 #endif
index 7d97c10f24535016a0ad447f1854274a7c853df7..c66be4904e1fa0db7277571e5163f0dfe6359b1b 100644 (file)
@@ -360,6 +360,7 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
                .cifs_sb = cifs_sb,
+               .path = path,
                .desired_access = GENERIC_READ,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
                .disposition = FILE_OPEN,
@@ -427,6 +428,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
                .cifs_sb = cifs_sb,
+               .path = path,
                .desired_access = GENERIC_WRITE,
                .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
                .disposition = FILE_CREATE,
index a0d286ee723dda465cecbe9d9e0c4f20c3887e3e..7f085ed2d866bb751270176120e0fc26d5d60d11 100644 (file)
@@ -22,6 +22,7 @@
 #ifdef CONFIG_CIFS_DFS_UPCALL
 #include "dns_resolve.h"
 #include "dfs_cache.h"
+#include "dfs.h"
 #endif
 #include "fs_context.h"
 #include "cached_dir.h"
@@ -134,6 +135,9 @@ tconInfoAlloc(void)
        spin_lock_init(&ret_buf->stat_lock);
        atomic_set(&ret_buf->num_local_opens, 0);
        atomic_set(&ret_buf->num_remote_opens, 0);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       INIT_LIST_HEAD(&ret_buf->dfs_ses_list);
+#endif
 
        return ret_buf;
 }
@@ -149,6 +153,9 @@ tconInfoFree(struct cifs_tcon *tcon)
        atomic_dec(&tconInfoAllocCount);
        kfree(tcon->nativeFileSystem);
        kfree_sensitive(tcon->password);
+#ifdef CONFIG_CIFS_DFS_UPCALL
+       dfs_put_root_smb_sessions(&tcon->dfs_ses_list);
+#endif
        kfree(tcon);
 }
 
@@ -1188,7 +1195,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
        kfree(cifs_sb->prepath);
 
        if (prefix && *prefix) {
-               cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC);
+               cifs_sb->prepath = cifs_sanitize_prepath(prefix, GFP_ATOMIC);
                if (!cifs_sb->prepath)
                        return -ENOMEM;
 
@@ -1255,6 +1262,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid,
                 * removing cached DFS targets that the client would eventually
                 * need during failover.
                 */
+               ses = CIFS_DFS_ROOT_SES(ses);
                if (ses->server->ops->get_dfs_refer &&
                    !ses->server->ops->get_dfs_refer(xid, ses, ref_path, &refs,
                                                     &num_refs, cifs_sb->local_nls,
index 9b956294e8643dfe57772699436ffab2bd0bcc85..163a03298430d08304647d3c137903f8afbef0bc 100644 (file)
@@ -107,6 +107,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 
        vars->oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = desired_access,
                .disposition = create_disposition,
                .create_options = cifs_create_options(cifs_sb, create_options),
@@ -234,15 +235,32 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                size[0] = 8; /* sizeof __le64 */
                data[0] = ptr;
 
-               rc = SMB2_set_info_init(tcon, server,
-                                       &rqst[num_rqst], COMPOUND_FID,
-                                       COMPOUND_FID, current->tgid,
-                                       FILE_END_OF_FILE_INFORMATION,
-                                       SMB2_O_INFO_FILE, 0, data, size);
+               if (cfile) {
+                       rc = SMB2_set_info_init(tcon, server,
+                                               &rqst[num_rqst],
+                                               cfile->fid.persistent_fid,
+                                               cfile->fid.volatile_fid,
+                                               current->tgid,
+                                               FILE_END_OF_FILE_INFORMATION,
+                                               SMB2_O_INFO_FILE, 0,
+                                               data, size);
+               } else {
+                       rc = SMB2_set_info_init(tcon, server,
+                                               &rqst[num_rqst],
+                                               COMPOUND_FID,
+                                               COMPOUND_FID,
+                                               current->tgid,
+                                               FILE_END_OF_FILE_INFORMATION,
+                                               SMB2_O_INFO_FILE, 0,
+                                               data, size);
+                       if (!rc) {
+                               smb2_set_next_command(tcon, &rqst[num_rqst]);
+                               smb2_set_related(&rqst[num_rqst]);
+                       }
+               }
                if (rc)
                        goto finished;
-               smb2_set_next_command(tcon, &rqst[num_rqst]);
-               smb2_set_related(&rqst[num_rqst++]);
+               num_rqst++;
                trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path);
                break;
        case SMB2_OP_SET_INFO:
index 6dfb865ee9d75155f1421b0a41677e32da15eb98..a81758225fcdc7b24b8921bf37ef95c79fde2ba3 100644 (file)
@@ -530,6 +530,14 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
        p = buf;
 
        spin_lock(&ses->iface_lock);
+       /* do not query too frequently, this time with lock held */
+       if (ses->iface_last_update &&
+           time_before(jiffies, ses->iface_last_update +
+                       (SMB_INTERFACE_POLL_INTERVAL * HZ))) {
+               spin_unlock(&ses->iface_lock);
+               return 0;
+       }
+
        /*
         * Go through iface_list and do kref_put to remove
         * any unused ifaces. ifaces in use will be removed
@@ -696,6 +704,12 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
        struct network_interface_info_ioctl_rsp *out_buf = NULL;
        struct cifs_ses *ses = tcon->ses;
 
+       /* do not query too frequently */
+       if (ses->iface_last_update &&
+           time_before(jiffies, ses->iface_last_update +
+                       (SMB_INTERFACE_POLL_INTERVAL * HZ)))
+               return 0;
+
        rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
                        FSCTL_QUERY_NETWORK_INTERFACE_INFO,
                        NULL /* no data input */, 0 /* no data input */,
@@ -703,7 +717,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_
        if (rc == -EOPNOTSUPP) {
                cifs_dbg(FYI,
                         "server does not support query network interfaces\n");
-               goto out;
+               ret_data_len = 0;
        } else if (rc != 0) {
                cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
                goto out;
@@ -731,6 +745,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = "",
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -774,6 +789,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = "",
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -821,6 +837,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -1105,6 +1122,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = FILE_WRITE_EA,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2096,6 +2114,7 @@ smb3_notify(const unsigned int xid, struct file *pfile,
        tcon = cifs_sb_master_tcon(cifs_sb);
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2168,6 +2187,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2500,6 +2520,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = desired_access,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2634,6 +2655,7 @@ smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = "",
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, 0),
@@ -2928,6 +2950,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, create_options),
@@ -3068,6 +3091,7 @@ smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = full_path,
                .desired_access = FILE_READ_ATTRIBUTES,
                .disposition = FILE_OPEN,
                .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT),
@@ -3208,6 +3232,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
 
        oparms = (struct cifs_open_parms) {
                .tcon = tcon,
+               .path = path,
                .desired_access = READ_CONTROL,
                .disposition = FILE_OPEN,
                /*
index 0e53265e1462a350d5c8bbde41893b50f3dac3ae..366f0c3b799b66368f79bd662b03c0d4f9852fd3 100644 (file)
@@ -144,7 +144,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
               struct TCP_Server_Info *server)
 {
        int rc = 0;
-       struct nls_table *nls_codepage;
+       struct nls_table *nls_codepage = NULL;
        struct cifs_ses *ses;
 
        /*
@@ -165,13 +165,9 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
        spin_lock(&tcon->tc_lock);
        if (tcon->status == TID_EXITING) {
                /*
-                * only tree disconnect, open, and write,
-                * (and ulogoff which does not have tcon)
-                * are allowed as we start force umount.
+                * only tree disconnect allowed when disconnecting ...
                 */
-               if ((smb2_command != SMB2_WRITE) &&
-                  (smb2_command != SMB2_CREATE) &&
-                  (smb2_command != SMB2_TREE_DISCONNECT)) {
+               if (smb2_command != SMB2_TREE_DISCONNECT) {
                        spin_unlock(&tcon->tc_lock);
                        cifs_dbg(FYI, "can not send cmd %d while umounting\n",
                                 smb2_command);
@@ -203,6 +199,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
        }
        spin_unlock(&server->srv_lock);
 
+again:
        rc = cifs_wait_for_server_reconnect(server, tcon->retry);
        if (rc)
                return rc;
@@ -219,8 +216,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
                 tcon->ses->chans_need_reconnect,
                 tcon->need_reconnect);
 
-       nls_codepage = load_nls_default();
-
+       mutex_lock(&ses->session_mutex);
        /*
         * Recheck after acquire mutex. If another thread is negotiating
         * and the server never sends an answer the socket will be closed
@@ -229,28 +225,38 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
        spin_lock(&server->srv_lock);
        if (server->tcpStatus == CifsNeedReconnect) {
                spin_unlock(&server->srv_lock);
+               mutex_unlock(&ses->session_mutex);
+
+               if (tcon->retry)
+                       goto again;
+
                rc = -EHOSTDOWN;
                goto out;
        }
        spin_unlock(&server->srv_lock);
 
+       nls_codepage = load_nls_default();
+
        /*
         * need to prevent multiple threads trying to simultaneously
         * reconnect the same SMB session
         */
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       if (!cifs_chan_needs_reconnect(ses, server)) {
+       if (!cifs_chan_needs_reconnect(ses, server) &&
+           ses->ses_status == SES_GOOD) {
                spin_unlock(&ses->chan_lock);
-
+               spin_unlock(&ses->ses_lock);
                /* this means that we only need to tree connect */
                if (tcon->need_reconnect)
                        goto skip_sess_setup;
 
+               mutex_unlock(&ses->session_mutex);
                goto out;
        }
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
-       mutex_lock(&ses->session_mutex);
        rc = cifs_negotiate_protocol(0, ses, server);
        if (!rc) {
                rc = cifs_setup_session(0, ses, server, nls_codepage);
@@ -266,10 +272,8 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
                mutex_unlock(&ses->session_mutex);
                goto out;
        }
-       mutex_unlock(&ses->session_mutex);
 
 skip_sess_setup:
-       mutex_lock(&ses->session_mutex);
        if (!tcon->need_reconnect) {
                mutex_unlock(&ses->session_mutex);
                goto out;
@@ -284,7 +288,7 @@ skip_sess_setup:
        cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
        if (rc) {
                /* If sess reconnected but tcon didn't, something strange ... */
-               pr_warn_once("reconnect tcon failed rc = %d\n", rc);
+               cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc);
                goto out;
        }
 
@@ -306,7 +310,6 @@ out:
        case SMB2_READ:
        case SMB2_WRITE:
        case SMB2_LOCK:
-       case SMB2_IOCTL:
        case SMB2_QUERY_DIRECTORY:
        case SMB2_CHANGE_NOTIFY:
        case SMB2_QUERY_INFO:
@@ -584,11 +587,15 @@ assemble_neg_contexts(struct smb2_negotiate_req *req,
 
 }
 
+/* If invalid preauth context warn but use what we requested, SHA-512 */
 static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt)
 {
        unsigned int len = le16_to_cpu(ctxt->DataLength);
 
-       /* If invalid preauth context warn but use what we requested, SHA-512 */
+       /*
+        * Caller checked that DataLength remains within SMB boundary. We still
+        * need to confirm that one HashAlgorithms member is accounted for.
+        */
        if (len < MIN_PREAUTH_CTXT_DATA_LEN) {
                pr_warn_once("server sent bad preauth context\n");
                return;
@@ -607,7 +614,11 @@ static void decode_compress_ctx(struct TCP_Server_Info *server,
 {
        unsigned int len = le16_to_cpu(ctxt->DataLength);
 
-       /* sizeof compress context is a one element compression capbility struct */
+       /*
+        * Caller checked that DataLength remains within SMB boundary. We still
+        * need to confirm that one CompressionAlgorithms member is accounted
+        * for.
+        */
        if (len < 10) {
                pr_warn_once("server sent bad compression cntxt\n");
                return;
@@ -629,6 +640,11 @@ static int decode_encrypt_ctx(struct TCP_Server_Info *server,
        unsigned int len = le16_to_cpu(ctxt->DataLength);
 
        cifs_dbg(FYI, "decode SMB3.11 encryption neg context of len %d\n", len);
+       /*
+        * Caller checked that DataLength remains within SMB boundary. We still
+        * need to confirm that one Cipher flexible array member is accounted
+        * for.
+        */
        if (len < MIN_ENCRYPT_CTXT_DATA_LEN) {
                pr_warn_once("server sent bad crypto ctxt len\n");
                return -EINVAL;
@@ -675,6 +691,11 @@ static void decode_signing_ctx(struct TCP_Server_Info *server,
 {
        unsigned int len = le16_to_cpu(pctxt->DataLength);
 
+       /*
+        * Caller checked that DataLength remains within SMB boundary. We still
+        * need to confirm that one SigningAlgorithms flexible array member is
+        * accounted for.
+        */
        if ((len < 4) || (len > 16)) {
                pr_warn_once("server sent bad signing negcontext\n");
                return;
@@ -716,14 +737,19 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
        for (i = 0; i < ctxt_cnt; i++) {
                int clen;
                /* check that offset is not beyond end of SMB */
-               if (len_of_ctxts == 0)
-                       break;
-
                if (len_of_ctxts < sizeof(struct smb2_neg_context))
                        break;
 
                pctx = (struct smb2_neg_context *)(offset + (char *)rsp);
-               clen = le16_to_cpu(pctx->DataLength);
+               clen = sizeof(struct smb2_neg_context)
+                       + le16_to_cpu(pctx->DataLength);
+               /*
+                * 2.2.4 SMB2 NEGOTIATE Response
+                * Subsequent negotiate contexts MUST appear at the first 8-byte
+                * aligned offset following the previous negotiate context.
+                */
+               if (i + 1 != ctxt_cnt)
+                       clen = ALIGN(clen, 8);
                if (clen > len_of_ctxts)
                        break;
 
@@ -744,12 +770,10 @@ static int smb311_decode_neg_context(struct smb2_negotiate_rsp *rsp,
                else
                        cifs_server_dbg(VFS, "unknown negcontext of type %d ignored\n",
                                le16_to_cpu(pctx->ContextType));
-
                if (rc)
                        break;
-               /* offsets must be 8 byte aligned */
-               clen = ALIGN(clen, 8);
-               offset += clen + sizeof(struct smb2_neg_context);
+
+               offset += clen;
                len_of_ctxts -= clen;
        }
        return rc;
@@ -1256,9 +1280,9 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
        if (rc)
                return rc;
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        if (is_binding) {
                req->hdr.SessionId = cpu_to_le64(ses->Suid);
@@ -1416,9 +1440,9 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
                goto out_put_spnego_key;
        }
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        /* keep session key if binding */
        if (!is_binding) {
@@ -1542,9 +1566,9 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
 
        cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        /* keep existing ses id and flags if binding */
        if (!is_binding) {
@@ -1610,9 +1634,9 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
 
        rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
 
-       spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
-       spin_unlock(&ses->chan_lock);
+       spin_lock(&ses->ses_lock);
+       is_binding = (ses->ses_status == SES_GOOD);
+       spin_unlock(&ses->ses_lock);
 
        /* keep existing ses id and flags if binding */
        if (!is_binding) {
@@ -2705,7 +2729,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
        rqst.rq_nvec = n_iov;
 
        /* no need to inc num_remote_opens because we close it just below */
-       trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE,
+       trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE_NOT_FILE,
                                    FILE_WRITE_ATTRIBUTES);
        /* resource #4: response buffer */
        rc = cifs_send_recv(xid, ses, server,
@@ -2973,7 +2997,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        if (rc)
                goto creat_exit;
 
-       trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid,
+       trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path,
                oparms->create_options, oparms->desired_access);
 
        rc = cifs_send_recv(xid, ses, server,
@@ -4156,10 +4180,12 @@ smb2_readv_callback(struct mid_q_entry *mid)
        struct smb2_hdr *shdr =
                                (struct smb2_hdr *)rdata->iov[0].iov_base;
        struct cifs_credits credits = { .value = 0, .instance = 0 };
-       struct smb_rqst rqst = { .rq_iov = &rdata->iov[1],
-                                .rq_nvec = 1,
-                                .rq_iter = rdata->iter,
-                                .rq_iter_size = iov_iter_count(&rdata->iter), };
+       struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], .rq_nvec = 1 };
+
+       if (rdata->got_bytes) {
+               rqst.rq_iter      = rdata->iter;
+               rqst.rq_iter_size = iov_iter_count(&rdata->iter);
+       };
 
        WARN_ONCE(rdata->server != mid->server,
                  "rdata server %p != mid server %p",
index 381babc1212c9e8a95911e6382e5ba4ff5c3cc80..790acf65a0926cbe3316d591a3bc7a1b97120974 100644 (file)
@@ -81,6 +81,7 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
        struct cifs_ses *ses = NULL;
        int i;
        int rc = 0;
+       bool is_binding = false;
 
        spin_lock(&cifs_tcp_ses_lock);
 
@@ -97,9 +98,12 @@ int smb2_get_sign_key(__u64 ses_id, struct TCP_Server_Info *server, u8 *key)
        goto out;
 
 found:
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       if (cifs_chan_needs_reconnect(ses, server) &&
-           !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) {
+
+       is_binding = (cifs_chan_needs_reconnect(ses, server) &&
+                     ses->ses_status == SES_GOOD);
+       if (is_binding) {
                /*
                 * If we are in the process of binding a new channel
                 * to an existing session, use the master connection
@@ -107,6 +111,7 @@ found:
                 */
                memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE);
                spin_unlock(&ses->chan_lock);
+               spin_unlock(&ses->ses_lock);
                goto out;
        }
 
@@ -119,10 +124,12 @@ found:
                if (chan->server == server) {
                        memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE);
                        spin_unlock(&ses->chan_lock);
+                       spin_unlock(&ses->ses_lock);
                        goto out;
                }
        }
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
        cifs_dbg(VFS,
                 "%s: Could not find channel signing key for session 0x%llx\n",
@@ -392,11 +399,15 @@ generate_smb3signingkey(struct cifs_ses *ses,
        bool is_binding = false;
        int chan_index = 0;
 
+       spin_lock(&ses->ses_lock);
        spin_lock(&ses->chan_lock);
-       is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
+       is_binding = (cifs_chan_needs_reconnect(ses, server) &&
+                     ses->ses_status == SES_GOOD);
+
        chan_index = cifs_ses_get_chan_index(ses, server);
        /* TODO: introduce ref counting for channels when the can be freed */
        spin_unlock(&ses->chan_lock);
+       spin_unlock(&ses->ses_lock);
 
        /*
         * All channels use the same encryption/decryption keys but
@@ -425,7 +436,7 @@ generate_smb3signingkey(struct cifs_ses *ses,
 
                /* safe to access primary channel, since it will never go away */
                spin_lock(&ses->chan_lock);
-               memcpy(ses->chans[0].signkey, ses->smb3signingkey,
+               memcpy(ses->chans[chan_index].signkey, ses->smb3signingkey,
                       SMB3_SIGN_KEY_SIZE);
                spin_unlock(&ses->chan_lock);
 
index 110070ba8b04e3b3e4aa2315d1cfce1c933ea809..d3053bd8ae7312656b04fe97063f50c7c8938a24 100644 (file)
@@ -701,13 +701,15 @@ DECLARE_EVENT_CLASS(smb3_open_enter_class,
        TP_PROTO(unsigned int xid,
                __u32   tid,
                __u64   sesid,
+               const char *full_path,
                int     create_options,
                int     desired_access),
-       TP_ARGS(xid, tid, sesid, create_options, desired_access),
+       TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access),
        TP_STRUCT__entry(
                __field(unsigned int, xid)
                __field(__u32, tid)
                __field(__u64, sesid)
+               __string(path, full_path)
                __field(int, create_options)
                __field(int, desired_access)
        ),
@@ -715,11 +717,12 @@ DECLARE_EVENT_CLASS(smb3_open_enter_class,
                __entry->xid = xid;
                __entry->tid = tid;
                __entry->sesid = sesid;
+               __assign_str(path, full_path);
                __entry->create_options = create_options;
                __entry->desired_access = desired_access;
        ),
-       TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x",
-               __entry->xid, __entry->sesid, __entry->tid,
+       TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s cr_opts=0x%x des_access=0x%x",
+               __entry->xid, __entry->sesid, __entry->tid, __get_str(path),
                __entry->create_options, __entry->desired_access)
 )
 
@@ -728,9 +731,10 @@ DEFINE_EVENT(smb3_open_enter_class, smb3_##name,  \
        TP_PROTO(unsigned int xid,              \
                __u32   tid,                    \
                __u64   sesid,                  \
+               const char *full_path,          \
                int     create_options,         \
                int     desired_access),        \
-       TP_ARGS(xid, tid, sesid, create_options, desired_access))
+       TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access))
 
 DEFINE_SMB3_OPEN_ENTER_EVENT(open_enter);
 DEFINE_SMB3_OPEN_ENTER_EVENT(posix_mkdir_enter);
index b42050c68e6c95a1420dfc3e5ccecff75dee6cd6..24bdd5f4d3bcc725a9763266270a790f03d00a49 100644 (file)
@@ -278,7 +278,7 @@ static int
 __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
                struct smb_rqst *rqst)
 {
-       int rc = 0;
+       int rc;
        struct kvec *iov;
        int n_vec;
        unsigned int send_length = 0;
@@ -289,6 +289,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
        struct msghdr smb_msg = {};
        __be32 rfc1002_marker;
 
+       cifs_in_send_inc(server);
        if (cifs_rdma_enabled(server)) {
                /* return -EAGAIN when connecting or reconnecting */
                rc = -EAGAIN;
@@ -297,14 +298,17 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
                goto smbd_done;
        }
 
+       rc = -EAGAIN;
        if (ssocket == NULL)
-               return -EAGAIN;
+               goto out;
 
+       rc = -ERESTARTSYS;
        if (fatal_signal_pending(current)) {
                cifs_dbg(FYI, "signal pending before send request\n");
-               return -ERESTARTSYS;
+               goto out;
        }
 
+       rc = 0;
        /* cork the socket */
        tcp_sock_set_cork(ssocket->sk, true);
 
@@ -407,7 +411,8 @@ smbd_done:
                         rc);
        else if (rc > 0)
                rc = 0;
-
+out:
+       cifs_in_send_dec(server);
        return rc;
 }
 
@@ -826,9 +831,7 @@ cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
         * I/O response may come back and free the mid entry on another thread.
         */
        cifs_save_when_sent(mid);
-       cifs_in_send_inc(server);
        rc = smb_send_rqst(server, 1, rqst, flags);
-       cifs_in_send_dec(server);
 
        if (rc < 0) {
                revert_current_mid(server, mid->credits);
@@ -1144,9 +1147,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                else
                        midQ[i]->callback = cifs_compound_last_callback;
        }
-       cifs_in_send_inc(server);
        rc = smb_send_rqst(server, num_rqst, rqst, flags);
-       cifs_in_send_dec(server);
 
        for (i = 0; i < num_rqst; i++)
                cifs_save_when_sent(midQ[i]);
@@ -1396,9 +1397,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
 
        midQ->mid_state = MID_REQUEST_SUBMITTED;
 
-       cifs_in_send_inc(server);
        rc = smb_send(server, in_buf, len);
-       cifs_in_send_dec(server);
        cifs_save_when_sent(midQ);
 
        if (rc < 0)
@@ -1539,9 +1538,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
        }
 
        midQ->mid_state = MID_REQUEST_SUBMITTED;
-       cifs_in_send_inc(server);
        rc = smb_send(server, in_buf, len);
-       cifs_in_send_dec(server);
        cifs_save_when_sent(midQ);
 
        if (rc < 0)
index 50e762fa1a148beb53e4c437177ced731c8afd03..4ad5531686d81aa4e9395f58ceb04be13520b5a2 100644 (file)
@@ -487,9 +487,5 @@ const struct xattr_handler *cifs_xattr_handlers[] = {
        &smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
        &cifs_cifs_ntsd_full_xattr_handler,
        &smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
-#ifdef CONFIG_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        NULL
 };
index 4afcbbe63e685f8b4e2d225e3f86360b55bda4ac..18677cd4e62f543187966501bb52364b5f6b3a55 100644 (file)
@@ -1599,12 +1599,6 @@ static int configfs_dir_close(struct inode *inode, struct file *file)
        return 0;
 }
 
-/* Relationship between s_mode and the DT_xxx types */
-static inline unsigned char dt_type(struct configfs_dirent *sd)
-{
-       return (sd->s_mode >> 12) & 15;
-}
-
 static int configfs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct dentry *dentry = file->f_path.dentry;
@@ -1654,7 +1648,8 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
                name = configfs_get_name(next);
                len = strlen(name);
 
-               if (!dir_emit(ctx, name, len, ino, dt_type(next)))
+               if (!dir_emit(ctx, name, len, ino,
+                             fs_umode_to_dtype(next->s_mode)))
                        return 0;
 
                spin_lock(&configfs_dirent_lock);
index 78086f8dbda5261f6b36a9fe8523debe81c97faa..13d336a6cc5da5675fa322d3d793c13a56291848 100644 (file)
@@ -92,6 +92,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
         * destroying any subkeys embedded in it.
         */
 
+       if (WARN_ON(!sb->s_master_keys))
+               return;
        spin_lock(&sb->s_master_keys->lock);
        hlist_del_rcu(&mk->mk_node);
        spin_unlock(&sb->s_master_keys->lock);
@@ -207,10 +209,11 @@ static int allocate_filesystem_keyring(struct super_block *sb)
  * Release all encryption keys that have been added to the filesystem, along
  * with the keyring that contains them.
  *
- * This is called at unmount time.  The filesystem's underlying block device(s)
- * are still available at this time; this is important because after user file
- * accesses have been allowed, this function may need to evict keys from the
- * keyslots of an inline crypto engine, which requires the block device(s).
+ * This is called at unmount time, after all potentially-encrypted inodes have
+ * been evicted.  The filesystem's underlying block device(s) are still
+ * available at this time; this is important because after user file accesses
+ * have been allowed, this function may need to evict keys from the keyslots of
+ * an inline crypto engine, which requires the block device(s).
  */
 void fscrypt_destroy_keyring(struct super_block *sb)
 {
@@ -227,12 +230,12 @@ void fscrypt_destroy_keyring(struct super_block *sb)
 
                hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
                        /*
-                        * Since all inodes were already evicted, every key
-                        * remaining in the keyring should have an empty inode
-                        * list, and should only still be in the keyring due to
-                        * the single active ref associated with ->mk_secret.
-                        * There should be no structural refs beyond the one
-                        * associated with the active ref.
+                        * Since all potentially-encrypted inodes were already
+                        * evicted, every key remaining in the keyring should
+                        * have an empty inode list, and should only still be in
+                        * the keyring due to the single active ref associated
+                        * with ->mk_secret.  There should be no structural refs
+                        * beyond the one associated with the active ref.
                         */
                        WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
                        WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
index 3e457a16c7d1828f5a70c8c9f5dcad4a422cd2ad..2ababb89918de64e2b299492ad6099792b5486a0 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -781,6 +781,33 @@ out:
        return ret;
 }
 
+static int __dax_clear_dirty_range(struct address_space *mapping,
+               pgoff_t start, pgoff_t end)
+{
+       XA_STATE(xas, &mapping->i_pages, start);
+       unsigned int scanned = 0;
+       void *entry;
+
+       xas_lock_irq(&xas);
+       xas_for_each(&xas, entry, end) {
+               entry = get_unlocked_entry(&xas, 0);
+               xas_clear_mark(&xas, PAGECACHE_TAG_DIRTY);
+               xas_clear_mark(&xas, PAGECACHE_TAG_TOWRITE);
+               put_unlocked_entry(&xas, entry, WAKE_NEXT);
+
+               if (++scanned % XA_CHECK_SCHED)
+                       continue;
+
+               xas_pause(&xas);
+               xas_unlock_irq(&xas);
+               cond_resched();
+               xas_lock_irq(&xas);
+       }
+       xas_unlock_irq(&xas);
+
+       return 0;
+}
+
 /*
  * Delete DAX entry at @index from @mapping.  Wait for it
  * to be unlocked before deleting it.
@@ -1258,15 +1285,20 @@ static s64 dax_unshare_iter(struct iomap_iter *iter)
        /* don't bother with blocks that are not shared to start with */
        if (!(iomap->flags & IOMAP_F_SHARED))
                return length;
-       /* don't bother with holes or unwritten extents */
-       if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN)
-               return length;
 
        id = dax_read_lock();
        ret = dax_iomap_direct_access(iomap, pos, length, &daddr, NULL);
        if (ret < 0)
                goto out_unlock;
 
+       /* zero the distance if srcmap is HOLE or UNWRITTEN */
+       if (srcmap->flags & IOMAP_F_SHARED || srcmap->type == IOMAP_UNWRITTEN) {
+               memset(daddr, 0, length);
+               dax_flush(iomap->dax_dev, daddr, length);
+               ret = length;
+               goto out_unlock;
+       }
+
        ret = dax_iomap_direct_access(srcmap, pos, length, &saddr, NULL);
        if (ret < 0)
                goto out_unlock;
@@ -1435,6 +1467,16 @@ static loff_t dax_iomap_iter(const struct iomap_iter *iomi,
         * written by write(2) is visible in mmap.
         */
        if (iomap->flags & IOMAP_F_NEW || cow) {
+               /*
+                * Filesystem allows CoW on non-shared extents. The src extents
+                * may have been mmapped with dirty mark before. To be able to
+                * invalidate its dax entries, we need to clear the dirty mark
+                * in advance.
+                */
+               if (cow)
+                       __dax_clear_dirty_range(iomi->inode->i_mapping,
+                                               pos >> PAGE_SHIFT,
+                                               (end - 1) >> PAGE_SHIFT);
                invalidate_inode_pages2_range(iomi->inode->i_mapping,
                                              pos >> PAGE_SHIFT,
                                              (end - 1) >> PAGE_SHIFT);
@@ -2022,8 +2064,8 @@ int dax_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
 
        while ((ret = iomap_iter(&src_iter, ops)) > 0 &&
               (ret = iomap_iter(&dst_iter, ops)) > 0) {
-               compared = dax_range_compare_iter(&src_iter, &dst_iter, len,
-                                                 same);
+               compared = dax_range_compare_iter(&src_iter, &dst_iter,
+                               min(src_iter.len, dst_iter.len), same);
                if (compared < 0)
                        return ret;
                src_iter.processed = dst_iter.processed = compared;
index 4f25015aa5342a332c76ad7d931a507784eea764..fe3db0eda8e47e00384ad352a97c9df360175a9a 100644 (file)
@@ -72,24 +72,6 @@ static struct ctl_table pty_table[] = {
        {}
 };
 
-static struct ctl_table pty_kern_table[] = {
-       {
-               .procname       = "pty",
-               .mode           = 0555,
-               .child          = pty_table,
-       },
-       {}
-};
-
-static struct ctl_table pty_root_table[] = {
-       {
-               .procname       = "kernel",
-               .mode           = 0555,
-               .child          = pty_kern_table,
-       },
-       {}
-};
-
 struct pts_mount_opts {
        int setuid;
        int setgid;
@@ -630,7 +612,7 @@ static int __init init_devpts_fs(void)
 {
        int err = register_filesystem(&devpts_fs_type);
        if (!err) {
-               register_sysctl_table(pty_root_table);
+               register_sysctl("kernel/pty", pty_table);
        }
        return err;
 }
index ab0d7ea89813a6c99e77da8381c7e4b8dfec3bd2..0b380bb8a81e11532d4488782d61fb5420198057 100644 (file)
@@ -86,7 +86,6 @@ struct dio_submit {
        sector_t final_block_in_request;/* doesn't change */
        int boundary;                   /* prev block is at a boundary */
        get_block_t *get_block;         /* block mapping function */
-       dio_submit_t *submit_io;        /* IO submition function */
 
        loff_t logical_offset_in_bio;   /* current first logical block in bio */
        sector_t final_block_in_bio;    /* current final block in bio + 1 */
@@ -431,10 +430,7 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
 
        dio->bio_disk = bio->bi_bdev->bd_disk;
 
-       if (sdio->submit_io)
-               sdio->submit_io(bio, dio->inode, sdio->logical_offset_in_bio);
-       else
-               submit_bio(bio);
+       submit_bio(bio);
 
        sdio->bio = NULL;
        sdio->boundary = 0;
@@ -1098,7 +1094,7 @@ static inline int drop_refcount(struct dio *dio)
 ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
                struct block_device *bdev, struct iov_iter *iter,
                get_block_t get_block, dio_iodone_t end_io,
-               dio_submit_t submit_io, int flags)
+               int flags)
 {
        unsigned i_blkbits = READ_ONCE(inode->i_blkbits);
        unsigned blkbits = i_blkbits;
@@ -1215,7 +1211,6 @@ ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
 
        sdio.get_block = get_block;
        dio->end_io = end_io;
-       sdio.submit_io = submit_io;
        sdio.final_block_in_bio = -1;
        sdio.next_block_for_io = -1;
 
index 144ace9e0dd9116e928c2b77884b46c7c2adb1ea..83274915ba6dca20e263a868b6a60efb9670323d 100644 (file)
@@ -1210,10 +1210,6 @@ static const struct xattr_handler ecryptfs_xattr_handler = {
 };
 
 const struct xattr_handler *ecryptfs_xattr_handlers[] = {
-#ifdef CONFIG_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &ecryptfs_xattr_handler,
        NULL
 };
index c08c0f578bc694eb449e355fc60a80d553395b53..6fe9a779fa91643430ede2c84a4a7c1ff4899f66 100644 (file)
@@ -27,11 +27,15 @@ void erofs_put_metabuf(struct erofs_buf *buf)
        buf->page = NULL;
 }
 
-void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
-                 erofs_blk_t blkaddr, enum erofs_kmap_type type)
+/*
+ * Derive the block size from inode->i_blkbits to make compatible with
+ * anonymous inode in fscache mode.
+ */
+void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
+                 enum erofs_kmap_type type)
 {
-       struct address_space *const mapping = inode->i_mapping;
-       erofs_off_t offset = blknr_to_addr(blkaddr);
+       struct inode *inode = buf->inode;
+       erofs_off_t offset = (erofs_off_t)blkaddr << inode->i_blkbits;
        pgoff_t index = offset >> PAGE_SHIFT;
        struct page *page = buf->page;
        struct folio *folio;
@@ -41,7 +45,7 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
                erofs_put_metabuf(buf);
 
                nofs_flag = memalloc_nofs_save();
-               folio = read_cache_folio(mapping, index, NULL, NULL);
+               folio = read_cache_folio(inode->i_mapping, index, NULL, NULL);
                memalloc_nofs_restore(nofs_flag);
                if (IS_ERR(folio))
                        return folio;
@@ -63,14 +67,19 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
        return buf->base + (offset & ~PAGE_MASK);
 }
 
-void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
-                        erofs_blk_t blkaddr, enum erofs_kmap_type type)
+void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
 {
        if (erofs_is_fscache_mode(sb))
-               return erofs_bread(buf, EROFS_SB(sb)->s_fscache->inode,
-                                  blkaddr, type);
+               buf->inode = EROFS_SB(sb)->s_fscache->inode;
+       else
+               buf->inode = sb->s_bdev->bd_inode;
+}
 
-       return erofs_bread(buf, sb->s_bdev->bd_inode, blkaddr, type);
+void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
+                        erofs_blk_t blkaddr, enum erofs_kmap_type type)
+{
+       erofs_init_metabuf(buf, sb);
+       return erofs_bread(buf, blkaddr, type);
 }
 
 static int erofs_map_blocks_flatmode(struct inode *inode,
@@ -79,33 +88,32 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
        erofs_blk_t nblocks, lastblk;
        u64 offset = map->m_la;
        struct erofs_inode *vi = EROFS_I(inode);
+       struct super_block *sb = inode->i_sb;
        bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
 
-       nblocks = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ);
+       nblocks = erofs_iblks(inode);
        lastblk = nblocks - tailendpacking;
 
        /* there is no hole in flatmode */
        map->m_flags = EROFS_MAP_MAPPED;
-       if (offset < blknr_to_addr(lastblk)) {
-               map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la;
-               map->m_plen = blknr_to_addr(lastblk) - offset;
+       if (offset < erofs_pos(sb, lastblk)) {
+               map->m_pa = erofs_pos(sb, vi->raw_blkaddr) + map->m_la;
+               map->m_plen = erofs_pos(sb, lastblk) - offset;
        } else if (tailendpacking) {
                map->m_pa = erofs_iloc(inode) + vi->inode_isize +
-                       vi->xattr_isize + erofs_blkoff(offset);
+                       vi->xattr_isize + erofs_blkoff(sb, offset);
                map->m_plen = inode->i_size - offset;
 
                /* inline data should be located in the same meta block */
-               if (erofs_blkoff(map->m_pa) + map->m_plen > EROFS_BLKSIZ) {
-                       erofs_err(inode->i_sb,
-                                 "inline data cross block boundary @ nid %llu",
+               if (erofs_blkoff(sb, map->m_pa) + map->m_plen > sb->s_blocksize) {
+                       erofs_err(sb, "inline data cross block boundary @ nid %llu",
                                  vi->nid);
                        DBG_BUGON(1);
                        return -EFSCORRUPTED;
                }
                map->m_flags |= EROFS_MAP_META;
        } else {
-               erofs_err(inode->i_sb,
-                         "internal error @ nid: %llu (size %llu), m_la 0x%llx",
+               erofs_err(sb, "internal error @ nid: %llu (size %llu), m_la 0x%llx",
                          vi->nid, inode->i_size, map->m_la);
                DBG_BUGON(1);
                return -EIO;
@@ -148,29 +156,29 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
        pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
                    vi->xattr_isize, unit) + unit * chunknr;
 
-       kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP);
+       kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(sb, pos), EROFS_KMAP);
        if (IS_ERR(kaddr)) {
                err = PTR_ERR(kaddr);
                goto out;
        }
        map->m_la = chunknr << vi->chunkbits;
        map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
-                           roundup(inode->i_size - map->m_la, EROFS_BLKSIZ));
+                       round_up(inode->i_size - map->m_la, sb->s_blocksize));
 
        /* handle block map */
        if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
-               __le32 *blkaddr = kaddr + erofs_blkoff(pos);
+               __le32 *blkaddr = kaddr + erofs_blkoff(sb, pos);
 
                if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
                        map->m_flags = 0;
                } else {
-                       map->m_pa = blknr_to_addr(le32_to_cpu(*blkaddr));
+                       map->m_pa = erofs_pos(sb, le32_to_cpu(*blkaddr));
                        map->m_flags = EROFS_MAP_MAPPED;
                }
                goto out_unlock;
        }
        /* parse chunk indexes */
-       idx = kaddr + erofs_blkoff(pos);
+       idx = kaddr + erofs_blkoff(sb, pos);
        switch (le32_to_cpu(idx->blkaddr)) {
        case EROFS_NULL_ADDR:
                map->m_flags = 0;
@@ -178,7 +186,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
        default:
                map->m_deviceid = le16_to_cpu(idx->device_id) &
                        EROFS_SB(sb)->device_id_mask;
-               map->m_pa = blknr_to_addr(le32_to_cpu(idx->blkaddr));
+               map->m_pa = erofs_pos(sb, le32_to_cpu(idx->blkaddr));
                map->m_flags = EROFS_MAP_MAPPED;
                break;
        }
@@ -197,7 +205,6 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
        struct erofs_device_info *dif;
        int id;
 
-       /* primary device by default */
        map->m_bdev = sb->s_bdev;
        map->m_daxdev = EROFS_SB(sb)->dax_dev;
        map->m_dax_part_off = EROFS_SB(sb)->dax_part_off;
@@ -210,20 +217,25 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
                        up_read(&devs->rwsem);
                        return -ENODEV;
                }
+               if (devs->flatdev) {
+                       map->m_pa += erofs_pos(sb, dif->mapped_blkaddr);
+                       up_read(&devs->rwsem);
+                       return 0;
+               }
                map->m_bdev = dif->bdev;
                map->m_daxdev = dif->dax_dev;
                map->m_dax_part_off = dif->dax_part_off;
                map->m_fscache = dif->fscache;
                up_read(&devs->rwsem);
-       } else if (devs->extra_devices) {
+       } else if (devs->extra_devices && !devs->flatdev) {
                down_read(&devs->rwsem);
                idr_for_each_entry(&devs->tree, dif, id) {
                        erofs_off_t startoff, length;
 
                        if (!dif->mapped_blkaddr)
                                continue;
-                       startoff = blknr_to_addr(dif->mapped_blkaddr);
-                       length = blknr_to_addr(dif->blocks);
+                       startoff = erofs_pos(sb, dif->mapped_blkaddr);
+                       length = erofs_pos(sb, dif->blocks);
 
                        if (map->m_pa >= startoff &&
                            map->m_pa < startoff + length) {
@@ -244,6 +256,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
                unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
 {
        int ret;
+       struct super_block *sb = inode->i_sb;
        struct erofs_map_blocks map;
        struct erofs_map_dev mdev;
 
@@ -258,7 +271,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
                .m_deviceid = map.m_deviceid,
                .m_pa = map.m_pa,
        };
-       ret = erofs_map_dev(inode->i_sb, &mdev);
+       ret = erofs_map_dev(sb, &mdev);
        if (ret)
                return ret;
 
@@ -284,11 +297,11 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
                struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
 
                iomap->type = IOMAP_INLINE;
-               ptr = erofs_read_metabuf(&buf, inode->i_sb,
-                                        erofs_blknr(mdev.m_pa), EROFS_KMAP);
+               ptr = erofs_read_metabuf(&buf, sb,
+                               erofs_blknr(sb, mdev.m_pa), EROFS_KMAP);
                if (IS_ERR(ptr))
                        return PTR_ERR(ptr);
-               iomap->inline_data = ptr + erofs_blkoff(mdev.m_pa);
+               iomap->inline_data = ptr + erofs_blkoff(sb, mdev.m_pa);
                iomap->private = buf.base;
        } else {
                iomap->type = IOMAP_MAPPED;
index 51b7ac7166d9656c05ef437e680f92a57b09d0ba..7021e2cf6146338459ba40f41fa3cca57ccd9849 100644 (file)
@@ -42,7 +42,7 @@ int z_erofs_load_lz4_config(struct super_block *sb,
                if (!sbi->lz4.max_pclusterblks) {
                        sbi->lz4.max_pclusterblks = 1;  /* reserved case */
                } else if (sbi->lz4.max_pclusterblks >
-                          Z_EROFS_PCLUSTER_MAX_SIZE / EROFS_BLKSIZ) {
+                          erofs_blknr(sb, Z_EROFS_PCLUSTER_MAX_SIZE)) {
                        erofs_err(sb, "too large lz4 pclusterblks %u",
                                  sbi->lz4.max_pclusterblks);
                        return -EINVAL;
@@ -221,13 +221,13 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,
                support_0padding = true;
                ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
                                min_t(unsigned int, rq->inputsize,
-                                     EROFS_BLKSIZ - rq->pageofs_in));
+                                     rq->sb->s_blocksize - rq->pageofs_in));
                if (ret) {
                        kunmap_atomic(headpage);
                        return ret;
                }
                may_inplace = !((rq->pageofs_in + rq->inputsize) &
-                               (EROFS_BLKSIZ - 1));
+                               (rq->sb->s_blocksize - 1));
        }
 
        inputmargin = rq->pageofs_in;
index d38e19c112704c958cc7d4e618df5169ad4c3ed1..73091fbe3ea453d377f20bc4cfc0c2de5f76c1e5 100644 (file)
@@ -166,8 +166,8 @@ int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
        /* 1. get the exact LZMA compressed size */
        kin = kmap(*rq->in);
        err = z_erofs_fixup_insize(rq, kin + rq->pageofs_in,
-                                  min_t(unsigned int, rq->inputsize,
-                                        EROFS_BLKSIZ - rq->pageofs_in));
+                       min_t(unsigned int, rq->inputsize,
+                             rq->sb->s_blocksize - rq->pageofs_in));
        if (err) {
                kunmap(*rq->in);
                return err;
index 6970b09b83079cd6630458a19bb9246f875ca939..b80abec0531aadc10d0e0ba9a6a4db94d81061d5 100644 (file)
@@ -50,44 +50,43 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
 {
        struct inode *dir = file_inode(f);
        struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
+       struct super_block *sb = dir->i_sb;
+       unsigned long bsz = sb->s_blocksize;
        const size_t dirsize = i_size_read(dir);
-       unsigned int i = ctx->pos / EROFS_BLKSIZ;
-       unsigned int ofs = ctx->pos % EROFS_BLKSIZ;
+       unsigned int i = erofs_blknr(sb, ctx->pos);
+       unsigned int ofs = erofs_blkoff(sb, ctx->pos);
        int err = 0;
        bool initial = true;
 
+       buf.inode = dir;
        while (ctx->pos < dirsize) {
                struct erofs_dirent *de;
                unsigned int nameoff, maxsize;
 
-               de = erofs_bread(&buf, dir, i, EROFS_KMAP);
+               de = erofs_bread(&buf, i, EROFS_KMAP);
                if (IS_ERR(de)) {
-                       erofs_err(dir->i_sb,
-                                 "fail to readdir of logical block %u of nid %llu",
+                       erofs_err(sb, "fail to readdir of logical block %u of nid %llu",
                                  i, EROFS_I(dir)->nid);
                        err = PTR_ERR(de);
                        break;
                }
 
                nameoff = le16_to_cpu(de->nameoff);
-               if (nameoff < sizeof(struct erofs_dirent) ||
-                   nameoff >= EROFS_BLKSIZ) {
-                       erofs_err(dir->i_sb,
-                                 "invalid de[0].nameoff %u @ nid %llu",
+               if (nameoff < sizeof(struct erofs_dirent) || nameoff >= bsz) {
+                       erofs_err(sb, "invalid de[0].nameoff %u @ nid %llu",
                                  nameoff, EROFS_I(dir)->nid);
                        err = -EFSCORRUPTED;
                        break;
                }
 
-               maxsize = min_t(unsigned int,
-                               dirsize - ctx->pos + ofs, EROFS_BLKSIZ);
+               maxsize = min_t(unsigned int, dirsize - ctx->pos + ofs, bsz);
 
                /* search dirents at the arbitrary position */
                if (initial) {
                        initial = false;
 
                        ofs = roundup(ofs, sizeof(struct erofs_dirent));
-                       ctx->pos = blknr_to_addr(i) + ofs;
+                       ctx->pos = erofs_pos(sb, i) + ofs;
                        if (ofs >= nameoff)
                                goto skip_this;
                }
@@ -97,7 +96,7 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
                if (err)
                        break;
 skip_this:
-               ctx->pos = blknr_to_addr(i) + maxsize;
+               ctx->pos = erofs_pos(sb, i) + maxsize;
                ++i;
                ofs = 0;
        }
index dbcd24371002bbebefed025ba15415e3193101ed..2c7b16e340fef3358f598355234c1dc5441d14ad 100644 (file)
@@ -27,6 +27,7 @@
 #define EROFS_FEATURE_INCOMPAT_ZTAILPACKING    0x00000010
 #define EROFS_FEATURE_INCOMPAT_FRAGMENTS       0x00000020
 #define EROFS_FEATURE_INCOMPAT_DEDUPE          0x00000020
+#define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES  0x00000040
 #define EROFS_ALL_FEATURE_INCOMPAT             \
        (EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \
         EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
@@ -36,7 +37,8 @@
         EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \
         EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \
         EROFS_FEATURE_INCOMPAT_FRAGMENTS | \
-        EROFS_FEATURE_INCOMPAT_DEDUPE)
+        EROFS_FEATURE_INCOMPAT_DEDUPE | \
+        EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES)
 
 #define EROFS_SB_EXTSLOT_SIZE  16
 
@@ -53,7 +55,7 @@ struct erofs_super_block {
        __le32 magic;           /* file system magic number */
        __le32 checksum;        /* crc32c(super_block) */
        __le32 feature_compat;
-       __u8 blkszbits;         /* support block_size == PAGE_SIZE only */
+       __u8 blkszbits;         /* filesystem block size in bit shift */
        __u8 sb_extslots;       /* superblock size = 128 + sb_extslots * 16 */
 
        __le16 root_nid;        /* nid of root directory */
@@ -75,49 +77,46 @@ struct erofs_super_block {
        } __packed u1;
        __le16 extra_devices;   /* # of devices besides the primary device */
        __le16 devt_slotoff;    /* startoff = devt_slotoff * devt_slotsize */
-       __u8 reserved[6];
+       __u8 dirblkbits;        /* directory block size in bit shift */
+       __u8 xattr_prefix_count;        /* # of long xattr name prefixes */
+       __le32 xattr_prefix_start;      /* start of long xattr prefixes */
        __le64 packed_nid;      /* nid of the special packed inode */
        __u8 reserved2[24];
 };
 
 /*
- * erofs inode datalayout (i_format in on-disk inode):
+ * EROFS inode datalayout (i_format in on-disk inode):
  * 0 - uncompressed flat inode without tail-packing inline data:
- * inode, [xattrs], ... | ... | no-holed data
  * 1 - compressed inode with non-compact indexes:
- * inode, [xattrs], [map_header], extents ... | ...
  * 2 - uncompressed flat inode with tail-packing inline data:
- * inode, [xattrs], tailpacking data, ... | ... | no-holed data
  * 3 - compressed inode with compact indexes:
- * inode, [xattrs], map_header, extents ... | ...
  * 4 - chunk-based inode with (optional) multi-device support:
- * inode, [xattrs], chunk indexes ... | ...
  * 5~7 - reserved
  */
 enum {
        EROFS_INODE_FLAT_PLAIN                  = 0,
-       EROFS_INODE_FLAT_COMPRESSION_LEGACY     = 1,
+       EROFS_INODE_COMPRESSED_FULL             = 1,
        EROFS_INODE_FLAT_INLINE                 = 2,
-       EROFS_INODE_FLAT_COMPRESSION            = 3,
+       EROFS_INODE_COMPRESSED_COMPACT          = 3,
        EROFS_INODE_CHUNK_BASED                 = 4,
        EROFS_INODE_DATALAYOUT_MAX
 };
 
 static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
 {
-       return datamode == EROFS_INODE_FLAT_COMPRESSION ||
-               datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY;
+       return datamode == EROFS_INODE_COMPRESSED_COMPACT ||
+               datamode == EROFS_INODE_COMPRESSED_FULL;
 }
 
 /* bit definitions of inode i_format */
-#define EROFS_I_VERSION_BITS            1
-#define EROFS_I_DATALAYOUT_BITS         3
+#define EROFS_I_VERSION_MASK            0x01
+#define EROFS_I_DATALAYOUT_MASK         0x07
 
 #define EROFS_I_VERSION_BIT             0
 #define EROFS_I_DATALAYOUT_BIT          1
+#define EROFS_I_ALL_BIT                        4
 
-#define EROFS_I_ALL    \
-       ((1 << (EROFS_I_DATALAYOUT_BIT + EROFS_I_DATALAYOUT_BITS)) - 1)
+#define EROFS_I_ALL    ((1 << EROFS_I_ALL_BIT) - 1)
 
 /* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */
 #define EROFS_CHUNK_FORMAT_BLKBITS_MASK                0x001F
@@ -127,11 +126,30 @@ static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
 #define EROFS_CHUNK_FORMAT_ALL \
        (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES)
 
+/* 32-byte on-disk inode */
+#define EROFS_INODE_LAYOUT_COMPACT     0
+/* 64-byte on-disk inode */
+#define EROFS_INODE_LAYOUT_EXTENDED    1
+
 struct erofs_inode_chunk_info {
        __le16 format;          /* chunk blkbits, etc. */
        __le16 reserved;
 };
 
+union erofs_inode_i_u {
+       /* total compressed blocks for compressed inodes */
+       __le32 compressed_blocks;
+
+       /* block address for uncompressed flat inodes */
+       __le32 raw_blkaddr;
+
+       /* for device files, used to indicate old/new device # */
+       __le32 rdev;
+
+       /* for chunk-based files, it contains the summary info */
+       struct erofs_inode_chunk_info c;
+};
+
 /* 32-byte reduced form of an ondisk inode */
 struct erofs_inode_compact {
        __le16 i_format;        /* inode format hints */
@@ -142,29 +160,14 @@ struct erofs_inode_compact {
        __le16 i_nlink;
        __le32 i_size;
        __le32 i_reserved;
-       union {
-               /* total compressed blocks for compressed inodes */
-               __le32 compressed_blocks;
-               /* block address for uncompressed flat inodes */
-               __le32 raw_blkaddr;
-
-               /* for device files, used to indicate old/new device # */
-               __le32 rdev;
-
-               /* for chunk-based files, it contains the summary info */
-               struct erofs_inode_chunk_info c;
-       } i_u;
-       __le32 i_ino;           /* only used for 32-bit stat compatibility */
+       union erofs_inode_i_u i_u;
+
+       __le32 i_ino;           /* only used for 32-bit stat compatibility */
        __le16 i_uid;
        __le16 i_gid;
        __le32 i_reserved2;
 };
 
-/* 32-byte on-disk inode */
-#define EROFS_INODE_LAYOUT_COMPACT     0
-/* 64-byte on-disk inode */
-#define EROFS_INODE_LAYOUT_EXTENDED    1
-
 /* 64-byte complete form of an ondisk inode */
 struct erofs_inode_extended {
        __le16 i_format;        /* inode format hints */
@@ -174,22 +177,9 @@ struct erofs_inode_extended {
        __le16 i_mode;
        __le16 i_reserved;
        __le64 i_size;
-       union {
-               /* total compressed blocks for compressed inodes */
-               __le32 compressed_blocks;
-               /* block address for uncompressed flat inodes */
-               __le32 raw_blkaddr;
-
-               /* for device files, used to indicate old/new device # */
-               __le32 rdev;
-
-               /* for chunk-based files, it contains the summary info */
-               struct erofs_inode_chunk_info c;
-       } i_u;
-
-       /* only used for 32-bit stat compatibility */
-       __le32 i_ino;
+       union erofs_inode_i_u i_u;
 
+       __le32 i_ino;           /* only used for 32-bit stat compatibility */
        __le32 i_uid;
        __le32 i_gid;
        __le64 i_mtime;
@@ -198,10 +188,6 @@ struct erofs_inode_extended {
        __u8   i_reserved2[16];
 };
 
-#define EROFS_MAX_SHARED_XATTRS         (128)
-/* h_shared_count between 129 ... 255 are special # */
-#define EROFS_SHARED_XATTR_EXTENT       (255)
-
 /*
  * inline xattrs (n == i_xattr_icount):
  * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes
@@ -228,6 +214,13 @@ struct erofs_xattr_ibody_header {
 #define EROFS_XATTR_INDEX_LUSTRE            5
 #define EROFS_XATTR_INDEX_SECURITY          6
 
+/*
+ * bit 7 of e_name_index is set when it refers to a long xattr name prefix,
+ * while the remained lower bits represent the index of the prefix.
+ */
+#define EROFS_XATTR_LONG_PREFIX                0x80
+#define EROFS_XATTR_LONG_PREFIX_MASK   0x7f
+
 /* xattr entry (for both inline & shared xattrs) */
 struct erofs_xattr_entry {
        __u8   e_name_len;      /* length of name */
@@ -237,6 +230,12 @@ struct erofs_xattr_entry {
        char   e_name[];        /* attribute name */
 };
 
+/* long xattr name prefix */
+struct erofs_xattr_long_prefix {
+       __u8   base_index;      /* short xattr name prefix index */
+       char   infix[];         /* infix apart from short prefix */
+};
+
 static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount)
 {
        if (!i_xattr_icount)
@@ -267,6 +266,22 @@ struct erofs_inode_chunk_index {
        __le32 blkaddr;         /* start block address of this inode chunk */
 };
 
+/* dirent sorts in alphabet order, thus we can do binary search */
+struct erofs_dirent {
+       __le64 nid;     /* node number */
+       __le16 nameoff; /* start offset of file name */
+       __u8 file_type; /* file type */
+       __u8 reserved;  /* reserved */
+} __packed;
+
+/*
+ * EROFS file types should match generic FT_* types and
+ * it seems no need to add BUILD_BUG_ONs since potential
+ * unmatchness will break other fses as well...
+ */
+
+#define EROFS_NAME_LEN      255
+
 /* maximum supported size of a physical compression cluster */
 #define Z_EROFS_PCLUSTER_MAX_SIZE      (1024 * 1024)
 
@@ -336,10 +351,8 @@ struct z_erofs_map_header {
        __u8    h_clusterbits;
 };
 
-#define Z_EROFS_VLE_LEGACY_HEADER_PADDING       8
-
 /*
- * Fixed-sized output compression on-disk logical cluster type:
+ * On-disk logical cluster type:
  *    0   - literal (uncompressed) lcluster
  *    1,3 - compressed lcluster (for HEAD lclusters)
  *    2   - compressed lcluster (for NONHEAD lclusters)
@@ -363,27 +376,27 @@ struct z_erofs_map_header {
  *        di_u.delta[1] = distance to the next HEAD lcluster
  */
 enum {
-       Z_EROFS_VLE_CLUSTER_TYPE_PLAIN          = 0,
-       Z_EROFS_VLE_CLUSTER_TYPE_HEAD1          = 1,
-       Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD        = 2,
-       Z_EROFS_VLE_CLUSTER_TYPE_HEAD2          = 3,
-       Z_EROFS_VLE_CLUSTER_TYPE_MAX
+       Z_EROFS_LCLUSTER_TYPE_PLAIN     = 0,
+       Z_EROFS_LCLUSTER_TYPE_HEAD1     = 1,
+       Z_EROFS_LCLUSTER_TYPE_NONHEAD   = 2,
+       Z_EROFS_LCLUSTER_TYPE_HEAD2     = 3,
+       Z_EROFS_LCLUSTER_TYPE_MAX
 };
 
-#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS        2
-#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT         0
+#define Z_EROFS_LI_LCLUSTER_TYPE_BITS        2
+#define Z_EROFS_LI_LCLUSTER_TYPE_BIT         0
 
 /* (noncompact only, HEAD) This pcluster refers to partial decompressed data */
-#define Z_EROFS_VLE_DI_PARTIAL_REF             (1 << 15)
+#define Z_EROFS_LI_PARTIAL_REF         (1 << 15)
 
 /*
  * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the
  * compressed block count of a compressed extent (in logical clusters, aka.
  * block count of a pcluster).
  */
-#define Z_EROFS_VLE_DI_D0_CBLKCNT              (1 << 11)
+#define Z_EROFS_LI_D0_CBLKCNT          (1 << 11)
 
-struct z_erofs_vle_decompressed_index {
+struct z_erofs_lcluster_index {
        __le16 di_advise;
        /* where to decompress in the head lcluster */
        __le16 di_clusterofs;
@@ -400,25 +413,8 @@ struct z_erofs_vle_decompressed_index {
        } di_u;
 };
 
-#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \
-       (round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \
-        sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING)
-
-/* dirent sorts in alphabet order, thus we can do binary search */
-struct erofs_dirent {
-       __le64 nid;     /* node number */
-       __le16 nameoff; /* start offset of file name */
-       __u8 file_type; /* file type */
-       __u8 reserved;  /* reserved */
-} __packed;
-
-/*
- * EROFS file types should match generic FT_* types and
- * it seems no need to add BUILD_BUG_ONs since potential
- * unmatchness will break other fses as well...
- */
-
-#define EROFS_NAME_LEN      255
+#define Z_EROFS_FULL_INDEX_ALIGN(end)  \
+       (ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8)
 
 /* check the EROFS on-disk layout strictly at compile time */
 static inline void erofs_check_ondisk_layout_definitions(void)
@@ -435,15 +431,15 @@ static inline void erofs_check_ondisk_layout_definitions(void)
        BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4);
        BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8);
        BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8);
-       BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8);
+       BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8);
        BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12);
        /* keep in sync between 2 index structures for better extendibility */
        BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) !=
-                    sizeof(struct z_erofs_vle_decompressed_index));
+                    sizeof(struct z_erofs_lcluster_index));
        BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128);
 
-       BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) <
-                    Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1);
+       BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) <
+                    Z_EROFS_LCLUSTER_TYPE_MAX - 1);
        /* exclude old compiler versions like gcc 7.5.0 */
        BUILD_BUG_ON(__builtin_constant_p(fmh) ?
                     fmh != cpu_to_le64(1ULL << 63) : 0);
index 96a87c023128e0ddd18c9f06f9256239cf49126e..87ff35bff8d5bb3acb8dbc4d79c07d1d018cba56 100644 (file)
@@ -209,8 +209,8 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_request *primary)
                void *src;
 
                /* For tail packing layout, the offset may be non-zero. */
-               offset = erofs_blkoff(map.m_pa);
-               blknr = erofs_blknr(map.m_pa);
+               offset = erofs_blkoff(sb, map.m_pa);
+               blknr = erofs_blknr(sb, map.m_pa);
                size = map.m_llen;
 
                src = erofs_read_metabuf(&buf, sb, blknr, EROFS_KMAP);
@@ -460,6 +460,7 @@ static struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb
        inode->i_size = OFFSET_MAX;
        inode->i_mapping->a_ops = &erofs_fscache_meta_aops;
        mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
+       inode->i_blkbits = EROFS_SB(sb)->blkszbits;
        inode->i_private = ctx;
 
        ctx->cookie = cookie;
index 4be7dda3cd24dfddaf3c9b28f5035432d1f59cf4..d70b12b81507fad3d601744b3fa55a6fd2212ead 100644 (file)
@@ -23,11 +23,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
        unsigned int ifmt;
        int err;
 
-       blkaddr = erofs_blknr(inode_loc);
-       *ofs = erofs_blkoff(inode_loc);
-
-       erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u",
-                 __func__, vi->nid, *ofs, blkaddr);
+       blkaddr = erofs_blknr(sb, inode_loc);
+       *ofs = erofs_blkoff(sb, inode_loc);
 
        kaddr = erofs_read_metabuf(buf, sb, blkaddr, EROFS_KMAP);
        if (IS_ERR(kaddr)) {
@@ -58,11 +55,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
        case EROFS_INODE_LAYOUT_EXTENDED:
                vi->inode_isize = sizeof(struct erofs_inode_extended);
                /* check if the extended inode acrosses block boundary */
-               if (*ofs + vi->inode_isize <= EROFS_BLKSIZ) {
+               if (*ofs + vi->inode_isize <= sb->s_blocksize) {
                        *ofs += vi->inode_isize;
                        die = (struct erofs_inode_extended *)dic;
                } else {
-                       const unsigned int gotten = EROFS_BLKSIZ - *ofs;
+                       const unsigned int gotten = sb->s_blocksize - *ofs;
 
                        copied = kmalloc(vi->inode_isize, GFP_NOFS);
                        if (!copied) {
@@ -176,7 +173,7 @@ static void *erofs_read_inode(struct erofs_buf *buf,
                        err = -EOPNOTSUPP;
                        goto err_out;
                }
-               vi->chunkbits = LOG_BLOCK_SIZE +
+               vi->chunkbits = sb->s_blocksize_bits +
                        (vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
        }
        inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
@@ -188,11 +185,12 @@ static void *erofs_read_inode(struct erofs_buf *buf,
        if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
            vi->datalayout == EROFS_INODE_FLAT_PLAIN)
                inode->i_flags |= S_DAX;
+
        if (!nblks)
                /* measure inode.i_blocks as generic filesystems */
-               inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
+               inode->i_blocks = round_up(inode->i_size, sb->s_blocksize) >> 9;
        else
-               inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK;
+               inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
        return kaddr;
 
 bogusimode:
@@ -210,11 +208,12 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
                              unsigned int m_pofs)
 {
        struct erofs_inode *vi = EROFS_I(inode);
+       unsigned int bsz = i_blocksize(inode);
        char *lnk;
 
        /* if it cannot be handled with fast symlink scheme */
        if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
-           inode->i_size >= EROFS_BLKSIZ || inode->i_size < 0) {
+           inode->i_size >= bsz || inode->i_size < 0) {
                inode->i_op = &erofs_symlink_iops;
                return 0;
        }
@@ -225,7 +224,7 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
 
        m_pofs += vi->xattr_isize;
        /* inline symlink data shouldn't cross block boundary */
-       if (m_pofs + inode->i_size > EROFS_BLKSIZ) {
+       if (m_pofs + inode->i_size > bsz) {
                kfree(lnk);
                erofs_err(inode->i_sb,
                          "inline data cross block boundary @ nid %llu",
@@ -289,10 +288,15 @@ static int erofs_fill_inode(struct inode *inode)
        }
 
        if (erofs_inode_is_data_compressed(vi->datalayout)) {
-               if (!erofs_is_fscache_mode(inode->i_sb))
-                       err = z_erofs_fill_inode(inode);
-               else
-                       err = -EOPNOTSUPP;
+#ifdef CONFIG_EROFS_FS_ZIP
+               if (!erofs_is_fscache_mode(inode->i_sb) &&
+                   inode->i_sb->s_blocksize_bits == PAGE_SHIFT) {
+                       inode->i_mapping->a_ops = &z_erofs_aops;
+                       err = 0;
+                       goto out_unlock;
+               }
+#endif
+               err = -EOPNOTSUPP;
                goto out_unlock;
        }
        inode->i_mapping->a_ops = &erofs_raw_access_aops;
index 1db018f8c2e89d459155fb8447f73ac558daa7b2..af0431a40647905738e2d2533d02d644f2a49c8d 100644 (file)
@@ -31,10 +31,8 @@ __printf(3, 4) void _erofs_info(struct super_block *sb,
 #define erofs_info(sb, fmt, ...) \
        _erofs_info(sb, __func__, fmt "\n", ##__VA_ARGS__)
 #ifdef CONFIG_EROFS_FS_DEBUG
-#define erofs_dbg(x, ...)       pr_debug(x "\n", ##__VA_ARGS__)
 #define DBG_BUGON               BUG_ON
 #else
-#define erofs_dbg(x, ...)       ((void)0)
 #define DBG_BUGON(x)            ((void)(x))
 #endif /* !CONFIG_EROFS_FS_DEBUG */
 
@@ -81,6 +79,7 @@ struct erofs_dev_context {
        struct rw_semaphore rwsem;
 
        unsigned int extra_devices;
+       bool flatdev;
 };
 
 struct erofs_fs_context {
@@ -116,6 +115,11 @@ struct erofs_fscache {
        char *name;
 };
 
+struct erofs_xattr_prefix_item {
+       struct erofs_xattr_long_prefix *prefix;
+       u8 infix_len;
+};
+
 struct erofs_sb_info {
        struct erofs_mount_opts opt;    /* options */
 #ifdef CONFIG_EROFS_FS_ZIP
@@ -133,8 +137,8 @@ struct erofs_sb_info {
        struct inode *managed_cache;
 
        struct erofs_sb_lz4_info lz4;
-       struct inode *packed_inode;
 #endif /* CONFIG_EROFS_FS_ZIP */
+       struct inode *packed_inode;
        struct erofs_dev_context *devs;
        struct dax_device *dax_dev;
        u64 dax_part_off;
@@ -144,11 +148,14 @@ struct erofs_sb_info {
        u32 meta_blkaddr;
 #ifdef CONFIG_EROFS_FS_XATTR
        u32 xattr_blkaddr;
+       u32 xattr_prefix_start;
+       u8 xattr_prefix_count;
+       struct erofs_xattr_prefix_item *xattr_prefixes;
 #endif
        u16 device_id_mask;     /* valid bits of device id to be used */
 
-       /* inode slot unit size in bit shift */
-       unsigned char islotbits;
+       unsigned char islotbits;        /* inode slot unit size in bit shift */
+       unsigned char blkszbits;        /* filesystem block size in bit shift */
 
        u32 sb_size;                    /* total superblock size */
        u32 build_time_nsec;
@@ -156,6 +163,7 @@ struct erofs_sb_info {
 
        /* what we really care is nid, rather than ino.. */
        erofs_nid_t root_nid;
+       erofs_nid_t packed_nid;
        /* used for statfs, f_files - f_favail */
        u64 inos;
 
@@ -240,27 +248,13 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
                                        VAL != EROFS_LOCKED_MAGIC);
 }
 
-/* we strictly follow PAGE_SIZE and no buffer head yet */
-#define LOG_BLOCK_SIZE         PAGE_SHIFT
-
-#undef LOG_SECTORS_PER_BLOCK
-#define LOG_SECTORS_PER_BLOCK  (PAGE_SHIFT - 9)
-
-#undef SECTORS_PER_BLOCK
-#define SECTORS_PER_BLOCK      (1 << SECTORS_PER_BLOCK)
-
-#define EROFS_BLKSIZ           (1 << LOG_BLOCK_SIZE)
-
-#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ)
-#error erofs cannot be used in this platform
-#endif
-
 enum erofs_kmap_type {
        EROFS_NO_KMAP,          /* don't map the buffer */
        EROFS_KMAP,             /* use kmap_local_page() to map the buffer */
 };
 
 struct erofs_buf {
+       struct inode *inode;
        struct page *page;
        void *base;
        enum erofs_kmap_type kmap_type;
@@ -269,9 +263,10 @@ struct erofs_buf {
 
 #define ROOT_NID(sb)           ((sb)->root_nid)
 
-#define erofs_blknr(addr)       ((addr) / EROFS_BLKSIZ)
-#define erofs_blkoff(addr)      ((addr) % EROFS_BLKSIZ)
-#define blknr_to_addr(nr)       ((erofs_off_t)(nr) * EROFS_BLKSIZ)
+#define erofs_blknr(sb, addr)  ((addr) >> (sb)->s_blocksize_bits)
+#define erofs_blkoff(sb, addr) ((addr) & ((sb)->s_blocksize - 1))
+#define erofs_pos(sb, blk)     ((erofs_off_t)(blk) << (sb)->s_blocksize_bits)
+#define erofs_iblks(i) (round_up((i)->i_size, i_blocksize(i)) >> (i)->i_blkbits)
 
 #define EROFS_FEATURE_FUNCS(name, compat, feature) \
 static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \
@@ -288,6 +283,7 @@ EROFS_FEATURE_FUNCS(compr_head2, incompat, INCOMPAT_COMPR_HEAD2)
 EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
 EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
 EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
+EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
 EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
 
 /* atomic flag definitions */
@@ -306,7 +302,7 @@ struct erofs_inode {
 
        unsigned char datalayout;
        unsigned char inode_isize;
-       unsigned short xattr_isize;
+       unsigned int xattr_isize;
 
        unsigned int xattr_shared_count;
        unsigned int *xattr_shared_xattrs;
@@ -343,28 +339,18 @@ static inline erofs_off_t erofs_iloc(struct inode *inode)
 {
        struct erofs_sb_info *sbi = EROFS_I_SB(inode);
 
-       return blknr_to_addr(sbi->meta_blkaddr) +
+       return erofs_pos(inode->i_sb, sbi->meta_blkaddr) +
                (EROFS_I(inode)->nid << sbi->islotbits);
 }
 
-static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
-                                         unsigned int bits)
-{
-
-       return (value >> bit) & ((1 << bits) - 1);
-}
-
-
-static inline unsigned int erofs_inode_version(unsigned int value)
+static inline unsigned int erofs_inode_version(unsigned int ifmt)
 {
-       return erofs_bitrange(value, EROFS_I_VERSION_BIT,
-                             EROFS_I_VERSION_BITS);
+       return (ifmt >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASK;
 }
 
-static inline unsigned int erofs_inode_datalayout(unsigned int value)
+static inline unsigned int erofs_inode_datalayout(unsigned int ifmt)
 {
-       return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
-                             EROFS_I_DATALAYOUT_BITS);
+       return (ifmt >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASK;
 }
 
 /*
@@ -451,10 +437,13 @@ extern const struct iomap_ops z_erofs_iomap_report_ops;
 #define EROFS_REG_COOKIE_SHARE         0x0001
 #define EROFS_REG_COOKIE_NEED_NOEXIST  0x0002
 
+void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
+                         erofs_off_t *offset, int *lengthp);
 void erofs_unmap_metabuf(struct erofs_buf *buf);
 void erofs_put_metabuf(struct erofs_buf *buf);
-void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
-                 erofs_blk_t blkaddr, enum erofs_kmap_type type);
+void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
+                 enum erofs_kmap_type type);
+void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb);
 void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
                         erofs_blk_t blkaddr, enum erofs_kmap_type type);
 int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev);
@@ -521,7 +510,6 @@ int erofs_try_to_free_cached_page(struct page *page);
 int z_erofs_load_lz4_config(struct super_block *sb,
                            struct erofs_super_block *dsb,
                            struct z_erofs_lz4_cfgs *lz4, int len);
-int z_erofs_fill_inode(struct inode *inode);
 int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
                            int flags);
 #else
@@ -541,7 +529,6 @@ static inline int z_erofs_load_lz4_config(struct super_block *sb,
        }
        return 0;
 }
-static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; }
 #endif /* !CONFIG_EROFS_FS_ZIP */
 
 #ifdef CONFIG_EROFS_FS_ZIP_LZMA
index 966eabc61c1378bc5f79770b67e6fb77a1e14547..d4f631d39f0fa83141eafcb13951bb3fd36598bd 100644 (file)
@@ -89,7 +89,8 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
 static void *erofs_find_target_block(struct erofs_buf *target,
                struct inode *dir, struct erofs_qstr *name, int *_ndirents)
 {
-       int head = 0, back = DIV_ROUND_UP(dir->i_size, EROFS_BLKSIZ) - 1;
+       unsigned int bsz = i_blocksize(dir);
+       int head = 0, back = erofs_iblks(dir) - 1;
        unsigned int startprfx = 0, endprfx = 0;
        void *candidate = ERR_PTR(-ENOENT);
 
@@ -98,10 +99,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
                struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
                struct erofs_dirent *de;
 
-               de = erofs_bread(&buf, dir, mid, EROFS_KMAP);
+               buf.inode = dir;
+               de = erofs_bread(&buf, mid, EROFS_KMAP);
                if (!IS_ERR(de)) {
-                       const int nameoff = nameoff_from_disk(de->nameoff,
-                                                             EROFS_BLKSIZ);
+                       const int nameoff = nameoff_from_disk(de->nameoff, bsz);
                        const int ndirents = nameoff / sizeof(*de);
                        int diff;
                        unsigned int matched;
@@ -121,11 +122,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
 
                        dname.name = (u8 *)de + nameoff;
                        if (ndirents == 1)
-                               dname.end = (u8 *)de + EROFS_BLKSIZ;
+                               dname.end = (u8 *)de + bsz;
                        else
                                dname.end = (u8 *)de +
-                                       nameoff_from_disk(de[1].nameoff,
-                                                         EROFS_BLKSIZ);
+                                       nameoff_from_disk(de[1].nameoff, bsz);
 
                        /* string comparison without already matched prefix */
                        diff = erofs_dirnamecmp(name, &dname, &matched);
@@ -171,6 +171,7 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
 
        qn.name = name->name;
        qn.end = name->name + name->len;
+       buf.inode = dir;
 
        ndirents = 0;
        de = erofs_find_target_block(&buf, dir, &qn, &ndirents);
@@ -178,7 +179,8 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
                return PTR_ERR(de);
 
        if (ndirents)
-               de = find_target_dirent(&qn, (u8 *)de, EROFS_BLKSIZ, ndirents);
+               de = find_target_dirent(&qn, (u8 *)de, i_blocksize(dir),
+                                       ndirents);
 
        if (!IS_ERR(de)) {
                *nid = le64_to_cpu(de->nid);
@@ -203,16 +205,13 @@ static struct dentry *erofs_lookup(struct inode *dir, struct dentry *dentry,
 
        err = erofs_namei(dir, &dentry->d_name, &nid, &d_type);
 
-       if (err == -ENOENT) {
+       if (err == -ENOENT)
                /* negative dentry */
                inode = NULL;
-       } else if (err) {
+       else if (err)
                inode = ERR_PTR(err);
-       } else {
-               erofs_dbg("%s, %pd (nid %llu) found, d_type %u", __func__,
-                         dentry, nid, d_type);
+       else
                inode = erofs_iget(dir->i_sb, nid);
-       }
        return d_splice_alias(inode, dentry);
 }
 
index 19b1ae79cec4169800e308014add7466f7916b23..811ab66d805ede335ab7f84aff510ba1fbdd549c 100644 (file)
@@ -52,18 +52,21 @@ void _erofs_info(struct super_block *sb, const char *function,
 
 static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
 {
+       size_t len = 1 << EROFS_SB(sb)->blkszbits;
        struct erofs_super_block *dsb;
        u32 expected_crc, crc;
 
-       dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET,
-                     EROFS_BLKSIZ - EROFS_SUPER_OFFSET, GFP_KERNEL);
+       if (len > EROFS_SUPER_OFFSET)
+               len -= EROFS_SUPER_OFFSET;
+
+       dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, len, GFP_KERNEL);
        if (!dsb)
                return -ENOMEM;
 
        expected_crc = le32_to_cpu(dsb->checksum);
        dsb->checksum = 0;
        /* to allow for x86 boot sectors and other oddities. */
-       crc = crc32c(~0, dsb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET);
+       crc = crc32c(~0, dsb, len);
        kfree(dsb);
 
        if (crc != expected_crc) {
@@ -123,20 +126,19 @@ static bool check_layout_compatibility(struct super_block *sb,
        return true;
 }
 
-#ifdef CONFIG_EROFS_FS_ZIP
 /* read variable-sized metadata, offset will be aligned by 4-byte */
-static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
-                                erofs_off_t *offset, int *lengthp)
+void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
+                         erofs_off_t *offset, int *lengthp)
 {
        u8 *buffer, *ptr;
        int len, i, cnt;
 
        *offset = round_up(*offset, 4);
-       ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*offset), EROFS_KMAP);
+       ptr = erofs_bread(buf, erofs_blknr(sb, *offset), EROFS_KMAP);
        if (IS_ERR(ptr))
                return ptr;
 
-       len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(*offset)]);
+       len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(sb, *offset)]);
        if (!len)
                len = U16_MAX + 1;
        buffer = kmalloc(len, GFP_KERNEL);
@@ -146,19 +148,20 @@ static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
        *lengthp = len;
 
        for (i = 0; i < len; i += cnt) {
-               cnt = min(EROFS_BLKSIZ - (int)erofs_blkoff(*offset), len - i);
-               ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*offset),
-                                        EROFS_KMAP);
+               cnt = min_t(int, sb->s_blocksize - erofs_blkoff(sb, *offset),
+                           len - i);
+               ptr = erofs_bread(buf, erofs_blknr(sb, *offset), EROFS_KMAP);
                if (IS_ERR(ptr)) {
                        kfree(buffer);
                        return ptr;
                }
-               memcpy(buffer + i, ptr + erofs_blkoff(*offset), cnt);
+               memcpy(buffer + i, ptr + erofs_blkoff(sb, *offset), cnt);
                *offset += cnt;
        }
        return buffer;
 }
 
+#ifdef CONFIG_EROFS_FS_ZIP
 static int erofs_load_compr_cfgs(struct super_block *sb,
                                 struct erofs_super_block *dsb)
 {
@@ -175,6 +178,7 @@ static int erofs_load_compr_cfgs(struct super_block *sb,
                return -EINVAL;
        }
 
+       erofs_init_metabuf(&buf, sb);
        offset = EROFS_SUPER_OFFSET + sbi->sb_size;
        alg = 0;
        for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) {
@@ -228,10 +232,10 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
        struct block_device *bdev;
        void *ptr;
 
-       ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*pos), EROFS_KMAP);
+       ptr = erofs_read_metabuf(buf, sb, erofs_blknr(sb, *pos), EROFS_KMAP);
        if (IS_ERR(ptr))
                return PTR_ERR(ptr);
-       dis = ptr + erofs_blkoff(*pos);
+       dis = ptr + erofs_blkoff(sb, *pos);
 
        if (!dif->path) {
                if (!dis->tag[0]) {
@@ -248,7 +252,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
                if (IS_ERR(fscache))
                        return PTR_ERR(fscache);
                dif->fscache = fscache;
-       } else {
+       } else if (!sbi->devs->flatdev) {
                bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL,
                                          sb->s_type);
                if (IS_ERR(bdev))
@@ -290,6 +294,9 @@ static int erofs_scan_devices(struct super_block *sb,
        if (!ondisk_extradevs)
                return 0;
 
+       if (!sbi->devs->extra_devices && !erofs_is_fscache_mode(sb))
+               sbi->devs->flatdev = true;
+
        sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
        pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
        down_read(&sbi->devs->rwsem);
@@ -329,7 +336,6 @@ static int erofs_read_superblock(struct super_block *sb)
        struct erofs_sb_info *sbi;
        struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
        struct erofs_super_block *dsb;
-       unsigned int blkszbits;
        void *data;
        int ret;
 
@@ -348,6 +354,16 @@ static int erofs_read_superblock(struct super_block *sb)
                goto out;
        }
 
+       sbi->blkszbits  = dsb->blkszbits;
+       if (sbi->blkszbits < 9 || sbi->blkszbits > PAGE_SHIFT) {
+               erofs_err(sb, "blkszbits %u isn't supported", sbi->blkszbits);
+               goto out;
+       }
+       if (dsb->dirblkbits) {
+               erofs_err(sb, "dirblkbits %u isn't supported", dsb->dirblkbits);
+               goto out;
+       }
+
        sbi->feature_compat = le32_to_cpu(dsb->feature_compat);
        if (erofs_sb_has_sb_chksum(sbi)) {
                ret = erofs_superblock_csum_verify(sb, data);
@@ -356,19 +372,11 @@ static int erofs_read_superblock(struct super_block *sb)
        }
 
        ret = -EINVAL;
-       blkszbits = dsb->blkszbits;
-       /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
-       if (blkszbits != LOG_BLOCK_SIZE) {
-               erofs_err(sb, "blkszbits %u isn't supported on this platform",
-                         blkszbits);
-               goto out;
-       }
-
        if (!check_layout_compatibility(sb, dsb))
                goto out;
 
        sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE;
-       if (sbi->sb_size > EROFS_BLKSIZ) {
+       if (sbi->sb_size > PAGE_SIZE - EROFS_SUPER_OFFSET) {
                erofs_err(sb, "invalid sb_extslots %u (more than a fs block)",
                          sbi->sb_size);
                goto out;
@@ -377,20 +385,12 @@ static int erofs_read_superblock(struct super_block *sb)
        sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
 #ifdef CONFIG_EROFS_FS_XATTR
        sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
+       sbi->xattr_prefix_start = le32_to_cpu(dsb->xattr_prefix_start);
+       sbi->xattr_prefix_count = dsb->xattr_prefix_count;
 #endif
        sbi->islotbits = ilog2(sizeof(struct erofs_inode_compact));
        sbi->root_nid = le16_to_cpu(dsb->root_nid);
-#ifdef CONFIG_EROFS_FS_ZIP
-       sbi->packed_inode = NULL;
-       if (erofs_sb_has_fragments(sbi) && dsb->packed_nid) {
-               sbi->packed_inode =
-                       erofs_iget(sb, le64_to_cpu(dsb->packed_nid));
-               if (IS_ERR(sbi->packed_inode)) {
-                       ret = PTR_ERR(sbi->packed_inode);
-                       goto out;
-               }
-       }
-#endif
+       sbi->packed_nid = le64_to_cpu(dsb->packed_nid);
        sbi->inos = le64_to_cpu(dsb->inos);
 
        sbi->build_time = le64_to_cpu(dsb->build_time);
@@ -417,8 +417,6 @@ static int erofs_read_superblock(struct super_block *sb)
        /* handle multiple devices */
        ret = erofs_scan_devices(sb, dsb);
 
-       if (erofs_sb_has_ztailpacking(sbi))
-               erofs_info(sb, "EXPERIMENTAL compressed inline data feature in use. Use at your own risk!");
        if (erofs_is_fscache_mode(sb))
                erofs_info(sb, "EXPERIMENTAL fscache-based on-demand read feature in use. Use at your own risk!");
        if (erofs_sb_has_fragments(sbi))
@@ -733,9 +731,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
        sbi->domain_id = ctx->domain_id;
        ctx->domain_id = NULL;
 
+       sbi->blkszbits = PAGE_SHIFT;
        if (erofs_is_fscache_mode(sb)) {
-               sb->s_blocksize = EROFS_BLKSIZ;
-               sb->s_blocksize_bits = LOG_BLOCK_SIZE;
+               sb->s_blocksize = PAGE_SIZE;
+               sb->s_blocksize_bits = PAGE_SHIFT;
 
                err = erofs_fscache_register_fs(sb);
                if (err)
@@ -745,8 +744,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
                if (err)
                        return err;
        } else {
-               if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) {
-                       erofs_err(sb, "failed to set erofs blksize");
+               if (!sb_set_blocksize(sb, PAGE_SIZE)) {
+                       errorfc(fc, "failed to set initial blksize");
                        return -EINVAL;
                }
 
@@ -759,12 +758,24 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
        if (err)
                return err;
 
-       if (test_opt(&sbi->opt, DAX_ALWAYS)) {
-               BUILD_BUG_ON(EROFS_BLKSIZ != PAGE_SIZE);
+       if (sb->s_blocksize_bits != sbi->blkszbits) {
+               if (erofs_is_fscache_mode(sb)) {
+                       errorfc(fc, "unsupported blksize for fscache mode");
+                       return -EINVAL;
+               }
+               if (!sb_set_blocksize(sb, 1 << sbi->blkszbits)) {
+                       errorfc(fc, "failed to set erofs blksize");
+                       return -EINVAL;
+               }
+       }
 
+       if (test_opt(&sbi->opt, DAX_ALWAYS)) {
                if (!sbi->dax_dev) {
                        errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
                        clear_opt(&sbi->opt, DAX_ALWAYS);
+               } else if (sbi->blkszbits != PAGE_SHIFT) {
+                       errorfc(fc, "unsupported blocksize for DAX");
+                       clear_opt(&sbi->opt, DAX_ALWAYS);
                }
        }
 
@@ -799,10 +810,22 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
 
        erofs_shrinker_register(sb);
        /* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */
+       if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) {
+               sbi->packed_inode = erofs_iget(sb, sbi->packed_nid);
+               if (IS_ERR(sbi->packed_inode)) {
+                       err = PTR_ERR(sbi->packed_inode);
+                       sbi->packed_inode = NULL;
+                       return err;
+               }
+       }
        err = erofs_init_managed_cache(sb);
        if (err)
                return err;
 
+       err = erofs_xattr_prefixes_init(sb);
+       if (err)
+               return err;
+
        err = erofs_register_sysfs(sb);
        if (err)
                return err;
@@ -962,12 +985,13 @@ static void erofs_put_super(struct super_block *sb)
 
        erofs_unregister_sysfs(sb);
        erofs_shrinker_unregister(sb);
+       erofs_xattr_prefixes_cleanup(sb);
 #ifdef CONFIG_EROFS_FS_ZIP
        iput(sbi->managed_cache);
        sbi->managed_cache = NULL;
+#endif
        iput(sbi->packed_inode);
        sbi->packed_inode = NULL;
-#endif
        erofs_free_dev_context(sbi->devs);
        sbi->devs = NULL;
        erofs_fscache_unregister_fs(sb);
@@ -1060,7 +1084,7 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
                id = huge_encode_dev(sb->s_bdev->bd_dev);
 
        buf->f_type = sb->s_magic;
-       buf->f_bsize = EROFS_BLKSIZ;
+       buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = sbi->total_blocks;
        buf->f_bfree = buf->f_bavail = 0;
 
index 60729b1220b6bbdb1a5e3dc01058538689b96545..cd80499351e05c1e3900a71f468b51eaa8d009ad 100644 (file)
@@ -7,6 +7,19 @@
 #include <linux/security.h>
 #include "xattr.h"
 
+static inline erofs_blk_t erofs_xattr_blkaddr(struct super_block *sb,
+                                             unsigned int xattr_id)
+{
+       return EROFS_SB(sb)->xattr_blkaddr +
+              erofs_blknr(sb, xattr_id * sizeof(__u32));
+}
+
+static inline unsigned int erofs_xattr_blkoff(struct super_block *sb,
+                                             unsigned int xattr_id)
+{
+       return erofs_blkoff(sb, xattr_id * sizeof(__u32));
+}
+
 struct xattr_iter {
        struct super_block *sb;
        struct erofs_buf buf;
@@ -16,7 +29,7 @@ struct xattr_iter {
        unsigned int ofs;
 };
 
-static int init_inode_xattrs(struct inode *inode)
+static int erofs_init_inode_xattrs(struct inode *inode)
 {
        struct erofs_inode *const vi = EROFS_I(inode);
        struct xattr_iter it;
@@ -68,8 +81,8 @@ static int init_inode_xattrs(struct inode *inode)
        }
 
        it.buf = __EROFS_BUF_INITIALIZER;
-       it.blkaddr = erofs_blknr(erofs_iloc(inode) + vi->inode_isize);
-       it.ofs = erofs_blkoff(erofs_iloc(inode) + vi->inode_isize);
+       it.blkaddr = erofs_blknr(sb, erofs_iloc(inode) + vi->inode_isize);
+       it.ofs = erofs_blkoff(sb, erofs_iloc(inode) + vi->inode_isize);
 
        /* read in shared xattr array (non-atomic, see kmalloc below) */
        it.kaddr = erofs_read_metabuf(&it.buf, sb, it.blkaddr, EROFS_KMAP);
@@ -92,9 +105,9 @@ static int init_inode_xattrs(struct inode *inode)
        it.ofs += sizeof(struct erofs_xattr_ibody_header);
 
        for (i = 0; i < vi->xattr_shared_count; ++i) {
-               if (it.ofs >= EROFS_BLKSIZ) {
+               if (it.ofs >= sb->s_blocksize) {
                        /* cannot be unaligned */
-                       DBG_BUGON(it.ofs != EROFS_BLKSIZ);
+                       DBG_BUGON(it.ofs != sb->s_blocksize);
 
                        it.kaddr = erofs_read_metabuf(&it.buf, sb, ++it.blkaddr,
                                                      EROFS_KMAP);
@@ -139,15 +152,15 @@ struct xattr_iter_handlers {
 
 static inline int xattr_iter_fixup(struct xattr_iter *it)
 {
-       if (it->ofs < EROFS_BLKSIZ)
+       if (it->ofs < it->sb->s_blocksize)
                return 0;
 
-       it->blkaddr += erofs_blknr(it->ofs);
+       it->blkaddr += erofs_blknr(it->sb, it->ofs);
        it->kaddr = erofs_read_metabuf(&it->buf, it->sb, it->blkaddr,
                                       EROFS_KMAP);
        if (IS_ERR(it->kaddr))
                return PTR_ERR(it->kaddr);
-       it->ofs = erofs_blkoff(it->ofs);
+       it->ofs = erofs_blkoff(it->sb, it->ofs);
        return 0;
 }
 
@@ -157,7 +170,8 @@ static int inline_xattr_iter_begin(struct xattr_iter *it,
        struct erofs_inode *const vi = EROFS_I(inode);
        unsigned int xattr_header_sz, inline_xattr_ofs;
 
-       xattr_header_sz = inlinexattr_header_size(inode);
+       xattr_header_sz = sizeof(struct erofs_xattr_ibody_header) +
+                         sizeof(u32) * vi->xattr_shared_count;
        if (xattr_header_sz >= vi->xattr_isize) {
                DBG_BUGON(xattr_header_sz > vi->xattr_isize);
                return -ENOATTR;
@@ -165,8 +179,8 @@ static int inline_xattr_iter_begin(struct xattr_iter *it,
 
        inline_xattr_ofs = vi->inode_isize + xattr_header_sz;
 
-       it->blkaddr = erofs_blknr(erofs_iloc(inode) + inline_xattr_ofs);
-       it->ofs = erofs_blkoff(erofs_iloc(inode) + inline_xattr_ofs);
+       it->blkaddr = erofs_blknr(it->sb, erofs_iloc(inode) + inline_xattr_ofs);
+       it->ofs = erofs_blkoff(it->sb, erofs_iloc(inode) + inline_xattr_ofs);
        it->kaddr = erofs_read_metabuf(&it->buf, inode->i_sb, it->blkaddr,
                                       EROFS_KMAP);
        if (IS_ERR(it->kaddr))
@@ -222,8 +236,8 @@ static int xattr_foreach(struct xattr_iter *it,
        processed = 0;
 
        while (processed < entry.e_name_len) {
-               if (it->ofs >= EROFS_BLKSIZ) {
-                       DBG_BUGON(it->ofs > EROFS_BLKSIZ);
+               if (it->ofs >= it->sb->s_blocksize) {
+                       DBG_BUGON(it->ofs > it->sb->s_blocksize);
 
                        err = xattr_iter_fixup(it);
                        if (err)
@@ -231,7 +245,7 @@ static int xattr_foreach(struct xattr_iter *it,
                        it->ofs = 0;
                }
 
-               slice = min_t(unsigned int, EROFS_BLKSIZ - it->ofs,
+               slice = min_t(unsigned int, it->sb->s_blocksize - it->ofs,
                              entry.e_name_len - processed);
 
                /* handle name */
@@ -257,8 +271,8 @@ static int xattr_foreach(struct xattr_iter *it,
        }
 
        while (processed < value_sz) {
-               if (it->ofs >= EROFS_BLKSIZ) {
-                       DBG_BUGON(it->ofs > EROFS_BLKSIZ);
+               if (it->ofs >= it->sb->s_blocksize) {
+                       DBG_BUGON(it->ofs > it->sb->s_blocksize);
 
                        err = xattr_iter_fixup(it);
                        if (err)
@@ -266,7 +280,7 @@ static int xattr_foreach(struct xattr_iter *it,
                        it->ofs = 0;
                }
 
-               slice = min_t(unsigned int, EROFS_BLKSIZ - it->ofs,
+               slice = min_t(unsigned int, it->sb->s_blocksize - it->ofs,
                              value_sz - processed);
                op->value(it, processed, it->kaddr + it->ofs, slice);
                it->ofs += slice;
@@ -283,17 +297,45 @@ struct getxattr_iter {
        struct xattr_iter it;
 
        char *buffer;
-       int buffer_size, index;
+       int buffer_size, index, infix_len;
        struct qstr name;
 };
 
+static int erofs_xattr_long_entrymatch(struct getxattr_iter *it,
+                                      struct erofs_xattr_entry *entry)
+{
+       struct erofs_sb_info *sbi = EROFS_SB(it->it.sb);
+       struct erofs_xattr_prefix_item *pf = sbi->xattr_prefixes +
+               (entry->e_name_index & EROFS_XATTR_LONG_PREFIX_MASK);
+
+       if (pf >= sbi->xattr_prefixes + sbi->xattr_prefix_count)
+               return -ENOATTR;
+
+       if (it->index != pf->prefix->base_index ||
+           it->name.len != entry->e_name_len + pf->infix_len)
+               return -ENOATTR;
+
+       if (memcmp(it->name.name, pf->prefix->infix, pf->infix_len))
+               return -ENOATTR;
+
+       it->infix_len = pf->infix_len;
+       return 0;
+}
+
 static int xattr_entrymatch(struct xattr_iter *_it,
                            struct erofs_xattr_entry *entry)
 {
        struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it);
 
-       return (it->index != entry->e_name_index ||
-               it->name.len != entry->e_name_len) ? -ENOATTR : 0;
+       /* should also match the infix for long name prefixes */
+       if (entry->e_name_index & EROFS_XATTR_LONG_PREFIX)
+               return erofs_xattr_long_entrymatch(it, entry);
+
+       if (it->index != entry->e_name_index ||
+           it->name.len != entry->e_name_len)
+               return -ENOATTR;
+       it->infix_len = 0;
+       return 0;
 }
 
 static int xattr_namematch(struct xattr_iter *_it,
@@ -301,7 +343,9 @@ static int xattr_namematch(struct xattr_iter *_it,
 {
        struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it);
 
-       return memcmp(buf, it->name.name + processed, len) ? -ENOATTR : 0;
+       if (memcmp(buf, it->name.name + it->infix_len + processed, len))
+               return -ENOATTR;
+       return 0;
 }
 
 static int xattr_checkbuffer(struct xattr_iter *_it,
@@ -351,21 +395,18 @@ static int inline_getxattr(struct inode *inode, struct getxattr_iter *it)
 static int shared_getxattr(struct inode *inode, struct getxattr_iter *it)
 {
        struct erofs_inode *const vi = EROFS_I(inode);
-       struct super_block *const sb = inode->i_sb;
-       struct erofs_sb_info *const sbi = EROFS_SB(sb);
-       unsigned int i;
+       struct super_block *const sb = it->it.sb;
+       unsigned int i, xsid;
        int ret = -ENOATTR;
 
        for (i = 0; i < vi->xattr_shared_count; ++i) {
-               erofs_blk_t blkaddr =
-                       xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]);
-
-               it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]);
-               it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb, blkaddr,
-                                                 EROFS_KMAP);
+               xsid = vi->xattr_shared_xattrs[i];
+               it->it.blkaddr = erofs_xattr_blkaddr(sb, xsid);
+               it->it.ofs = erofs_xattr_blkoff(sb, xsid);
+               it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb,
+                                                 it->it.blkaddr, EROFS_KMAP);
                if (IS_ERR(it->it.kaddr))
                        return PTR_ERR(it->it.kaddr);
-               it->it.blkaddr = blkaddr;
 
                ret = xattr_foreach(&it->it, &find_xattr_handlers, NULL);
                if (ret != -ENOATTR)
@@ -394,7 +435,7 @@ int erofs_getxattr(struct inode *inode, int index,
        if (!name)
                return -EINVAL;
 
-       ret = init_inode_xattrs(inode);
+       ret = erofs_init_inode_xattrs(inode);
        if (ret)
                return ret;
 
@@ -421,20 +462,9 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
                                   struct dentry *unused, struct inode *inode,
                                   const char *name, void *buffer, size_t size)
 {
-       struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
-
-       switch (handler->flags) {
-       case EROFS_XATTR_INDEX_USER:
-               if (!test_opt(&sbi->opt, XATTR_USER))
-                       return -EOPNOTSUPP;
-               break;
-       case EROFS_XATTR_INDEX_TRUSTED:
-               break;
-       case EROFS_XATTR_INDEX_SECURITY:
-               break;
-       default:
-               return -EINVAL;
-       }
+       if (handler->flags == EROFS_XATTR_INDEX_USER &&
+           !test_opt(&EROFS_I_SB(inode)->opt, XATTR_USER))
+               return -EOPNOTSUPP;
 
        return erofs_getxattr(inode, handler->flags, name, buffer, size);
 }
@@ -463,10 +493,6 @@ const struct xattr_handler __maybe_unused erofs_xattr_security_handler = {
 
 const struct xattr_handler *erofs_xattr_handlers[] = {
        &erofs_xattr_user_handler,
-#ifdef CONFIG_EROFS_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &erofs_xattr_trusted_handler,
 #ifdef CONFIG_EROFS_FS_SECURITY
        &erofs_xattr_security_handler,
@@ -487,29 +513,40 @@ static int xattr_entrylist(struct xattr_iter *_it,
 {
        struct listxattr_iter *it =
                container_of(_it, struct listxattr_iter, it);
-       unsigned int prefix_len;
-       const char *prefix;
-
-       const struct xattr_handler *h =
-               erofs_xattr_handler(entry->e_name_index);
+       unsigned int base_index = entry->e_name_index;
+       unsigned int prefix_len, infix_len = 0;
+       const char *prefix, *infix = NULL;
+
+       if (entry->e_name_index & EROFS_XATTR_LONG_PREFIX) {
+               struct erofs_sb_info *sbi = EROFS_SB(_it->sb);
+               struct erofs_xattr_prefix_item *pf = sbi->xattr_prefixes +
+                       (entry->e_name_index & EROFS_XATTR_LONG_PREFIX_MASK);
+
+               if (pf >= sbi->xattr_prefixes + sbi->xattr_prefix_count)
+                       return 1;
+               infix = pf->prefix->infix;
+               infix_len = pf->infix_len;
+               base_index = pf->prefix->base_index;
+       }
 
-       if (!h || (h->list && !h->list(it->dentry)))
+       prefix = erofs_xattr_prefix(base_index, it->dentry);
+       if (!prefix)
                return 1;
-
-       prefix = xattr_prefix(h);
        prefix_len = strlen(prefix);
 
        if (!it->buffer) {
-               it->buffer_ofs += prefix_len + entry->e_name_len + 1;
+               it->buffer_ofs += prefix_len + infix_len +
+                                       entry->e_name_len + 1;
                return 1;
        }
 
-       if (it->buffer_ofs + prefix_len
+       if (it->buffer_ofs + prefix_len + infix_len +
                + entry->e_name_len + 1 > it->buffer_size)
                return -ERANGE;
 
        memcpy(it->buffer + it->buffer_ofs, prefix, prefix_len);
-       it->buffer_ofs += prefix_len;
+       memcpy(it->buffer + it->buffer_ofs + prefix_len, infix, infix_len);
+       it->buffer_ofs += prefix_len + infix_len;
        return 0;
 }
 
@@ -563,21 +600,18 @@ static int shared_listxattr(struct listxattr_iter *it)
 {
        struct inode *const inode = d_inode(it->dentry);
        struct erofs_inode *const vi = EROFS_I(inode);
-       struct super_block *const sb = inode->i_sb;
-       struct erofs_sb_info *const sbi = EROFS_SB(sb);
-       unsigned int i;
+       struct super_block *const sb = it->it.sb;
+       unsigned int i, xsid;
        int ret = 0;
 
        for (i = 0; i < vi->xattr_shared_count; ++i) {
-               erofs_blk_t blkaddr =
-                       xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]);
-
-               it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]);
-               it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb, blkaddr,
-                                                 EROFS_KMAP);
+               xsid = vi->xattr_shared_xattrs[i];
+               it->it.blkaddr = erofs_xattr_blkaddr(sb, xsid);
+               it->it.ofs = erofs_xattr_blkoff(sb, xsid);
+               it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb,
+                                                 it->it.blkaddr, EROFS_KMAP);
                if (IS_ERR(it->it.kaddr))
                        return PTR_ERR(it->it.kaddr);
-               it->it.blkaddr = blkaddr;
 
                ret = xattr_foreach(&it->it, &list_xattr_handlers, NULL);
                if (ret)
@@ -592,7 +626,7 @@ ssize_t erofs_listxattr(struct dentry *dentry,
        int ret;
        struct listxattr_iter it;
 
-       ret = init_inode_xattrs(d_inode(dentry));
+       ret = erofs_init_inode_xattrs(d_inode(dentry));
        if (ret == -ENOATTR)
                return 0;
        if (ret)
@@ -613,6 +647,62 @@ ssize_t erofs_listxattr(struct dentry *dentry,
        return ret;
 }
 
+void erofs_xattr_prefixes_cleanup(struct super_block *sb)
+{
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
+       int i;
+
+       if (sbi->xattr_prefixes) {
+               for (i = 0; i < sbi->xattr_prefix_count; i++)
+                       kfree(sbi->xattr_prefixes[i].prefix);
+               kfree(sbi->xattr_prefixes);
+               sbi->xattr_prefixes = NULL;
+       }
+}
+
+int erofs_xattr_prefixes_init(struct super_block *sb)
+{
+       struct erofs_sb_info *sbi = EROFS_SB(sb);
+       struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
+       erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2;
+       struct erofs_xattr_prefix_item *pfs;
+       int ret = 0, i, len;
+
+       if (!sbi->xattr_prefix_count)
+               return 0;
+
+       pfs = kzalloc(sbi->xattr_prefix_count * sizeof(*pfs), GFP_KERNEL);
+       if (!pfs)
+               return -ENOMEM;
+
+       if (erofs_sb_has_fragments(sbi))
+               buf.inode = sbi->packed_inode;
+       else
+               erofs_init_metabuf(&buf, sb);
+
+       for (i = 0; i < sbi->xattr_prefix_count; i++) {
+               void *ptr = erofs_read_metadata(sb, &buf, &pos, &len);
+
+               if (IS_ERR(ptr)) {
+                       ret = PTR_ERR(ptr);
+                       break;
+               } else if (len < sizeof(*pfs->prefix) ||
+                          len > EROFS_NAME_LEN + sizeof(*pfs->prefix)) {
+                       kfree(ptr);
+                       ret = -EFSCORRUPTED;
+                       break;
+               }
+               pfs[i].prefix = ptr;
+               pfs[i].infix_len = len - sizeof(struct erofs_xattr_long_prefix);
+       }
+
+       erofs_put_metabuf(&buf);
+       sbi->xattr_prefixes = pfs;
+       if (ret)
+               erofs_xattr_prefixes_cleanup(sb);
+       return ret;
+}
+
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
 struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu)
 {
index 0a43c9ee9f8f3ba8d7cf999d90d39f435c78cfbf..f16283cb8c9301c1f0ce81d5bd321ca4c04d8c72 100644 (file)
 /* Attribute not found */
 #define ENOATTR         ENODATA
 
-static inline unsigned int inlinexattr_header_size(struct inode *inode)
-{
-       return sizeof(struct erofs_xattr_ibody_header) +
-               sizeof(u32) * EROFS_I(inode)->xattr_shared_count;
-}
-
-static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi,
-                                         unsigned int xattr_id)
-{
-#ifdef CONFIG_EROFS_FS_XATTR
-       return sbi->xattr_blkaddr +
-               xattr_id * sizeof(__u32) / EROFS_BLKSIZ;
-#else
-       return 0;
-#endif
-}
-
-static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi,
-                                            unsigned int xattr_id)
-{
-       return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ;
-}
-
 #ifdef CONFIG_EROFS_FS_XATTR
 extern const struct xattr_handler erofs_xattr_user_handler;
 extern const struct xattr_handler erofs_xattr_trusted_handler;
 extern const struct xattr_handler erofs_xattr_security_handler;
 
-static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)
+static inline const char *erofs_xattr_prefix(unsigned int idx,
+                                            struct dentry *dentry)
 {
+       const struct xattr_handler *handler = NULL;
+
        static const struct xattr_handler *xattr_handler_map[] = {
                [EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler,
 #ifdef CONFIG_EROFS_FS_POSIX_ACL
-               [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] =
-                       &posix_acl_access_xattr_handler,
-               [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] =
-                       &posix_acl_default_xattr_handler,
+               [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
+               [EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
 #endif
                [EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler,
 #ifdef CONFIG_EROFS_FS_SECURITY
@@ -57,15 +35,24 @@ static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)
 #endif
        };
 
-       return idx && idx < ARRAY_SIZE(xattr_handler_map) ?
-               xattr_handler_map[idx] : NULL;
+       if (idx && idx < ARRAY_SIZE(xattr_handler_map))
+               handler = xattr_handler_map[idx];
+
+       if (!xattr_handler_can_list(handler, dentry))
+               return NULL;
+
+       return xattr_prefix(handler);
 }
 
 extern const struct xattr_handler *erofs_xattr_handlers[];
 
+int erofs_xattr_prefixes_init(struct super_block *sb);
+void erofs_xattr_prefixes_cleanup(struct super_block *sb);
 int erofs_getxattr(struct inode *, int, const char *, void *, size_t);
 ssize_t erofs_listxattr(struct dentry *, char *, size_t);
 #else
+static inline int erofs_xattr_prefixes_init(struct super_block *sb) { return 0; }
+static inline void erofs_xattr_prefixes_cleanup(struct super_block *sb) {}
 static inline int erofs_getxattr(struct inode *inode, int index,
                                 const char *name, void *buffer,
                                 size_t buffer_size)
index f1708c77a9912ec8f05adf194dde1c1e9e90573e..45f21db2303a9d72b606c92d5783cb724b5d5705 100644 (file)
@@ -807,7 +807,7 @@ static int z_erofs_register_pcluster(struct z_erofs_decompress_frontend *fe)
 
        if (ztailpacking) {
                pcl->obj.index = 0;     /* which indicates ztailpacking */
-               pcl->pageofs_in = erofs_blkoff(map->m_pa);
+               pcl->pageofs_in = erofs_blkoff(fe->inode->i_sb, map->m_pa);
                pcl->tailpacking_size = map->m_plen;
        } else {
                pcl->obj.index = map->m_pa >> PAGE_SHIFT;
@@ -930,6 +930,7 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos,
                                 struct page *page, unsigned int pageofs,
                                 unsigned int len)
 {
+       struct super_block *sb = inode->i_sb;
        struct inode *packed_inode = EROFS_I_SB(inode)->packed_inode;
        struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
        u8 *src, *dst;
@@ -938,19 +939,19 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos,
        if (!packed_inode)
                return -EFSCORRUPTED;
 
+       buf.inode = packed_inode;
        pos += EROFS_I(inode)->z_fragmentoff;
        for (i = 0; i < len; i += cnt) {
                cnt = min_t(unsigned int, len - i,
-                           EROFS_BLKSIZ - erofs_blkoff(pos));
-               src = erofs_bread(&buf, packed_inode,
-                                 erofs_blknr(pos), EROFS_KMAP);
+                           sb->s_blocksize - erofs_blkoff(sb, pos));
+               src = erofs_bread(&buf, erofs_blknr(sb, pos), EROFS_KMAP);
                if (IS_ERR(src)) {
                        erofs_put_metabuf(&buf);
                        return PTR_ERR(src);
                }
 
                dst = kmap_local_page(page);
-               memcpy(dst + pageofs + i, src + erofs_blkoff(pos), cnt);
+               memcpy(dst + pageofs + i, src + erofs_blkoff(sb, pos), cnt);
                kunmap_local(dst);
                pos += cnt;
        }
@@ -978,8 +979,6 @@ repeat:
 
        if (offset + cur < map->m_la ||
            offset + cur >= map->m_la + map->m_llen) {
-               erofs_dbg("out-of-range map @ pos %llu", offset + cur);
-
                if (z_erofs_collector_end(fe))
                        fe->backmost = false;
                map->m_la = offset + cur;
@@ -1005,7 +1004,8 @@ repeat:
                void *mp;
 
                mp = erofs_read_metabuf(&fe->map.buf, inode->i_sb,
-                                       erofs_blknr(map->m_pa), EROFS_NO_KMAP);
+                                       erofs_blknr(inode->i_sb, map->m_pa),
+                                       EROFS_NO_KMAP);
                if (IS_ERR(mp)) {
                        err = PTR_ERR(mp);
                        erofs_err(inode->i_sb,
@@ -1103,9 +1103,6 @@ out:
        if (err)
                z_erofs_page_mark_eio(page);
        z_erofs_onlinepage_endio(page);
-
-       erofs_dbg("%s, finish page: %pK spiltted: %u map->m_llen %llu",
-                 __func__, page, spiltted, map->m_llen);
        return err;
 }
 
@@ -1726,11 +1723,11 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
 
                /* no device id here, thus it will always succeed */
                mdev = (struct erofs_map_dev) {
-                       .m_pa = blknr_to_addr(pcl->obj.index),
+                       .m_pa = erofs_pos(sb, pcl->obj.index),
                };
                (void)erofs_map_dev(sb, &mdev);
 
-               cur = erofs_blknr(mdev.m_pa);
+               cur = erofs_blknr(sb, mdev.m_pa);
                end = cur + pcl->pclusterpages;
 
                do {
@@ -1764,7 +1761,7 @@ submit_bio_retry:
 
                                last_bdev = mdev.m_bdev;
                                bio->bi_iter.bi_sector = (sector_t)cur <<
-                                       LOG_SECTORS_PER_BLOCK;
+                                       (sb->s_blocksize_bits - 9);
                                bio->bi_private = q[JQ_SUBMIT];
                                if (f->readahead)
                                        bio->bi_opf |= REQ_RAHEAD;
index 655da4d739cb68ea2e83cf2ed69e9ba1927bfc14..d37c5c89c72878b416159e8680e58831ad9fd3d9 100644 (file)
@@ -7,24 +7,6 @@
 #include <asm/unaligned.h>
 #include <trace/events/erofs.h>
 
-int z_erofs_fill_inode(struct inode *inode)
-{
-       struct erofs_inode *const vi = EROFS_I(inode);
-       struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
-
-       if (!erofs_sb_has_big_pcluster(sbi) &&
-           !erofs_sb_has_ztailpacking(sbi) && !erofs_sb_has_fragments(sbi) &&
-           vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
-               vi->z_advise = 0;
-               vi->z_algorithmtype[0] = 0;
-               vi->z_algorithmtype[1] = 0;
-               vi->z_logical_clusterbits = LOG_BLOCK_SIZE;
-               set_bit(EROFS_I_Z_INITED_BIT, &vi->flags);
-       }
-       inode->i_mapping->a_ops = &z_erofs_aops;
-       return 0;
-}
-
 struct z_erofs_maprecorder {
        struct inode *inode;
        struct erofs_map_blocks *map;
@@ -45,47 +27,50 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 {
        struct inode *const inode = m->inode;
        struct erofs_inode *const vi = EROFS_I(inode);
-       const erofs_off_t pos =
-               Z_EROFS_VLE_LEGACY_INDEX_ALIGN(erofs_iloc(inode) +
-                               vi->inode_isize + vi->xattr_isize) +
-               lcn * sizeof(struct z_erofs_vle_decompressed_index);
-       struct z_erofs_vle_decompressed_index *di;
+       const erofs_off_t pos = Z_EROFS_FULL_INDEX_ALIGN(erofs_iloc(inode) +
+                       vi->inode_isize + vi->xattr_isize) +
+                       lcn * sizeof(struct z_erofs_lcluster_index);
+       struct z_erofs_lcluster_index *di;
        unsigned int advise, type;
 
        m->kaddr = erofs_read_metabuf(&m->map->buf, inode->i_sb,
-                                     erofs_blknr(pos), EROFS_KMAP);
+                                     erofs_blknr(inode->i_sb, pos), EROFS_KMAP);
        if (IS_ERR(m->kaddr))
                return PTR_ERR(m->kaddr);
 
-       m->nextpackoff = pos + sizeof(struct z_erofs_vle_decompressed_index);
+       m->nextpackoff = pos + sizeof(struct z_erofs_lcluster_index);
        m->lcn = lcn;
-       di = m->kaddr + erofs_blkoff(pos);
+       di = m->kaddr + erofs_blkoff(inode->i_sb, pos);
 
        advise = le16_to_cpu(di->di_advise);
-       type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) &
-               ((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1);
+       type = (advise >> Z_EROFS_LI_LCLUSTER_TYPE_BIT) &
+               ((1 << Z_EROFS_LI_LCLUSTER_TYPE_BITS) - 1);
        switch (type) {
-       case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+       case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
                m->clusterofs = 1 << vi->z_logical_clusterbits;
                m->delta[0] = le16_to_cpu(di->di_u.delta[0]);
-               if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) {
+               if (m->delta[0] & Z_EROFS_LI_D0_CBLKCNT) {
                        if (!(vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 |
                                        Z_EROFS_ADVISE_BIG_PCLUSTER_2))) {
                                DBG_BUGON(1);
                                return -EFSCORRUPTED;
                        }
                        m->compressedblks = m->delta[0] &
-                               ~Z_EROFS_VLE_DI_D0_CBLKCNT;
+                               ~Z_EROFS_LI_D0_CBLKCNT;
                        m->delta[0] = 1;
                }
                m->delta[1] = le16_to_cpu(di->di_u.delta[1]);
                break;
-       case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
-               if (advise & Z_EROFS_VLE_DI_PARTIAL_REF)
+       case Z_EROFS_LCLUSTER_TYPE_PLAIN:
+       case Z_EROFS_LCLUSTER_TYPE_HEAD1:
+       case Z_EROFS_LCLUSTER_TYPE_HEAD2:
+               if (advise & Z_EROFS_LI_PARTIAL_REF)
                        m->partialref = true;
                m->clusterofs = le16_to_cpu(di->di_clusterofs);
+               if (m->clusterofs >= 1 << vi->z_logical_clusterbits) {
+                       DBG_BUGON(1);
+                       return -EFSCORRUPTED;
+               }
                m->pblk = le32_to_cpu(di->di_u.blkaddr);
                break;
        default:
@@ -121,13 +106,13 @@ static int get_compacted_la_distance(unsigned int lclusterbits,
                lo = decode_compactedbits(lclusterbits, lomask,
                                          in, encodebits * i, &type);
 
-               if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+               if (type != Z_EROFS_LCLUSTER_TYPE_NONHEAD)
                        return d1;
                ++d1;
        } while (++i < vcnt);
 
-       /* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */
-       if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT))
+       /* vcnt - 1 (Z_EROFS_LCLUSTER_TYPE_NONHEAD) item */
+       if (!(lo & Z_EROFS_LI_D0_CBLKCNT))
                d1 += lo - 1;
        return d1;
 }
@@ -156,7 +141,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
                         (vcnt << amortizedshift);
        big_pcluster = vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1;
        encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt;
-       eofs = erofs_blkoff(pos);
+       eofs = erofs_blkoff(m->inode->i_sb, pos);
        base = round_down(eofs, vcnt << amortizedshift);
        in = m->kaddr + base;
 
@@ -165,19 +150,19 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
        lo = decode_compactedbits(lclusterbits, lomask,
                                  in, encodebits * i, &type);
        m->type = type;
-       if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
+       if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
                m->clusterofs = 1 << lclusterbits;
 
                /* figure out lookahead_distance: delta[1] if needed */
                if (lookahead)
                        m->delta[1] = get_compacted_la_distance(lclusterbits,
                                                encodebits, vcnt, in, i);
-               if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
+               if (lo & Z_EROFS_LI_D0_CBLKCNT) {
                        if (!big_pcluster) {
                                DBG_BUGON(1);
                                return -EFSCORRUPTED;
                        }
-                       m->compressedblks = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
+                       m->compressedblks = lo & ~Z_EROFS_LI_D0_CBLKCNT;
                        m->delta[0] = 1;
                        return 0;
                } else if (i + 1 != (int)vcnt) {
@@ -191,9 +176,9 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
                 */
                lo = decode_compactedbits(lclusterbits, lomask,
                                          in, encodebits * (i - 1), &type);
-               if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+               if (type != Z_EROFS_LCLUSTER_TYPE_NONHEAD)
                        lo = 0;
-               else if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT)
+               else if (lo & Z_EROFS_LI_D0_CBLKCNT)
                        lo = 1;
                m->delta[0] = lo + 1;
                return 0;
@@ -207,7 +192,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
                        --i;
                        lo = decode_compactedbits(lclusterbits, lomask,
                                                  in, encodebits * i, &type);
-                       if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
+                       if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD)
                                i -= lo;
 
                        if (i >= 0)
@@ -219,10 +204,10 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
                        --i;
                        lo = decode_compactedbits(lclusterbits, lomask,
                                                  in, encodebits * i, &type);
-                       if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
-                               if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
+                       if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
+                               if (lo & Z_EROFS_LI_D0_CBLKCNT) {
                                        --i;
-                                       nblk += lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
+                                       nblk += lo & ~Z_EROFS_LI_D0_CBLKCNT;
                                        continue;
                                }
                                /* bigpcluster shouldn't have plain d0 == 1 */
@@ -249,7 +234,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
        const unsigned int lclusterbits = vi->z_logical_clusterbits;
        const erofs_off_t ebase = sizeof(struct z_erofs_map_header) +
                ALIGN(erofs_iloc(inode) + vi->inode_isize + vi->xattr_isize, 8);
-       const unsigned int totalidx = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ);
+       unsigned int totalidx = erofs_iblks(inode);
        unsigned int compacted_4b_initial, compacted_2b;
        unsigned int amortizedshift;
        erofs_off_t pos;
@@ -290,7 +275,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 out:
        pos += lcn * (1 << amortizedshift);
        m->kaddr = erofs_read_metabuf(&m->map->buf, inode->i_sb,
-                                     erofs_blknr(pos), EROFS_KMAP);
+                                     erofs_blknr(inode->i_sb, pos), EROFS_KMAP);
        if (IS_ERR(m->kaddr))
                return PTR_ERR(m->kaddr);
        return unpack_compacted_index(m, amortizedshift, pos, lookahead);
@@ -301,10 +286,10 @@ static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
 {
        const unsigned int datamode = EROFS_I(m->inode)->datalayout;
 
-       if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
+       if (datamode == EROFS_INODE_COMPRESSED_FULL)
                return legacy_load_cluster_from_disk(m, lcn);
 
-       if (datamode == EROFS_INODE_FLAT_COMPRESSION)
+       if (datamode == EROFS_INODE_COMPRESSED_COMPACT)
                return compacted_load_cluster_from_disk(m, lcn, lookahead);
 
        return -EINVAL;
@@ -326,7 +311,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
                        return err;
 
                switch (m->type) {
-               case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+               case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
                        if (!m->delta[0]) {
                                erofs_err(m->inode->i_sb,
                                          "invalid lookback distance 0 @ nid %llu",
@@ -336,9 +321,9 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
                        }
                        lookback_distance = m->delta[0];
                        continue;
-               case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-               case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
-               case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
+               case Z_EROFS_LCLUSTER_TYPE_PLAIN:
+               case Z_EROFS_LCLUSTER_TYPE_HEAD1:
+               case Z_EROFS_LCLUSTER_TYPE_HEAD2:
                        m->headtype = m->type;
                        m->map->m_la = (lcn << lclusterbits) | m->clusterofs;
                        return 0;
@@ -360,21 +345,22 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
 static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
                                            unsigned int initial_lcn)
 {
+       struct super_block *sb = m->inode->i_sb;
        struct erofs_inode *const vi = EROFS_I(m->inode);
        struct erofs_map_blocks *const map = m->map;
        const unsigned int lclusterbits = vi->z_logical_clusterbits;
        unsigned long lcn;
        int err;
 
-       DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN &&
-                 m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 &&
-                 m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD2);
+       DBG_BUGON(m->type != Z_EROFS_LCLUSTER_TYPE_PLAIN &&
+                 m->type != Z_EROFS_LCLUSTER_TYPE_HEAD1 &&
+                 m->type != Z_EROFS_LCLUSTER_TYPE_HEAD2);
        DBG_BUGON(m->type != m->headtype);
 
-       if (m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
-           ((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1) &&
+       if (m->headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN ||
+           ((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD1) &&
             !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) ||
-           ((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) &&
+           ((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) &&
             !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2))) {
                map->m_plen = 1ULL << lclusterbits;
                return 0;
@@ -396,19 +382,19 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
         * BUG_ON in the debugging mode only for developers to notice that.
         */
        DBG_BUGON(lcn == initial_lcn &&
-                 m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD);
+                 m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD);
 
        switch (m->type) {
-       case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
+       case Z_EROFS_LCLUSTER_TYPE_PLAIN:
+       case Z_EROFS_LCLUSTER_TYPE_HEAD1:
+       case Z_EROFS_LCLUSTER_TYPE_HEAD2:
                /*
                 * if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
                 * rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
                 */
-               m->compressedblks = 1 << (lclusterbits - LOG_BLOCK_SIZE);
+               m->compressedblks = 1 << (lclusterbits - sb->s_blocksize_bits);
                break;
-       case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+       case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
                if (m->delta[0] != 1)
                        goto err_bonus_cblkcnt;
                if (m->compressedblks)
@@ -422,7 +408,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
                return -EFSCORRUPTED;
        }
 out:
-       map->m_plen = (u64)m->compressedblks << LOG_BLOCK_SIZE;
+       map->m_plen = erofs_pos(sb, m->compressedblks);
        return 0;
 err_bonus_cblkcnt:
        erofs_err(m->inode->i_sb,
@@ -452,12 +438,12 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
                if (err)
                        return err;
 
-               if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
+               if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
                        DBG_BUGON(!m->delta[1] &&
                                  m->clusterofs != 1 << lclusterbits);
-               } else if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
-                          m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 ||
-                          m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) {
+               } else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN ||
+                          m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 ||
+                          m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) {
                        /* go on until the next HEAD lcluster */
                        if (lcn != headlcn)
                                break;
@@ -476,8 +462,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
 }
 
 static int z_erofs_do_map_blocks(struct inode *inode,
-                                struct erofs_map_blocks *map,
-                                int flags)
+                                struct erofs_map_blocks *map, int flags)
 {
        struct erofs_inode *const vi = EROFS_I(inode);
        bool ztailpacking = vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER;
@@ -507,9 +492,9 @@ static int z_erofs_do_map_blocks(struct inode *inode,
        end = (m.lcn + 1ULL) << lclusterbits;
 
        switch (m.type) {
-       case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
-       case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
+       case Z_EROFS_LCLUSTER_TYPE_PLAIN:
+       case Z_EROFS_LCLUSTER_TYPE_HEAD1:
+       case Z_EROFS_LCLUSTER_TYPE_HEAD2:
                if (endoff >= m.clusterofs) {
                        m.headtype = m.type;
                        map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
@@ -534,7 +519,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
                map->m_flags |= EROFS_MAP_FULL_MAPPED;
                m.delta[0] = 1;
                fallthrough;
-       case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
+       case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
                /* get the corresponding first chunk */
                err = z_erofs_extent_lookback(&m, m.delta[0]);
                if (err)
@@ -555,7 +540,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
                vi->z_tailextent_headlcn = m.lcn;
                /* for non-compact indexes, fragmentoff is 64 bits */
                if (fragment &&
-                   vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
+                   vi->datalayout == EROFS_INODE_COMPRESSED_FULL)
                        vi->z_fragmentoff |= (u64)m.pblk << 32;
        }
        if (ztailpacking && m.lcn == vi->z_tailextent_headlcn) {
@@ -565,13 +550,13 @@ static int z_erofs_do_map_blocks(struct inode *inode,
        } else if (fragment && m.lcn == vi->z_tailextent_headlcn) {
                map->m_flags |= EROFS_MAP_FRAGMENT;
        } else {
-               map->m_pa = blknr_to_addr(m.pblk);
+               map->m_pa = erofs_pos(inode->i_sb, m.pblk);
                err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
                if (err)
                        goto unmap_out;
        }
 
-       if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN) {
+       if (m.headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN) {
                if (map->m_llen > map->m_plen) {
                        DBG_BUGON(1);
                        err = -EFSCORRUPTED;
@@ -583,7 +568,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
                else
                        map->m_algorithmformat =
                                Z_EROFS_COMPRESSION_SHIFTED;
-       } else if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) {
+       } else if (m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) {
                map->m_algorithmformat = vi->z_algorithmtype[1];
        } else {
                map->m_algorithmformat = vi->z_algorithmtype[0];
@@ -592,7 +577,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
        if ((flags & EROFS_GET_BLOCKS_FIEMAP) ||
            ((flags & EROFS_GET_BLOCKS_READMORE) &&
             map->m_algorithmformat == Z_EROFS_COMPRESSION_LZMA &&
-            map->m_llen >= EROFS_BLKSIZ)) {
+            map->m_llen >= i_blocksize(inode))) {
                err = z_erofs_get_extent_decompressedlen(&m);
                if (!err)
                        map->m_flags |= EROFS_MAP_FULL_MAPPED;
@@ -600,9 +585,6 @@ static int z_erofs_do_map_blocks(struct inode *inode,
 
 unmap_out:
        erofs_unmap_metabuf(&m.map->buf);
-       erofs_dbg("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o",
-                 __func__, map->m_la, map->m_pa,
-                 map->m_llen, map->m_plen, map->m_flags);
        return err;
 }
 
@@ -633,13 +615,13 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
                goto out_unlock;
 
        pos = ALIGN(erofs_iloc(inode) + vi->inode_isize + vi->xattr_isize, 8);
-       kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP);
+       kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(sb, pos), EROFS_KMAP);
        if (IS_ERR(kaddr)) {
                err = PTR_ERR(kaddr);
                goto out_unlock;
        }
 
-       h = kaddr + erofs_blkoff(pos);
+       h = kaddr + erofs_blkoff(sb, pos);
        /*
         * if the highest bit of the 8-byte map header is set, the whole file
         * is stored in the packed inode. The rest bits keeps z_fragmentoff.
@@ -663,7 +645,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
                goto out_put_metabuf;
        }
 
-       vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7);
+       vi->z_logical_clusterbits = sb->s_blocksize_bits + (h->h_clusterbits & 7);
        if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) &&
            vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 |
                            Z_EROFS_ADVISE_BIG_PCLUSTER_2)) {
@@ -672,7 +654,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
                err = -EFSCORRUPTED;
                goto out_put_metabuf;
        }
-       if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION &&
+       if (vi->datalayout == EROFS_INODE_COMPRESSED_COMPACT &&
            !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^
            !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2)) {
                erofs_err(sb, "big pcluster head1/2 of compact indexes should be consistent for nid %llu",
@@ -692,7 +674,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
                erofs_put_metabuf(&map.buf);
 
                if (!map.m_plen ||
-                   erofs_blkoff(map.m_pa) + map.m_plen > EROFS_BLKSIZ) {
+                   erofs_blkoff(sb, map.m_pa) + map.m_plen > sb->s_blocksize) {
                        erofs_err(sb, "invalid tail-packing pclustersize %llu",
                                  map.m_plen);
                        err = -EFSCORRUPTED;
index 249ca6c0b7843ff1fa9d102ad14c15e54c0ad578..95850a13ce8d01a79658a7c04748f12914d6a199 100644 (file)
@@ -228,7 +228,6 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
        struct file *file = iocb->ki_filp;
        struct eventfd_ctx *ctx = file->private_data;
        __u64 ucnt = 0;
-       DECLARE_WAITQUEUE(wait, current);
 
        if (iov_iter_count(to) < sizeof(ucnt))
                return -EINVAL;
@@ -239,23 +238,11 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
                        spin_unlock_irq(&ctx->wqh.lock);
                        return -EAGAIN;
                }
-               __add_wait_queue(&ctx->wqh, &wait);
-               for (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (ctx->count)
-                               break;
-                       if (signal_pending(current)) {
-                               __remove_wait_queue(&ctx->wqh, &wait);
-                               __set_current_state(TASK_RUNNING);
-                               spin_unlock_irq(&ctx->wqh.lock);
-                               return -ERESTARTSYS;
-                       }
+
+               if (wait_event_interruptible_locked_irq(ctx->wqh, ctx->count)) {
                        spin_unlock_irq(&ctx->wqh.lock);
-                       schedule();
-                       spin_lock_irq(&ctx->wqh.lock);
+                       return -ERESTARTSYS;
                }
-               __remove_wait_queue(&ctx->wqh, &wait);
-               __set_current_state(TASK_RUNNING);
        }
        eventfd_ctx_do_read(ctx, &ucnt);
        current->in_eventfd = 1;
@@ -275,7 +262,6 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
        struct eventfd_ctx *ctx = file->private_data;
        ssize_t res;
        __u64 ucnt;
-       DECLARE_WAITQUEUE(wait, current);
 
        if (count < sizeof(ucnt))
                return -EINVAL;
@@ -288,23 +274,10 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
        if (ULLONG_MAX - ctx->count > ucnt)
                res = sizeof(ucnt);
        else if (!(file->f_flags & O_NONBLOCK)) {
-               __add_wait_queue(&ctx->wqh, &wait);
-               for (res = 0;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       if (ULLONG_MAX - ctx->count > ucnt) {
-                               res = sizeof(ucnt);
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               res = -ERESTARTSYS;
-                               break;
-                       }
-                       spin_unlock_irq(&ctx->wqh.lock);
-                       schedule();
-                       spin_lock_irq(&ctx->wqh.lock);
-               }
-               __remove_wait_queue(&ctx->wqh, &wait);
-               __set_current_state(TASK_RUNNING);
+               res = wait_event_interruptible_locked_irq(ctx->wqh,
+                               ULLONG_MAX - ctx->count > ucnt);
+               if (!res)
+                       res = sizeof(ucnt);
        }
        if (likely(res > 0)) {
                ctx->count += ucnt;
index 64659b110973339dbbbbf061a2107e3a7246916b..f6d25050dd7aac42ab1dd59799a05827f2fd7e37 100644 (file)
@@ -483,8 +483,8 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
  * (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.
index 641abfa4b718a4c0f1b7fc06618f13201a35e36b..b126af5f8b15211a20f95c44561902d9a29ea2fd 100644 (file)
@@ -101,8 +101,8 @@ static void ext2_xattr_rehash(struct ext2_xattr_header *,
 static const struct xattr_handler *ext2_xattr_handler_map[] = {
        [EXT2_XATTR_INDEX_USER]              = &ext2_xattr_user_handler,
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
-       [EXT2_XATTR_INDEX_POSIX_ACL_ACCESS]  = &posix_acl_access_xattr_handler,
-       [EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
+       [EXT2_XATTR_INDEX_POSIX_ACL_ACCESS]  = &nop_posix_acl_access,
+       [EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
 #endif
        [EXT2_XATTR_INDEX_TRUSTED]           = &ext2_xattr_trusted_handler,
 #ifdef CONFIG_EXT2_FS_SECURITY
@@ -113,10 +113,6 @@ static const struct xattr_handler *ext2_xattr_handler_map[] = {
 const struct xattr_handler *ext2_xattr_handlers[] = {
        &ext2_xattr_user_handler,
        &ext2_xattr_trusted_handler,
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
 #ifdef CONFIG_EXT2_FS_SECURITY
        &ext2_xattr_security_handler,
 #endif
@@ -125,14 +121,18 @@ const struct xattr_handler *ext2_xattr_handlers[] = {
 
 #define EA_BLOCK_CACHE(inode)  (EXT2_SB(inode->i_sb)->s_ea_block_cache)
 
-static inline const struct xattr_handler *
-ext2_xattr_handler(int name_index)
+static inline const char *ext2_xattr_prefix(int name_index,
+                                           struct dentry *dentry)
 {
        const struct xattr_handler *handler = NULL;
 
        if (name_index > 0 && name_index < ARRAY_SIZE(ext2_xattr_handler_map))
                handler = ext2_xattr_handler_map[name_index];
-       return handler;
+
+       if (!xattr_handler_can_list(handler, dentry))
+               return NULL;
+
+       return xattr_prefix(handler);
 }
 
 static bool
@@ -333,11 +333,10 @@ bad_block:
        /* list the attribute names */
        for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
             entry = EXT2_XATTR_NEXT(entry)) {
-               const struct xattr_handler *handler =
-                       ext2_xattr_handler(entry->e_name_index);
+               const char *prefix;
 
-               if (handler && (!handler->list || handler->list(dentry))) {
-                       const char *prefix = handler->prefix ?: handler->name;
+               prefix = ext2_xattr_prefix(entry->e_name_index, dentry);
+               if (prefix) {
                        size_t prefix_len = strlen(prefix);
                        size_t size = prefix_len + entry->e_name_len + 1;
 
index 31e21de56432d194e1e95eaa5d326e32c0cbcdc2..a5010b5b8a8c11b5909c137b649fe5d04849d832 100644 (file)
@@ -3884,10 +3884,8 @@ static int ext4_rename(struct mnt_idmap *idmap, struct inode *old_dir,
                                goto end_rename;
                }
                retval = ext4_rename_dir_prepare(handle, &old);
-               if (retval) {
-                       inode_unlock(old.inode);
+               if (retval)
                        goto end_rename;
-               }
        }
        /*
         * If we're renaming a file within an inline_data dir and adding or
index f43e526112ae837498c918637f50d7e15a004a0a..76d1ef0efbf4bb75161b25887588021d157839db 100644 (file)
@@ -2500,7 +2500,7 @@ static void ext4_apply_quota_options(struct fs_context *fc,
                        qname = rcu_replace_pointer(sbi->s_qf_names[i], qname,
                                                lockdep_is_held(&sb->s_umount));
                        if (qname)
-                               kfree_rcu(qname);
+                               kfree_rcu_mightsleep(qname);
                }
        }
 
index 767454d74cd696fbd20c4a0d925b645b893c70a6..dadad29bd81bf0739273c1283592a246967b9234 100644 (file)
@@ -88,8 +88,8 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *);
 static const struct xattr_handler * const ext4_xattr_handler_map[] = {
        [EXT4_XATTR_INDEX_USER]              = &ext4_xattr_user_handler,
 #ifdef CONFIG_EXT4_FS_POSIX_ACL
-       [EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &posix_acl_access_xattr_handler,
-       [EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
+       [EXT4_XATTR_INDEX_POSIX_ACL_ACCESS]  = &nop_posix_acl_access,
+       [EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
 #endif
        [EXT4_XATTR_INDEX_TRUSTED]           = &ext4_xattr_trusted_handler,
 #ifdef CONFIG_EXT4_FS_SECURITY
@@ -101,10 +101,6 @@ static const struct xattr_handler * const ext4_xattr_handler_map[] = {
 const struct xattr_handler *ext4_xattr_handlers[] = {
        &ext4_xattr_user_handler,
        &ext4_xattr_trusted_handler,
-#ifdef CONFIG_EXT4_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
 #ifdef CONFIG_EXT4_FS_SECURITY
        &ext4_xattr_security_handler,
 #endif
@@ -173,14 +169,18 @@ static void ext4_xattr_block_csum_set(struct inode *inode,
                                                bh->b_blocknr, BHDR(bh));
 }
 
-static inline const struct xattr_handler *
-ext4_xattr_handler(int name_index)
+static inline const char *ext4_xattr_prefix(int name_index,
+                                           struct dentry *dentry)
 {
        const struct xattr_handler *handler = NULL;
 
        if (name_index > 0 && name_index < ARRAY_SIZE(ext4_xattr_handler_map))
                handler = ext4_xattr_handler_map[name_index];
-       return handler;
+
+       if (!xattr_handler_can_list(handler, dentry))
+               return NULL;
+
+       return xattr_prefix(handler);
 }
 
 static int
@@ -740,11 +740,10 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
        size_t rest = buffer_size;
 
        for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
-               const struct xattr_handler *handler =
-                       ext4_xattr_handler(entry->e_name_index);
+               const char *prefix;
 
-               if (handler && (!handler->list || handler->list(dentry))) {
-                       const char *prefix = handler->prefix ?: handler->name;
+               prefix = ext4_xattr_prefix(entry->e_name_index, dentry);
+               if (prefix) {
                        size_t prefix_len = strlen(prefix);
                        size_t size = prefix_len + entry->e_name_len + 1;
 
index d92edbbdc30e72f1bb1a9fe1e231d009c6d309c2..213805d3592cca4acc3cc3206b6ed7021ad6dc37 100644 (file)
@@ -192,8 +192,8 @@ const struct xattr_handler f2fs_xattr_security_handler = {
 static const struct xattr_handler *f2fs_xattr_handler_map[] = {
        [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
-       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
-       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
+       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
+       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
 #endif
        [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
 #ifdef CONFIG_F2FS_FS_SECURITY
@@ -204,10 +204,6 @@ static const struct xattr_handler *f2fs_xattr_handler_map[] = {
 
 const struct xattr_handler *f2fs_xattr_handlers[] = {
        &f2fs_xattr_user_handler,
-#ifdef CONFIG_F2FS_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &f2fs_xattr_trusted_handler,
 #ifdef CONFIG_F2FS_FS_SECURITY
        &f2fs_xattr_security_handler,
@@ -216,13 +212,18 @@ const struct xattr_handler *f2fs_xattr_handlers[] = {
        NULL,
 };
 
-static inline const struct xattr_handler *f2fs_xattr_handler(int index)
+static inline const char *f2fs_xattr_prefix(int index,
+                                           struct dentry *dentry)
 {
        const struct xattr_handler *handler = NULL;
 
        if (index > 0 && index < ARRAY_SIZE(f2fs_xattr_handler_map))
                handler = f2fs_xattr_handler_map[index];
-       return handler;
+
+       if (!xattr_handler_can_list(handler, dentry))
+               return NULL;
+
+       return xattr_prefix(handler);
 }
 
 static struct f2fs_xattr_entry *__find_xattr(void *base_addr,
@@ -573,12 +574,12 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
        last_base_addr = (void *)base_addr + XATTR_SIZE(inode);
 
        list_for_each_xattr(entry, base_addr) {
-               const struct xattr_handler *handler =
-                       f2fs_xattr_handler(entry->e_name_index);
                const char *prefix;
                size_t prefix_len;
                size_t size;
 
+               prefix = f2fs_xattr_prefix(entry->e_name_index, dentry);
+
                if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
                        (void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) {
                        f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
@@ -590,10 +591,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
                        goto cleanup;
                }
 
-               if (!handler || (handler->list && !handler->list(dentry)))
+               if (!prefix)
                        continue;
 
-               prefix = xattr_prefix(handler);
                prefix_len = strlen(prefix);
                size = prefix_len + entry->e_name_len + 1;
                if (buffer) {
index 195dc23e0d83109df6cb3942813ecb0e4d8caf5d..1db3e3c24b43a0252756efc7720b4a8b3bf032d3 100644 (file)
@@ -978,6 +978,16 @@ restart:
                        continue;
                }
 
+               /*
+                * If wb_tryget fails, the wb has been shutdown, skip it.
+                *
+                * Pin @wb so that it stays on @bdi->wb_list.  This allows
+                * continuing iteration from @wb after dropping and
+                * regrabbing rcu read lock.
+                */
+               if (!wb_tryget(wb))
+                       continue;
+
                /* alloc failed, execute synchronously using on-stack fallback */
                work = &fallback_work;
                *work = *base_work;
@@ -986,13 +996,6 @@ restart:
                work->done = &fallback_work_done;
 
                wb_queue_work(wb, work);
-
-               /*
-                * Pin @wb so that it stays on @bdi->wb_list.  This allows
-                * continuing iteration from @wb after dropping and
-                * regrabbing rcu read lock.
-                */
-               wb_get(wb);
                last_wb = wb;
 
                rcu_read_unlock();
index eb4f88e3dc97fe101fcfe340837496c54cf614b8..1a8f82f478cb7aa4a01f7286ff2f1e939ee5caca 100644 (file)
@@ -2257,30 +2257,31 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
        int res;
        int oldfd;
        struct fuse_dev *fud = NULL;
+       struct fd f;
 
        switch (cmd) {
        case FUSE_DEV_IOC_CLONE:
-               res = -EFAULT;
-               if (!get_user(oldfd, (__u32 __user *)arg)) {
-                       struct file *old = fget(oldfd);
-
-                       res = -EINVAL;
-                       if (old) {
-                               /*
-                                * Check against file->f_op because CUSE
-                                * uses the same ioctl handler.
-                                */
-                               if (old->f_op == file->f_op)
-                                       fud = fuse_get_dev(old);
-
-                               if (fud) {
-                                       mutex_lock(&fuse_mutex);
-                                       res = fuse_device_clone(fud->fc, file);
-                                       mutex_unlock(&fuse_mutex);
-                               }
-                               fput(old);
-                       }
+               if (get_user(oldfd, (__u32 __user *)arg))
+                       return -EFAULT;
+
+               f = fdget(oldfd);
+               if (!f.file)
+                       return -EINVAL;
+
+               /*
+                * Check against file->f_op because CUSE
+                * uses the same ioctl handler.
+                */
+               if (f.file->f_op == file->f_op)
+                       fud = fuse_get_dev(f.file);
+
+               res = -EINVAL;
+               if (fud) {
+                       mutex_lock(&fuse_mutex);
+                       res = fuse_device_clone(fud->fc, file);
+                       mutex_unlock(&fuse_mutex);
                }
+               fdput(f);
                break;
        default:
                res = -ENOTTY;
index de37a3a06a7169c628de17abe08ed14b56335108..89d97f6188e05ee58a195c72a5e3936177ba2733 100644 (file)
@@ -1419,7 +1419,7 @@ out:
 
 static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
 {
-       return (unsigned long)ii->iov->iov_base + ii->iov_offset;
+       return (unsigned long)iter_iov(ii)->iov_base + ii->iov_offset;
 }
 
 static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
index 6fe9ca253b709e8b8c193ab9a038206cd1f6c069..2e215e8c3c88e57d6ed17ba6cc5cb22420e99af6 100644 (file)
@@ -83,8 +83,26 @@ static int gfs2_dhash(const struct dentry *dentry, struct qstr *str)
        return 0;
 }
 
+static int gfs2_dentry_delete(const struct dentry *dentry)
+{
+       struct gfs2_inode *ginode;
+
+       if (d_really_is_negative(dentry))
+               return 0;
+
+       ginode = GFS2_I(d_inode(dentry));
+       if (!gfs2_holder_initialized(&ginode->i_iopen_gh))
+               return 0;
+
+       if (test_bit(GLF_DEMOTE, &ginode->i_iopen_gh.gh_gl->gl_flags))
+               return 1;
+
+       return 0;
+}
+
 const struct dentry_operations gfs2_dops = {
        .d_revalidate = gfs2_drevalidate,
        .d_hash = gfs2_dhash,
+       .d_delete = gfs2_dentry_delete,
 };
 
index adf6d17cf03353872b4f74202d5dcc3594bb9326..93b36d026bb478b30b1b438e69313db28e16fa30 100644 (file)
@@ -1501,8 +1501,6 @@ const struct xattr_handler *gfs2_xattr_handlers_max[] = {
        /* GFS2_FS_FORMAT_MIN */
        &gfs2_xattr_user_handler,
        &gfs2_xattr_security_handler,
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
        NULL,
 };
 
index abb91f5fae9211b752914df35a96e50dff846301..b21660475ac1cc703428cabf1f953b1ea3fb095a 100644 (file)
@@ -511,7 +511,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        if (type == HFSPLUS_FOLDER) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
-               WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_folder));
+               if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
+                       pr_err("bad catalog folder entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
                                        sizeof(struct hfsplus_cat_folder));
                hfsplus_get_perms(inode, &folder->permissions, 1);
@@ -531,7 +535,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        } else if (type == HFSPLUS_FILE) {
                struct hfsplus_cat_file *file = &entry.file;
 
-               WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_file));
+               if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
+                       pr_err("bad catalog file entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
                                        sizeof(struct hfsplus_cat_file));
 
@@ -562,6 +570,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                pr_err("bad catalog entry used to create inode\n");
                res = -EIO;
        }
+out:
        return res;
 }
 
@@ -570,6 +579,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
        struct inode *main_inode = inode;
        struct hfs_find_data fd;
        hfsplus_cat_entry entry;
+       int res = 0;
 
        if (HFSPLUS_IS_RSRC(inode))
                main_inode = HFSPLUS_I(inode)->rsrc_inode;
@@ -588,7 +598,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
        if (S_ISDIR(main_inode->i_mode)) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
-               WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_folder));
+               if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
+                       pr_err("bad catalog folder entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_folder));
                /* simple node checks? */
@@ -613,7 +627,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
        } else {
                struct hfsplus_cat_file *file = &entry.file;
 
-               WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_file));
+               if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
+                       pr_err("bad catalog file entry\n");
+                       res = -EIO;
+                       goto out;
+               }
                hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
                                        sizeof(struct hfsplus_cat_file));
                hfsplus_inode_write_fork(inode, &file->data_fork);
@@ -634,7 +652,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
        set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
 out:
        hfs_find_exit(&fd);
-       return 0;
+       return res;
 }
 
 int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa)
index 4558dc2f13557368fb0200d826fe2edba5de3f1e..3ec5a8f7b644d058ef23762f9a26fdfc137084ca 100644 (file)
@@ -1804,8 +1804,8 @@ EXPORT_SYMBOL(bmap);
 
 /*
  * With relative atime, only update atime if the previous atime is
- * earlier than either the ctime or mtime or if at least a day has
- * passed since the last atime update.
+ * earlier than or equal to either the ctime or mtime,
+ * or if at least a day has passed since the last atime update.
  */
 static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
                             struct timespec64 now)
@@ -1814,12 +1814,12 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
        if (!(mnt->mnt_flags & MNT_RELATIME))
                return 1;
        /*
-        * Is mtime younger than atime? If yes, update atime:
+        * Is mtime younger than or equal to atime? If yes, update atime:
         */
        if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
                return 1;
        /*
-        * Is ctime younger than atime? If yes, update atime:
+        * Is ctime younger than or equal to atime? If yes, update atime:
         */
        if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
                return 1;
index dc4eb91a577a80f16a3f49729e8c6f6dec2aeb3b..ab36ed8fa41caf2134cb5a1f0599a7f80590bf7c 100644 (file)
@@ -259,8 +259,6 @@ ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *po
 /*
  * fs/attr.c
  */
-int setattr_should_drop_sgid(struct mnt_idmap *idmap,
-                            const struct inode *inode);
 struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns);
 struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap);
 void mnt_idmap_put(struct mnt_idmap *idmap);
index da3e18503c6582074257e2714216bfb24b3a6f32..aa4048a27f31f1de95178d4cbedda3fe02f459d3 100644 (file)
@@ -919,17 +919,14 @@ const struct xattr_handler *jffs2_xattr_handlers[] = {
        &jffs2_user_xattr_handler,
 #ifdef CONFIG_JFFS2_FS_SECURITY
        &jffs2_security_xattr_handler,
-#endif
-#ifdef CONFIG_JFFS2_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
 #endif
        &jffs2_trusted_xattr_handler,
        NULL
 };
 
-static const struct xattr_handler *xprefix_to_handler(int xprefix) {
-       const struct xattr_handler *ret;
+static const char *jffs2_xattr_prefix(int xprefix, struct dentry *dentry)
+{
+       const struct xattr_handler *ret = NULL;
 
        switch (xprefix) {
        case JFFS2_XPREFIX_USER:
@@ -942,20 +939,23 @@ static const struct xattr_handler *xprefix_to_handler(int xprefix) {
 #endif
 #ifdef CONFIG_JFFS2_FS_POSIX_ACL
        case JFFS2_XPREFIX_ACL_ACCESS:
-               ret = &posix_acl_access_xattr_handler;
+               ret = &nop_posix_acl_access;
                break;
        case JFFS2_XPREFIX_ACL_DEFAULT:
-               ret = &posix_acl_default_xattr_handler;
+               ret = &nop_posix_acl_default;
                break;
 #endif
        case JFFS2_XPREFIX_TRUSTED:
                ret = &jffs2_trusted_xattr_handler;
                break;
        default:
-               ret = NULL;
-               break;
+               return NULL;
        }
-       return ret;
+
+       if (!xattr_handler_can_list(ret, dentry))
+               return NULL;
+
+       return xattr_prefix(ret);
 }
 
 ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -966,7 +966,6 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
        struct jffs2_inode_cache *ic = f->inocache;
        struct jffs2_xattr_ref *ref, **pref;
        struct jffs2_xattr_datum *xd;
-       const struct xattr_handler *xhandle;
        const char *prefix;
        ssize_t prefix_len, len, rc;
        int retry = 0;
@@ -998,10 +997,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
                                        goto out;
                        }
                }
-               xhandle = xprefix_to_handler(xd->xprefix);
-               if (!xhandle || (xhandle->list && !xhandle->list(dentry)))
+
+               prefix = jffs2_xattr_prefix(xd->xprefix, dentry);
+               if (!prefix)
                        continue;
-               prefix = xhandle->prefix ?: xhandle->name;
                prefix_len = strlen(prefix);
                rc = prefix_len + xd->name_len + 1;
 
index 2e8461ce74de697df24518f27e7e4cd99fcdd665..961569c1115901b84ec84cb58b93d53561dd5a96 100644 (file)
@@ -691,6 +691,35 @@ void grab_metapage(struct metapage * mp)
        unlock_page(mp->page);
 }
 
+static int metapage_write_one(struct page *page)
+{
+       struct folio *folio = page_folio(page);
+       struct address_space *mapping = folio->mapping;
+       struct writeback_control wbc = {
+               .sync_mode = WB_SYNC_ALL,
+               .nr_to_write = folio_nr_pages(folio),
+       };
+       int ret = 0;
+
+       BUG_ON(!folio_test_locked(folio));
+
+       folio_wait_writeback(folio);
+
+       if (folio_clear_dirty_for_io(folio)) {
+               folio_get(folio);
+               ret = metapage_writepage(page, &wbc);
+               if (ret == 0)
+                       folio_wait_writeback(folio);
+               folio_put(folio);
+       } else {
+               folio_unlock(folio);
+       }
+
+       if (!ret)
+               ret = filemap_check_errors(mapping);
+       return ret;
+}
+
 void force_metapage(struct metapage *mp)
 {
        struct page *page = mp->page;
@@ -700,8 +729,8 @@ void force_metapage(struct metapage *mp)
        get_page(page);
        lock_page(page);
        set_page_dirty(page);
-       if (write_one_page(page))
-               jfs_error(mp->sb, "write_one_page() failed\n");
+       if (metapage_write_one(page))
+               jfs_error(mp->sb, "metapage_write_one() failed\n");
        clear_bit(META_forcewrite, &mp->flag);
        put_page(page);
 }
@@ -746,9 +775,9 @@ void release_metapage(struct metapage * mp)
                set_page_dirty(page);
                if (test_bit(META_sync, &mp->flag)) {
                        clear_bit(META_sync, &mp->flag);
-                       if (write_one_page(page))
-                               jfs_error(mp->sb, "write_one_page() failed\n");
-                       lock_page(page); /* write_one_page unlocks the page */
+                       if (metapage_write_one(page))
+                               jfs_error(mp->sb, "metapage_write_one() failed\n");
+                       lock_page(page);
                }
        } else if (mp->lsn)     /* discard_metapage doesn't remove it */
                remove_from_logsync(mp);
index f817798fa1eb1e28a0608c02de1bda1609bdd8a3..931e50018f888a5c26a05a98e23966031c3ff70b 100644 (file)
@@ -986,10 +986,6 @@ static const struct xattr_handler jfs_trusted_xattr_handler = {
 };
 
 const struct xattr_handler *jfs_xattr_handlers[] = {
-#ifdef CONFIG_JFS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &jfs_os2_xattr_handler,
        &jfs_user_xattr_handler,
        &jfs_security_xattr_handler,
index ef00b5fe8ceea9d9dd3c16a76d89c151dec282fd..90de0e498371119769759d0d1dbb9d30e50d2660 100644 (file)
@@ -1748,12 +1748,6 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
        return error;
 }
 
-/* Relationship between mode and the DT_xxx types */
-static inline unsigned char dt_type(struct kernfs_node *kn)
-{
-       return (kn->mode >> 12) & 15;
-}
-
 static int kernfs_dir_fop_release(struct inode *inode, struct file *filp)
 {
        kernfs_put(filp->private_data);
@@ -1831,7 +1825,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
             pos;
             pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) {
                const char *name = pos->name;
-               unsigned int type = dt_type(pos);
+               unsigned int type = fs_umode_to_dtype(pos->mode);
                int len = strlen(name);
                ino_t ino = kernfs_ino(pos);
 
index 6e61b5bc7d86ed5add4e940a3972068a508c52a0..cead696b656a8cd2a39a3fa4598dd656f39515b0 100644 (file)
@@ -727,8 +727,9 @@ static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
                goto smb3signkey_ret;
        }
 
-       if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
-           conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
+       if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
+           (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
+            conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
                rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
        else
                rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
index 5b10b03800c163fb7704ef3d56ba7b664874d932..365ac32af505804f270eadaabfba989dbd5e6bfb 100644 (file)
@@ -112,10 +112,8 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
        struct ksmbd_conn *conn = work->conn;
        struct list_head *requests_queue = NULL;
 
-       if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
+       if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE)
                requests_queue = &conn->requests;
-               work->synchronous = true;
-       }
 
        if (requests_queue) {
                atomic_inc(&conn->req_running);
@@ -136,14 +134,14 @@ int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
 
        if (!work->multiRsp)
                atomic_dec(&conn->req_running);
-       spin_lock(&conn->request_lock);
        if (!work->multiRsp) {
+               spin_lock(&conn->request_lock);
                list_del_init(&work->request_entry);
-               if (!work->synchronous)
-                       list_del_init(&work->async_request_entry);
+               spin_unlock(&conn->request_lock);
+               if (work->asynchronous)
+                       release_async_work(work);
                ret = 0;
        }
-       spin_unlock(&conn->request_lock);
 
        wake_up_all(&conn->req_running_q);
        return ret;
@@ -298,7 +296,7 @@ int ksmbd_conn_handler_loop(void *p)
                kvfree(conn->request_buf);
                conn->request_buf = NULL;
 
-               size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
+               size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
                if (size != sizeof(hdr_buf))
                        break;
 
@@ -319,20 +317,14 @@ int ksmbd_conn_handler_loop(void *p)
                }
 
                /*
-                * Check if pdu size is valid (min : smb header size,
-                * max : 0x00FFFFFF).
+                * Check maximum pdu size(0x00FFFFFF).
                 */
-               if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
-                   pdu_size > MAX_STREAM_PROT_LEN) {
+               if (pdu_size > MAX_STREAM_PROT_LEN)
                        break;
-               }
 
                /* 4 for rfc1002 length field */
                size = pdu_size + 4;
-               conn->request_buf = kvmalloc(size,
-                                            GFP_KERNEL |
-                                            __GFP_NOWARN |
-                                            __GFP_NORETRY);
+               conn->request_buf = kvmalloc(size, GFP_KERNEL);
                if (!conn->request_buf)
                        break;
 
@@ -344,7 +336,7 @@ int ksmbd_conn_handler_loop(void *p)
                 * We already read 4 bytes to find out PDU size, now
                 * read in PDU
                 */
-               size = t->ops->read(t, conn->request_buf + 4, pdu_size);
+               size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
                if (size < 0) {
                        pr_err("sock_read failed: %d\n", size);
                        break;
index 3643354a3fa79c2b351c581691eff7ee74fe761b..0e3a848defaf3214ed752deed6c51854890a4194 100644 (file)
@@ -114,7 +114,8 @@ struct ksmbd_transport_ops {
        int (*prepare)(struct ksmbd_transport *t);
        void (*disconnect)(struct ksmbd_transport *t);
        void (*shutdown)(struct ksmbd_transport *t);
-       int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
+       int (*read)(struct ksmbd_transport *t, char *buf,
+                   unsigned int size, int max_retries);
        int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
                      int size, bool need_invalidate_rkey,
                      unsigned int remote_key);
index 3234f2cf6327cf22ac227c64e4be8afb376073ef..f8ae6144c0aea6ba8724fbed3b48f0d1e719d6a1 100644 (file)
@@ -68,7 +68,7 @@ struct ksmbd_work {
        /* Request is encrypted */
        bool                            encrypted:1;
        /* Is this SYNC or ASYNC ksmbd_work */
-       bool                            synchronous:1;
+       bool                            asynchronous:1;
        bool                            need_invalidate_rkey:1;
 
        unsigned int                    remote_key;
index 394b6ceac4312685ebbd57a6087de345b0c4111b..0d8242789dc8fd7a4e39d0ca52bd6e0263275dca 100644 (file)
@@ -289,10 +289,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
        work->request_buf = conn->request_buf;
        conn->request_buf = NULL;
 
-       if (ksmbd_init_smb_server(work)) {
-               ksmbd_free_work_struct(work);
-               return -EINVAL;
-       }
+       ksmbd_init_smb_server(work);
 
        ksmbd_conn_enqueue_request(work);
        atomic_inc(&conn->r_count);
index 0685c1c77b9fc2b443866480ed7a7ae89dad7c18..67b7e766a06bace88ef65d2afdb7dff514f9f364 100644 (file)
@@ -229,9 +229,6 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
        struct smb2_negotiate_rsp *rsp;
        struct ksmbd_conn *conn = work->conn;
 
-       if (conn->need_neg == false)
-               return -EINVAL;
-
        *(__be32 *)work->response_buf =
                cpu_to_be32(conn->vals->header_size);
 
@@ -498,12 +495,6 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
        rsp_hdr->SessionId = rcv_hdr->SessionId;
        memcpy(rsp_hdr->Signature, rcv_hdr->Signature, 16);
 
-       work->synchronous = true;
-       if (work->async_id) {
-               ksmbd_release_id(&conn->async_ida, work->async_id);
-               work->async_id = 0;
-       }
-
        return 0;
 }
 
@@ -644,7 +635,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
                pr_err("Failed to alloc async message id\n");
                return id;
        }
-       work->synchronous = false;
+       work->asynchronous = true;
        work->async_id = id;
        rsp_hdr->Id.AsyncId = cpu_to_le64(id);
 
@@ -664,6 +655,24 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
        return 0;
 }
 
+void release_async_work(struct ksmbd_work *work)
+{
+       struct ksmbd_conn *conn = work->conn;
+
+       spin_lock(&conn->request_lock);
+       list_del_init(&work->async_request_entry);
+       spin_unlock(&conn->request_lock);
+
+       work->asynchronous = 0;
+       work->cancel_fn = NULL;
+       kfree(work->cancel_argv);
+       work->cancel_argv = NULL;
+       if (work->async_id) {
+               ksmbd_release_id(&conn->async_ida, work->async_id);
+               work->async_id = 0;
+       }
+}
+
 void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
 {
        struct smb2_hdr *rsp_hdr;
@@ -867,17 +876,21 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
 }
 
 static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
-                                 struct smb2_preauth_neg_context *pneg_ctxt)
+                                 struct smb2_preauth_neg_context *pneg_ctxt,
+                                 int len_of_ctxts)
 {
-       __le32 err = STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
+       /*
+        * sizeof(smb2_preauth_neg_context) assumes SMB311_SALT_SIZE Salt,
+        * which may not be present. Only check for used HashAlgorithms[1].
+        */
+       if (len_of_ctxts < MIN_PREAUTH_CTXT_DATA_LEN)
+               return STATUS_INVALID_PARAMETER;
 
-       if (pneg_ctxt->HashAlgorithms == SMB2_PREAUTH_INTEGRITY_SHA512) {
-               conn->preauth_info->Preauth_HashId =
-                       SMB2_PREAUTH_INTEGRITY_SHA512;
-               err = STATUS_SUCCESS;
-       }
+       if (pneg_ctxt->HashAlgorithms != SMB2_PREAUTH_INTEGRITY_SHA512)
+               return STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP;
 
-       return err;
+       conn->preauth_info->Preauth_HashId = SMB2_PREAUTH_INTEGRITY_SHA512;
+       return STATUS_SUCCESS;
 }
 
 static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
@@ -1005,7 +1018,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
                                break;
 
                        status = decode_preauth_ctxt(conn,
-                                                    (struct smb2_preauth_neg_context *)pctx);
+                                                    (struct smb2_preauth_neg_context *)pctx,
+                                                    len_of_ctxts);
                        if (status != STATUS_SUCCESS)
                                break;
                } else if (pctx->ContextType == SMB2_ENCRYPTION_CAPABILITIES) {
@@ -2977,8 +2991,11 @@ int smb2_open(struct ksmbd_work *work)
                                                        sizeof(struct smb_acl) +
                                                        sizeof(struct smb_ace) * ace_num * 2,
                                                        GFP_KERNEL);
-                                       if (!pntsd)
+                                       if (!pntsd) {
+                                               posix_acl_release(fattr.cf_acls);
+                                               posix_acl_release(fattr.cf_dacls);
                                                goto err_out;
+                                       }
 
                                        rc = build_sec_desc(idmap,
                                                            pntsd, NULL, 0,
@@ -4934,6 +4951,10 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
 
                info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
 
+               if (test_share_config_flag(work->tcon->share_conf,
+                   KSMBD_SHARE_FLAG_STREAMS))
+                       info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS);
+
                info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
                len = smbConvertToUTF16((__le16 *)info->FileSystemName,
                                        "NTFS", PATH_MAX, conn->local_nls, 0);
@@ -7038,13 +7059,9 @@ skip:
 
                                ksmbd_vfs_posix_lock_wait(flock);
 
-                               spin_lock(&work->conn->request_lock);
                                spin_lock(&fp->f_lock);
                                list_del(&work->fp_entry);
-                               work->cancel_fn = NULL;
-                               kfree(argv);
                                spin_unlock(&fp->f_lock);
-                               spin_unlock(&work->conn->request_lock);
 
                                if (work->state != KSMBD_WORK_ACTIVE) {
                                        list_del(&smb_lock->llist);
@@ -7062,6 +7079,7 @@ skip:
                                                work->send_no_response = 1;
                                                goto out;
                                        }
+
                                        init_smb2_rsp_hdr(work);
                                        smb2_set_err_rsp(work);
                                        rsp->hdr.Status =
@@ -7074,7 +7092,7 @@ skip:
                                spin_lock(&work->conn->llist_lock);
                                list_del(&smb_lock->clist);
                                spin_unlock(&work->conn->llist_lock);
-
+                               release_async_work(work);
                                goto retry;
                        } else if (!rc) {
                                spin_lock(&work->conn->llist_lock);
@@ -7444,13 +7462,16 @@ static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
        if (in_count == 0)
                return -EINVAL;
 
+       start = le64_to_cpu(qar_req->file_offset);
+       length = le64_to_cpu(qar_req->length);
+
+       if (start < 0 || length < 0)
+               return -EINVAL;
+
        fp = ksmbd_lookup_fd_fast(work, id);
        if (!fp)
                return -ENOENT;
 
-       start = le64_to_cpu(qar_req->file_offset);
-       length = le64_to_cpu(qar_req->length);
-
        ret = ksmbd_vfs_fqar_lseek(fp, start, length,
                                   qar_rsp, in_count, out_count);
        if (ret && ret != -E2BIG)
@@ -7751,7 +7772,7 @@ int smb2_ioctl(struct ksmbd_work *work)
 
                off = le64_to_cpu(zero_data->FileOffset);
                bfz = le64_to_cpu(zero_data->BeyondFinalZero);
-               if (off > bfz) {
+               if (off < 0 || bfz < 0 || off > bfz) {
                        ret = -EINVAL;
                        goto out;
                }
index 0c8a770fe3189b0caeea15c6e04009f5864560c3..9420dd2813fb782157a0ae7ebc41c9fa83d2cb76 100644 (file)
@@ -486,6 +486,7 @@ int find_matching_smb2_dialect(int start_index, __le16 *cli_dialects,
 struct file_lock *smb_flock_init(struct file *f);
 int setup_async_work(struct ksmbd_work *work, void (*fn)(void **),
                     void **arg);
+void release_async_work(struct ksmbd_work *work);
 void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status);
 struct channel *lookup_chann_list(struct ksmbd_session *sess,
                                  struct ksmbd_conn *conn);
index fa2b54df6ee6ff2aad4da4f3090010b26a863c63..af0c2a9b85290de8201640dc2f45896453443fe5 100644 (file)
@@ -283,20 +283,121 @@ err_out:
        return BAD_PROT_ID;
 }
 
-int ksmbd_init_smb_server(struct ksmbd_work *work)
+#define SMB_COM_NEGOTIATE_EX   0x0
+
+/**
+ * get_smb1_cmd_val() - get smb command value from smb header
+ * @work:      smb work containing smb header
+ *
+ * Return:      smb command value
+ */
+static u16 get_smb1_cmd_val(struct ksmbd_work *work)
 {
-       struct ksmbd_conn *conn = work->conn;
+       return SMB_COM_NEGOTIATE_EX;
+}
 
-       if (conn->need_neg == false)
+/**
+ * init_smb1_rsp_hdr() - initialize smb negotiate response header
+ * @work:      smb work containing smb request
+ *
+ * Return:      0 on success, otherwise -EINVAL
+ */
+static int init_smb1_rsp_hdr(struct ksmbd_work *work)
+{
+       struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
+       struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
+
+       /*
+        * Remove 4 byte direct TCP header.
+        */
+       *(__be32 *)work->response_buf =
+               cpu_to_be32(sizeof(struct smb_hdr) - 4);
+
+       rsp_hdr->Command = SMB_COM_NEGOTIATE;
+       *(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
+       rsp_hdr->Flags = SMBFLG_RESPONSE;
+       rsp_hdr->Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
+               SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
+       rsp_hdr->Pid = rcv_hdr->Pid;
+       rsp_hdr->Mid = rcv_hdr->Mid;
+       return 0;
+}
+
+/**
+ * smb1_check_user_session() - check for valid session for a user
+ * @work:      smb work containing smb request buffer
+ *
+ * Return:      0 on success, otherwise error
+ */
+static int smb1_check_user_session(struct ksmbd_work *work)
+{
+       unsigned int cmd = work->conn->ops->get_cmd_val(work);
+
+       if (cmd == SMB_COM_NEGOTIATE_EX)
                return 0;
 
-       init_smb3_11_server(conn);
+       return -EINVAL;
+}
+
+/**
+ * smb1_allocate_rsp_buf() - allocate response buffer for a command
+ * @work:      smb work containing smb request
+ *
+ * Return:      0 on success, otherwise -ENOMEM
+ */
+static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
+{
+       work->response_buf = kmalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
+                       GFP_KERNEL | __GFP_ZERO);
+       work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
+
+       if (!work->response_buf) {
+               pr_err("Failed to allocate %u bytes buffer\n",
+                               MAX_CIFS_SMALL_BUFFER_SIZE);
+               return -ENOMEM;
+       }
 
-       if (conn->ops->get_cmd_val(work) != SMB_COM_NEGOTIATE)
-               conn->need_neg = false;
        return 0;
 }
 
+static struct smb_version_ops smb1_server_ops = {
+       .get_cmd_val = get_smb1_cmd_val,
+       .init_rsp_hdr = init_smb1_rsp_hdr,
+       .allocate_rsp_buf = smb1_allocate_rsp_buf,
+       .check_user_session = smb1_check_user_session,
+};
+
+static int smb1_negotiate(struct ksmbd_work *work)
+{
+       return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
+}
+
+static struct smb_version_cmds smb1_server_cmds[1] = {
+       [SMB_COM_NEGOTIATE_EX]  = { .proc = smb1_negotiate, },
+};
+
+static void init_smb1_server(struct ksmbd_conn *conn)
+{
+       conn->ops = &smb1_server_ops;
+       conn->cmds = smb1_server_cmds;
+       conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+}
+
+void ksmbd_init_smb_server(struct ksmbd_work *work)
+{
+       struct ksmbd_conn *conn = work->conn;
+       __le32 proto;
+
+       if (conn->need_neg == false)
+               return;
+
+       proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+       if (proto == SMB1_PROTO_NUMBER)
+               init_smb1_server(conn);
+       else
+               init_smb3_11_server(conn);
+}
+
 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
                                      struct ksmbd_file *dir,
                                      struct ksmbd_dir_info *d_info,
@@ -434,7 +535,7 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
 
 static int __smb2_negotiate(struct ksmbd_conn *conn)
 {
-       return (conn->dialect >= SMB21_PROT_ID &&
+       return (conn->dialect >= SMB20_PROT_ID &&
                conn->dialect <= SMB311_PROT_ID);
 }
 
@@ -442,9 +543,16 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
 {
        struct smb_negotiate_rsp *neg_rsp = work->response_buf;
 
-       ksmbd_debug(SMB, "Unsupported SMB protocol\n");
-       neg_rsp->hdr.Status.CifsError = STATUS_INVALID_LOGON_TYPE;
-       return -EINVAL;
+       ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
+
+       /* Add 2 byte bcc and 2 byte DialectIndex. */
+       inc_rfc1001_len(work->response_buf, 4);
+       neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
+
+       neg_rsp->hdr.WordCount = 1;
+       neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
+       neg_rsp->ByteCount = 0;
+       return 0;
 }
 
 int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
@@ -457,23 +565,12 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
        ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
 
        if (command == SMB2_NEGOTIATE_HE) {
-               struct smb2_hdr *smb2_hdr = smb2_get_msg(work->request_buf);
-
-               if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
-                       ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
-                       command = SMB_COM_NEGOTIATE;
-               }
-       }
-
-       if (command == SMB2_NEGOTIATE_HE && __smb2_negotiate(conn)) {
                ret = smb2_handle_negotiate(work);
-               init_smb2_neg_rsp(work);
                return ret;
        }
 
        if (command == SMB_COM_NEGOTIATE) {
                if (__smb2_negotiate(conn)) {
-                       conn->need_neg = true;
                        init_smb3_11_server(conn);
                        init_smb2_neg_rsp(work);
                        ksmbd_debug(SMB, "Upgrade to SMB2 negotiation\n");
index e663ab9ea759092d9e1cb0282b76d0059490581c..9130d2e3cd78c0966d266f7bf72dfe390bd06462 100644 (file)
 
 #define SMB1_PROTO_NUMBER              cpu_to_le32(0x424d53ff)
 #define SMB_COM_NEGOTIATE              0x72
-
 #define SMB1_CLIENT_GUID_SIZE          (16)
+
+#define SMBFLG_RESPONSE 0x80   /* this PDU is a response from server */
+
+#define SMBFLG2_IS_LONG_NAME   cpu_to_le16(0x40)
+#define SMBFLG2_EXT_SEC                cpu_to_le16(0x800)
+#define SMBFLG2_ERR_STATUS     cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE                cpu_to_le16(0x8000)
+
 struct smb_hdr {
        __be32 smb_buf_length;
        __u8 Protocol[4];
@@ -199,28 +206,7 @@ struct smb_negotiate_req {
 struct smb_negotiate_rsp {
        struct smb_hdr hdr;     /* wct = 17 */
        __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
-       __u8 SecurityMode;
-       __le16 MaxMpxCount;
-       __le16 MaxNumberVcs;
-       __le32 MaxBufferSize;
-       __le32 MaxRawSize;
-       __le32 SessionKey;
-       __le32 Capabilities;    /* see below */
-       __le32 SystemTimeLow;
-       __le32 SystemTimeHigh;
-       __le16 ServerTimeZone;
-       __u8 EncryptionKeyLength;
        __le16 ByteCount;
-       union {
-               unsigned char EncryptionKey[8]; /* cap extended security off */
-               /* followed by Domain name - if extended security is off */
-               /* followed by 16 bytes of server GUID */
-               /* then security blob if cap_extended_security negotiated */
-               struct {
-                       unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
-                       unsigned char SecurityBlob[1];
-               } __packed extended_response;
-       } __packed u;
 } __packed;
 
 struct filesystem_attribute_info {
@@ -441,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
 
 int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
 
-int ksmbd_init_smb_server(struct ksmbd_work *work);
+void ksmbd_init_smb_server(struct ksmbd_work *work);
 
 struct ksmbd_kstat;
 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
index 096eda9ef873b670b46e735178bccb15742c4268..c06efc020bd95475cfd83884fe79b11638c57f5a 100644 (file)
@@ -670,7 +670,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
 }
 
 static int smb_direct_read(struct ksmbd_transport *t, char *buf,
-                          unsigned int size)
+                          unsigned int size, int unused)
 {
        struct smb_direct_recvmsg *recvmsg;
        struct smb_direct_data_transfer *data_transfer;
index 603893fd87f57d632107258052df2b79407db3ae..20e85e2701f26cf38daac453a41cc5eee2c14245 100644 (file)
@@ -291,16 +291,18 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
 
 /**
  * ksmbd_tcp_readv() - read data from socket in given iovec
- * @t:         TCP transport instance
- * @iov_orig:  base IO vector
- * @nr_segs:   number of segments in base iov
- * @to_read:   number of bytes to read from socket
+ * @t:                 TCP transport instance
+ * @iov_orig:          base IO vector
+ * @nr_segs:           number of segments in base iov
+ * @to_read:           number of bytes to read from socket
+ * @max_retries:       maximum retry count
  *
  * Return:     on success return number of bytes read from socket,
  *             otherwise return error number
  */
 static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
-                          unsigned int nr_segs, unsigned int to_read)
+                          unsigned int nr_segs, unsigned int to_read,
+                          int max_retries)
 {
        int length = 0;
        int total_read;
@@ -308,7 +310,6 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
        struct msghdr ksmbd_msg;
        struct kvec *iov;
        struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
-       int max_retry = 2;
 
        iov = get_conn_iovec(t, nr_segs);
        if (!iov)
@@ -335,14 +336,23 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
                } else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
                        total_read = -EAGAIN;
                        break;
-               } else if ((length == -ERESTARTSYS || length == -EAGAIN) &&
-                          max_retry) {
+               } else if (length == -ERESTARTSYS || length == -EAGAIN) {
+                       /*
+                        * If max_retries is negative, Allow unlimited
+                        * retries to keep connection with inactive sessions.
+                        */
+                       if (max_retries == 0) {
+                               total_read = length;
+                               break;
+                       } else if (max_retries > 0) {
+                               max_retries--;
+                       }
+
                        usleep_range(1000, 2000);
                        length = 0;
-                       max_retry--;
                        continue;
                } else if (length <= 0) {
-                       total_read = -EAGAIN;
+                       total_read = length;
                        break;
                }
        }
@@ -358,14 +368,15 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
  * Return:     on success return number of bytes read from socket,
  *             otherwise return error number
  */
-static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf, unsigned int to_read)
+static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
+                         unsigned int to_read, int max_retries)
 {
        struct kvec iov;
 
        iov.iov_base = buf;
        iov.iov_len = to_read;
 
-       return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read);
+       return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
 }
 
 static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
index a0db699ddafda5a51700cd1b30635a6dd5adf4a1..9ae676906ed394409eb4ba84a4d9a9113e73aea9 100644 (file)
@@ -113,24 +113,6 @@ cp_convert:
        goto out;
 }
 
-/*
- * is_char_allowed() - check for valid character
- * @ch:                input character to be checked
- *
- * Return:     1 if char is allowed, otherwise 0
- */
-static inline int is_char_allowed(char *ch)
-{
-       /* check for control chars, wildcards etc. */
-       if (!(*ch & 0x80) &&
-           (*ch <= 0x1f ||
-            *ch == '?' || *ch == '"' || *ch == '<' ||
-            *ch == '>' || *ch == '|'))
-               return 0;
-
-       return 1;
-}
-
 /*
  * smb_from_utf16() - convert utf16le string to local charset
  * @to:                destination buffer
index 4eda519c30022f1a676869053a4ecda36b24dd53..89cf614a32715877c9bc500bffff502383db9d97 100644 (file)
@@ -174,12 +174,6 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
 }
 EXPORT_SYMBOL(dcache_dir_lseek);
 
-/* Relationship between i_mode and the DT_xxx types */
-static inline unsigned char dt_type(struct inode *inode)
-{
-       return (inode->i_mode >> 12) & 15;
-}
-
 /*
  * Directory is locked and all positive dentries in it are safe, since
  * for ramfs-type trees they can't go away without unlink() or rmdir(),
@@ -206,7 +200,8 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
 
        while ((next = scan_positives(cursor, p, 1, next)) != NULL) {
                if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
-                             d_inode(next)->i_ino, dt_type(d_inode(next))))
+                             d_inode(next)->i_ino,
+                             fs_umode_to_dtype(d_inode(next)->i_mode)))
                        break;
                ctx->pos++;
                p = &next->d_child;
index 7df6324ccb8ab33ac9e04de7cbcfb11bb4eb1413..8161667c976f8c487de84ba9fcba189ae29072d9 100644 (file)
@@ -261,7 +261,6 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
        u32 exclusive;
        int error;
        __be32 *p;
-       s32 end;
 
        memset(lock, 0, sizeof(*lock));
        locks_init_lock(fl);
@@ -285,13 +284,7 @@ static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
        fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
        p = xdr_decode_hyper(p, &l_offset);
        xdr_decode_hyper(p, &l_len);
-       end = l_offset + l_len - 1;
-
-       fl->fl_start = (loff_t)l_offset;
-       if (l_len == 0 || end < 0)
-               fl->fl_end = OFFSET_MAX;
-       else
-               fl->fl_end = (loff_t)end;
+       nlm4svc_set_file_lock_range(fl, l_offset, l_len);
        error = 0;
 out:
        return error;
index 712fdfeb8ef063bd1ad12f80c3c2ddf30f75101e..5fcbf30cd275928d1d364cf63e4f39fb61cb2a5a 100644 (file)
@@ -33,6 +33,17 @@ loff_t_to_s64(loff_t offset)
        return res;
 }
 
+void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len)
+{
+       s64 end = off + len - 1;
+
+       fl->fl_start = off;
+       if (len == 0 || end < 0)
+               fl->fl_end = OFFSET_MAX;
+       else
+               fl->fl_end = end;
+}
+
 /*
  * NLM file handles are defined by specification to be a variable-length
  * XDR opaque no longer than 1024 bytes. However, this implementation
@@ -80,7 +91,7 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
        locks_init_lock(fl);
        fl->fl_flags = FL_POSIX;
        fl->fl_type  = F_RDLCK;
-
+       nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
        return true;
 }
 
index edfedfbccaef471e9eb6fe02a20df58069d9b6dc..f04f7be589331992c794fe96296db96dbfba2e18 100644 (file)
@@ -3574,9 +3574,9 @@ static int do_open(struct nameidata *nd,
 /**
  * vfs_tmpfile - create tmpfile
  * @idmap:     idmap of the mount the inode was found from
- * @dentry:    pointer to dentry of the base directory
+ * @parentpath:        pointer to the path of the base directory
+ * @file:      file descriptor of the new tmpfile
  * @mode:      mode of the new tmpfile
- * @open_flag: flags
  *
  * Create a temporary file.
  *
index bc0f15257b49c2f00f76ba53df2af8f44c6519c0..54847db5b8195d1a698a3a0db3ad1fdb7cdf06c2 100644 (file)
@@ -2617,15 +2617,12 @@ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *
           (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) {
                char *buf = (char *)__get_free_page(GFP_KERNEL);
                char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM);
-               struct tm tm;
 
-               time64_to_tm(sb->s_time_max, 0, &tm);
-
-               pr_warn("%s filesystem being %s at %s supports timestamps until %04ld (0x%llx)\n",
+               pr_warn("%s filesystem being %s at %s supports timestamps until %ptTd (0x%llx)\n",
                        sb->s_type->name,
                        is_mounted(mnt) ? "remounted" : "mounted",
-                       mntpath,
-                       tm.tm_year+1900, (unsigned long long)sb->s_time_max);
+                       mntpath, &sb->s_time_max,
+                       (unsigned long long)sb->s_time_max);
 
                free_page((unsigned long)buf);
                sb->s_iflags |= SB_I_TS_EXPIRY_WARNED;
@@ -4183,9 +4180,9 @@ out:
        unlock_mount_hash();
 
        if (kattr->propagation) {
-               namespace_unlock();
                if (err)
                        cleanup_group_ids(mnt, NULL);
+               namespace_unlock();
        }
 
        return err;
@@ -4197,7 +4194,7 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
        int err = 0;
        struct ns_common *ns;
        struct user_namespace *mnt_userns;
-       struct file *file;
+       struct fd f;
 
        if (!((attr->attr_set | attr->attr_clr) & MOUNT_ATTR_IDMAP))
                return 0;
@@ -4213,16 +4210,16 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
        if (attr->userns_fd > INT_MAX)
                return -EINVAL;
 
-       file = fget(attr->userns_fd);
-       if (!file)
+       f = fdget(attr->userns_fd);
+       if (!f.file)
                return -EBADF;
 
-       if (!proc_ns_file(file)) {
+       if (!proc_ns_file(f.file)) {
                err = -EINVAL;
                goto out_fput;
        }
 
-       ns = get_proc_ns(file_inode(file));
+       ns = get_proc_ns(file_inode(f.file));
        if (ns->ops->type != CLONE_NEWUSER) {
                err = -EINVAL;
                goto out_fput;
@@ -4251,7 +4248,7 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
        kattr->mnt_userns = get_user_ns(mnt_userns);
 
 out_fput:
-       fput(file);
+       fdput(f);
        return err;
 }
 
index e9a45dea748a2494707e851735deeafa1b89fdd2..8a4c866874297c18bdf63ebcf878d8e5b313b586 100644 (file)
@@ -139,7 +139,7 @@ static ssize_t netfs_extract_user_to_sg(struct iov_iter *iter,
                        size_t seg = min_t(size_t, PAGE_SIZE - off, len);
 
                        *pages++ = NULL;
-                       sg_set_page(sg, page, len, off);
+                       sg_set_page(sg, page, seg, off);
                        sgtable->nents++;
                        sg++;
                        len -= seg;
index 14a72224b6571b9617d586f766e39dcb5f1772eb..c1c7ed2fd860e797b1c50430deb047931b5b0464 100644 (file)
@@ -75,7 +75,6 @@ config NFS_V3_ACL
 config NFS_V4
        tristate "NFS client support for NFS version 4"
        depends on NFS_FS
-       select SUNRPC_GSS
        select KEYS
        help
          This option enables support for version 4 of the NFS protocol
index a41c3ee4549c074fcdcbb91cbcfce463803fb78b..6fbcbb8d6587a2754b0d7283abf2a66ba4211056 100644 (file)
@@ -3089,7 +3089,6 @@ static void nfs_access_add_rbtree(struct inode *inode,
                else
                        goto found;
        }
-       set->timestamp = ktime_get_ns();
        rb_link_node(&set->rb_node, parent, p);
        rb_insert_color(&set->rb_node, root_node);
        list_add_tail(&set->lru, &nfsi->access_cache_entry_lru);
@@ -3114,6 +3113,7 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set,
        cache->fsgid = cred->fsgid;
        cache->group_info = get_group_info(cred->group_info);
        cache->mask = set->mask;
+       cache->timestamp = ktime_get_ns();
 
        /* The above field assignments must be visible
         * before this item appears on the lru.  We cannot easily
index 222a28320e1c211efd6c7898d26855931863cbab..97a76706fd542b9aa149a578a04aa8b42bbf2aad 100644 (file)
@@ -717,9 +717,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
                if ((attr->ia_valid & ATTR_KILL_SUID) != 0 &&
                    inode->i_mode & S_ISUID)
                        inode->i_mode &= ~S_ISUID;
-               if ((attr->ia_valid & ATTR_KILL_SGID) != 0 &&
-                   (inode->i_mode & (S_ISGID | S_IXGRP)) ==
-                    (S_ISGID | S_IXGRP))
+               if (setattr_should_drop_sgid(&nop_mnt_idmap, inode))
                        inode->i_mode &= ~S_ISGID;
                if ((attr->ia_valid & ATTR_MODE) != 0) {
                        int mode = attr->ia_mode & S_IALLUGO;
index 4fa37dc038b58f1038f0cdeac06823f85976e63e..b333ea119ef54986a0f166536a82c7578c160928 100644 (file)
@@ -17,7 +17,6 @@ extern int nfs3_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
 extern int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
                struct posix_acl *dfacl);
 extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
-extern const struct xattr_handler *nfs3_xattr_handlers[];
 #else
 static inline int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
                struct posix_acl *dfacl)
index 1247f544a440e41303637a252d864eeb97b990fb..349cc4f60a28da8a32169916120c9383bd434363 100644 (file)
@@ -300,12 +300,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)
index 7c5809431e61b73771ddf047f860272690c0f038..8a9be9e47f7663a8b89b93e13cc4664553fd8ae6 100644 (file)
@@ -14,9 +14,6 @@ struct nfs_subversion nfs_v3 = {
        .rpc_vers = &nfs_version3,
        .rpc_ops  = &nfs_v3_clientops,
        .sops     = &nfs_sops,
-#ifdef CONFIG_NFS_V3_ACL
-       .xattr    = nfs3_xattr_handlers,
-#endif
 };
 
 static int __init init_nfs_v3(void)
index 22a93ae46cd72058db4a44eb760d6abb2f8c9576..5607b1e2b8212b661dc56490ef61019408dd6b01 100644 (file)
@@ -1980,8 +1980,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
        if (!data->rpc_done) {
                if (data->rpc_status)
                        return ERR_PTR(data->rpc_status);
-               /* cached opens have already been processed */
-               goto update;
+               return nfs4_try_open_cached(data);
        }
 
        ret = nfs_refresh_inode(inode, &data->f_attr);
@@ -1990,7 +1989,7 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data)
 
        if (data->o_res.delegation_type != 0)
                nfs4_opendata_check_deleg(data, state);
-update:
+
        if (!update_open_stateid(state, &data->o_res.stateid,
                                NULL, data->o_arg.fmode))
                return ERR_PTR(-EAGAIN);
index c380cff4108e0693bd04580c18b2da9747f486da..e90988591df4f253f130d5d10eb4a60e5d9843da 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
@@ -337,6 +338,7 @@ int nfs_read_folio(struct file *file, struct folio *folio)
 
        trace_nfs_aop_readpage(inode, folio);
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
+       task_io_account_read(folio_size(folio));
 
        /*
         * Try to flush any pending writes to the file..
@@ -393,6 +395,7 @@ void nfs_readahead(struct readahead_control *ractl)
 
        trace_nfs_aop_readahead(inode, readahead_pos(ractl), nr_pages);
        nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
+       task_io_account_read(readahead_length(ractl));
 
        ret = -ESTALE;
        if (NFS_STALE(inode))
index 05ae23657527da80dc0c66469df936dfff92c5eb..397c096d874eb8fa0aa1849134570962090e62e1 100644 (file)
@@ -1274,9 +1274,6 @@ int nfs_get_tree_common(struct fs_context *fc)
                if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS)
                        fc->sb_flags |= SB_SYNCHRONOUS;
 
-       if (server->caps & NFS_CAP_SECURITY_LABEL)
-               fc->lsm_flags |= SECURITY_LSM_NATIVE_LABELS;
-
        /* Get a superblock - note that we may end up sharing one that already exists */
        fc->s_fs_info = server;
        s = sget_fc(fc, compare_super, nfs_set_super);
index 7c441f2bd4440c17bd1e5c59d172ff4595c8cb31..43b88eaf0673ab0bfda775646b40835d264e3748 100644 (file)
@@ -73,7 +73,7 @@ config NFSD_V4
        bool "NFS server support for NFS version 4"
        depends on NFSD && PROC_FS
        select FS_POSIX_ACL
-       select SUNRPC_GSS
+       select RPCSEC_GSS_KRB5
        select CRYPTO
        select CRYPTO_MD5
        select CRYPTO_SHA256
index 04697f8dc37d6a6d8e3e28a2f423d80619322759..01d7fd108cf3df6bd1abdd050c4a75c14b34fd3d 100644 (file)
@@ -297,6 +297,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
 
 out_free_dev:
        kfree(dev);
+       gdp->gd_device = NULL;
        return ret;
 }
 
index 2a815f5a52c4bec59f08570da6dc47701532ef57..4039ffcf90ba5879bb38583b4a11efeb729f49e6 100644 (file)
@@ -946,8 +946,8 @@ static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct r
                if (!kcred)
                        return NULL;
 
-               kcred->uid = ses->se_cb_sec.uid;
-               kcred->gid = ses->se_cb_sec.gid;
+               kcred->fsuid = ses->se_cb_sec.uid;
+               kcred->fsgid = ses->se_cb_sec.gid;
                return kcred;
        }
 }
index e12e5a4ad5023de6fefac0b958f5b9b237b8e9a2..76db2fe296244366fd146490a5d1c9767e2c4961 100644 (file)
@@ -2476,10 +2476,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
        for (i = 0; i < argp->opcnt; i++) {
                op = &argp->ops[i];
                op->replay = NULL;
+               op->opdesc = NULL;
 
                if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
                        return false;
                if (nfsd4_opnum_in_range(argp, op)) {
+                       op->opdesc = OPDESC(op);
                        op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
                        if (op->status != nfs_ok)
                                trace_nfsd_compound_decode_err(argp->rqstp,
@@ -2490,7 +2492,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
                        op->opnum = OP_ILLEGAL;
                        op->status = nfserr_op_illegal;
                }
-               op->opdesc = OPDESC(op);
+
                /*
                 * We'll try to cache the result in the DRC if any one
                 * op in the compound wants to be cached:
@@ -3444,8 +3446,7 @@ out_acl:
                p = xdr_reserve_space(xdr, 4);
                if (!p)
                        goto out_resource;
-               err = xattr_supported_namespace(d_inode(dentry),
-                                               XATTR_USER_PREFIX);
+               err = xattr_supports_user_prefix(d_inode(dentry));
                *p++ = cpu_to_be32(err == 0);
        }
 
@@ -5400,10 +5401,8 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
        __be32 *p;
 
        p = xdr_reserve_space(xdr, 8);
-       if (!p) {
-               WARN_ON_ONCE(1);
-               return;
-       }
+       if (!p)
+               goto release;
        *p++ = cpu_to_be32(op->opnum);
        post_err_offset = xdr->buf->len;
 
@@ -5418,8 +5417,6 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
        op->status = encoder(resp, op->status, &op->u);
        if (op->status)
                trace_nfsd_compound_encode_err(rqstp, op->opnum, op->status);
-       if (opdesc && opdesc->op_release)
-               opdesc->op_release(&op->u);
        xdr_commit_encode(xdr);
 
        /* nfsd4_check_resp_size guarantees enough room for error status */
@@ -5460,6 +5457,9 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
        }
 status:
        *p = op->status;
+release:
+       if (opdesc && opdesc->op_release)
+               opdesc->op_release(&op->u);
 }
 
 /* 
index 502e1b7742dbf604e8a30f502f34292fb38ed1cc..5783209f17fc522a4c211149d5e55cd6184ff594 100644 (file)
@@ -941,8 +941,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
        struct page *last_page;
 
        last_page = page + (offset + sd->len - 1) / PAGE_SIZE;
-       for (page += offset / PAGE_SIZE; page <= last_page; page++)
+       for (page += offset / PAGE_SIZE; page <= last_page; page++) {
+               /*
+                * Skip page replacement when extending the contents
+                * of the current page.
+                */
+               if (page == *(rqstp->rq_next_page - 1))
+                       continue;
                svc_rqst_replace_page(rqstp, page);
+       }
        if (rqstp->rq_res.page_len == 0)        // first call
                rqstp->rq_res.page_base = offset % PAGE_SIZE;
        rqstp->rq_res.page_len += sd->len;
index 2681a449edc162da2adee43f78e4e53dc9a2aa95..13592e82eaf68b2d92851e0218a99bd7842af9c4 100644 (file)
@@ -2219,6 +2219,7 @@ static int nilfs_btree_assign_p(struct nilfs_bmap *btree,
        /* on-disk format */
        binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
        binfo->bi_dat.bi_level = level;
+       memset(binfo->bi_dat.bi_pad, 0, sizeof(binfo->bi_dat.bi_pad));
 
        return 0;
 }
index a35f2795b2422ffefc8a22b1892a557b146b2fc6..4c85914f2abc37a7d2ccb66115072196d3f60427 100644 (file)
@@ -314,6 +314,7 @@ static int nilfs_direct_assign_p(struct nilfs_bmap *direct,
 
        binfo->bi_dat.bi_blkoff = cpu_to_le64(key);
        binfo->bi_dat.bi_level = 0;
+       memset(binfo->bi_dat.bi_pad, 0, sizeof(binfo->bi_dat.bi_pad));
 
        return 0;
 }
index 5ccc638ae92f7d2bf7cc7f3f9cad79e56dd20b2e..1dfbc0c34513fb022ff6b2c55f817cddea410dde 100644 (file)
@@ -71,7 +71,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
        if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
                return -EINVAL;
 
-       buf = (void *)__get_free_pages(GFP_NOFS, 0);
+       buf = (void *)get_zeroed_page(GFP_NOFS);
        if (unlikely(!buf))
                return -ENOMEM;
        maxmembs = PAGE_SIZE / argv->v_size;
index 19446a8243d79156940632def1d909c152d44ac2..228659612c0d76a67243755fc3512839c561e98c 100644 (file)
@@ -430,6 +430,23 @@ static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci)
        return 0;
 }
 
+/**
+ * nilfs_segctor_zeropad_segsum - zero pad the rest of the segment summary area
+ * @sci: segment constructor object
+ *
+ * nilfs_segctor_zeropad_segsum() zero-fills unallocated space at the end of
+ * the current segment summary block.
+ */
+static void nilfs_segctor_zeropad_segsum(struct nilfs_sc_info *sci)
+{
+       struct nilfs_segsum_pointer *ssp;
+
+       ssp = sci->sc_blk_cnt > 0 ? &sci->sc_binfo_ptr : &sci->sc_finfo_ptr;
+       if (ssp->offset < ssp->bh->b_size)
+               memset(ssp->bh->b_data + ssp->offset, 0,
+                      ssp->bh->b_size - ssp->offset);
+}
+
 static int nilfs_segctor_feed_segment(struct nilfs_sc_info *sci)
 {
        sci->sc_nblk_this_inc += sci->sc_curseg->sb_sum.nblocks;
@@ -438,6 +455,7 @@ static int nilfs_segctor_feed_segment(struct nilfs_sc_info *sci)
                                * The current segment is filled up
                                * (internal code)
                                */
+       nilfs_segctor_zeropad_segsum(sci);
        sci->sc_curseg = NILFS_NEXT_SEGBUF(sci->sc_curseg);
        return nilfs_segctor_reset_segment_buffer(sci);
 }
@@ -542,6 +560,7 @@ static int nilfs_segctor_add_file_block(struct nilfs_sc_info *sci,
                goto retry;
        }
        if (unlikely(required)) {
+               nilfs_segctor_zeropad_segsum(sci);
                err = nilfs_segbuf_extend_segsum(segbuf);
                if (unlikely(err))
                        goto failed;
@@ -1533,6 +1552,7 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
                nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);
                sci->sc_stage = prev_stage;
        }
+       nilfs_segctor_zeropad_segsum(sci);
        nilfs_segctor_truncate_segments(sci, sci->sc_curseg, nilfs->ns_sufile);
        return 0;
 
@@ -2609,11 +2629,10 @@ static int nilfs_segctor_thread(void *arg)
        goto loop;
 
  end_thread:
-       spin_unlock(&sci->sc_state_lock);
-
        /* end sync. */
        sci->sc_task = NULL;
        wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */
+       spin_unlock(&sci->sc_state_lock);
        return 0;
 }
 
index 1422b8ba24ed625ac9fe39b6fda522f3eb172774..77f1e5778d1c84504b14289e72ff89c52d6df9a8 100644 (file)
@@ -482,6 +482,7 @@ static void nilfs_put_super(struct super_block *sb)
                up_write(&nilfs->ns_sem);
        }
 
+       nilfs_sysfs_delete_device_group(nilfs);
        iput(nilfs->ns_sufile);
        iput(nilfs->ns_cpfile);
        iput(nilfs->ns_dat);
@@ -1105,6 +1106,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
        nilfs_put_root(fsroot);
 
  failed_unload:
+       nilfs_sysfs_delete_device_group(nilfs);
        iput(nilfs->ns_sufile);
        iput(nilfs->ns_cpfile);
        iput(nilfs->ns_dat);
index 3a4c9c150cbf575228f80ac67871ad4d1bd4efcf..2894152a6b25cf0f0183c8f20312fbb339200c59 100644 (file)
@@ -87,7 +87,6 @@ void destroy_nilfs(struct the_nilfs *nilfs)
 {
        might_sleep();
        if (nilfs_init(nilfs)) {
-               nilfs_sysfs_delete_device_group(nilfs);
                brelse(nilfs->ns_sbh[0]);
                brelse(nilfs->ns_sbh[1]);
        }
@@ -305,6 +304,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
                goto failed;
        }
 
+       err = nilfs_sysfs_create_device_group(sb);
+       if (unlikely(err))
+               goto sysfs_error;
+
        if (valid_fs)
                goto skip_recovery;
 
@@ -366,6 +369,9 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
        goto failed;
 
  failed_unload:
+       nilfs_sysfs_delete_device_group(nilfs);
+
+ sysfs_error:
        iput(nilfs->ns_cpfile);
        iput(nilfs->ns_sufile);
        iput(nilfs->ns_dat);
@@ -697,10 +703,6 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
        if (err)
                goto failed_sbh;
 
-       err = nilfs_sysfs_create_device_group(sb);
-       if (err)
-               goto failed_sbh;
-
        set_nilfs_init(nilfs);
        err = 0;
  out:
index 8f430bfad48746a39a1b428a2fed682baae49213..22fb1cf7e1fc5ba99ab232699a62b91edb676b22 100644 (file)
@@ -663,7 +663,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        struct fanotify_info *info = fanotify_event_info(event);
        unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
        unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
-       struct file *f = NULL;
+       struct file *f = NULL, *pidfd_file = NULL;
        int ret, pidfd = FAN_NOPIDFD, fd = FAN_NOFD;
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -718,7 +718,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
                    !pid_has_task(event->pid, PIDTYPE_TGID)) {
                        pidfd = FAN_NOPIDFD;
                } else {
-                       pidfd = pidfd_create(event->pid, 0);
+                       pidfd = pidfd_prepare(event->pid, 0, &pidfd_file);
                        if (pidfd < 0)
                                pidfd = FAN_EPIDFD;
                }
@@ -751,6 +751,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        if (f)
                fd_install(fd, f);
 
+       if (pidfd_file)
+               fd_install(pidfd, pidfd_file);
+
        return metadata.event_len;
 
 out_close_fd:
@@ -759,8 +762,10 @@ out_close_fd:
                fput(f);
        }
 
-       if (pidfd >= 0)
-               close_fd(pidfd);
+       if (pidfd >= 0) {
+               put_unused_fd(pidfd);
+               fput(pidfd_file);
+       }
 
        return ret;
 }
index f8df60b3b901a37d401e7df24afdc4b56f59fb27..f602a96a1afec392fa8e2b31ff8f4d9c8f532284 100644 (file)
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -235,24 +235,6 @@ bool proc_ns_file(const struct file *file)
        return file->f_op == &ns_file_operations;
 }
 
-struct file *proc_ns_fget(int fd)
-{
-       struct file *file;
-
-       file = fget(fd);
-       if (!file)
-               return ERR_PTR(-EBADF);
-
-       if (file->f_op != &ns_file_operations)
-               goto out_invalid;
-
-       return file;
-
-out_invalid:
-       fput(file);
-       return ERR_PTR(-EINVAL);
-}
-
 /**
  * ns_match() - Returns true if current namespace matches dev/ino provided.
  * @ns: current namespace
index ff64302e87e5846c6b26735f8d096df6403612ed..7324cf92493228795bf7934beb2fc6776f74d82f 100644 (file)
@@ -1033,10 +1033,6 @@ static const struct xattr_handler ntfs_other_xattr_handler = {
 };
 
 const struct xattr_handler *ntfs_xattr_handlers[] = {
-#ifdef CONFIG_NTFS3_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &ntfs_other_xattr_handler,
        NULL,
 };
index 1d65f6ef00ca8ba7a42eae4c3e87ff885201c43b..8dfc284e85f0936da24ee4e28ed46460ab7f4e55 100644 (file)
@@ -1977,11 +1977,26 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
        }
 
        if (unlikely(copied < len) && wc->w_target_page) {
+               loff_t new_isize;
+
                if (!PageUptodate(wc->w_target_page))
                        copied = 0;
 
-               ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
-                                      start+len);
+               new_isize = max_t(loff_t, i_size_read(inode), pos + copied);
+               if (new_isize > page_offset(wc->w_target_page))
+                       ocfs2_zero_new_buffers(wc->w_target_page, start+copied,
+                                              start+len);
+               else {
+                       /*
+                        * When page is fully beyond new isize (data copy
+                        * failed), do not bother zeroing the page. Invalidate
+                        * it instead so that writeback does not get confused
+                        * put page & buffer dirty bits into inconsistent
+                        * state.
+                        */
+                       block_invalidate_folio(page_folio(wc->w_target_page),
+                                               0, PAGE_SIZE);
+               }
        }
        if (wc->w_target_page)
                flush_dcache_page(wc->w_target_page);
@@ -2448,7 +2463,7 @@ static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 
        return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
                                    iter, get_block,
-                                   ocfs2_dio_end_io, NULL, 0);
+                                   ocfs2_dio_end_io, 0);
 }
 
 const struct address_space_operations ocfs2_aops = {
index 9175dbc472011ec1005863edeac6bb925fc64dee..17c52225b87d4bc4cfa1b2986120ee9ae6cc4b97 100644 (file)
@@ -242,6 +242,7 @@ static int ocfs2_mknod(struct mnt_idmap *idmap,
        int want_meta = 0;
        int xattr_credits = 0;
        struct ocfs2_security_xattr_info si = {
+               .name = NULL,
                .enable = 1,
        };
        int did_quota_inode = 0;
@@ -1805,6 +1806,7 @@ static int ocfs2_symlink(struct mnt_idmap *idmap,
        int want_clusters = 0;
        int xattr_credits = 0;
        struct ocfs2_security_xattr_info si = {
+               .name = NULL,
                .enable = 1,
        };
        int did_quota = 0, did_quota_inode = 0;
index 5a656dc683f10808becf926728e4ba155424a7f4..564ab48d03effaf6d24d0dd30531db7e5241f876 100644 (file)
@@ -2952,10 +2952,11 @@ retry:
                 */
                if (PAGE_SIZE <= OCFS2_SB(sb)->s_clustersize) {
                        if (PageDirty(page)) {
-                               /*
-                                * write_on_page will unlock the page on return
-                                */
-                               ret = write_one_page(page);
+                               unlock_page(page);
+                               put_page(page);
+
+                               ret = filemap_write_and_wait_range(mapping,
+                                               offset, map_end - 1);
                                goto retry;
                        }
                }
index 389308efe854f872648f2fafe08a9666e9e38c97..4ac77ff6e676aeeae585ea8806f488a7c964e10c 100644 (file)
@@ -89,21 +89,17 @@ static struct ocfs2_xattr_def_value_root def_xv = {
 
 const struct xattr_handler *ocfs2_xattr_handlers[] = {
        &ocfs2_xattr_user_handler,
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
        &ocfs2_xattr_trusted_handler,
        &ocfs2_xattr_security_handler,
        NULL
 };
 
 static const struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
-       [OCFS2_XATTR_INDEX_USER]        = &ocfs2_xattr_user_handler,
-       [OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]
-                                       = &posix_acl_access_xattr_handler,
-       [OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]
-                                       = &posix_acl_default_xattr_handler,
-       [OCFS2_XATTR_INDEX_TRUSTED]     = &ocfs2_xattr_trusted_handler,
-       [OCFS2_XATTR_INDEX_SECURITY]    = &ocfs2_xattr_security_handler,
+       [OCFS2_XATTR_INDEX_USER]                = &ocfs2_xattr_user_handler,
+       [OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]    = &nop_posix_acl_access,
+       [OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]   = &nop_posix_acl_default,
+       [OCFS2_XATTR_INDEX_TRUSTED]             = &ocfs2_xattr_trusted_handler,
+       [OCFS2_XATTR_INDEX_SECURITY]            = &ocfs2_xattr_security_handler,
 };
 
 struct ocfs2_xattr_info {
@@ -7259,9 +7255,21 @@ static int ocfs2_xattr_security_set(const struct xattr_handler *handler,
 static int ocfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
                     void *fs_info)
 {
+       struct ocfs2_security_xattr_info *si = fs_info;
        const struct xattr *xattr;
        int err = 0;
 
+       if (si) {
+               si->value = kmemdup(xattr_array->value, xattr_array->value_len,
+                                   GFP_KERNEL);
+               if (!si->value)
+                       return -ENOMEM;
+
+               si->name = xattr_array->name;
+               si->value_len = xattr_array->value_len;
+               return 0;
+       }
+
        for (xattr = xattr_array; xattr->name != NULL; xattr++) {
                err = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
                                      xattr->name, xattr->value,
@@ -7277,13 +7285,23 @@ int ocfs2_init_security_get(struct inode *inode,
                            const struct qstr *qstr,
                            struct ocfs2_security_xattr_info *si)
 {
+       int ret;
+
        /* check whether ocfs2 support feature xattr */
        if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))
                return -EOPNOTSUPP;
-       if (si)
-               return security_old_inode_init_security(inode, dir, qstr,
-                                                       &si->name, &si->value,
-                                                       &si->value_len);
+       if (si) {
+               ret = security_inode_init_security(inode, dir, qstr,
+                                                  &ocfs2_initxattrs, si);
+               /*
+                * security_inode_init_security() does not return -EOPNOTSUPP,
+                * we have to check the xattr ourselves.
+                */
+               if (!ret && !si->name)
+                       si->enable = 0;
+
+               return ret;
+       }
 
        return security_inode_init_security(inode, dir, qstr,
                                            &ocfs2_initxattrs, NULL);
index 4401a73d4032d856958a7164b9efa133466688a3..4478adcc4f3a0570a9c8c586fbfe8fe2c642ac12 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -1196,13 +1196,21 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
        }
 
        /*
-        * In order to ensure programs get explicit errors when trying to use
-        * O_TMPFILE on old kernels, O_TMPFILE is implemented such that it
-        * looks like (O_DIRECTORY|O_RDWR & ~O_CREAT) to old kernels. But we
-        * have to require userspace to explicitly set it.
+        * Block bugs where O_DIRECTORY | O_CREAT created regular files.
+        * Note, that blocking O_DIRECTORY | O_CREAT here also protects
+        * O_TMPFILE below which requires O_DIRECTORY being raised.
         */
+       if ((flags & (O_DIRECTORY | O_CREAT)) == (O_DIRECTORY | O_CREAT))
+               return -EINVAL;
+
+       /* Now handle the creative implementation of O_TMPFILE. */
        if (flags & __O_TMPFILE) {
-               if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
+               /*
+                * In order to ensure programs get explicit errors when trying
+                * to use O_TMPFILE on old kernels we enforce that O_DIRECTORY
+                * is raised alongside __O_TMPFILE.
+                */
+               if (!(flags & O_DIRECTORY))
                        return -EINVAL;
                if (!(acc_mode & MAY_WRITE))
                        return -EINVAL;
index 6ecad4f94ae6ef504fb54714c04afdd0a7017782..68b62689a63e248f73881dffc7861e0ff1bc9335 100644 (file)
@@ -555,8 +555,6 @@ static const struct xattr_handler orangefs_xattr_default_handler = {
 };
 
 const struct xattr_handler *orangefs_xattr_handlers[] = {
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
        &orangefs_xattr_default_handler,
        NULL
 };
index c14e90764e356565cf25561ea92793526e760c47..f658cc8ea4920487810216c0e0d94086730debff 100644 (file)
@@ -81,8 +81,7 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de
        int error = 0;
        size_t slen;
 
-       if (!(old->d_inode->i_opflags & IOP_XATTR) ||
-           !(new->d_inode->i_opflags & IOP_XATTR))
+       if (!old->d_inode->i_op->listxattr || !new->d_inode->i_op->listxattr)
                return 0;
 
        list_size = vfs_listxattr(old, NULL, 0);
index f1d9f75f8786ce51ae60723eff63dac5b59c9f7f..f97ad8b40dbbd27fd29e025371ee2b79f1866e69 100644 (file)
@@ -1055,20 +1055,12 @@ static const struct xattr_handler ovl_other_xattr_handler = {
 };
 
 static const struct xattr_handler *ovl_trusted_xattr_handlers[] = {
-#ifdef CONFIG_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &ovl_own_trusted_xattr_handler,
        &ovl_other_xattr_handler,
        NULL
 };
 
 static const struct xattr_handler *ovl_user_xattr_handlers[] = {
-#ifdef CONFIG_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &ovl_own_user_xattr_handler,
        &ovl_other_xattr_handler,
        NULL
index 468e4e65a615d770919e0d952e17d0f4f1a7c02f..3cede8b18c8b6ff385815ae51e911b6b6af81e56 100644 (file)
@@ -214,7 +214,6 @@ static struct mount *next_group(struct mount *m, struct mount *origin)
 
 /* all accesses are serialized by namespace_sem */
 static struct mount *last_dest, *first_source, *last_source, *dest_master;
-static struct mountpoint *mp;
 static struct hlist_head *list;
 
 static inline bool peers(struct mount *m1, struct mount *m2)
@@ -222,7 +221,7 @@ static inline bool peers(struct mount *m1, struct mount *m2)
        return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
 }
 
-static int propagate_one(struct mount *m)
+static int propagate_one(struct mount *m, struct mountpoint *dest_mp)
 {
        struct mount *child;
        int type;
@@ -230,7 +229,7 @@ static int propagate_one(struct mount *m)
        if (IS_MNT_NEW(m))
                return 0;
        /* skip if mountpoint isn't covered by it */
-       if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
+       if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root))
                return 0;
        if (peers(m, last_dest)) {
                type = CL_MAKE_SHARED;
@@ -262,7 +261,7 @@ static int propagate_one(struct mount *m)
        if (IS_ERR(child))
                return PTR_ERR(child);
        read_seqlock_excl(&mount_lock);
-       mnt_set_mountpoint(m, mp, child);
+       mnt_set_mountpoint(m, dest_mp, child);
        if (m->mnt_master != dest_master)
                SET_MNT_MARK(m->mnt_master);
        read_sequnlock_excl(&mount_lock);
@@ -299,13 +298,12 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
        last_dest = dest_mnt;
        first_source = source_mnt;
        last_source = source_mnt;
-       mp = dest_mp;
        list = tree_list;
        dest_master = dest_mnt->mnt_master;
 
        /* all peers of dest_mnt, except dest_mnt itself */
        for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
-               ret = propagate_one(n);
+               ret = propagate_one(n, dest_mp);
                if (ret)
                        goto out;
        }
@@ -316,7 +314,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
                /* everything in that slave group */
                n = m;
                do {
-                       ret = propagate_one(n);
+                       ret = propagate_one(n, dest_mp);
                        if (ret)
                                goto out;
                        n = next_peer(n);
index 5a76fb35923a5de9c1e362cf1d849ee5d2650106..7fa1b738bbab07cf93453bfd4e4f52d62bb09ebe 100644 (file)
@@ -957,25 +957,62 @@ set_posix_acl(struct mnt_idmap *idmap, struct dentry *dentry,
 }
 EXPORT_SYMBOL(set_posix_acl);
 
+int posix_acl_listxattr(struct inode *inode, char **buffer,
+                       ssize_t *remaining_size)
+{
+       int err;
+
+       if (!IS_POSIXACL(inode))
+               return 0;
+
+       if (inode->i_acl) {
+               err = xattr_list_one(buffer, remaining_size,
+                                    XATTR_NAME_POSIX_ACL_ACCESS);
+               if (err)
+                       return err;
+       }
+
+       if (inode->i_default_acl) {
+               err = xattr_list_one(buffer, remaining_size,
+                                    XATTR_NAME_POSIX_ACL_DEFAULT);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 static bool
 posix_acl_xattr_list(struct dentry *dentry)
 {
        return IS_POSIXACL(d_backing_inode(dentry));
 }
 
-const struct xattr_handler posix_acl_access_xattr_handler = {
+/*
+ * nop_posix_acl_access - legacy xattr handler for access POSIX ACLs
+ *
+ * This is the legacy POSIX ACL access xattr handler. It is used by some
+ * filesystems to implement their ->listxattr() inode operation. New code
+ * should never use them.
+ */
+const struct xattr_handler nop_posix_acl_access = {
        .name = XATTR_NAME_POSIX_ACL_ACCESS,
-       .flags = ACL_TYPE_ACCESS,
        .list = posix_acl_xattr_list,
 };
-EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
+EXPORT_SYMBOL_GPL(nop_posix_acl_access);
 
-const struct xattr_handler posix_acl_default_xattr_handler = {
+/*
+ * nop_posix_acl_default - legacy xattr handler for default POSIX ACLs
+ *
+ * This is the legacy POSIX ACL default xattr handler. It is used by some
+ * filesystems to implement their ->listxattr() inode operation. New code
+ * should never use them.
+ */
+const struct xattr_handler nop_posix_acl_default = {
        .name = XATTR_NAME_POSIX_ACL_DEFAULT,
-       .flags = ACL_TYPE_DEFAULT,
        .list = posix_acl_xattr_list,
 };
-EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
+EXPORT_SYMBOL_GPL(nop_posix_acl_default);
 
 int simple_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
                   struct posix_acl *acl, int type)
@@ -1094,12 +1131,10 @@ retry_deleg:
        if (error)
                goto out_inode_unlock;
 
-       if (inode->i_opflags & IOP_XATTR)
+       if (likely(!is_bad_inode(inode)))
                error = set_posix_acl(idmap, dentry, acl_type, kacl);
-       else if (unlikely(is_bad_inode(inode)))
-               error = -EIO;
        else
-               error = -EOPNOTSUPP;
+               error = -EIO;
        if (!error) {
                fsnotify_xattr(dentry);
                evm_inode_post_set_acl(dentry, acl_name, kacl);
@@ -1204,12 +1239,10 @@ retry_deleg:
        if (error)
                goto out_inode_unlock;
 
-       if (inode->i_opflags & IOP_XATTR)
+       if (likely(!is_bad_inode(inode)))
                error = set_posix_acl(idmap, dentry, acl_type, NULL);
-       else if (unlikely(is_bad_inode(inode)))
-               error = -EIO;
        else
-               error = -EOPNOTSUPP;
+               error = -EIO;
        if (!error) {
                fsnotify_xattr(dentry);
                evm_inode_post_remove_acl(idmap, dentry, acl_name);
diff --git a/fs/qnx4/README b/fs/qnx4/README
deleted file mode 100644 (file)
index 1f1e320..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-  This is a snapshot of the QNX4 filesystem for Linux.
-  Please send diffs and remarks to <al@alarsen.net> .
-  
-Credits :
-
-Richard "Scuba" A. Frowijn     <scuba@wxs.nl>
-Frank "Jedi/Sector One" Denis  <j@pureftpd.org>
-Anders Larsen                  <al@alarsen.net> (Maintainer)
diff --git a/fs/qnx6/README b/fs/qnx6/README
deleted file mode 100644 (file)
index 116d622..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-
-  This is a snapshot of the QNX6 filesystem for Linux.
-  Please send diffs and remarks to <chaosman@ontika.net> .
-
-Credits :
-
-Al Viro                <viro@ZenIV.linux.org.uk> (endless patience with me & support ;))
-Kai Bankett    <chaosman@ontika.net> (Maintainer)
index 7a2ff6157eda4aadae53f3e8b8687988b1a8413c..a21ba3be7dbe73024125c2a4d619d65185456717 100644 (file)
@@ -749,15 +749,14 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
                return -EOPNOTSUPP;
 
        while (iov_iter_count(iter)) {
-               struct iovec iovec = iov_iter_iovec(iter);
                ssize_t nr;
 
                if (type == READ) {
-                       nr = filp->f_op->read(filp, iovec.iov_base,
-                                             iovec.iov_len, ppos);
+                       nr = filp->f_op->read(filp, iter_iov_addr(iter),
+                                               iter_iov_len(iter), ppos);
                } else {
-                       nr = filp->f_op->write(filp, iovec.iov_base,
-                                              iovec.iov_len, ppos);
+                       nr = filp->f_op->write(filp, iter_iov_addr(iter),
+                                               iter_iov_len(iter), ppos);
                }
 
                if (nr < 0) {
@@ -766,7 +765,7 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
                        break;
                }
                ret += nr;
-               if (nr != iovec.iov_len)
+               if (nr != iter_iov_len(iter))
                        break;
                iov_iter_advance(iter, nr);
        }
index 467d13da198f90cef5dd6ed5b29623916ecb3042..b54cc7048f0276dd1d2ac9e12f6bc4c2bcf5a87d 100644 (file)
@@ -261,3 +261,10 @@ const struct inode_operations reiserfs_file_inode_operations = {
        .fileattr_get = reiserfs_fileattr_get,
        .fileattr_set = reiserfs_fileattr_set,
 };
+
+const struct inode_operations reiserfs_priv_file_inode_operations = {
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+       .fileattr_get = reiserfs_fileattr_get,
+       .fileattr_set = reiserfs_fileattr_set,
+};
index d54cab854f60d3401c5537a68fbd1d75aa54a93a..d8debbb6105f34e00f2b60e75c6278e92f625465 100644 (file)
@@ -2087,10 +2087,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
         * Mark it private if we're creating the privroot
         * or something under it.
         */
-       if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) {
-               inode->i_flags |= S_PRIVATE;
-               inode->i_opflags &= ~IOP_XATTR;
-       }
+       if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root)
+               reiserfs_init_priv_inode(inode);
 
        if (reiserfs_posixacl(inode->i_sb)) {
                reiserfs_write_unlock(inode->i_sb);
index 42d2c20e13455a7ad86a7d87dc5c61fdda82ab63..52240cc891cf03090d686edfeeab0d5801b19a5c 100644 (file)
@@ -378,13 +378,11 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
 
                /*
                 * Propagate the private flag so we know we're
-                * in the priv tree.  Also clear IOP_XATTR
+                * in the priv tree.  Also clear xattr support
                 * since we don't have xattrs on xattr files.
                 */
-               if (IS_PRIVATE(dir)) {
-                       inode->i_flags |= S_PRIVATE;
-                       inode->i_opflags &= ~IOP_XATTR;
-               }
+               if (IS_PRIVATE(dir))
+                       reiserfs_init_priv_inode(inode);
        }
        reiserfs_write_unlock(dir->i_sb);
        if (retval == IO_ERROR) {
@@ -1649,6 +1647,48 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
        return retval;
 }
 
+static const struct inode_operations reiserfs_priv_dir_inode_operations = {
+       .create = reiserfs_create,
+       .lookup = reiserfs_lookup,
+       .link = reiserfs_link,
+       .unlink = reiserfs_unlink,
+       .symlink = reiserfs_symlink,
+       .mkdir = reiserfs_mkdir,
+       .rmdir = reiserfs_rmdir,
+       .mknod = reiserfs_mknod,
+       .rename = reiserfs_rename,
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+       .fileattr_get = reiserfs_fileattr_get,
+       .fileattr_set = reiserfs_fileattr_set,
+};
+
+static const struct inode_operations reiserfs_priv_symlink_inode_operations = {
+       .get_link       = page_get_link,
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+};
+
+static const struct inode_operations reiserfs_priv_special_inode_operations = {
+       .setattr = reiserfs_setattr,
+       .permission = reiserfs_permission,
+};
+
+void reiserfs_init_priv_inode(struct inode *inode)
+{
+       inode->i_flags |= S_PRIVATE;
+       inode->i_opflags &= ~IOP_XATTR;
+
+       if (S_ISREG(inode->i_mode))
+               inode->i_op = &reiserfs_priv_file_inode_operations;
+       else if (S_ISDIR(inode->i_mode))
+               inode->i_op = &reiserfs_priv_dir_inode_operations;
+       else if (S_ISLNK(inode->i_mode))
+               inode->i_op = &reiserfs_priv_symlink_inode_operations;
+       else
+               inode->i_op = &reiserfs_priv_special_inode_operations;
+}
+
 /* directories can handle most operations...  */
 const struct inode_operations reiserfs_dir_inode_operations = {
        .create = reiserfs_create,
index 98e6f53c2fe0d00a78b3595ed3845b454c1f7508..1bccf6a2e908fbb2771b7cdbdba7a147bb92e351 100644 (file)
@@ -3106,6 +3106,7 @@ int reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len);
 
 /* namei.c */
+void reiserfs_init_priv_inode(struct inode *inode);
 void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
 int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
                        struct treepath *path, struct reiserfs_dir_entry *de);
@@ -3175,6 +3176,7 @@ void reiserfs_unmap_buffer(struct buffer_head *);
 
 /* file.c */
 extern const struct inode_operations reiserfs_file_inode_operations;
+extern const struct inode_operations reiserfs_priv_file_inode_operations;
 extern const struct file_operations reiserfs_file_operations;
 extern const struct address_space_operations reiserfs_address_space_operations;
 
index 06d810c72c527d04c7116e2a36db1b705a16624f..6510279671596c4f5a666145b5f7be85d2d0ddea 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/quotaops.h>
 #include <linux/security.h>
 #include <linux/posix_acl_xattr.h>
+#include <linux/xattr.h>
 
 #define PRIVROOT_NAME ".reiserfs_priv"
 #define XAROOT_NAME   "xattrs"
@@ -770,23 +771,34 @@ out:
                        (handler) != NULL;                      \
                        (handler) = *(handlers)++)
 
+static inline bool reiserfs_posix_acl_list(const char *name,
+                                          struct dentry *dentry)
+{
+       return (posix_acl_type(name) >= 0) &&
+              IS_POSIXACL(d_backing_inode(dentry));
+}
+
 /* This is the implementation for the xattr plugin infrastructure */
-static inline const struct xattr_handler *
-find_xattr_handler_prefix(const struct xattr_handler **handlers,
-                          const char *name)
+static inline bool reiserfs_xattr_list(const struct xattr_handler **handlers,
+                                      const char *name, struct dentry *dentry)
 {
-       const struct xattr_handler *xah;
+       if (handlers) {
+               const struct xattr_handler *xah = NULL;
 
-       if (!handlers)
-               return NULL;
+               for_each_xattr_handler(handlers, xah) {
+                       const char *prefix = xattr_prefix(xah);
 
-       for_each_xattr_handler(handlers, xah) {
-               const char *prefix = xattr_prefix(xah);
-               if (strncmp(prefix, name, strlen(prefix)) == 0)
-                       break;
+                       if (strncmp(prefix, name, strlen(prefix)))
+                               continue;
+
+                       if (!xattr_handler_can_list(xah, dentry))
+                               return false;
+
+                       return true;
+               }
        }
 
-       return xah;
+       return reiserfs_posix_acl_list(name, dentry);
 }
 
 struct listxattr_buf {
@@ -807,12 +819,8 @@ static bool listxattr_filler(struct dir_context *ctx, const char *name,
 
        if (name[0] != '.' ||
            (namelen != 1 && (name[1] != '.' || namelen != 2))) {
-               const struct xattr_handler *handler;
-
-               handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
-                                                   name);
-               if (!handler /* Unsupported xattr name */ ||
-                   (handler->list && !handler->list(b->dentry)))
+               if (!reiserfs_xattr_list(b->dentry->d_sb->s_xattr, name,
+                                        b->dentry))
                        return true;
                size = namelen + 1;
                if (b->buf) {
@@ -888,8 +896,7 @@ static int create_privroot(struct dentry *dentry)
                return -EOPNOTSUPP;
        }
 
-       d_inode(dentry)->i_flags |= S_PRIVATE;
-       d_inode(dentry)->i_opflags &= ~IOP_XATTR;
+       reiserfs_init_priv_inode(d_inode(dentry));
        reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
                      "storage.\n", PRIVROOT_NAME);
 
@@ -910,10 +917,6 @@ const struct xattr_handler *reiserfs_xattr_handlers[] = {
 #endif
 #ifdef CONFIG_REISERFS_FS_SECURITY
        &reiserfs_xattr_security_handler,
-#endif
-#ifdef CONFIG_REISERFS_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
 #endif
        NULL
 };
@@ -975,10 +978,8 @@ int reiserfs_lookup_privroot(struct super_block *s)
        if (!IS_ERR(dentry)) {
                REISERFS_SB(s)->priv_root = dentry;
                d_set_d_op(dentry, &xattr_lookup_poison_ops);
-               if (d_really_is_positive(dentry)) {
-                       d_inode(dentry)->i_flags |= S_PRIVATE;
-                       d_inode(dentry)->i_opflags &= ~IOP_XATTR;
-               }
+               if (d_really_is_positive(dentry))
+                       reiserfs_init_priv_inode(d_inode(dentry));
        } else
                err = PTR_ERR(dentry);
        inode_unlock(d_inode(s->s_root));
index 41c0ea84fbffcae46eef80b1580230c3dae289b2..6e0a099dd7886bd571aa4a4c56957de7a6f357ac 100644 (file)
@@ -39,6 +39,22 @@ static bool security_list(struct dentry *dentry)
        return !IS_PRIVATE(d_inode(dentry));
 }
 
+static int
+reiserfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+                   void *fs_info)
+{
+       struct reiserfs_security_handle *sec = fs_info;
+
+       sec->value = kmemdup(xattr_array->value, xattr_array->value_len,
+                            GFP_KERNEL);
+       if (!sec->value)
+               return -ENOMEM;
+
+       sec->name = xattr_array->name;
+       sec->length = xattr_array->value_len;
+       return 0;
+}
+
 /* Initializes the security context for a new inode and returns the number
  * of blocks needed for the transaction. If successful, reiserfs_security
  * must be released using reiserfs_security_free when the caller is done. */
@@ -56,12 +72,9 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
        if (IS_PRIVATE(dir))
                return 0;
 
-       error = security_old_inode_init_security(inode, dir, qstr, &sec->name,
-                                                &sec->value, &sec->length);
+       error = security_inode_init_security(inode, dir, qstr,
+                                            &reiserfs_initxattrs, sec);
        if (error) {
-               if (error == -EOPNOTSUPP)
-                       error = 0;
-
                sec->name = NULL;
                sec->value = NULL;
                sec->length = 0;
@@ -82,11 +95,15 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th,
                            struct inode *inode,
                            struct reiserfs_security_handle *sec)
 {
+       char xattr_name[XATTR_NAME_MAX + 1] = XATTR_SECURITY_PREFIX;
        int error;
-       if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
+
+       if (XATTR_SECURITY_PREFIX_LEN + strlen(sec->name) > XATTR_NAME_MAX)
                return -EINVAL;
 
-       error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
+       strlcat(xattr_name, sec->name, sizeof(xattr_name));
+
+       error = reiserfs_xattr_set_handle(th, inode, xattr_name, sec->value,
                                          sec->length, XATTR_CREATE);
        if (error == -ENODATA || error == -EOPNOTSUPP)
                error = 0;
index 2c3dec2b6dfaf18477a0734bb08e6c0b79d5dcf2..0af8d150394f6a968ba37a7c2f88afad1b2914fa 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/export.h>
 #include <linux/syscalls.h>
 #include <linux/uio.h>
+#include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/gfp.h>
 #include <linux/socket.h>
@@ -1165,6 +1166,9 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
                ret = do_splice_from(ipipe, out, &offset, len, flags);
                file_end_write(out);
 
+               if (ret > 0)
+                       fsnotify_modify(out);
+
                if (!off_out)
                        out->f_pos = offset;
                else
@@ -1188,6 +1192,10 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
                        flags |= SPLICE_F_NONBLOCK;
 
                ret = splice_file_to_pipe(in, opipe, &offset, len, flags);
+
+               if (ret > 0)
+                       fsnotify_access(in);
+
                if (!off_in)
                        in->f_pos = offset;
                else
index 84332d5cb817abbec2e206f7d25ce5db134a8fc8..04bc62ab7dfea9dde08c407fd4b5c04a7cbaedb0 100644 (file)
@@ -475,13 +475,22 @@ void generic_shutdown_super(struct super_block *sb)
 
                cgroup_writeback_umount();
 
-               /* evict all inodes with zero refcount */
+               /* Evict all inodes with zero refcount. */
                evict_inodes(sb);
-               /* only nonzero refcount inodes can have marks */
+
+               /*
+                * Clean up and evict any inodes that still have references due
+                * to fsnotify or the security policy.
+                */
                fsnotify_sb_delete(sb);
-               fscrypt_destroy_keyring(sb);
                security_sb_delete(sb);
 
+               /*
+                * Now that all potentially-encrypted inodes have been evicted,
+                * the fscrypt keyring can be destroyed.
+                */
+               fscrypt_destroy_keyring(sb);
+
                if (sb->s_dio_done_wq) {
                        destroy_workqueue(sb->s_dio_done_wq);
                        sb->s_dio_done_wq = NULL;
index 999bceb999742804f3b8cb3b5ededa5ffa724ea5..cdb3d632c63da878f83fff438267532ccebb8277 100644 (file)
@@ -28,12 +28,6 @@ const struct file_operations sysv_dir_operations = {
        .fsync          = generic_file_fsync,
 };
 
-inline void dir_put_page(struct page *page, void *page_addr)
-{
-       kunmap_local((void *)((unsigned long)page_addr & PAGE_MASK));
-       put_page(page);
-}
-
 static void dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
 {
        struct address_space *mapping = page->mapping;
@@ -58,7 +52,7 @@ static int sysv_handle_dirsync(struct inode *dir)
 }
 
 /*
- * Calls to dir_get_page()/dir_put_page() must be nested according to the
+ * Calls to dir_get_page()/put_and_unmap_page() must be nested according to the
  * rules documented in mm/highmem.rst.
  *
  * NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_page()
@@ -109,11 +103,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
                        if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
                                        fs16_to_cpu(SYSV_SB(sb), de->inode),
                                        DT_UNKNOWN)) {
-                               dir_put_page(page, kaddr);
+                               put_and_unmap_page(page, kaddr);
                                return 0;
                        }
                }
-               dir_put_page(page, kaddr);
+               put_and_unmap_page(page, kaddr);
        }
        return 0;
 }
@@ -137,7 +131,7 @@ static inline int namecompare(int len, int maxlen,
  * itself (as a parameter - res_dir). It does NOT read the inode of the
  * entry - you'll have to do that yourself if you want to.
  *
- * On Success dir_put_page() should be called on *res_page.
+ * On Success put_and_unmap_page() should be called on *res_page.
  *
  * sysv_find_entry() acts as a call to dir_get_page() and must be treated
  * accordingly for nesting purposes.
@@ -172,7 +166,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
                                                        name, de->name))
                                        goto found;
                        }
-                       dir_put_page(page, kaddr);
+                       put_and_unmap_page(page, kaddr);
                }
 
                if (++n >= npages)
@@ -215,7 +209,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
                                goto out_page;
                        de++;
                }
-               dir_put_page(page, kaddr);
+               put_and_unmap_page(page, kaddr);
        }
        BUG();
        return -EINVAL;
@@ -234,7 +228,7 @@ got_it:
        mark_inode_dirty(dir);
        err = sysv_handle_dirsync(dir);
 out_page:
-       dir_put_page(page, kaddr);
+       put_and_unmap_page(page, kaddr);
        return err;
 out_unlock:
        unlock_page(page);
@@ -327,12 +321,12 @@ int sysv_empty_dir(struct inode * inode)
                        if (de->name[1] != '.' || de->name[2])
                                goto not_empty;
                }
-               dir_put_page(page, kaddr);
+               put_and_unmap_page(page, kaddr);
        }
        return 1;
 
 not_empty:
-       dir_put_page(page, kaddr);
+       put_and_unmap_page(page, kaddr);
        return 0;
 }
 
@@ -358,7 +352,7 @@ int sysv_set_link(struct sysv_dir_entry *de, struct page *page,
 }
 
 /*
- * Calls to dir_get_page()/dir_put_page() must be nested according to the
+ * Calls to dir_get_page()/put_and_unmap_page() must be nested according to the
  * rules documented in mm/highmem.rst.
  *
  * sysv_dotdot() acts as a call to dir_get_page() and must be treated
@@ -382,7 +376,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry)
        
        if (de) {
                res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
-               dir_put_page(page, de);
+               put_and_unmap_page(page, de);
        }
        return res;
 }
index a25862773d82cf53a7bb5b02200ff2f62f34f541..2b2dba4c4f56ec3e41a0e401d94ee627d09b08b7 100644 (file)
@@ -164,7 +164,7 @@ static int sysv_unlink(struct inode * dir, struct dentry * dentry)
                inode->i_ctime = dir->i_ctime;
                inode_dec_link_count(inode);
        }
-       dir_put_page(page, de);
+       put_and_unmap_page(page, de);
        return err;
 }
 
@@ -227,7 +227,7 @@ static int sysv_rename(struct mnt_idmap *idmap, struct inode *old_dir,
                if (!new_de)
                        goto out_dir;
                err = sysv_set_link(new_de, new_page, old_inode);
-               dir_put_page(new_page, new_de);
+               put_and_unmap_page(new_page, new_de);
                if (err)
                        goto out_dir;
                new_inode->i_ctime = current_time(new_inode);
@@ -256,9 +256,9 @@ static int sysv_rename(struct mnt_idmap *idmap, struct inode *old_dir,
 
 out_dir:
        if (dir_de)
-               dir_put_page(dir_page, dir_de);
+               put_and_unmap_page(dir_page, dir_de);
 out_old:
-       dir_put_page(old_page, old_de);
+       put_and_unmap_page(old_page, old_de);
 out:
        return err;
 }
index f2c36ea42df66d050cf45e1e50a2df1eaf333dfa..e3f988b469ee98d7451a7174e158c02adad91393 100644 (file)
@@ -148,7 +148,6 @@ extern void sysv_destroy_icache(void);
 
 
 /* dir.c */
-extern void dir_put_page(struct page *page, void *vaddr);
 extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **);
 extern int sysv_add_link(struct dentry *, struct inode *);
 extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
index 391efaf1d528975256d9ac4cd3230daaaebb4702..379d75796a5ce305e2e2dcc2921153bbd6006f6b 100644 (file)
@@ -42,11 +42,10 @@ static inline int ufs_match(struct super_block *sb, int len,
        return !memcmp(name, de->d_name, len);
 }
 
-static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
+static void ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
 {
        struct address_space *mapping = page->mapping;
        struct inode *dir = mapping->host;
-       int err = 0;
 
        inode_inc_iversion(dir);
        block_write_end(NULL, mapping, pos, len, len, page, NULL);
@@ -54,10 +53,16 @@ static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
                i_size_write(dir, pos+len);
                mark_inode_dirty(dir);
        }
-       if (IS_DIRSYNC(dir))
-               err = write_one_page(page);
-       else
-               unlock_page(page);
+       unlock_page(page);
+}
+
+static int ufs_handle_dirsync(struct inode *dir)
+{
+       int err;
+
+       err = filemap_write_and_wait(dir->i_mapping);
+       if (!err)
+               err = sync_inode_metadata(dir, 1);
        return err;
 }
 
@@ -99,11 +104,12 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
        de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
        ufs_set_de_type(dir->i_sb, de, inode->i_mode);
 
-       err = ufs_commit_chunk(page, pos, len);
+       ufs_commit_chunk(page, pos, len);
        ufs_put_page(page);
        if (update_times)
                dir->i_mtime = dir->i_ctime = current_time(dir);
        mark_inode_dirty(dir);
+       ufs_handle_dirsync(dir);
 }
 
 
@@ -390,10 +396,11 @@ got_it:
        de->d_ino = cpu_to_fs32(sb, inode->i_ino);
        ufs_set_de_type(sb, de, inode->i_mode);
 
-       err = ufs_commit_chunk(page, pos, rec_len);
+       ufs_commit_chunk(page, pos, rec_len);
        dir->i_mtime = dir->i_ctime = current_time(dir);
 
        mark_inode_dirty(dir);
+       err = ufs_handle_dirsync(dir);
        /* OFFSET_CACHE */
 out_put:
        ufs_put_page(page);
@@ -531,9 +538,10 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
        if (pde)
                pde->d_reclen = cpu_to_fs16(sb, to - from);
        dir->d_ino = 0;
-       err = ufs_commit_chunk(page, pos, to - from);
+       ufs_commit_chunk(page, pos, to - from);
        inode->i_ctime = inode->i_mtime = current_time(inode);
        mark_inode_dirty(inode);
+       err = ufs_handle_dirsync(inode);
 out:
        ufs_put_page(page);
        UFSD("EXIT\n");
@@ -579,7 +587,8 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
        strcpy (de->d_name, "..");
        kunmap(page);
 
-       err = ufs_commit_chunk(page, 0, chunk_size);
+       ufs_commit_chunk(page, 0, chunk_size);
+       err = ufs_handle_dirsync(inode);
 fail:
        put_page(page);
        return err;
index 44d1ee429eb0c71d223cfe8364506dd636143d6f..40f9e1a2ebdd6d2d10a84167898af571ce2201e2 100644 (file)
@@ -1955,8 +1955,10 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
        ret = -EFAULT;
        if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api)))
                goto out;
-       /* Ignore unsupported features (userspace built against newer kernel) */
-       features = uffdio_api.features & UFFD_API_FEATURES;
+       features = uffdio_api.features;
+       ret = -EINVAL;
+       if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES))
+               goto err_out;
        ret = -EPERM;
        if ((features & UFFD_FEATURE_EVENT_FORK) && !capable(CAP_SYS_PTRACE))
                goto err_out;
index e13db6507b38b64b3c7e3acaff729831fc3daab2..7a0e3a84d370bc1d3a320762c7781fd4f752ec14 100644 (file)
@@ -8,7 +8,6 @@
 #include "fsverity_private.h"
 
 #include <linux/mount.h>
-#include <linux/pagemap.h>
 #include <linux/sched/signal.h>
 #include <linux/uaccess.h>
 
@@ -367,25 +366,27 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
                goto out_drop_write;
 
        err = enable_verity(filp, &arg);
-       if (err)
-               goto out_allow_write_access;
 
        /*
-        * Some pages of the file may have been evicted from pagecache after
-        * being used in the Merkle tree construction, then read into pagecache
-        * again by another process reading from the file concurrently.  Since
-        * these pages didn't undergo verification against the file digest which
-        * fs-verity now claims to be enforcing, we have to wipe the pagecache
-        * to ensure that all future reads are verified.
+        * We no longer drop the inode's pagecache after enabling verity.  This
+        * used to be done to try to avoid a race condition where pages could be
+        * evicted after being used in the Merkle tree construction, then
+        * re-instantiated by a concurrent read.  Such pages are unverified, and
+        * the backing storage could have filled them with different content, so
+        * they shouldn't be used to fulfill reads once verity is enabled.
+        *
+        * But, dropping the pagecache has a big performance impact, and it
+        * doesn't fully solve the race condition anyway.  So for those reasons,
+        * and also because this race condition isn't very important relatively
+        * speaking (especially for small-ish files, where the chance of a page
+        * being used, evicted, *and* re-instantiated all while enabling verity
+        * is quite small), we no longer drop the inode's pagecache.
         */
-       filemap_write_and_wait(inode->i_mapping);
-       invalidate_inode_pages2(inode->i_mapping);
 
        /*
         * allow_write_access() is needed to pair with deny_write_access().
         * Regardless, the filesystem won't allow writing to verity files.
         */
-out_allow_write_access:
        allow_write_access(filp);
 out_drop_write:
        mnt_drop_write_file(filp);
index f50e3b5b52c932eb3635a9fc146ba3aad6126270..e2508222750b35eabe154cf1d5609f95680bcc69 100644 (file)
@@ -387,15 +387,15 @@ EXPORT_SYMBOL_GPL(fsverity_enqueue_verify_work);
 int __init fsverity_init_workqueue(void)
 {
        /*
-        * Use an unbound workqueue to allow bios to be verified in parallel
-        * even when they happen to complete on the same CPU.  This sacrifices
-        * locality, but it's worthwhile since hashing is CPU-intensive.
+        * Use a high-priority workqueue to prioritize verification work, which
+        * blocks reads from completing, over regular application tasks.
         *
-        * Also use a high-priority workqueue to prioritize verification work,
-        * which blocks reads from completing, over regular application tasks.
+        * For performance reasons, don't use an unbound workqueue.  Using an
+        * unbound workqueue for crypto operations causes excessive scheduler
+        * latency on ARM64.
         */
        fsverity_read_workqueue = alloc_workqueue("fsverity_read_queue",
-                                                 WQ_UNBOUND | WQ_HIGHPRI,
+                                                 WQ_HIGHPRI,
                                                  num_online_cpus());
        if (!fsverity_read_workqueue)
                return -ENOMEM;
index 14a7eb3c8fa898ffb2a697968efb9eb70bd7bac2..fcf67d80d7f9cad3d3d8c3b6672f4100e87aed0e 100644 (file)
@@ -160,11 +160,10 @@ xattr_permission(struct mnt_idmap *idmap, struct inode *inode,
  * Look for any handler that deals with the specified namespace.
  */
 int
-xattr_supported_namespace(struct inode *inode, const char *prefix)
+xattr_supports_user_prefix(struct inode *inode)
 {
        const struct xattr_handler **handlers = inode->i_sb->s_xattr;
        const struct xattr_handler *handler;
-       size_t preflen;
 
        if (!(inode->i_opflags & IOP_XATTR)) {
                if (unlikely(is_bad_inode(inode)))
@@ -172,16 +171,15 @@ xattr_supported_namespace(struct inode *inode, const char *prefix)
                return -EOPNOTSUPP;
        }
 
-       preflen = strlen(prefix);
-
        for_each_xattr_handler(handlers, handler) {
-               if (!strncmp(xattr_prefix(handler), prefix, preflen))
+               if (!strncmp(xattr_prefix(handler), XATTR_USER_PREFIX,
+                            XATTR_USER_PREFIX_LEN))
                        return 0;
        }
 
        return -EOPNOTSUPP;
 }
-EXPORT_SYMBOL(xattr_supported_namespace);
+EXPORT_SYMBOL(xattr_supports_user_prefix);
 
 int
 __vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
@@ -460,6 +458,28 @@ nolsm:
 }
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
+/**
+ * vfs_listxattr - retrieve \0 separated list of xattr names
+ * @dentry: the dentry from whose inode the xattr names are retrieved
+ * @list: buffer to store xattr names into
+ * @size: size of the buffer
+ *
+ * This function returns the names of all xattrs associated with the
+ * inode of @dentry.
+ *
+ * Note, for legacy reasons the vfs_listxattr() function lists POSIX
+ * ACLs as well. Since POSIX ACLs are decoupled from IOP_XATTR the
+ * vfs_listxattr() function doesn't check for this flag since a
+ * filesystem could implement POSIX ACLs without implementing any other
+ * xattrs.
+ *
+ * However, since all codepaths that remove IOP_XATTR also assign of
+ * inode operations that either don't implement or implement a stub
+ * ->listxattr() operation.
+ *
+ * Return: On success, the size of the buffer that was used. On error a
+ *         negative error code.
+ */
 ssize_t
 vfs_listxattr(struct dentry *dentry, char *list, size_t size)
 {
@@ -469,7 +489,8 @@ vfs_listxattr(struct dentry *dentry, char *list, size_t size)
        error = security_inode_listxattr(dentry);
        if (error)
                return error;
-       if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
+
+       if (inode->i_op->listxattr) {
                error = inode->i_op->listxattr(dentry, list, size);
        } else {
                error = security_inode_listsecurity(inode, list, size);
@@ -949,6 +970,21 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
        return error;
 }
 
+int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
+{
+       size_t len;
+
+       len = strlen(name) + 1;
+       if (*buffer) {
+               if (*remaining_size < len)
+                       return -ERANGE;
+               memcpy(*buffer, name, len);
+               *buffer += len;
+       }
+       *remaining_size -= len;
+       return 0;
+}
+
 /*
  * Combine the results of the list() operation from every xattr_handler in the
  * list.
@@ -957,33 +993,22 @@ ssize_t
 generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 {
        const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
-       unsigned int size = 0;
-
-       if (!buffer) {
-               for_each_xattr_handler(handlers, handler) {
-                       if (!handler->name ||
-                           (handler->list && !handler->list(dentry)))
-                               continue;
-                       size += strlen(handler->name) + 1;
-               }
-       } else {
-               char *buf = buffer;
-               size_t len;
-
-               for_each_xattr_handler(handlers, handler) {
-                       if (!handler->name ||
-                           (handler->list && !handler->list(dentry)))
-                               continue;
-                       len = strlen(handler->name);
-                       if (len + 1 > buffer_size)
-                               return -ERANGE;
-                       memcpy(buf, handler->name, len + 1);
-                       buf += len + 1;
-                       buffer_size -= len + 1;
-               }
-               size = buf - buffer;
+       ssize_t remaining_size = buffer_size;
+       int err = 0;
+
+       err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size);
+       if (err)
+               return err;
+
+       for_each_xattr_handler(handlers, handler) {
+               if (!handler->name || (handler->list && !handler->list(dentry)))
+                       continue;
+               err = xattr_list_one(&buffer, &remaining_size, handler->name);
+               if (err)
+                       return err;
        }
-       return size;
+
+       return err ? err : buffer_size - remaining_size;
 }
 EXPORT_SYMBOL(generic_listxattr);
 
@@ -1245,20 +1270,6 @@ static bool xattr_is_trusted(const char *name)
        return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
-static int xattr_list_one(char **buffer, ssize_t *remaining_size,
-                         const char *name)
-{
-       size_t len = strlen(name) + 1;
-       if (*buffer) {
-               if (*remaining_size < len)
-                       return -ERANGE;
-               memcpy(*buffer, name, len);
-               *buffer += len;
-       }
-       *remaining_size -= len;
-       return 0;
-}
-
 /**
  * simple_xattr_list - list all xattr objects
  * @inode: inode from which to get the xattrs
@@ -1287,22 +1298,9 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
        ssize_t remaining_size = size;
        int err = 0;
 
-#ifdef CONFIG_FS_POSIX_ACL
-       if (IS_POSIXACL(inode)) {
-               if (inode->i_acl) {
-                       err = xattr_list_one(&buffer, &remaining_size,
-                                            XATTR_NAME_POSIX_ACL_ACCESS);
-                       if (err)
-                               return err;
-               }
-               if (inode->i_default_acl) {
-                       err = xattr_list_one(&buffer, &remaining_size,
-                                            XATTR_NAME_POSIX_ACL_DEFAULT);
-                       if (err)
-                               return err;
-               }
-       }
-#endif
+       err = posix_acl_listxattr(inode, &buffer, &remaining_size);
+       if (err)
+               return err;
 
        read_lock(&xattrs->lock);
        for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) {
index 03135a1c31b673fa435ed3853e83b166eb5e6b29..92d88dc3c9f71fad2424ddfba6692234ff57e16b 100644 (file)
@@ -63,6 +63,7 @@ xfs-y                         += xfs_aops.o \
                                   xfs_bmap_util.o \
                                   xfs_bio_io.o \
                                   xfs_buf.o \
+                                  xfs_dahash_test.o \
                                   xfs_dir2_readdir.o \
                                   xfs_discard.o \
                                   xfs_error.o \
index 6a037173d20d99e60239ad51e15c2a66822ae5df..203f16c48c19902e607b77250d41114d67205b97 100644 (file)
@@ -3045,6 +3045,8 @@ xfs_alloc_read_agf(
                pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level);
                if (xfs_agfl_needs_reset(pag->pag_mount, agf))
                        set_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
+               else
+                       clear_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate);
 
                /*
                 * Update the in-core allocbt counter. Filter out the rmapbt
@@ -3255,6 +3257,8 @@ xfs_alloc_vextent_finish(
        XFS_STATS_INC(mp, xs_allocx);
        XFS_STATS_ADD(mp, xs_allocb, args->len);
 
+       trace_xfs_alloc_vextent_finish(args);
+
 out_drop_perag:
        if (drop_perag && args->pag) {
                xfs_perag_rele(args->pag);
@@ -3279,8 +3283,14 @@ xfs_alloc_vextent_this_ag(
        xfs_agnumber_t          minimum_agno;
        int                     error;
 
+       ASSERT(args->pag != NULL);
+       ASSERT(args->pag->pag_agno == agno);
+
        args->agno = agno;
        args->agbno = 0;
+
+       trace_xfs_alloc_vextent_this_ag(args);
+
        error = xfs_alloc_vextent_check_args(args, XFS_AGB_TO_FSB(mp, agno, 0),
                        &minimum_agno);
        if (error) {
@@ -3323,11 +3333,14 @@ xfs_alloc_vextent_iterate_ags(
        uint32_t                flags)
 {
        struct xfs_mount        *mp = args->mp;
+       xfs_agnumber_t          restart_agno = minimum_agno;
        xfs_agnumber_t          agno;
        int                     error = 0;
 
+       if (flags & XFS_ALLOC_FLAG_TRYLOCK)
+               restart_agno = 0;
 restart:
-       for_each_perag_wrap_range(mp, start_agno, minimum_agno,
+       for_each_perag_wrap_range(mp, start_agno, restart_agno,
                        mp->m_sb.sb_agcount, agno, args->pag) {
                args->agno = agno;
                error = xfs_alloc_vextent_prepare_ag(args);
@@ -3366,6 +3379,7 @@ restart:
         */
        if (flags) {
                flags = 0;
+               restart_agno = minimum_agno;
                goto restart;
        }
 
@@ -3394,8 +3408,13 @@ xfs_alloc_vextent_start_ag(
        bool                    bump_rotor = false;
        int                     error;
 
+       ASSERT(args->pag == NULL);
+
        args->agno = NULLAGNUMBER;
        args->agbno = NULLAGBLOCK;
+
+       trace_xfs_alloc_vextent_start_ag(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
@@ -3442,8 +3461,13 @@ xfs_alloc_vextent_first_ag(
        xfs_agnumber_t          start_agno;
        int                     error;
 
+       ASSERT(args->pag == NULL);
+
        args->agno = NULLAGNUMBER;
        args->agbno = NULLAGBLOCK;
+
+       trace_xfs_alloc_vextent_first_ag(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
@@ -3470,8 +3494,14 @@ xfs_alloc_vextent_exact_bno(
        xfs_agnumber_t          minimum_agno;
        int                     error;
 
+       ASSERT(args->pag != NULL);
+       ASSERT(args->pag->pag_agno == XFS_FSB_TO_AGNO(mp, target));
+
        args->agno = XFS_FSB_TO_AGNO(mp, target);
        args->agbno = XFS_FSB_TO_AGBNO(mp, target);
+
+       trace_xfs_alloc_vextent_exact_bno(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
@@ -3502,8 +3532,14 @@ xfs_alloc_vextent_near_bno(
        bool                    needs_perag = args->pag == NULL;
        int                     error;
 
+       if (!needs_perag)
+               ASSERT(args->pag->pag_agno == XFS_FSB_TO_AGNO(mp, target));
+
        args->agno = XFS_FSB_TO_AGNO(mp, target);
        args->agbno = XFS_FSB_TO_AGBNO(mp, target);
+
+       trace_xfs_alloc_vextent_near_bno(args);
+
        error = xfs_alloc_vextent_check_args(args, target, &minimum_agno);
        if (error) {
                if (error == -ENOSPC)
diff --git a/fs/xfs/xfs_dahash_test.c b/fs/xfs/xfs_dahash_test.c
new file mode 100644 (file)
index 0000000..230651a
--- /dev/null
@@ -0,0 +1,662 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_dahash_test.h"
+
+/* 4096 random bytes */
+static uint8_t __initdata __attribute__((__aligned__(8))) test_buf[] =
+{
+       0x5b, 0x85, 0x21, 0xcb, 0x09, 0x68, 0x7d, 0x30,
+       0xc7, 0x69, 0xd7, 0x30, 0x92, 0xde, 0x59, 0xe4,
+       0xc9, 0x6e, 0x8b, 0xdb, 0x98, 0x6b, 0xaa, 0x60,
+       0xa8, 0xb5, 0xbc, 0x6c, 0xa9, 0xb1, 0x5b, 0x2c,
+       0xea, 0xb4, 0x92, 0x6a, 0x3f, 0x79, 0x91, 0xe4,
+       0xe9, 0x70, 0x51, 0x8c, 0x7f, 0x95, 0x6f, 0x1a,
+       0x56, 0xa1, 0x5c, 0x27, 0x03, 0x67, 0x9f, 0x3a,
+       0xe2, 0x31, 0x11, 0x29, 0x6b, 0x98, 0xfc, 0xc4,
+       0x53, 0x24, 0xc5, 0x8b, 0xce, 0x47, 0xb2, 0xb9,
+       0x32, 0xcb, 0xc1, 0xd0, 0x03, 0x57, 0x4e, 0xd4,
+       0xe9, 0x3c, 0xa1, 0x63, 0xcf, 0x12, 0x0e, 0xca,
+       0xe1, 0x13, 0xd1, 0x93, 0xa6, 0x88, 0x5c, 0x61,
+       0x5b, 0xbb, 0xf0, 0x19, 0x46, 0xb4, 0xcf, 0x9e,
+       0xb6, 0x6b, 0x4c, 0x3a, 0xcf, 0x60, 0xf9, 0x7a,
+       0x8d, 0x07, 0x63, 0xdb, 0x40, 0xe9, 0x0b, 0x6f,
+       0xad, 0x97, 0xf1, 0xed, 0xd0, 0x1e, 0x26, 0xfd,
+       0xbf, 0xb7, 0xc8, 0x04, 0x94, 0xf8, 0x8b, 0x8c,
+       0xf1, 0xab, 0x7a, 0xd4, 0xdd, 0xf3, 0xe8, 0x88,
+       0xc3, 0xed, 0x17, 0x8a, 0x9b, 0x40, 0x0d, 0x53,
+       0x62, 0x12, 0x03, 0x5f, 0x1b, 0x35, 0x32, 0x1f,
+       0xb4, 0x7b, 0x93, 0x78, 0x0d, 0xdb, 0xce, 0xa4,
+       0xc0, 0x47, 0xd5, 0xbf, 0x68, 0xe8, 0x5d, 0x74,
+       0x8f, 0x8e, 0x75, 0x1c, 0xb2, 0x4f, 0x9a, 0x60,
+       0xd1, 0xbe, 0x10, 0xf4, 0x5c, 0xa1, 0x53, 0x09,
+       0xa5, 0xe0, 0x09, 0x54, 0x85, 0x5c, 0xdc, 0x07,
+       0xe7, 0x21, 0x69, 0x7b, 0x8a, 0xfd, 0x90, 0xf1,
+       0x22, 0xd0, 0xb4, 0x36, 0x28, 0xe6, 0xb8, 0x0f,
+       0x39, 0xde, 0xc8, 0xf3, 0x86, 0x60, 0x34, 0xd2,
+       0x5e, 0xdf, 0xfd, 0xcf, 0x0f, 0xa9, 0x65, 0xf0,
+       0xd5, 0x4d, 0x96, 0x40, 0xe3, 0xdf, 0x3f, 0x95,
+       0x5a, 0x39, 0x19, 0x93, 0xf4, 0x75, 0xce, 0x22,
+       0x00, 0x1c, 0x93, 0xe2, 0x03, 0x66, 0xf4, 0x93,
+       0x73, 0x86, 0x81, 0x8e, 0x29, 0x44, 0x48, 0x86,
+       0x61, 0x7c, 0x48, 0xa3, 0x43, 0xd2, 0x9c, 0x8d,
+       0xd4, 0x95, 0xdd, 0xe1, 0x22, 0x89, 0x3a, 0x40,
+       0x4c, 0x1b, 0x8a, 0x04, 0xa8, 0x09, 0x69, 0x8b,
+       0xea, 0xc6, 0x55, 0x8e, 0x57, 0xe6, 0x64, 0x35,
+       0xf0, 0xc7, 0x16, 0x9f, 0x5d, 0x5e, 0x86, 0x40,
+       0x46, 0xbb, 0xe5, 0x45, 0x88, 0xfe, 0xc9, 0x63,
+       0x15, 0xfb, 0xf5, 0xbd, 0x71, 0x61, 0xeb, 0x7b,
+       0x78, 0x70, 0x07, 0x31, 0x03, 0x9f, 0xb2, 0xc8,
+       0xa7, 0xab, 0x47, 0xfd, 0xdf, 0xa0, 0x78, 0x72,
+       0xa4, 0x2a, 0xe4, 0xb6, 0xba, 0xc0, 0x1e, 0x86,
+       0x71, 0xe6, 0x3d, 0x18, 0x37, 0x70, 0xe6, 0xff,
+       0xe0, 0xbc, 0x0b, 0x22, 0xa0, 0x1f, 0xd3, 0xed,
+       0xa2, 0x55, 0x39, 0xab, 0xa8, 0x13, 0x73, 0x7c,
+       0x3f, 0xb2, 0xd6, 0x19, 0xac, 0xff, 0x99, 0xed,
+       0xe8, 0xe6, 0xa6, 0x22, 0xe3, 0x9c, 0xf1, 0x30,
+       0xdc, 0x01, 0x0a, 0x56, 0xfa, 0xe4, 0xc9, 0x99,
+       0xdd, 0xa8, 0xd8, 0xda, 0x35, 0x51, 0x73, 0xb4,
+       0x40, 0x86, 0x85, 0xdb, 0x5c, 0xd5, 0x85, 0x80,
+       0x14, 0x9c, 0xfd, 0x98, 0xa9, 0x82, 0xc5, 0x37,
+       0xff, 0x32, 0x5d, 0xd0, 0x0b, 0xfa, 0xdc, 0x04,
+       0x5e, 0x09, 0xd2, 0xca, 0x17, 0x4b, 0x1a, 0x8e,
+       0x15, 0xe1, 0xcc, 0x4e, 0x52, 0x88, 0x35, 0xbd,
+       0x48, 0xfe, 0x15, 0xa0, 0x91, 0xfd, 0x7e, 0x6c,
+       0x0e, 0x5d, 0x79, 0x1b, 0x81, 0x79, 0xd2, 0x09,
+       0x34, 0x70, 0x3d, 0x81, 0xec, 0xf6, 0x24, 0xbb,
+       0xfb, 0xf1, 0x7b, 0xdf, 0x54, 0xea, 0x80, 0x9b,
+       0xc7, 0x99, 0x9e, 0xbd, 0x16, 0x78, 0x12, 0x53,
+       0x5e, 0x01, 0xa7, 0x4e, 0xbd, 0x67, 0xe1, 0x9b,
+       0x4c, 0x0e, 0x61, 0x45, 0x97, 0xd2, 0xf0, 0x0f,
+       0xfe, 0x15, 0x08, 0xb7, 0x11, 0x4c, 0xe7, 0xff,
+       0x81, 0x53, 0xff, 0x91, 0x25, 0x38, 0x7e, 0x40,
+       0x94, 0xe5, 0xe0, 0xad, 0xe6, 0xd9, 0x79, 0xb6,
+       0x92, 0xc9, 0xfc, 0xde, 0xc3, 0x1a, 0x23, 0xbb,
+       0xdd, 0xc8, 0x51, 0x0c, 0x3a, 0x72, 0xfa, 0x73,
+       0x6f, 0xb7, 0xee, 0x61, 0x39, 0x03, 0x01, 0x3f,
+       0x7f, 0x94, 0x2e, 0x2e, 0xba, 0x3a, 0xbb, 0xb4,
+       0xfa, 0x6a, 0x17, 0xfe, 0xea, 0xef, 0x5e, 0x66,
+       0x97, 0x3f, 0x32, 0x3d, 0xd7, 0x3e, 0xb1, 0xf1,
+       0x6c, 0x14, 0x4c, 0xfd, 0x37, 0xd3, 0x38, 0x80,
+       0xfb, 0xde, 0xa6, 0x24, 0x1e, 0xc8, 0xca, 0x7f,
+       0x3a, 0x93, 0xd8, 0x8b, 0x18, 0x13, 0xb2, 0xe5,
+       0xe4, 0x93, 0x05, 0x53, 0x4f, 0x84, 0x66, 0xa7,
+       0x58, 0x5c, 0x7b, 0x86, 0x52, 0x6d, 0x0d, 0xce,
+       0xa4, 0x30, 0x7d, 0xb6, 0x18, 0x9f, 0xeb, 0xff,
+       0x22, 0xbb, 0x72, 0x29, 0xb9, 0x44, 0x0b, 0x48,
+       0x1e, 0x84, 0x71, 0x81, 0xe3, 0x6d, 0x73, 0x26,
+       0x92, 0xb4, 0x4d, 0x2a, 0x29, 0xb8, 0x1f, 0x72,
+       0xed, 0xd0, 0xe1, 0x64, 0x77, 0xea, 0x8e, 0x88,
+       0x0f, 0xef, 0x3f, 0xb1, 0x3b, 0xad, 0xf9, 0xc9,
+       0x8b, 0xd0, 0xac, 0xc6, 0xcc, 0xa9, 0x40, 0xcc,
+       0x76, 0xf6, 0x3b, 0x53, 0xb5, 0x88, 0xcb, 0xc8,
+       0x37, 0xf1, 0xa2, 0xba, 0x23, 0x15, 0x99, 0x09,
+       0xcc, 0xe7, 0x7a, 0x3b, 0x37, 0xf7, 0x58, 0xc8,
+       0x46, 0x8c, 0x2b, 0x2f, 0x4e, 0x0e, 0xa6, 0x5c,
+       0xea, 0x85, 0x55, 0xba, 0x02, 0x0e, 0x0e, 0x48,
+       0xbc, 0xe1, 0xb1, 0x01, 0x35, 0x79, 0x13, 0x3d,
+       0x1b, 0xc0, 0x53, 0x68, 0x11, 0xe7, 0x95, 0x0f,
+       0x9d, 0x3f, 0x4c, 0x47, 0x7b, 0x4d, 0x1c, 0xae,
+       0x50, 0x9b, 0xcb, 0xdd, 0x05, 0x8d, 0x9a, 0x97,
+       0xfd, 0x8c, 0xef, 0x0c, 0x1d, 0x67, 0x73, 0xa8,
+       0x28, 0x36, 0xd5, 0xb6, 0x92, 0x33, 0x40, 0x75,
+       0x0b, 0x51, 0xc3, 0x64, 0xba, 0x1d, 0xc2, 0xcc,
+       0xee, 0x7d, 0x54, 0x0f, 0x27, 0x69, 0xa7, 0x27,
+       0x63, 0x30, 0x29, 0xd9, 0xc8, 0x84, 0xd8, 0xdf,
+       0x9f, 0x68, 0x8d, 0x04, 0xca, 0xa6, 0xc5, 0xc7,
+       0x7a, 0x5c, 0xc8, 0xd1, 0xcb, 0x4a, 0xec, 0xd0,
+       0xd8, 0x20, 0x69, 0xc5, 0x17, 0xcd, 0x78, 0xc8,
+       0x75, 0x23, 0x30, 0x69, 0xc9, 0xd4, 0xea, 0x5c,
+       0x4f, 0x6b, 0x86, 0x3f, 0x8b, 0xfe, 0xee, 0x44,
+       0xc9, 0x7c, 0xb7, 0xdd, 0x3e, 0xe5, 0xec, 0x54,
+       0x03, 0x3e, 0xaa, 0x82, 0xc6, 0xdf, 0xb2, 0x38,
+       0x0e, 0x5d, 0xb3, 0x88, 0xd9, 0xd3, 0x69, 0x5f,
+       0x8f, 0x70, 0x8a, 0x7e, 0x11, 0xd9, 0x1e, 0x7b,
+       0x38, 0xf1, 0x42, 0x1a, 0xc0, 0x35, 0xf5, 0xc7,
+       0x36, 0x85, 0xf5, 0xf7, 0xb8, 0x7e, 0xc7, 0xef,
+       0x18, 0xf1, 0x63, 0xd6, 0x7a, 0xc6, 0xc9, 0x0e,
+       0x4d, 0x69, 0x4f, 0x84, 0xef, 0x26, 0x41, 0x0c,
+       0xec, 0xc7, 0xe0, 0x7e, 0x3c, 0x67, 0x01, 0x4c,
+       0x62, 0x1a, 0x20, 0x6f, 0xee, 0x47, 0x4d, 0xc0,
+       0x99, 0x13, 0x8d, 0x91, 0x4a, 0x26, 0xd4, 0x37,
+       0x28, 0x90, 0x58, 0x75, 0x66, 0x2b, 0x0a, 0xdf,
+       0xda, 0xee, 0x92, 0x25, 0x90, 0x62, 0x39, 0x9e,
+       0x44, 0x98, 0xad, 0xc1, 0x88, 0xed, 0xe4, 0xb4,
+       0xaf, 0xf5, 0x8c, 0x9b, 0x48, 0x4d, 0x56, 0x60,
+       0x97, 0x0f, 0x61, 0x59, 0x9e, 0xa6, 0x27, 0xfe,
+       0xc1, 0x91, 0x15, 0x38, 0xb8, 0x0f, 0xae, 0x61,
+       0x7d, 0x26, 0x13, 0x5a, 0x73, 0xff, 0x1c, 0xa3,
+       0x61, 0x04, 0x58, 0x48, 0x55, 0x44, 0x11, 0xfe,
+       0x15, 0xca, 0xc3, 0xbd, 0xca, 0xc5, 0xb4, 0x40,
+       0x5d, 0x1b, 0x7f, 0x39, 0xb5, 0x9c, 0x35, 0xec,
+       0x61, 0x15, 0x32, 0x32, 0xb8, 0x4e, 0x40, 0x9f,
+       0x17, 0x1f, 0x0a, 0x4d, 0xa9, 0x91, 0xef, 0xb7,
+       0xb0, 0xeb, 0xc2, 0x83, 0x9a, 0x6c, 0xd2, 0x79,
+       0x43, 0x78, 0x5e, 0x2f, 0xe5, 0xdd, 0x1a, 0x3c,
+       0x45, 0xab, 0x29, 0x40, 0x3a, 0x37, 0x5b, 0x6f,
+       0xd7, 0xfc, 0x48, 0x64, 0x3c, 0x49, 0xfb, 0x21,
+       0xbe, 0xc3, 0xff, 0x07, 0xfb, 0x17, 0xe9, 0xc9,
+       0x0c, 0x4c, 0x5c, 0x15, 0x9e, 0x8e, 0x22, 0x30,
+       0x0a, 0xde, 0x48, 0x7f, 0xdb, 0x0d, 0xd1, 0x2b,
+       0x87, 0x38, 0x9e, 0xcc, 0x5a, 0x01, 0x16, 0xee,
+       0x75, 0x49, 0x0d, 0x30, 0x01, 0x34, 0x6a, 0xb6,
+       0x9a, 0x5a, 0x2a, 0xec, 0xbb, 0x48, 0xac, 0xd3,
+       0x77, 0x83, 0xd8, 0x08, 0x86, 0x4f, 0x48, 0x09,
+       0x29, 0x41, 0x79, 0xa1, 0x03, 0x12, 0xc4, 0xcd,
+       0x90, 0x55, 0x47, 0x66, 0x74, 0x9a, 0xcc, 0x4f,
+       0x35, 0x8c, 0xd6, 0x98, 0xef, 0xeb, 0x45, 0xb9,
+       0x9a, 0x26, 0x2f, 0x39, 0xa5, 0x70, 0x6d, 0xfc,
+       0xb4, 0x51, 0xee, 0xf4, 0x9c, 0xe7, 0x38, 0x59,
+       0xad, 0xf4, 0xbc, 0x46, 0xff, 0x46, 0x8e, 0x60,
+       0x9c, 0xa3, 0x60, 0x1d, 0xf8, 0x26, 0x72, 0xf5,
+       0x72, 0x9d, 0x68, 0x80, 0x04, 0xf6, 0x0b, 0xa1,
+       0x0a, 0xd5, 0xa7, 0x82, 0x3a, 0x3e, 0x47, 0xa8,
+       0x5a, 0xde, 0x59, 0x4f, 0x7b, 0x07, 0xb3, 0xe9,
+       0x24, 0x19, 0x3d, 0x34, 0x05, 0xec, 0xf1, 0xab,
+       0x6e, 0x64, 0x8f, 0xd3, 0xe6, 0x41, 0x86, 0x80,
+       0x70, 0xe3, 0x8d, 0x60, 0x9c, 0x34, 0x25, 0x01,
+       0x07, 0x4d, 0x19, 0x41, 0x4e, 0x3d, 0x5c, 0x7e,
+       0xa8, 0xf5, 0xcc, 0xd5, 0x7b, 0xe2, 0x7d, 0x3d,
+       0x49, 0x86, 0x7d, 0x07, 0xb7, 0x10, 0xe3, 0x35,
+       0xb8, 0x84, 0x6d, 0x76, 0xab, 0x17, 0xc6, 0x38,
+       0xb4, 0xd3, 0x28, 0x57, 0xad, 0xd3, 0x88, 0x5a,
+       0xda, 0xea, 0xc8, 0x94, 0xcc, 0x37, 0x19, 0xac,
+       0x9c, 0x9f, 0x4b, 0x00, 0x15, 0xc0, 0xc8, 0xca,
+       0x1f, 0x15, 0xaa, 0xe0, 0xdb, 0xf9, 0x2f, 0x57,
+       0x1b, 0x24, 0xc7, 0x6f, 0x76, 0x29, 0xfb, 0xed,
+       0x25, 0x0d, 0xc0, 0xfe, 0xbd, 0x5a, 0xbf, 0x20,
+       0x08, 0x51, 0x05, 0xec, 0x71, 0xa3, 0xbf, 0xef,
+       0x5e, 0x99, 0x75, 0xdb, 0x3c, 0x5f, 0x9a, 0x8c,
+       0xbb, 0x19, 0x5c, 0x0e, 0x93, 0x19, 0xf8, 0x6a,
+       0xbc, 0xf2, 0x12, 0x54, 0x2f, 0xcb, 0x28, 0x64,
+       0x88, 0xb3, 0x92, 0x0d, 0x96, 0xd1, 0xa6, 0xe4,
+       0x1f, 0xf1, 0x4d, 0xa4, 0xab, 0x1c, 0xee, 0x54,
+       0xf2, 0xad, 0x29, 0x6d, 0x32, 0x37, 0xb2, 0x16,
+       0x77, 0x5c, 0xdc, 0x2e, 0x54, 0xec, 0x75, 0x26,
+       0xc6, 0x36, 0xd9, 0x17, 0x2c, 0xf1, 0x7a, 0xdc,
+       0x4b, 0xf1, 0xe2, 0xd9, 0x95, 0xba, 0xac, 0x87,
+       0xc1, 0xf3, 0x8e, 0x58, 0x08, 0xd8, 0x87, 0x60,
+       0xc9, 0xee, 0x6a, 0xde, 0xa4, 0xd2, 0xfc, 0x0d,
+       0xe5, 0x36, 0xc4, 0x5c, 0x52, 0xb3, 0x07, 0x54,
+       0x65, 0x24, 0xc1, 0xb1, 0xd1, 0xb1, 0x53, 0x13,
+       0x31, 0x79, 0x7f, 0x05, 0x76, 0xeb, 0x37, 0x59,
+       0x15, 0x2b, 0xd1, 0x3f, 0xac, 0x08, 0x97, 0xeb,
+       0x91, 0x98, 0xdf, 0x6c, 0x09, 0x0d, 0x04, 0x9f,
+       0xdc, 0x3b, 0x0e, 0x60, 0x68, 0x47, 0x23, 0x15,
+       0x16, 0xc6, 0x0b, 0x35, 0xf8, 0x77, 0xa2, 0x78,
+       0x50, 0xd4, 0x64, 0x22, 0x33, 0xff, 0xfb, 0x93,
+       0x71, 0x46, 0x50, 0x39, 0x1b, 0x9c, 0xea, 0x4e,
+       0x8d, 0x0c, 0x37, 0xe5, 0x5c, 0x51, 0x3a, 0x31,
+       0xb2, 0x85, 0x84, 0x3f, 0x41, 0xee, 0xa2, 0xc1,
+       0xc6, 0x13, 0x3b, 0x54, 0x28, 0xd2, 0x18, 0x37,
+       0xcc, 0x46, 0x9f, 0x6a, 0x91, 0x3d, 0x5a, 0x15,
+       0x3c, 0x89, 0xa3, 0x61, 0x06, 0x7d, 0x2e, 0x78,
+       0xbe, 0x7d, 0x40, 0xba, 0x2f, 0x95, 0xb1, 0x2f,
+       0x87, 0x3b, 0x8a, 0xbe, 0x6a, 0xf4, 0xc2, 0x31,
+       0x74, 0xee, 0x91, 0xe0, 0x23, 0xaa, 0x5d, 0x7f,
+       0xdd, 0xf0, 0x44, 0x8c, 0x0b, 0x59, 0x2b, 0xfc,
+       0x48, 0x3a, 0xdf, 0x07, 0x05, 0x38, 0x6c, 0xc9,
+       0xeb, 0x18, 0x24, 0x68, 0x8d, 0x58, 0x98, 0xd3,
+       0x31, 0xa3, 0xe4, 0x70, 0x59, 0xb1, 0x21, 0xbe,
+       0x7e, 0x65, 0x7d, 0xb8, 0x04, 0xab, 0xf6, 0xe4,
+       0xd7, 0xda, 0xec, 0x09, 0x8f, 0xda, 0x6d, 0x24,
+       0x07, 0xcc, 0x29, 0x17, 0x05, 0x78, 0x1a, 0xc1,
+       0xb1, 0xce, 0xfc, 0xaa, 0x2d, 0xe7, 0xcc, 0x85,
+       0x84, 0x84, 0x03, 0x2a, 0x0c, 0x3f, 0xa9, 0xf8,
+       0xfd, 0x84, 0x53, 0x59, 0x5c, 0xf0, 0xd4, 0x09,
+       0xf0, 0xd2, 0x6c, 0x32, 0x03, 0xb0, 0xa0, 0x8c,
+       0x52, 0xeb, 0x23, 0x91, 0x88, 0x43, 0x13, 0x46,
+       0xf6, 0x1e, 0xb4, 0x1b, 0xf5, 0x8e, 0x3a, 0xb5,
+       0x3d, 0x00, 0xf6, 0xe5, 0x08, 0x3d, 0x5f, 0x39,
+       0xd3, 0x21, 0x69, 0xbc, 0x03, 0x22, 0x3a, 0xd2,
+       0x5c, 0x84, 0xf8, 0x15, 0xc4, 0x80, 0x0b, 0xbc,
+       0x29, 0x3c, 0xf3, 0x95, 0x98, 0xcd, 0x8f, 0x35,
+       0xbc, 0xa5, 0x3e, 0xfc, 0xd4, 0x13, 0x9e, 0xde,
+       0x4f, 0xce, 0x71, 0x9d, 0x09, 0xad, 0xf2, 0x80,
+       0x6b, 0x65, 0x7f, 0x03, 0x00, 0x14, 0x7c, 0x15,
+       0x85, 0x40, 0x6d, 0x70, 0xea, 0xdc, 0xb3, 0x63,
+       0x35, 0x4f, 0x4d, 0xe0, 0xd9, 0xd5, 0x3c, 0x58,
+       0x56, 0x23, 0x80, 0xe2, 0x36, 0xdd, 0x75, 0x1d,
+       0x94, 0x11, 0x41, 0x8e, 0xe0, 0x81, 0x8e, 0xcf,
+       0xe0, 0xe5, 0xf6, 0xde, 0xd1, 0xe7, 0x04, 0x12,
+       0x79, 0x92, 0x2b, 0x71, 0x2a, 0x79, 0x8b, 0x7c,
+       0x44, 0x79, 0x16, 0x30, 0x4e, 0xf4, 0xf6, 0x9b,
+       0xb7, 0x40, 0xa3, 0x5a, 0xa7, 0x69, 0x3e, 0xc1,
+       0x3a, 0x04, 0xd0, 0x88, 0xa0, 0x3b, 0xdd, 0xc6,
+       0x9e, 0x7e, 0x1e, 0x1e, 0x8f, 0x44, 0xf7, 0x73,
+       0x67, 0x1e, 0x1a, 0x78, 0xfa, 0x62, 0xf4, 0xa9,
+       0xa8, 0xc6, 0x5b, 0xb8, 0xfa, 0x06, 0x7d, 0x5e,
+       0x38, 0x1c, 0x9a, 0x39, 0xe9, 0x39, 0x98, 0x22,
+       0x0b, 0xa7, 0xac, 0x0b, 0xf3, 0xbc, 0xf1, 0xeb,
+       0x8c, 0x81, 0xe3, 0x48, 0x8a, 0xed, 0x42, 0xc2,
+       0x38, 0xcf, 0x3e, 0xda, 0xd2, 0x89, 0x8d, 0x9c,
+       0x53, 0xb5, 0x2f, 0x41, 0x01, 0x26, 0x84, 0x9c,
+       0xa3, 0x56, 0xf6, 0x49, 0xc7, 0xd4, 0x9f, 0x93,
+       0x1b, 0x96, 0x49, 0x5e, 0xad, 0xb3, 0x84, 0x1f,
+       0x3c, 0xa4, 0xe0, 0x9b, 0xd1, 0x90, 0xbc, 0x38,
+       0x6c, 0xdd, 0x95, 0x4d, 0x9d, 0xb1, 0x71, 0x57,
+       0x2d, 0x34, 0xe8, 0xb8, 0x42, 0xc7, 0x99, 0x03,
+       0xc7, 0x07, 0x30, 0x65, 0x91, 0x55, 0xd5, 0x90,
+       0x70, 0x97, 0x37, 0x68, 0xd4, 0x11, 0xf9, 0xe8,
+       0xce, 0xec, 0xdc, 0x34, 0xd5, 0xd3, 0xb7, 0xc4,
+       0xb8, 0x97, 0x05, 0x92, 0xad, 0xf8, 0xe2, 0x36,
+       0x64, 0x41, 0xc9, 0xc5, 0x41, 0x77, 0x52, 0xd7,
+       0x2c, 0xa5, 0x24, 0x2f, 0xd9, 0x34, 0x0b, 0x47,
+       0x35, 0xa7, 0x28, 0x8b, 0xc5, 0xcd, 0xe9, 0x46,
+       0xac, 0x39, 0x94, 0x3c, 0x10, 0xc6, 0x29, 0x73,
+       0x0e, 0x0e, 0x5d, 0xe0, 0x71, 0x03, 0x8a, 0x72,
+       0x0e, 0x26, 0xb0, 0x7d, 0x84, 0xed, 0x95, 0x23,
+       0x49, 0x5a, 0x45, 0x83, 0x45, 0x60, 0x11, 0x4a,
+       0x46, 0x31, 0xd4, 0xd8, 0x16, 0x54, 0x98, 0x58,
+       0xed, 0x6d, 0xcc, 0x5d, 0xd6, 0x50, 0x61, 0x9f,
+       0x9d, 0xc5, 0x3e, 0x9d, 0x32, 0x47, 0xde, 0x96,
+       0xe1, 0x5d, 0xd8, 0xf8, 0xb4, 0x69, 0x6f, 0xb9,
+       0x15, 0x90, 0x57, 0x7a, 0xf6, 0xad, 0xb0, 0x5b,
+       0xf5, 0xa6, 0x36, 0x94, 0xfd, 0x84, 0xce, 0x1c,
+       0x0f, 0x4b, 0xd0, 0xc2, 0x5b, 0x6b, 0x56, 0xef,
+       0x73, 0x93, 0x0b, 0xc3, 0xee, 0xd9, 0xcf, 0xd3,
+       0xa4, 0x22, 0x58, 0xcd, 0x50, 0x6e, 0x65, 0xf4,
+       0xe9, 0xb7, 0x71, 0xaf, 0x4b, 0xb3, 0xb6, 0x2f,
+       0x0f, 0x0e, 0x3b, 0xc9, 0x85, 0x14, 0xf5, 0x17,
+       0xe8, 0x7a, 0x3a, 0xbf, 0x5f, 0x5e, 0xf8, 0x18,
+       0x48, 0xa6, 0x72, 0xab, 0x06, 0x95, 0xe9, 0xc8,
+       0xa7, 0xf4, 0x32, 0x44, 0x04, 0x0c, 0x84, 0x98,
+       0x73, 0xe3, 0x89, 0x8d, 0x5f, 0x7e, 0x4a, 0x42,
+       0x8f, 0xc5, 0x28, 0xb1, 0x82, 0xef, 0x1c, 0x97,
+       0x31, 0x3b, 0x4d, 0xe0, 0x0e, 0x10, 0x10, 0x97,
+       0x93, 0x49, 0x78, 0x2f, 0x0d, 0x86, 0x8b, 0xa1,
+       0x53, 0xa9, 0x81, 0x20, 0x79, 0xe7, 0x07, 0x77,
+       0xb6, 0xac, 0x5e, 0xd2, 0x05, 0xcd, 0xe9, 0xdb,
+       0x8a, 0x94, 0x82, 0x8a, 0x23, 0xb9, 0x3d, 0x1c,
+       0xa9, 0x7d, 0x72, 0x4a, 0xed, 0x33, 0xa3, 0xdb,
+       0x21, 0xa7, 0x86, 0x33, 0x45, 0xa5, 0xaa, 0x56,
+       0x45, 0xb5, 0x83, 0x29, 0x40, 0x47, 0x79, 0x04,
+       0x6e, 0xb9, 0x95, 0xd0, 0x81, 0x77, 0x2d, 0x48,
+       0x1e, 0xfe, 0xc3, 0xc2, 0x1e, 0xe5, 0xf2, 0xbe,
+       0xfd, 0x3b, 0x94, 0x9f, 0xc4, 0xc4, 0x26, 0x9d,
+       0xe4, 0x66, 0x1e, 0x19, 0xee, 0x6c, 0x79, 0x97,
+       0x11, 0x31, 0x4b, 0x0d, 0x01, 0xcb, 0xde, 0xa8,
+       0xf6, 0x6d, 0x7c, 0x39, 0x46, 0x4e, 0x7e, 0x3f,
+       0x94, 0x17, 0xdf, 0xa1, 0x7d, 0xd9, 0x1c, 0x8e,
+       0xbc, 0x7d, 0x33, 0x7d, 0xe3, 0x12, 0x40, 0xca,
+       0xab, 0x37, 0x11, 0x46, 0xd4, 0xae, 0xef, 0x44,
+       0xa2, 0xb3, 0x6a, 0x66, 0x0e, 0x0c, 0x90, 0x7f,
+       0xdf, 0x5c, 0x66, 0x5f, 0xf2, 0x94, 0x9f, 0xa6,
+       0x73, 0x4f, 0xeb, 0x0d, 0xad, 0xbf, 0xc0, 0x63,
+       0x5c, 0xdc, 0x46, 0x51, 0xe8, 0x8e, 0x90, 0x19,
+       0xa8, 0xa4, 0x3c, 0x91, 0x79, 0xfa, 0x7e, 0x58,
+       0x85, 0x13, 0x55, 0xc5, 0x19, 0x82, 0x37, 0x1b,
+       0x0a, 0x02, 0x1f, 0x99, 0x6b, 0x18, 0xf1, 0x28,
+       0x08, 0xa2, 0x73, 0xb8, 0x0f, 0x2e, 0xcd, 0xbf,
+       0xf3, 0x86, 0x7f, 0xea, 0xef, 0xd0, 0xbb, 0xa6,
+       0x21, 0xdf, 0x49, 0x73, 0x51, 0xcc, 0x36, 0xd3,
+       0x3e, 0xa0, 0xf8, 0x44, 0xdf, 0xd3, 0xa6, 0xbe,
+       0x8a, 0xd4, 0x57, 0xdd, 0x72, 0x94, 0x61, 0x0f,
+       0x82, 0xd1, 0x07, 0xb8, 0x7c, 0x18, 0x83, 0xdf,
+       0x3a, 0xe5, 0x50, 0x6a, 0x82, 0x20, 0xac, 0xa9,
+       0xa8, 0xff, 0xd9, 0xf3, 0x77, 0x33, 0x5a, 0x9e,
+       0x7f, 0x6d, 0xfe, 0x5d, 0x33, 0x41, 0x42, 0xe7,
+       0x6c, 0x19, 0xe0, 0x44, 0x8a, 0x15, 0xf6, 0x70,
+       0x98, 0xb7, 0x68, 0x4d, 0xfa, 0x97, 0x39, 0xb0,
+       0x8e, 0xe8, 0x84, 0x8b, 0x75, 0x30, 0xb7, 0x7d,
+       0x92, 0x69, 0x20, 0x9c, 0x81, 0xfb, 0x4b, 0xf4,
+       0x01, 0x50, 0xeb, 0xce, 0x0c, 0x1c, 0x6c, 0xb5,
+       0x4a, 0xd7, 0x27, 0x0c, 0xce, 0xbb, 0xe5, 0x85,
+       0xf0, 0xb6, 0xee, 0xd5, 0x70, 0xdd, 0x3b, 0xfc,
+       0xd4, 0x99, 0xf1, 0x33, 0xdd, 0x8b, 0xc4, 0x2f,
+       0xae, 0xab, 0x74, 0x96, 0x32, 0xc7, 0x4c, 0x56,
+       0x3c, 0x89, 0x0f, 0x96, 0x0b, 0x42, 0xc0, 0xcb,
+       0xee, 0x0f, 0x0b, 0x8c, 0xfb, 0x7e, 0x47, 0x7b,
+       0x64, 0x48, 0xfd, 0xb2, 0x00, 0x80, 0x89, 0xa5,
+       0x13, 0x55, 0x62, 0xfc, 0x8f, 0xe2, 0x42, 0x03,
+       0xb7, 0x4e, 0x2a, 0x79, 0xb4, 0x82, 0xea, 0x23,
+       0x49, 0xda, 0xaf, 0x52, 0x63, 0x1e, 0x60, 0x03,
+       0x89, 0x06, 0x44, 0x46, 0x08, 0xc3, 0xc4, 0x87,
+       0x70, 0x2e, 0xda, 0x94, 0xad, 0x6b, 0xe0, 0xe4,
+       0xd1, 0x8a, 0x06, 0xc2, 0xa8, 0xc0, 0xa7, 0x43,
+       0x3c, 0x47, 0x52, 0x0e, 0xc3, 0x77, 0x81, 0x11,
+       0x67, 0x0e, 0xa0, 0x70, 0x04, 0x47, 0x29, 0x40,
+       0x86, 0x0d, 0x34, 0x56, 0xa7, 0xc9, 0x35, 0x59,
+       0x68, 0xdc, 0x93, 0x81, 0x70, 0xee, 0x86, 0xd9,
+       0x80, 0x06, 0x40, 0x4f, 0x1a, 0x0d, 0x40, 0x30,
+       0x0b, 0xcb, 0x96, 0x47, 0xc1, 0xb7, 0x52, 0xfd,
+       0x56, 0xe0, 0x72, 0x4b, 0xfb, 0xbd, 0x92, 0x45,
+       0x61, 0x71, 0xc2, 0x33, 0x11, 0xbf, 0x52, 0x83,
+       0x79, 0x26, 0xe0, 0x49, 0x6b, 0xb7, 0x05, 0x8b,
+       0xe8, 0x0e, 0x87, 0x31, 0xd7, 0x9d, 0x8a, 0xf5,
+       0xc0, 0x5f, 0x2e, 0x58, 0x4a, 0xdb, 0x11, 0xb3,
+       0x6c, 0x30, 0x2a, 0x46, 0x19, 0xe3, 0x27, 0x84,
+       0x1f, 0x63, 0x6e, 0xf6, 0x57, 0xc7, 0xc9, 0xd8,
+       0x5e, 0xba, 0xb3, 0x87, 0xd5, 0x83, 0x26, 0x34,
+       0x21, 0x9e, 0x65, 0xde, 0x42, 0xd3, 0xbe, 0x7b,
+       0xbc, 0x91, 0x71, 0x44, 0x4d, 0x99, 0x3b, 0x31,
+       0xe5, 0x3f, 0x11, 0x4e, 0x7f, 0x13, 0x51, 0x3b,
+       0xae, 0x79, 0xc9, 0xd3, 0x81, 0x8e, 0x25, 0x40,
+       0x10, 0xfc, 0x07, 0x1e, 0xf9, 0x7b, 0x9a, 0x4b,
+       0x6c, 0xe3, 0xb3, 0xad, 0x1a, 0x0a, 0xdd, 0x9e,
+       0x59, 0x0c, 0xa2, 0xcd, 0xae, 0x48, 0x4a, 0x38,
+       0x5b, 0x47, 0x41, 0x94, 0x65, 0x6b, 0xbb, 0xeb,
+       0x5b, 0xe3, 0xaf, 0x07, 0x5b, 0xd4, 0x4a, 0xa2,
+       0xc9, 0x5d, 0x2f, 0x64, 0x03, 0xd7, 0x3a, 0x2c,
+       0x6e, 0xce, 0x76, 0x95, 0xb4, 0xb3, 0xc0, 0xf1,
+       0xe2, 0x45, 0x73, 0x7a, 0x5c, 0xab, 0xc1, 0xfc,
+       0x02, 0x8d, 0x81, 0x29, 0xb3, 0xac, 0x07, 0xec,
+       0x40, 0x7d, 0x45, 0xd9, 0x7a, 0x59, 0xee, 0x34,
+       0xf0, 0xe9, 0xd5, 0x7b, 0x96, 0xb1, 0x3d, 0x95,
+       0xcc, 0x86, 0xb5, 0xb6, 0x04, 0x2d, 0xb5, 0x92,
+       0x7e, 0x76, 0xf4, 0x06, 0xa9, 0xa3, 0x12, 0x0f,
+       0xb1, 0xaf, 0x26, 0xba, 0x7c, 0xfc, 0x7e, 0x1c,
+       0xbc, 0x2c, 0x49, 0x97, 0x53, 0x60, 0x13, 0x0b,
+       0xa6, 0x61, 0x83, 0x89, 0x42, 0xd4, 0x17, 0x0c,
+       0x6c, 0x26, 0x52, 0xc3, 0xb3, 0xd4, 0x67, 0xf5,
+       0xe3, 0x04, 0xb7, 0xf4, 0xcb, 0x80, 0xb8, 0xcb,
+       0x77, 0x56, 0x3e, 0xaa, 0x57, 0x54, 0xee, 0xb4,
+       0x2c, 0x67, 0xcf, 0xf2, 0xdc, 0xbe, 0x55, 0xf9,
+       0x43, 0x1f, 0x6e, 0x22, 0x97, 0x67, 0x7f, 0xc4,
+       0xef, 0xb1, 0x26, 0x31, 0x1e, 0x27, 0xdf, 0x41,
+       0x80, 0x47, 0x6c, 0xe2, 0xfa, 0xa9, 0x8c, 0x2a,
+       0xf6, 0xf2, 0xab, 0xf0, 0x15, 0xda, 0x6c, 0xc8,
+       0xfe, 0xb5, 0x23, 0xde, 0xa9, 0x05, 0x3f, 0x06,
+       0x54, 0x4c, 0xcd, 0xe1, 0xab, 0xfc, 0x0e, 0x62,
+       0x33, 0x31, 0x73, 0x2c, 0x76, 0xcb, 0xb4, 0x47,
+       0x1e, 0x20, 0xad, 0xd8, 0xf2, 0x31, 0xdd, 0xc4,
+       0x8b, 0x0c, 0x77, 0xbe, 0xe1, 0x8b, 0x26, 0x00,
+       0x02, 0x58, 0xd6, 0x8d, 0xef, 0xad, 0x74, 0x67,
+       0xab, 0x3f, 0xef, 0xcb, 0x6f, 0xb0, 0xcc, 0x81,
+       0x44, 0x4c, 0xaf, 0xe9, 0x49, 0x4f, 0xdb, 0xa0,
+       0x25, 0xa4, 0xf0, 0x89, 0xf1, 0xbe, 0xd8, 0x10,
+       0xff, 0xb1, 0x3b, 0x4b, 0xfa, 0x98, 0xf5, 0x79,
+       0x6d, 0x1e, 0x69, 0x4d, 0x57, 0xb1, 0xc8, 0x19,
+       0x1b, 0xbd, 0x1e, 0x8c, 0x84, 0xb7, 0x7b, 0xe8,
+       0xd2, 0x2d, 0x09, 0x41, 0x41, 0x37, 0x3d, 0xb1,
+       0x6f, 0x26, 0x5d, 0x71, 0x16, 0x3d, 0xb7, 0x83,
+       0x27, 0x2c, 0xa7, 0xb6, 0x50, 0xbd, 0x91, 0x86,
+       0xab, 0x24, 0xa1, 0x38, 0xfd, 0xea, 0x71, 0x55,
+       0x7e, 0x9a, 0x07, 0x77, 0x4b, 0xfa, 0x61, 0x66,
+       0x20, 0x1e, 0x28, 0x95, 0x18, 0x1b, 0xa4, 0xa0,
+       0xfd, 0xc0, 0x89, 0x72, 0x43, 0xd9, 0x3b, 0x49,
+       0x5a, 0x3f, 0x9d, 0xbf, 0xdb, 0xb4, 0x46, 0xea,
+       0x42, 0x01, 0x77, 0x23, 0x68, 0x95, 0xb6, 0x24,
+       0xb3, 0xa8, 0x6c, 0x28, 0x3b, 0x11, 0x40, 0x7e,
+       0x18, 0x65, 0x6d, 0xd8, 0x24, 0x42, 0x7d, 0x88,
+       0xc0, 0x52, 0xd9, 0x05, 0xe4, 0x95, 0x90, 0x87,
+       0x8c, 0xf4, 0xd0, 0x6b, 0xb9, 0x83, 0x99, 0x34,
+       0x6d, 0xfe, 0x54, 0x40, 0x94, 0x52, 0x21, 0x4f,
+       0x14, 0x25, 0xc5, 0xd6, 0x5e, 0x95, 0xdc, 0x0a,
+       0x2b, 0x89, 0x20, 0x11, 0x84, 0x48, 0xd6, 0x3a,
+       0xcd, 0x5c, 0x24, 0xad, 0x62, 0xe3, 0xb1, 0x93,
+       0x25, 0x8d, 0xcd, 0x7e, 0xfc, 0x27, 0xa3, 0x37,
+       0xfd, 0x84, 0xfc, 0x1b, 0xb2, 0xf1, 0x27, 0x38,
+       0x5a, 0xb7, 0xfc, 0xf2, 0xfa, 0x95, 0x66, 0xd4,
+       0xfb, 0xba, 0xa7, 0xd7, 0xa3, 0x72, 0x69, 0x48,
+       0x48, 0x8c, 0xeb, 0x28, 0x89, 0xfe, 0x33, 0x65,
+       0x5a, 0x36, 0x01, 0x7e, 0x06, 0x79, 0x0a, 0x09,
+       0x3b, 0x74, 0x11, 0x9a, 0x6e, 0xbf, 0xd4, 0x9e,
+       0x58, 0x90, 0x49, 0x4f, 0x4d, 0x08, 0xd4, 0xe5,
+       0x4a, 0x09, 0x21, 0xef, 0x8b, 0xb8, 0x74, 0x3b,
+       0x91, 0xdd, 0x36, 0x85, 0x60, 0x2d, 0xfa, 0xd4,
+       0x45, 0x7b, 0x45, 0x53, 0xf5, 0x47, 0x87, 0x7e,
+       0xa6, 0x37, 0xc8, 0x78, 0x7a, 0x68, 0x9d, 0x8d,
+       0x65, 0x2c, 0x0e, 0x91, 0x5c, 0xa2, 0x60, 0xf0,
+       0x8e, 0x3f, 0xe9, 0x1a, 0xcd, 0xaa, 0xe7, 0xd5,
+       0x77, 0x18, 0xaf, 0xc9, 0xbc, 0x18, 0xea, 0x48,
+       0x1b, 0xfb, 0x22, 0x48, 0x70, 0x16, 0x29, 0x9e,
+       0x5b, 0xc1, 0x2c, 0x66, 0x23, 0xbc, 0xf0, 0x1f,
+       0xef, 0xaf, 0xe4, 0xd6, 0x04, 0x19, 0x82, 0x7a,
+       0x0b, 0xba, 0x4b, 0x46, 0xb1, 0x6a, 0x85, 0x5d,
+       0xb4, 0x73, 0xd6, 0x21, 0xa1, 0x71, 0x60, 0x14,
+       0xee, 0x0a, 0x77, 0xc4, 0x66, 0x2e, 0xf9, 0x69,
+       0x30, 0xaf, 0x41, 0x0b, 0xc8, 0x83, 0x3c, 0x53,
+       0x99, 0x19, 0x27, 0x46, 0xf7, 0x41, 0x6e, 0x56,
+       0xdc, 0x94, 0x28, 0x67, 0x4e, 0xb7, 0x25, 0x48,
+       0x8a, 0xc2, 0xe0, 0x60, 0x96, 0xcc, 0x18, 0xf4,
+       0x84, 0xdd, 0xa7, 0x5e, 0x3e, 0x05, 0x0b, 0x26,
+       0x26, 0xb2, 0x5c, 0x1f, 0x57, 0x1a, 0x04, 0x7e,
+       0x6a, 0xe3, 0x2f, 0xb4, 0x35, 0xb6, 0x38, 0x40,
+       0x40, 0xcd, 0x6f, 0x87, 0x2e, 0xef, 0xa3, 0xd7,
+       0xa9, 0xc2, 0xe8, 0x0d, 0x27, 0xdf, 0x44, 0x62,
+       0x99, 0xa0, 0xfc, 0xcf, 0x81, 0x78, 0xcb, 0xfe,
+       0xe5, 0xa0, 0x03, 0x4e, 0x6c, 0xd7, 0xf4, 0xaf,
+       0x7a, 0xbb, 0x61, 0x82, 0xfe, 0x71, 0x89, 0xb2,
+       0x22, 0x7c, 0x8e, 0x83, 0x04, 0xce, 0xf6, 0x5d,
+       0x84, 0x8f, 0x95, 0x6a, 0x7f, 0xad, 0xfd, 0x32,
+       0x9c, 0x5e, 0xe4, 0x9c, 0x89, 0x60, 0x54, 0xaa,
+       0x96, 0x72, 0xd2, 0xd7, 0x36, 0x85, 0xa9, 0x45,
+       0xd2, 0x2a, 0xa1, 0x81, 0x49, 0x6f, 0x7e, 0x04,
+       0xfa, 0xe2, 0xfe, 0x90, 0x26, 0x77, 0x5a, 0x33,
+       0xb8, 0x04, 0x9a, 0x7a, 0xe6, 0x4c, 0x4f, 0xad,
+       0x72, 0x96, 0x08, 0x28, 0x58, 0x13, 0xf8, 0xc4,
+       0x1c, 0xf0, 0xc3, 0x45, 0x95, 0x49, 0x20, 0x8c,
+       0x9f, 0x39, 0x70, 0xe1, 0x77, 0xfe, 0xd5, 0x4b,
+       0xaf, 0x86, 0xda, 0xef, 0x22, 0x06, 0x83, 0x36,
+       0x29, 0x12, 0x11, 0x40, 0xbc, 0x3b, 0x86, 0xaa,
+       0xaa, 0x65, 0x60, 0xc3, 0x80, 0xca, 0xed, 0xa9,
+       0xf3, 0xb0, 0x79, 0x96, 0xa2, 0x55, 0x27, 0x28,
+       0x55, 0x73, 0x26, 0xa5, 0x50, 0xea, 0x92, 0x4b,
+       0x3c, 0x5c, 0x82, 0x33, 0xf0, 0x01, 0x3f, 0x03,
+       0xc1, 0x08, 0x05, 0xbf, 0x98, 0xf4, 0x9b, 0x6d,
+       0xa5, 0xa8, 0xb4, 0x82, 0x0c, 0x06, 0xfa, 0xff,
+       0x2d, 0x08, 0xf3, 0x05, 0x4f, 0x57, 0x2a, 0x39,
+       0xd4, 0x83, 0x0d, 0x75, 0x51, 0xd8, 0x5b, 0x1b,
+       0xd3, 0x51, 0x5a, 0x32, 0x2a, 0x9b, 0x32, 0xb2,
+       0xf2, 0xa4, 0x96, 0x12, 0xf2, 0xae, 0x40, 0x34,
+       0x67, 0xa8, 0xf5, 0x44, 0xd5, 0x35, 0x53, 0xfe,
+       0xa3, 0x60, 0x96, 0x63, 0x0f, 0x1f, 0x6e, 0xb0,
+       0x5a, 0x42, 0xa6, 0xfc, 0x51, 0x0b, 0x60, 0x27,
+       0xbc, 0x06, 0x71, 0xed, 0x65, 0x5b, 0x23, 0x86,
+       0x4a, 0x07, 0x3b, 0x22, 0x07, 0x46, 0xe6, 0x90,
+       0x3e, 0xf3, 0x25, 0x50, 0x1b, 0x4c, 0x7f, 0x03,
+       0x08, 0xa8, 0x36, 0x6b, 0x87, 0xe5, 0xe3, 0xdb,
+       0x9a, 0x38, 0x83, 0xff, 0x9f, 0x1a, 0x9f, 0x57,
+       0xa4, 0x2a, 0xf6, 0x37, 0xbc, 0x1a, 0xff, 0xc9,
+       0x1e, 0x35, 0x0c, 0xc3, 0x7c, 0xa3, 0xb2, 0xe5,
+       0xd2, 0xc6, 0xb4, 0x57, 0x47, 0xe4, 0x32, 0x16,
+       0x6d, 0xa9, 0xae, 0x64, 0xe6, 0x2d, 0x8d, 0xc5,
+       0x8d, 0x50, 0x8e, 0xe8, 0x1a, 0x22, 0x34, 0x2a,
+       0xd9, 0xeb, 0x51, 0x90, 0x4a, 0xb1, 0x41, 0x7d,
+       0x64, 0xf9, 0xb9, 0x0d, 0xf6, 0x23, 0x33, 0xb0,
+       0x33, 0xf4, 0xf7, 0x3f, 0x27, 0x84, 0xc6, 0x0f,
+       0x54, 0xa5, 0xc0, 0x2e, 0xec, 0x0b, 0x3a, 0x48,
+       0x6e, 0x80, 0x35, 0x81, 0x43, 0x9b, 0x90, 0xb1,
+       0xd0, 0x2b, 0xea, 0x21, 0xdc, 0xda, 0x5b, 0x09,
+       0xf4, 0xcc, 0x10, 0xb4, 0xc7, 0xfe, 0x79, 0x51,
+       0xc3, 0xc5, 0xac, 0x88, 0x74, 0x84, 0x0b, 0x4b,
+       0xca, 0x79, 0x16, 0x29, 0xfb, 0x69, 0x54, 0xdf,
+       0x41, 0x7e, 0xe9, 0xc7, 0x8e, 0xea, 0xa5, 0xfe,
+       0xfc, 0x76, 0x0e, 0x90, 0xc4, 0x92, 0x38, 0xad,
+       0x7b, 0x48, 0xe6, 0x6e, 0xf7, 0x21, 0xfd, 0x4e,
+       0x93, 0x0a, 0x7b, 0x41, 0x83, 0x68, 0xfb, 0x57,
+       0x51, 0x76, 0x34, 0xa9, 0x6c, 0x00, 0xaa, 0x4f,
+       0x66, 0x65, 0x98, 0x4a, 0x4f, 0xa3, 0xa0, 0xef,
+       0x69, 0x3f, 0xe3, 0x1c, 0x92, 0x8c, 0xfd, 0xd8,
+       0xe8, 0xde, 0x7c, 0x7f, 0x3e, 0x84, 0x8e, 0x69,
+       0x3c, 0xf1, 0xf2, 0x05, 0x46, 0xdc, 0x2f, 0x9d,
+       0x5e, 0x6e, 0x4c, 0xfb, 0xb5, 0x99, 0x2a, 0x59,
+       0x63, 0xc1, 0x34, 0xbc, 0x57, 0xc0, 0x0d, 0xb9,
+       0x61, 0x25, 0xf3, 0x33, 0x23, 0x51, 0xb6, 0x0d,
+       0x07, 0xa6, 0xab, 0x94, 0x4a, 0xb7, 0x2a, 0xea,
+       0xee, 0xac, 0xa3, 0xc3, 0x04, 0x8b, 0x0e, 0x56,
+       0xfe, 0x44, 0xa7, 0x39, 0xe2, 0xed, 0xed, 0xb4,
+       0x22, 0x2b, 0xac, 0x12, 0x32, 0x28, 0x91, 0xd8,
+       0xa5, 0xab, 0xff, 0x5f, 0xe0, 0x4b, 0xda, 0x78,
+       0x17, 0xda, 0xf1, 0x01, 0x5b, 0xcd, 0xe2, 0x5f,
+       0x50, 0x45, 0x73, 0x2b, 0xe4, 0x76, 0x77, 0xf4,
+       0x64, 0x1d, 0x43, 0xfb, 0x84, 0x7a, 0xea, 0x91,
+       0xae, 0xf9, 0x9e, 0xb7, 0xb4, 0xb0, 0x91, 0x5f,
+       0x16, 0x35, 0x9a, 0x11, 0xb8, 0xc7, 0xc1, 0x8c,
+       0xc6, 0x10, 0x8d, 0x2f, 0x63, 0x4a, 0xa7, 0x57,
+       0x3a, 0x51, 0xd6, 0x32, 0x2d, 0x64, 0x72, 0xd4,
+       0x66, 0xdc, 0x10, 0xa6, 0x67, 0xd6, 0x04, 0x23,
+       0x9d, 0x0a, 0x11, 0x77, 0xdd, 0x37, 0x94, 0x17,
+       0x3c, 0xbf, 0x8b, 0x65, 0xb0, 0x2e, 0x5e, 0x66,
+       0x47, 0x64, 0xac, 0xdd, 0xf0, 0x84, 0xfd, 0x39,
+       0xfa, 0x15, 0x5d, 0xef, 0xae, 0xca, 0xc1, 0x36,
+       0xa7, 0x5c, 0xbf, 0xc7, 0x08, 0xc2, 0x66, 0x00,
+       0x74, 0x74, 0x4e, 0x27, 0x3f, 0x55, 0x8a, 0xb7,
+       0x38, 0x66, 0x83, 0x6d, 0xcf, 0x99, 0x9e, 0x60,
+       0x8f, 0xdd, 0x2e, 0x62, 0x22, 0x0e, 0xef, 0x0c,
+       0x98, 0xa7, 0x85, 0x74, 0x3b, 0x9d, 0xec, 0x9e,
+       0xa9, 0x19, 0x72, 0xa5, 0x7f, 0x2c, 0x39, 0xb7,
+       0x7d, 0xb7, 0xf1, 0x12, 0x65, 0x27, 0x4b, 0x5a,
+       0xde, 0x17, 0xfe, 0xad, 0x44, 0xf3, 0x20, 0x4d,
+       0xfd, 0xe4, 0x1f, 0xb5, 0x81, 0xb0, 0x36, 0x37,
+       0x08, 0x6f, 0xc3, 0x0c, 0xe9, 0x85, 0x98, 0x82,
+       0xa9, 0x62, 0x0c, 0xc4, 0x97, 0xc0, 0x50, 0xc8,
+       0xa7, 0x3c, 0x50, 0x9f, 0x43, 0xb9, 0xcd, 0x5e,
+       0x4d, 0xfa, 0x1c, 0x4b, 0x0b, 0xa9, 0x98, 0x85,
+       0x38, 0x92, 0xac, 0x8d, 0xe4, 0xad, 0x9b, 0x98,
+       0xab, 0xd9, 0x38, 0xac, 0x62, 0x52, 0xa3, 0x22,
+       0x63, 0x0f, 0xbf, 0x95, 0x48, 0xdf, 0x69, 0xe7,
+       0x8b, 0x33, 0xd5, 0xb2, 0xbd, 0x05, 0x49, 0x49,
+       0x9d, 0x57, 0x73, 0x19, 0x33, 0xae, 0xfa, 0x33,
+       0xf1, 0x19, 0xa8, 0x80, 0xce, 0x04, 0x9f, 0xbc,
+       0x1d, 0x65, 0x82, 0x1b, 0xe5, 0x3a, 0x51, 0xc8,
+       0x1c, 0x21, 0xe3, 0x5d, 0xf3, 0x7d, 0x9b, 0x2f,
+       0x2c, 0x1d, 0x4a, 0x7f, 0x9b, 0x68, 0x35, 0xa3,
+       0xb2, 0x50, 0xf7, 0x62, 0x79, 0xcd, 0xf4, 0x98,
+       0x4f, 0xe5, 0x63, 0x7c, 0x3e, 0x45, 0x31, 0x8c,
+       0x16, 0xa0, 0x12, 0xc8, 0x58, 0xce, 0x39, 0xa6,
+       0xbc, 0x54, 0xdb, 0xc5, 0xe0, 0xd5, 0xba, 0xbc,
+       0xb9, 0x04, 0xf4, 0x8d, 0xe8, 0x2f, 0x15, 0x9d,
+};
+
+/* 100 test cases */
+static struct dahash_test {
+       uint16_t        start;  /* random 12 bit offset in buf */
+       uint16_t        length; /* random 8 bit length of test */
+       xfs_dahash_t    dahash; /* expected dahash result */
+} test[] __initdata =
+{
+       {0x0567, 0x0097, 0x96951389},
+       {0x0869, 0x0055, 0x6455ab4f},
+       {0x0c51, 0x00be, 0x8663afde},
+       {0x044a, 0x00fc, 0x98fbe432},
+       {0x0f29, 0x0079, 0x42371997},
+       {0x08ba, 0x0052, 0x942be4f7},
+       {0x01f2, 0x0013, 0x5262687e},
+       {0x09e3, 0x00e2, 0x8ffb0908},
+       {0x007c, 0x0051, 0xb3158491},
+       {0x0854, 0x001f, 0x83bb20d9},
+       {0x031b, 0x0008, 0x98970bdf},
+       {0x0de7, 0x0027, 0xbfbf6f6c},
+       {0x0f76, 0x0005, 0x906a7105},
+       {0x092e, 0x00d0, 0x86631850},
+       {0x0233, 0x0082, 0xdbdd914e},
+       {0x04c9, 0x0075, 0x5a400a9e},
+       {0x0b66, 0x0099, 0xae128b45},
+       {0x000d, 0x00ed, 0xe61c216a},
+       {0x0a31, 0x003d, 0xf69663b9},
+       {0x00a3, 0x0052, 0x643c39ae},
+       {0x0125, 0x00d5, 0x7c310b0d},
+       {0x0105, 0x004a, 0x06a77e74},
+       {0x0858, 0x008e, 0x265bc739},
+       {0x045e, 0x0095, 0x13d6b192},
+       {0x0dab, 0x003c, 0xc4498704},
+       {0x00cd, 0x00b5, 0x802a4e2d},
+       {0x069b, 0x008c, 0x5df60f71},
+       {0x0454, 0x006c, 0x5f03d8bb},
+       {0x040e, 0x0032, 0x0ce513b5},
+       {0x0874, 0x00e2, 0x6a811fb3},
+       {0x0521, 0x00b4, 0x93296833},
+       {0x0ddc, 0x00cf, 0xf9305338},
+       {0x0a70, 0x0023, 0x239549ea},
+       {0x083e, 0x0027, 0x2d88ba97},
+       {0x0241, 0x00a7, 0xfe0b32e1},
+       {0x0dfc, 0x0096, 0x1a11e815},
+       {0x023e, 0x001e, 0xebc9a1f3},
+       {0x067e, 0x0066, 0xb1067f81},
+       {0x09ea, 0x000e, 0x46fd7247},
+       {0x036b, 0x008c, 0x1a39acdf},
+       {0x078f, 0x0030, 0x964042ab},
+       {0x085c, 0x008f, 0x1829edab},
+       {0x02ec, 0x009f, 0x6aefa72d},
+       {0x043b, 0x00ce, 0x65642ff5},
+       {0x0a32, 0x00b8, 0xbd82759e},
+       {0x0d3c, 0x0087, 0xf4d66d54},
+       {0x09ec, 0x008a, 0x06bfa1ff},
+       {0x0902, 0x0015, 0x755025d2},
+       {0x08fe, 0x000e, 0xf690ce2d},
+       {0x00fb, 0x00dc, 0xe55f1528},
+       {0x0eaa, 0x003a, 0x0fe0a8d7},
+       {0x05fb, 0x0006, 0x86281cfb},
+       {0x0dd1, 0x00a7, 0x60ab51b4},
+       {0x0005, 0x001b, 0xf51d969b},
+       {0x077c, 0x00dd, 0xc2fed268},
+       {0x0575, 0x00f5, 0x432c0b1a},
+       {0x05be, 0x0088, 0x78baa04b},
+       {0x0c89, 0x0068, 0xeda9e428},
+       {0x0f5c, 0x0068, 0xec143c76},
+       {0x06a8, 0x0009, 0xd72651ce},
+       {0x060f, 0x008e, 0x765426cd},
+       {0x07b1, 0x0047, 0x2cfcfa0c},
+       {0x04f1, 0x0041, 0x55b172f9},
+       {0x0e05, 0x00ac, 0x61efde93},
+       {0x0bf7, 0x0097, 0x05b83eee},
+       {0x04e9, 0x00f3, 0x9928223a},
+       {0x023a, 0x0005, 0xdfada9bc},
+       {0x0acb, 0x000e, 0x2217cecd},
+       {0x0148, 0x0060, 0xbc3f7405},
+       {0x0764, 0x0059, 0xcbc201b1},
+       {0x021f, 0x0059, 0x5d6b2256},
+       {0x0f1e, 0x006c, 0xdefeeb45},
+       {0x071c, 0x00b9, 0xb9b59309},
+       {0x0564, 0x0063, 0xae064271},
+       {0x0b14, 0x0044, 0xdb867d9b},
+       {0x0e5a, 0x0055, 0xff06b685},
+       {0x015e, 0x00ba, 0x1115ccbc},
+       {0x0379, 0x00e6, 0x5f4e58dd},
+       {0x013b, 0x0067, 0x4897427e},
+       {0x0e64, 0x0071, 0x7af2b7a4},
+       {0x0a11, 0x0050, 0x92105726},
+       {0x0109, 0x0055, 0xd0d000f9},
+       {0x00aa, 0x0022, 0x815d229d},
+       {0x09ac, 0x004f, 0x02f9d985},
+       {0x0e1b, 0x00ce, 0x5cf92ab4},
+       {0x08af, 0x00d8, 0x17ca72d1},
+       {0x0e33, 0x000a, 0xda2dba6b},
+       {0x0ee3, 0x006a, 0xb00048e5},
+       {0x0648, 0x001a, 0x2364b8cb},
+       {0x0315, 0x0085, 0x0596fd0d},
+       {0x0fbb, 0x003e, 0x298230ca},
+       {0x0422, 0x006a, 0x78ada4ab},
+       {0x04ba, 0x0073, 0xced1fbc2},
+       {0x007d, 0x0061, 0x4b7ff236},
+       {0x070b, 0x00d0, 0x261cf0ae},
+       {0x0c1a, 0x0035, 0x8be92ee2},
+       {0x0af8, 0x0063, 0x824dcf03},
+       {0x08f8, 0x006d, 0xd289710c},
+       {0x021b, 0x00ee, 0x6ac1c41d},
+       {0x05b5, 0x00da, 0x8e52f0e2},
+};
+
+int __init
+xfs_dahash_test(void)
+{
+       unsigned int    i;
+       unsigned int    errors = 0;
+
+       for (i = 0; i < ARRAY_SIZE(test); i++) {
+               xfs_dahash_t    hash;
+
+               hash = xfs_da_hashname(test_buf + test[i].start,
+                               test[i].length);
+               if (hash != test[i].dahash)
+                       errors++;
+       }
+
+       if (errors) {
+               printk(KERN_ERR "xfs dir/attr hash test failed %u times!",
+                               errors);
+               return -ERANGE;
+       }
+
+       return 0;
+}
diff --git a/fs/xfs/xfs_dahash_test.h b/fs/xfs/xfs_dahash_test.h
new file mode 100644 (file)
index 0000000..1a05bf4
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_DAHASH_TEST_H__
+#define __XFS_DAHASH_TEST_H__
+
+int xfs_dahash_test(void);
+
+#endif /* __XFS_DAHASH_TEST_H__ */
+
index 69dbe78141280e7f82405129da19f0549a2d6ceb..285885c308bd7db943ca58357305a52a70cdcb6f 100644 (file)
@@ -1090,9 +1090,12 @@ xfs_buffered_write_iomap_begin(
                 */
                if (xfs_has_allocsize(mp))
                        prealloc_blocks = mp->m_allocsize_blocks;
-               else
+               else if (allocfork == XFS_DATA_FORK)
                        prealloc_blocks = xfs_iomap_prealloc_size(ip, allocfork,
                                                offset, count, &icur);
+               else
+                       prealloc_blocks = xfs_iomap_prealloc_size(ip, allocfork,
+                                               offset, count, &ccur);
                if (prealloc_blocks) {
                        xfs_extlen_t    align;
                        xfs_off_t       end_offset;
index 2479b5cbd75ecf51850aa0a1c6dfb79b1def8c2b..4f814f9e12ab50a74d68612ce22c8562b86c3756 100644 (file)
@@ -41,6 +41,7 @@
 #include "xfs_attr_item.h"
 #include "xfs_xattr.h"
 #include "xfs_iunlink_item.h"
+#include "xfs_dahash_test.h"
 
 #include <linux/magic.h>
 #include <linux/fs_context.h>
@@ -2286,6 +2287,10 @@ init_xfs_fs(void)
 
        xfs_check_ondisk_structs();
 
+       error = xfs_dahash_test();
+       if (error)
+               return error;
+
        printk(KERN_INFO XFS_VERSION_STRING " with "
                         XFS_BUILD_OPTIONS " enabled\n");
 
index 7dc0fd6a6504743389d67c571d97c12086e7b497..9c0006c55fec3c869d2484106eba463c581a6fcd 100644 (file)
@@ -1883,6 +1883,13 @@ DEFINE_ALLOC_EVENT(xfs_alloc_vextent_noagbp);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_loopfailed);
 DEFINE_ALLOC_EVENT(xfs_alloc_vextent_allfailed);
 
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_this_ag);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_start_ag);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_first_ag);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_exact_bno);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_near_bno);
+DEFINE_ALLOC_EVENT(xfs_alloc_vextent_finish);
+
 TRACE_EVENT(xfs_alloc_cur_check,
        TP_PROTO(struct xfs_mount *mp, xfs_btnum_t btnum, xfs_agblock_t bno,
                 xfs_extlen_t len, xfs_extlen_t diff, bool new),
index 7b9a0ed1b11f74b7870e0e52e4ad2fafad0feaf4..43e5c219aaed568ffb5a711b4583b2cdf1723d9c 100644 (file)
@@ -179,10 +179,6 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
        &xfs_xattr_user_handler,
        &xfs_xattr_trusted_handler,
        &xfs_xattr_security_handler,
-#ifdef CONFIG_XFS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        NULL
 };
 
index 738b0e28d74b521259ae3e3eafececafbb061c93..132f01d3461f143a0e227020b4be1876aa2934f7 100644 (file)
@@ -382,14 +382,28 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
        struct zonefs_zone *z = zonefs_inode_zone(inode);
        struct block_device *bdev = inode->i_sb->s_bdev;
        unsigned int max = bdev_max_zone_append_sectors(bdev);
+       pgoff_t start, end;
        struct bio *bio;
-       ssize_t size;
+       ssize_t size = 0;
        int nr_pages;
        ssize_t ret;
 
        max = ALIGN_DOWN(max << SECTOR_SHIFT, inode->i_sb->s_blocksize);
        iov_iter_truncate(from, max);
 
+       /*
+        * If the inode block size (zone write granularity) is smaller than the
+        * page size, we may be appending data belonging to the last page of the
+        * inode straddling inode->i_size, with that page already cached due to
+        * a buffered read or readahead. So make sure to invalidate that page.
+        * This will always be a no-op for the case where the block size is
+        * equal to the page size.
+        */
+       start = iocb->ki_pos >> PAGE_SHIFT;
+       end = (iocb->ki_pos + iov_iter_count(from) - 1) >> PAGE_SHIFT;
+       if (invalidate_inode_pages2_range(inode->i_mapping, start, end))
+               return -EBUSY;
+
        nr_pages = iov_iter_npages(from, BIO_MAX_VECS);
        if (!nr_pages)
                return 0;
@@ -426,7 +440,7 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from)
                if (bio->bi_iter.bi_sector != wpsector) {
                        zonefs_warn(inode->i_sb,
                                "Corrupted write pointer %llu for zone at %llu\n",
-                               wpsector, z->z_sector);
+                               bio->bi_iter.bi_sector, z->z_sector);
                        ret = -EIO;
                }
        }
@@ -567,11 +581,21 @@ static ssize_t zonefs_file_dio_write(struct kiocb *iocb, struct iov_iter *from)
                append = sync;
        }
 
-       if (append)
+       if (append) {
                ret = zonefs_file_dio_append(iocb, from);
-       else
+       } else {
+               /*
+                * iomap_dio_rw() may return ENOTBLK if there was an issue with
+                * page invalidation. Overwrite that error code with EBUSY to
+                * be consistent with zonefs_file_dio_append() return value for
+                * similar issues.
+                */
                ret = iomap_dio_rw(iocb, from, &zonefs_write_iomap_ops,
                                   &zonefs_write_dio_ops, 0, NULL, 0);
+               if (ret == -ENOTBLK)
+                       ret = -EBUSY;
+       }
+
        if (zonefs_zone_is_seq(z) &&
            (ret > 0 || ret == -EIOCBQUEUED)) {
                if (ret > 0)
index 0584e9f6e3397917d361e99f0ba1310f73414fb8..57acb895c03812fb47c44d11fbacef9115b7dafa 100644 (file)
@@ -657,6 +657,7 @@ static inline bool acpi_quirk_skip_acpi_ac_and_battery(void)
 #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
 bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev);
 int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip);
+bool acpi_quirk_skip_gpio_event_handlers(void);
 #else
 static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
 {
@@ -668,6 +669,10 @@ acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
        *skip = false;
        return 0;
 }
+static inline bool acpi_quirk_skip_gpio_event_handlers(void)
+{
+       return false;
+}
 #endif
 
 #ifdef CONFIG_PM
index 95e4f56f97546665165c3ede9ed85f8451f40c6a..1b4f81f1ac5db3e56545cb0e6098effe7a3b3c75 100644 (file)
@@ -723,8 +723,7 @@ typedef u32 acpi_event_type;
 #define ACPI_EVENT_POWER_BUTTON         2
 #define ACPI_EVENT_SLEEP_BUTTON         3
 #define ACPI_EVENT_RTC                  4
-#define ACPI_EVENT_PCIE_WAKE            5
-#define ACPI_EVENT_MAX                  5
+#define ACPI_EVENT_MAX                  4
 #define ACPI_NUM_FIXED_EVENTS           ACPI_EVENT_MAX + 1
 
 /*
index 8ed9bec03e5341ce3669a59ce8f882b1a42cf21e..ff5a8da5d88329c8a7f62f4f9afba8b55414583e 100644 (file)
@@ -59,8 +59,6 @@ extern void acpi_video_unregister(void);
 extern void acpi_video_register_backlight(void);
 extern int acpi_video_get_edid(struct acpi_device *device, int type,
                               int device_id, void **edid);
-extern enum acpi_backlight_type acpi_video_get_backlight_type(void);
-extern bool acpi_video_backlight_use_native(void);
 /*
  * Note: The value returned by acpi_video_handles_brightness_key_presses()
  * may change over time and should not be cached.
@@ -69,6 +67,19 @@ extern bool acpi_video_handles_brightness_key_presses(void);
 extern int acpi_video_get_levels(struct acpi_device *device,
                                 struct acpi_video_device_brightness **dev_br,
                                 int *pmax_level);
+
+extern enum acpi_backlight_type __acpi_video_get_backlight_type(bool native,
+                                                               bool *auto_detect);
+
+static inline enum acpi_backlight_type acpi_video_get_backlight_type(void)
+{
+       return __acpi_video_get_backlight_type(false, NULL);
+}
+
+static inline bool acpi_video_backlight_use_native(void)
+{
+       return __acpi_video_get_backlight_type(true, NULL) == acpi_backlight_native;
+}
 #else
 static inline void acpi_video_report_nolcd(void) { return; };
 static inline int acpi_video_register(void) { return -ENODEV; }
index 04b8be9f1a77ceb93375a26b6079bb122bea1877..e271d6708c876bd94d96b4bcc369f793c2e0b370 100644 (file)
@@ -130,7 +130,7 @@ ATOMIC_OP(xor, ^)
 #define arch_atomic_read(v)                    READ_ONCE((v)->counter)
 #define arch_atomic_set(v, i)                  WRITE_ONCE(((v)->counter), (i))
 
-#define arch_atomic_xchg(ptr, v)               (arch_xchg(&(ptr)->counter, (v)))
-#define arch_atomic_cmpxchg(v, old, new)       (arch_cmpxchg(&((v)->counter), (old), (new)))
+#define arch_atomic_xchg(ptr, v)               (arch_xchg(&(ptr)->counter, (u32)(v)))
+#define arch_atomic_cmpxchg(v, old, new)       (arch_cmpxchg(&((v)->counter), (u32)(old), (u32)(new)))
 
 #endif /* __ASM_GENERIC_ATOMIC_H */
index c3e7315b7c1d660ff02ce230d47287291f0e6787..3df9f59a544e48bdd375cf119f05fa13122ed747 100644 (file)
@@ -26,16 +26,16 @@ static inline unsigned long __generic_cmpxchg_local(volatile void *ptr,
        raw_local_irq_save(flags);
        switch (size) {
        case 1: prev = *(u8 *)ptr;
-               if (prev == (u8)old)
-                       *(u8 *)ptr = (u8)new;
+               if (prev == (old & 0xffu))
+                       *(u8 *)ptr = (new & 0xffu);
                break;
        case 2: prev = *(u16 *)ptr;
-               if (prev == (u16)old)
-                       *(u16 *)ptr = (u16)new;
+               if (prev == (old & 0xffffu))
+                       *(u16 *)ptr = (new & 0xffffu);
                break;
        case 4: prev = *(u32 *)ptr;
-               if (prev == (u32)old)
-                       *(u32 *)ptr = (u32)new;
+               if (prev == (old & 0xffffffffffu))
+                       *(u32 *)ptr = (new & 0xffffffffu);
                break;
        case 8: prev = *(u64 *)ptr;
                if (prev == old)
index dca4419922a971fea7037a70ce7a550d37a92459..848de25fc4bf8f2b4d5e368e1621beec90e25b4a 100644 (file)
@@ -32,7 +32,7 @@ unsigned long __generic_xchg(unsigned long x, volatile void *ptr, int size)
 #else
                local_irq_save(flags);
                ret = *(volatile u8 *)ptr;
-               *(volatile u8 *)ptr = x;
+               *(volatile u8 *)ptr = (x & 0xffu);
                local_irq_restore(flags);
                return ret;
 #endif /* __xchg_u8 */
@@ -43,7 +43,7 @@ unsigned long __generic_xchg(unsigned long x, volatile void *ptr, int size)
 #else
                local_irq_save(flags);
                ret = *(volatile u16 *)ptr;
-               *(volatile u16 *)ptr = x;
+               *(volatile u16 *)ptr = (x & 0xffffu);
                local_irq_restore(flags);
                return ret;
 #endif /* __xchg_u16 */
@@ -54,7 +54,7 @@ unsigned long __generic_xchg(unsigned long x, volatile void *ptr, int size)
 #else
                local_irq_save(flags);
                ret = *(volatile u32 *)ptr;
-               *(volatile u32 *)ptr = x;
+               *(volatile u32 *)ptr = (x & 0xffffffffu);
                local_irq_restore(flags);
                return ret;
 #endif /* __xchg_u32 */
index 4c44a29b5e8ef0e06d4af08e0ea4560e68fce6cf..587e7e9b9a375c8ed362f53b3860193bd5e913b4 100644 (file)
@@ -236,7 +236,7 @@ static inline u64 readq(const volatile void __iomem *addr)
 
        log_read_mmio(64, addr, _THIS_IP_, _RET_IP_);
        __io_br();
-       val = __le64_to_cpu(__raw_readq(addr));
+       val = __le64_to_cpu((__le64 __force)__raw_readq(addr));
        __io_ar(val);
        log_post_read_mmio(val, 64, addr, _THIS_IP_, _RET_IP_);
        return val;
@@ -287,7 +287,7 @@ static inline void writeq(u64 value, volatile void __iomem *addr)
 {
        log_write_mmio(value, 64, addr, _THIS_IP_, _RET_IP_);
        __io_bw();
-       __raw_writeq(__cpu_to_le64(value), addr);
+       __raw_writeq((u64 __force)__cpu_to_le64(value), addr);
        __io_aw();
        log_post_write_mmio(value, 64, addr, _THIS_IP_, _RET_IP_);
 }
@@ -319,7 +319,7 @@ static inline u16 readw_relaxed(const volatile void __iomem *addr)
        u16 val;
 
        log_read_mmio(16, addr, _THIS_IP_, _RET_IP_);
-       val = __le16_to_cpu(__raw_readw(addr));
+       val = __le16_to_cpu((__le16 __force)__raw_readw(addr));
        log_post_read_mmio(val, 16, addr, _THIS_IP_, _RET_IP_);
        return val;
 }
@@ -332,7 +332,7 @@ static inline u32 readl_relaxed(const volatile void __iomem *addr)
        u32 val;
 
        log_read_mmio(32, addr, _THIS_IP_, _RET_IP_);
-       val = __le32_to_cpu(__raw_readl(addr));
+       val = __le32_to_cpu((__le32 __force)__raw_readl(addr));
        log_post_read_mmio(val, 32, addr, _THIS_IP_, _RET_IP_);
        return val;
 }
@@ -345,7 +345,7 @@ static inline u64 readq_relaxed(const volatile void __iomem *addr)
        u64 val;
 
        log_read_mmio(64, addr, _THIS_IP_, _RET_IP_);
-       val = __le64_to_cpu(__raw_readq(addr));
+       val = __le64_to_cpu((__le64 __force)__raw_readq(addr));
        log_post_read_mmio(val, 64, addr, _THIS_IP_, _RET_IP_);
        return val;
 }
@@ -366,7 +366,7 @@ static inline void writeb_relaxed(u8 value, volatile void __iomem *addr)
 static inline void writew_relaxed(u16 value, volatile void __iomem *addr)
 {
        log_write_mmio(value, 16, addr, _THIS_IP_, _RET_IP_);
-       __raw_writew(cpu_to_le16(value), addr);
+       __raw_writew((u16 __force)cpu_to_le16(value), addr);
        log_post_write_mmio(value, 16, addr, _THIS_IP_, _RET_IP_);
 }
 #endif
@@ -376,7 +376,7 @@ static inline void writew_relaxed(u16 value, volatile void __iomem *addr)
 static inline void writel_relaxed(u32 value, volatile void __iomem *addr)
 {
        log_write_mmio(value, 32, addr, _THIS_IP_, _RET_IP_);
-       __raw_writel(__cpu_to_le32(value), addr);
+       __raw_writel((u32 __force)__cpu_to_le32(value), addr);
        log_post_write_mmio(value, 32, addr, _THIS_IP_, _RET_IP_);
 }
 #endif
@@ -386,7 +386,7 @@ static inline void writel_relaxed(u32 value, volatile void __iomem *addr)
 static inline void writeq_relaxed(u64 value, volatile void __iomem *addr)
 {
        log_write_mmio(value, 64, addr, _THIS_IP_, _RET_IP_);
-       __raw_writeq(__cpu_to_le64(value), addr);
+       __raw_writeq((u64 __force)__cpu_to_le64(value), addr);
        log_post_write_mmio(value, 64, addr, _THIS_IP_, _RET_IP_);
 }
 #endif
index 8845a2eca339dc0ad6f7cd1f9c9c0c7dafd48524..90d7f68ed39d6ec11648d3169f3244c3999597f5 100644 (file)
@@ -26,6 +26,8 @@
 #include <asm/ptrace.h>
 #include <asm/hyperv-tlfs.h>
 
+#define VTPM_BASE_ADDRESS 0xfed40000
+
 struct ms_hyperv_info {
        u32 features;
        u32 priv_high;
index 68f7aa2a7e55cc9cbdb382cb608af619544983e6..653992a6e9410464f73a5d75a3393c80324835a0 100644 (file)
@@ -28,6 +28,10 @@ struct public_key {
        bool key_is_private;
        const char *id_type;
        const char *pkey_algo;
+       unsigned long key_eflags;       /* key extension flags */
+#define KEY_EFLAG_CA           0       /* set if the CA basic constraints is set */
+#define KEY_EFLAG_DIGITALSIG   1       /* set if the digitalSignature usage is set */
+#define KEY_EFLAG_KEYCERTSIGN  2       /* set if the keyCertSign usage is set */
 };
 
 extern void public_key_free(struct public_key *key);
@@ -71,6 +75,21 @@ extern int restrict_link_by_key_or_keyring_chain(struct key *trust_keyring,
                                                 const union key_payload *payload,
                                                 struct key *trusted);
 
+#if IS_REACHABLE(CONFIG_ASYMMETRIC_KEY_TYPE)
+extern int restrict_link_by_ca(struct key *dest_keyring,
+                              const struct key_type *type,
+                              const union key_payload *payload,
+                              struct key *trust_keyring);
+#else
+static inline int restrict_link_by_ca(struct key *dest_keyring,
+                                     const struct key_type *type,
+                                     const union key_payload *payload,
+                                     struct key *trust_keyring)
+{
+       return 0;
+}
+#endif
+
 extern int query_asymmetric_key(const struct kernel_pkey_params *,
                                struct kernel_pkey_query *);
 
@@ -80,7 +99,16 @@ extern int create_signature(struct kernel_pkey_params *, const void *, void *);
 extern int verify_signature(const struct key *,
                            const struct public_key_signature *);
 
+#if IS_REACHABLE(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE)
 int public_key_verify_signature(const struct public_key *pkey,
                                const struct public_key_signature *sig);
+#else
+static inline
+int public_key_verify_signature(const struct public_key *pkey,
+                               const struct public_key_signature *sig)
+{
+       return -EINVAL;
+}
+#endif
 
 #endif /* _LINUX_PUBLIC_KEY_H */
index 42f86327b40a790f71d5d9d92369ce9f053867df..bf964cdfb3300d98365be6ae487f8d69d2d71f47 100644 (file)
@@ -423,11 +423,11 @@ struct drm_bridge_funcs {
         *
         * The returned array must be allocated with kmalloc() and will be
         * freed by the caller. If the allocation fails, NULL should be
-        * returned. num_output_fmts must be set to the returned array size.
+        * returned. num_input_fmts must be set to the returned array size.
         * Formats listed in the returned array should be listed in decreasing
         * preference order (the core will try all formats until it finds one
         * that works). When the format is not supported NULL should be
-        * returned and num_output_fmts should be set to 0.
+        * returned and num_input_fmts should be set to 0.
         *
         * This method is called on all elements of the bridge chain as part of
         * the bus format negotiation process that happens in
index 772a4adf52870a1fba07d0976b7b447c3de94abe..f1f00fc2dba614b6fa3de952030be476f1d85b8c 100644 (file)
@@ -476,7 +476,9 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
 void drm_gem_lru_init(struct drm_gem_lru *lru, struct mutex *lock);
 void drm_gem_lru_remove(struct drm_gem_object *obj);
 void drm_gem_lru_move_tail(struct drm_gem_lru *lru, struct drm_gem_object *obj);
-unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru, unsigned nr_to_scan,
+unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru,
+                              unsigned int nr_to_scan,
+                              unsigned long *remaining,
                               bool (*shrink)(struct drm_gem_object *obj));
 
 #endif /* __DRM_GEM_H__ */
index 9db9e5e504eeb32f5c527ccbbaa1773388af15ad..9935d1e2ff69a38437de9d5729d15fd6b64b0d18 100644 (file)
@@ -228,13 +228,6 @@ struct drm_sched_entity {
         */
        struct rb_node                  rb_tree_node;
 
-       /**
-        * @elapsed_ns:
-        *
-        * Records the amount of time where jobs from this entity were active
-        * on the GPU.
-        */
-       uint64_t elapsed_ns;
 };
 
 /**
index aa95439708dc967a38451506ef611c86dcb38de9..802495b202763cc95d58f886ad32baa7ae76bd4b 100644 (file)
 #define QCOM_ID_SA8155                 362
 #define QCOM_ID_SDA439                 363
 #define QCOM_ID_SDA429                 364
+#define QCOM_ID_SM7150                 365
 #define QCOM_ID_IPQ8070                        375
 #define QCOM_ID_IPQ8071                        376
 #define QCOM_ID_QM215                  386
 #define QCOM_ID_QCM2150                        436
 #define QCOM_ID_SDA429W                        437
 #define QCOM_ID_SM8350                 439
+#define QCOM_ID_QCM2290                        441
 #define QCOM_ID_SM6115                 444
 #define QCOM_ID_SC8280XP               449
 #define QCOM_ID_IPQ6005                        453
 #define QCOM_ID_SC7280                 487
 #define QCOM_ID_SC7180P                        495
 #define QCOM_ID_SM6375                 507
+#define QCOM_ID_IPQ9514                        510
+#define QCOM_ID_IPQ9550                        511
+#define QCOM_ID_IPQ9554                        512
+#define QCOM_ID_IPQ9570                        513
+#define QCOM_ID_IPQ9574                        514
 #define QCOM_ID_SM8550                 519
+#define QCOM_ID_IPQ9510                        521
+#define QCOM_ID_QRB4210                        523
+#define QCOM_ID_QRB2210                        524
+#define QCOM_ID_SA8775P                        534
 #define QCOM_ID_QRU1000                        539
 #define QCOM_ID_QDU1000                        545
 #define QCOM_ID_QDU1010                        587
index eea6ad69f0b07f450500dcbac279331161477887..ff53238585721700fc3276e8f116e8b25fd91fb2 100644 (file)
@@ -30,7 +30,6 @@
 #define R8A7795_PD_CA53_SCU            21
 #define R8A7795_PD_3DG_E               22
 #define R8A7795_PD_A3IR                        24
-#define R8A7795_PD_A2VC0               25      /* ES1.x only */
 #define R8A7795_PD_A2VC1               26
 
 /* Always-on power area */
index cf6fb8f2ac1bd15d9a8526cf954c04b8c7fde3be..c0d88b318e9068b03812863b374fb3d47550ef2c 100644 (file)
@@ -72,7 +72,7 @@ typedef void (*kunit_resource_free_t)(struct kunit_resource *);
  *             params.gfp = gfp;
  *
  *             return kunit_alloc_resource(test, kunit_kmalloc_init,
- *                     kunit_kmalloc_free, &params);
+ *                     kunit_kmalloc_free, gfp, &params);
  *     }
  *
  * Resources can also be named, with lookup/removal done on a name
index 08d3559dd7038c720cdf839936b049922144925a..57b309c6ca27b3ae0c6348cd3305cf4ecb6b1913 100644 (file)
@@ -34,7 +34,7 @@ DECLARE_STATIC_KEY_FALSE(kunit_running);
 struct kunit;
 
 /* Size of log associated with test. */
-#define KUNIT_LOG_SIZE 512
+#define KUNIT_LOG_SIZE 2048
 
 /* Maximum size of parameter description string. */
 #define KUNIT_PARAM_DESC_SIZE 128
@@ -420,7 +420,7 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...);
 #define kunit_log(lvl, test_or_suite, fmt, ...)                                \
        do {                                                            \
                printk(lvl fmt, ##__VA_ARGS__);                         \
-               kunit_log_append((test_or_suite)->log,  fmt "\n",       \
+               kunit_log_append((test_or_suite)->log,  fmt,            \
                                 ##__VA_ARGS__);                        \
        } while (0)
 
index 71916de7c6c4de30259b77a2b723e4947128b2fa..c52a6e6839da9c8df41d50fa295f9ccc0871f14c 100644 (file)
@@ -23,6 +23,19 @@ enum kvm_arch_timer_regs {
        TIMER_REG_CTL,
 };
 
+struct arch_timer_offset {
+       /*
+        * If set, pointer to one of the offsets in the kvm's offset
+        * structure. If NULL, assume a zero offset.
+        */
+       u64     *vm_offset;
+};
+
+struct arch_timer_vm_data {
+       /* Offset applied to the virtual timer/counter */
+       u64     voffset;
+};
+
 struct arch_timer_context {
        struct kvm_vcpu                 *vcpu;
 
@@ -32,6 +45,8 @@ struct arch_timer_context {
        /* Emulated Timer (may be unused) */
        struct hrtimer                  hrtimer;
 
+       /* Offset for this counter/timer */
+       struct arch_timer_offset        offset;
        /*
         * We have multiple paths which can save/restore the timer state onto
         * the hardware, so we need some way of keeping track of where the
index 0a24ab7cb66fa2eab5650f815d9a8370e9fb8cab..8e2eefa9fbc0f0747b756a2097cb882a95362873 100644 (file)
@@ -9,7 +9,14 @@
 #include <linux/phy.h>
 
 #if IS_ENABLED(CONFIG_ACPI_MDIO)
-int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode);
+int __acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode,
+                           struct module *owner);
+
+static inline int
+acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *handle)
+{
+       return __acpi_mdiobus_register(mdio, handle, THIS_MODULE);
+}
 #else /* CONFIG_ACPI_MDIO */
 static inline int
 acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
index 220c8c60e021a788f7062a35f44ddc7be4e4a332..f196c19f8e55c48a58b552649f9309ee686015a5 100644 (file)
@@ -226,6 +226,24 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit);
 
 extern u64 smccc_has_sve_hint;
 
+/**
+ * arm_smccc_get_soc_id_version()
+ *
+ * Returns the SOC ID version.
+ *
+ * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
+ */
+s32 arm_smccc_get_soc_id_version(void);
+
+/**
+ * arm_smccc_get_soc_id_revision()
+ *
+ * Returns the SOC ID revision.
+ *
+ * When ARM_SMCCC_ARCH_SOC_ID is not present, returns SMCCC_RET_NOT_SUPPORTED.
+ */
+s32 arm_smccc_get_soc_id_revision(void);
+
 /**
  * struct arm_smccc_res - Result from SMC/HVC call
  * @a0-a3 result values from registers 0 to 3
index dd5ce1137f04aeed0ce86b732b14d34c36710716..de0b0c3e7395a60f2316a99536fc58927eb36427 100644 (file)
@@ -228,6 +228,12 @@ static inline unsigned short req_get_ioprio(struct request *req)
        *(listptr) = rq;                                \
 } while (0)
 
+#define rq_list_add_tail(lastpptr, rq) do {            \
+       (rq)->rq_next = NULL;                           \
+       **(lastpptr) = rq;                              \
+       *(lastpptr) = &rq->rq_next;                     \
+} while (0)
+
 #define rq_list_pop(listptr)                           \
 ({                                                     \
        struct request *__req = NULL;                   \
index d1aee08f8c1811d645856ce4b92e24cb4cd236ab..941304f17492f05708d925bfd347755b2e5f272e 100644 (file)
@@ -1446,11 +1446,10 @@ static inline void blk_wake_io_task(struct task_struct *waiter)
                wake_up_process(waiter);
 }
 
-unsigned long bdev_start_io_acct(struct block_device *bdev,
-                                unsigned int sectors, enum req_op op,
+unsigned long bdev_start_io_acct(struct block_device *bdev, enum req_op op,
                                 unsigned long start_time);
 void bdev_end_io_acct(struct block_device *bdev, enum req_op op,
-               unsigned long start_time);
+                     unsigned int sectors, unsigned long start_time);
 
 unsigned long bio_start_io_acct(struct bio *bio);
 void bio_end_io_acct_remapped(struct bio *bio, unsigned long start_time,
index 842e72a5348fa3f571a1f1669af3c6c617ffe905..6f3175f0678a8d78153d96157eef9edc9bfce36e 100644 (file)
@@ -1363,7 +1363,13 @@ struct clk_hw_onecell_data {
        struct clk_hw *hws[];
 };
 
-#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
+#define CLK_OF_DECLARE(name, compat, fn) \
+       static void __init __##name##_of_clk_init_declare(struct device_node *np) \
+       {                                                               \
+               fn(np);                                                 \
+               fwnode_dev_initialized(of_fwnode_handle(np), true);     \
+       }                                                               \
+       OF_DECLARE_1(clk, name, compat, __##name##_of_clk_init_declare)
 
 /*
  * Use this macro when you have a driver that requires two initialization
index d4afa8508a806bc500c3a058799722eb9c74e749..3a7909ed54980d7a373335874c43135f57c3f384 100644 (file)
@@ -96,6 +96,7 @@ static inline void user_exit_irqoff(void) { }
 static inline int exception_enter(void) { return 0; }
 static inline void exception_exit(enum ctx_state prev_ctx) { }
 static inline int ct_state(void) { return -1; }
+static inline int __ct_state(void) { return -1; }
 static __always_inline bool context_tracking_guest_enter(void) { return false; }
 static inline void context_tracking_guest_exit(void) { }
 #define CT_WARN_ON(cond) do { } while (0)
index 4a4d56f771802bf97cfcf16eee960ca948a29974..fdd537ea513ffa35562cc636900e0a0a5b7faaa4 100644 (file)
@@ -46,7 +46,9 @@ struct context_tracking {
 
 #ifdef CONFIG_CONTEXT_TRACKING
 DECLARE_PER_CPU(struct context_tracking, context_tracking);
+#endif
 
+#ifdef CONFIG_CONTEXT_TRACKING_USER
 static __always_inline int __ct_state(void)
 {
        return arch_atomic_read(this_cpu_ptr(&context_tracking.state)) & CT_STATE_MASK;
index c6fab004104a80199e65add70ba9a466068b0a20..5b2f8147d1ae3fe1edb9b352ed79e5c4bd959342 100644 (file)
@@ -218,7 +218,6 @@ enum cpuhp_state {
        CPUHP_AP_PERF_X86_CQM_ONLINE,
        CPUHP_AP_PERF_X86_CSTATE_ONLINE,
        CPUHP_AP_PERF_X86_IDXD_ONLINE,
-       CPUHP_AP_PERF_X86_IOMMU_PERF_ONLINE,
        CPUHP_AP_PERF_S390_CF_ONLINE,
        CPUHP_AP_PERF_S390_SF_ONLINE,
        CPUHP_AP_PERF_ARM_CCI_ONLINE,
index d4901ca8883c33ea27b14d51dcd1d44cda53156d..ca736b05ec7b056ebafae5f347913ce1fec97d2d 100644 (file)
@@ -350,6 +350,23 @@ unsigned int __pure cpumask_next_wrap(int n, const struct cpumask *mask, int sta
 #define for_each_cpu_andnot(cpu, mask1, mask2)                         \
        for_each_andnot_bit(cpu, cpumask_bits(mask1), cpumask_bits(mask2), small_cpumask_bits)
 
+/**
+ * for_each_cpu_or - iterate over every cpu present in either mask
+ * @cpu: the (optionally unsigned) integer iterator
+ * @mask1: the first cpumask pointer
+ * @mask2: the second cpumask pointer
+ *
+ * This saves a temporary CPU mask in many places.  It is equivalent to:
+ *     struct cpumask tmp;
+ *     cpumask_or(&tmp, &mask1, &mask2);
+ *     for_each_cpu(cpu, &tmp)
+ *             ...
+ *
+ * After the loop, cpu is >= nr_cpu_ids.
+ */
+#define for_each_cpu_or(cpu, mask1, mask2)                             \
+       for_each_or_bit(cpu, cpumask_bits(mask1), cpumask_bits(mask2), small_cpumask_bits)
+
 /**
  * cpumask_any_but - return a "random" in a cpumask, but not this one.
  * @mask: the cpumask to search
index 04a733f0ba9562115470787468c3fc10b605a9d4..7aa62c92185f6467069fe07aedb8cf4e0041d352 100644 (file)
@@ -693,6 +693,7 @@ efi_guid_to_str(efi_guid_t *guid, char *out)
 }
 
 extern void efi_init (void);
+extern void efi_earlycon_reprobe(void);
 #ifdef CONFIG_EFI
 extern void efi_enter_virtual_mode (void);     /* switch EFI to virtual mode, if possible */
 #else
index d8d20514ea052259c466b311fc058b5faa7cb9c6..02d09cb57f6c92ec13906352e831118f06dbb1ae 100644 (file)
@@ -212,6 +212,7 @@ struct fb_deferred_io {
        /* delay between mkwrite and deferred handler */
        unsigned long delay;
        bool sort_pagereflist; /* sort pagelist by offset */
+       int open_count; /* number of opened files; protected by fb_info lock */
        struct mutex lock; /* mutex that protects the pageref list */
        struct list_head pagereflist; /* list of pagerefs for touched pages */
        /* callback */
index 4647864a5ffdbb972fb1a1a21eb79178755b72d5..5e4f39ef2e72cc00b5924f048d60394e6e579313 100644 (file)
@@ -14,6 +14,8 @@ unsigned long _find_next_and_bit(const unsigned long *addr1, const unsigned long
                                        unsigned long nbits, unsigned long start);
 unsigned long _find_next_andnot_bit(const unsigned long *addr1, const unsigned long *addr2,
                                        unsigned long nbits, unsigned long start);
+unsigned long _find_next_or_bit(const unsigned long *addr1, const unsigned long *addr2,
+                                       unsigned long nbits, unsigned long start);
 unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits,
                                         unsigned long start);
 extern unsigned long _find_first_bit(const unsigned long *addr, unsigned long size);
@@ -127,6 +129,36 @@ unsigned long find_next_andnot_bit(const unsigned long *addr1,
 }
 #endif
 
+#ifndef find_next_or_bit
+/**
+ * find_next_or_bit - find the next set bit in either memory regions
+ * @addr1: The first address to base the search on
+ * @addr2: The second address to base the search on
+ * @size: The bitmap size in bits
+ * @offset: The bitnumber to start searching at
+ *
+ * Returns the bit number for the next set bit
+ * If no bits are set, returns @size.
+ */
+static inline
+unsigned long find_next_or_bit(const unsigned long *addr1,
+               const unsigned long *addr2, unsigned long size,
+               unsigned long offset)
+{
+       if (small_const_nbits(size)) {
+               unsigned long val;
+
+               if (unlikely(offset >= size))
+                       return size;
+
+               val = (*addr1 | *addr2) & GENMASK(size - 1, offset);
+               return val ? __ffs(val) : size;
+       }
+
+       return _find_next_or_bit(addr1, addr2, size, offset);
+}
+#endif
+
 #ifndef find_next_zero_bit
 /**
  * find_next_zero_bit - find the next cleared bit in a memory region
@@ -536,6 +568,11 @@ unsigned long find_next_bit_le(const void *addr, unsigned
             (bit) = find_next_andnot_bit((addr1), (addr2), (size), (bit)), (bit) < (size);\
             (bit)++)
 
+#define for_each_or_bit(bit, addr1, addr2, size) \
+       for ((bit) = 0;                                                                 \
+            (bit) = find_next_or_bit((addr1), (addr2), (size), (bit)), (bit) < (size);\
+            (bit)++)
+
 /* same as for_each_set_bit() but use bit as value to start with */
 #define for_each_set_bit_from(bit, addr, size) \
        for (; (bit) = find_next_bit((addr), (size), (bit)), (bit) < (size); (bit)++)
index 1e449a5d7f5c19d27e4f111b54e2db0fa885dc46..250ea4efb7cb6ab257b03d3df704a598a9e9ff3a 100644 (file)
@@ -94,7 +94,7 @@ extern int qcom_scm_mem_protect_video_var(u32 cp_start, u32 cp_size,
                                          u32 cp_nonpixel_start,
                                          u32 cp_nonpixel_size);
 extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz,
-                              unsigned int *src,
+                              u64 *src,
                               const struct qcom_scm_vmperm *newvm,
                               unsigned int dest_cnt);
 
index c85916e9f7db500474d043c1f6a6b5e5c8d22020..ef2281a2accef88e1326ee4f8b1d970792288254 100644 (file)
@@ -2675,6 +2675,8 @@ extern struct inode *new_inode(struct super_block *sb);
 extern void free_inode_nonrcu(struct inode *inode);
 extern int setattr_should_drop_suidgid(struct mnt_idmap *, struct inode *);
 extern int file_remove_privs(struct file *);
+int setattr_should_drop_sgid(struct mnt_idmap *idmap,
+                            const struct inode *inode);
 
 /*
  * This must be used for allocating filesystems specific inodes to set
@@ -2778,7 +2780,7 @@ enum {
 ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
                             struct block_device *bdev, struct iov_iter *iter,
                             get_block_t get_block,
-                            dio_iodone_t end_io, dio_submit_t submit_io,
+                            dio_iodone_t end_io,
                             int flags);
 
 static inline ssize_t blockdev_direct_IO(struct kiocb *iocb,
@@ -2787,7 +2789,7 @@ static inline ssize_t blockdev_direct_IO(struct kiocb *iocb,
                                         get_block_t get_block)
 {
        return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter,
-                       get_block, NULL, NULL, DIO_LOCKING | DIO_SKIP_HOLES);
+                       get_block, NULL, DIO_LOCKING | DIO_SKIP_HOLES);
 }
 #endif
 
index 5469ffee21c73f2b34d3bc8548a351e46e01f2f7..ff6341e09925bc84539351c560661400c032305d 100644 (file)
@@ -104,7 +104,6 @@ struct fs_context {
        unsigned int            sb_flags;       /* Proposed superblock flags (SB_*) */
        unsigned int            sb_flags_mask;  /* Superblock flags that were changed */
        unsigned int            s_iflags;       /* OR'd with sb->s_iflags */
-       unsigned int            lsm_flags;      /* Information flags from the fs to the LSM */
        enum fs_context_purpose purpose:8;
        enum fs_context_phase   phase:8;        /* The phase the context is in */
        bool                    need_free:1;    /* Need to call ops->free() */
index 366c730beaa3e4c52423ae09a8c1f1e548bf2a87..402fc061de75cdc7582c70f9fb403671e4fef3d6 100644 (file)
@@ -980,7 +980,7 @@ static inline void __ftrace_enabled_restore(int enabled)
 #define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
 #define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
 
-static inline unsigned long get_lock_parent_ip(void)
+static __always_inline unsigned long get_lock_parent_ip(void)
 {
        unsigned long addr = CALLER_ADDR0;
 
index 501fa84867494787e0f7a20e077c1252c5e932d8..1b608e00290aa14e41ba6ee3321d9d26c18cb2ff 100644 (file)
 
 /**
  * instrument_read - instrument regular read access
+ * @v: address of access
+ * @size: size of access
  *
  * Instrument a regular read access. The instrumentation should be inserted
  * before the actual read happens.
- *
- * @ptr address of access
- * @size size of access
  */
 static __always_inline void instrument_read(const volatile void *v, size_t size)
 {
@@ -30,12 +29,11 @@ static __always_inline void instrument_read(const volatile void *v, size_t size)
 
 /**
  * instrument_write - instrument regular write access
+ * @v: address of access
+ * @size: size of access
  *
  * Instrument a regular write access. The instrumentation should be inserted
  * before the actual write happens.
- *
- * @ptr address of access
- * @size size of access
  */
 static __always_inline void instrument_write(const volatile void *v, size_t size)
 {
@@ -45,12 +43,11 @@ static __always_inline void instrument_write(const volatile void *v, size_t size
 
 /**
  * instrument_read_write - instrument regular read-write access
+ * @v: address of access
+ * @size: size of access
  *
  * Instrument a regular write access. The instrumentation should be inserted
  * before the actual write happens.
- *
- * @ptr address of access
- * @size size of access
  */
 static __always_inline void instrument_read_write(const volatile void *v, size_t size)
 {
@@ -60,12 +57,11 @@ static __always_inline void instrument_read_write(const volatile void *v, size_t
 
 /**
  * instrument_atomic_read - instrument atomic read access
+ * @v: address of access
+ * @size: size of access
  *
  * Instrument an atomic read access. The instrumentation should be inserted
  * before the actual read happens.
- *
- * @ptr address of access
- * @size size of access
  */
 static __always_inline void instrument_atomic_read(const volatile void *v, size_t size)
 {
@@ -75,12 +71,11 @@ static __always_inline void instrument_atomic_read(const volatile void *v, size_
 
 /**
  * instrument_atomic_write - instrument atomic write access
+ * @v: address of access
+ * @size: size of access
  *
  * Instrument an atomic write access. The instrumentation should be inserted
  * before the actual write happens.
- *
- * @ptr address of access
- * @size size of access
  */
 static __always_inline void instrument_atomic_write(const volatile void *v, size_t size)
 {
@@ -90,12 +85,11 @@ static __always_inline void instrument_atomic_write(const volatile void *v, size
 
 /**
  * instrument_atomic_read_write - instrument atomic read-write access
+ * @v: address of access
+ * @size: size of access
  *
  * Instrument an atomic read-write access. The instrumentation should be
  * inserted before the actual write happens.
- *
- * @ptr address of access
- * @size size of access
  */
 static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size)
 {
@@ -105,13 +99,12 @@ static __always_inline void instrument_atomic_read_write(const volatile void *v,
 
 /**
  * instrument_copy_to_user - instrument reads of copy_to_user
+ * @to: destination address
+ * @from: source address
+ * @n: number of bytes to copy
  *
  * Instrument reads from kernel memory, that are due to copy_to_user (and
  * variants). The instrumentation must be inserted before the accesses.
- *
- * @to destination address
- * @from source address
- * @n number of bytes to copy
  */
 static __always_inline void
 instrument_copy_to_user(void __user *to, const void *from, unsigned long n)
@@ -123,13 +116,12 @@ instrument_copy_to_user(void __user *to, const void *from, unsigned long n)
 
 /**
  * instrument_copy_from_user_before - add instrumentation before copy_from_user
+ * @to: destination address
+ * @from: source address
+ * @n: number of bytes to copy
  *
  * Instrument writes to kernel memory, that are due to copy_from_user (and
  * variants). The instrumentation should be inserted before the accesses.
- *
- * @to destination address
- * @from source address
- * @n number of bytes to copy
  */
 static __always_inline void
 instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n)
@@ -140,14 +132,13 @@ instrument_copy_from_user_before(const void *to, const void __user *from, unsign
 
 /**
  * instrument_copy_from_user_after - add instrumentation after copy_from_user
+ * @to: destination address
+ * @from: source address
+ * @n: number of bytes to copy
+ * @left: number of bytes not copied (as returned by copy_from_user)
  *
  * Instrument writes to kernel memory, that are due to copy_from_user (and
  * variants). The instrumentation should be inserted after the accesses.
- *
- * @to destination address
- * @from source address
- * @n number of bytes to copy
- * @left number of bytes not copied (as returned by copy_from_user)
  */
 static __always_inline void
 instrument_copy_from_user_after(const void *to, const void __user *from,
@@ -158,12 +149,11 @@ instrument_copy_from_user_after(const void *to, const void __user *from,
 
 /**
  * instrument_get_user() - add instrumentation to get_user()-like macros
+ * @to: destination variable, may not be address-taken
  *
  * get_user() and friends are fragile, so it may depend on the implementation
  * whether the instrumentation happens before or after the data is copied from
  * the userspace.
- *
- * @to destination variable, may not be address-taken
  */
 #define instrument_get_user(to)                                \
 ({                                                     \
@@ -175,14 +165,13 @@ instrument_copy_from_user_after(const void *to, const void __user *from,
 
 /**
  * instrument_put_user() - add instrumentation to put_user()-like macros
+ * @from: source address
+ * @ptr: userspace pointer to copy to
+ * @size: number of bytes to copy
  *
  * put_user() and friends are fragile, so it may depend on the implementation
  * whether the instrumentation happens before or after the data is copied from
  * the userspace.
- *
- * @from source address
- * @ptr userspace pointer to copy to
- * @size number of bytes to copy
  */
 #define instrument_put_user(from, ptr, size)                   \
 ({                                                             \
index cd5c5a27557f5605b78eed7531b58124b114fbd6..d12cd18aab3f49448a49f46c0e56689329c234e3 100644 (file)
@@ -122,6 +122,9 @@ int icc_link_destroy(struct icc_node *src, struct icc_node *dst);
 void icc_node_add(struct icc_node *node, struct icc_provider *provider);
 void icc_node_del(struct icc_node *node);
 int icc_nodes_remove(struct icc_provider *provider);
+void icc_provider_init(struct icc_provider *provider);
+int icc_provider_register(struct icc_provider *provider);
+void icc_provider_deregister(struct icc_provider *provider);
 int icc_provider_add(struct icc_provider *provider);
 void icc_provider_del(struct icc_provider *provider);
 struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
@@ -167,6 +170,15 @@ static inline int icc_nodes_remove(struct icc_provider *provider)
        return -ENOTSUPP;
 }
 
+static inline void icc_provider_init(struct icc_provider *provider) { }
+
+static inline int icc_provider_register(struct icc_provider *provider)
+{
+       return -ENOTSUPP;
+}
+
+static inline void icc_provider_deregister(struct icc_provider *provider) { }
+
 static inline int icc_provider_add(struct icc_provider *provider)
 {
        return -ENOTSUPP;
index 934e5dd4ccc08d14f8d8731a41fd73c3c73d4d96..35b9328ca3352eeca32b89914ee169421f965262 100644 (file)
@@ -27,7 +27,7 @@ struct io_uring_cmd {
        const void      *cmd;
        union {
                /* callback to defer completions to task context */
-               void (*task_work_cb)(struct io_uring_cmd *cmd);
+               void (*task_work_cb)(struct io_uring_cmd *cmd, unsigned);
                /* used for polled completion */
                void *cookie;
        };
@@ -39,9 +39,10 @@ struct io_uring_cmd {
 #if defined(CONFIG_IO_URING)
 int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
                              struct iov_iter *iter, void *ioucmd);
-void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2);
+void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2,
+                       unsigned issue_flags);
 void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
-                       void (*task_work_cb)(struct io_uring_cmd *));
+                       void (*task_work_cb)(struct io_uring_cmd *, unsigned));
 struct sock *io_uring_get_socket(struct file *file);
 void __io_uring_cancel(bool cancel_all);
 void __io_uring_free(struct task_struct *tsk);
@@ -72,11 +73,11 @@ static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
        return -EOPNOTSUPP;
 }
 static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret,
-               ssize_t ret2)
+               ssize_t ret2, unsigned issue_flags)
 {
 }
 static inline void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
-                       void (*task_work_cb)(struct io_uring_cmd *))
+                       void (*task_work_cb)(struct io_uring_cmd *, unsigned))
 {
 }
 static inline struct sock *io_uring_get_socket(struct file *file)
index 5686711b0f404080d04e3703f6120c038cff6786..2223f95079ce8bfae42c86153ad8bc3ad05f2b2f 100644 (file)
@@ -151,12 +151,6 @@ int gic_of_init(struct device_node *node, struct device_node *parent);
  */
 int gic_of_init_child(struct device *dev, struct gic_chip_data **gic, int irq);
 
-/*
- * Legacy platforms not converted to DT yet must use this to init
- * their GIC
- */
-void gic_init(void __iomem *dist , void __iomem *cpu);
-
 void gic_send_sgi(unsigned int cpu_id, unsigned int irq);
 int gic_get_cpu_id(unsigned int cpu);
 void gic_migrate_target(unsigned int new_cpu_id);
index e38ae3c346184630f1691d6431ffbc3675bd8194..30b17647ce3c73e56c06aaf94863cc70ed206a93 100644 (file)
@@ -134,11 +134,12 @@ void kmsan_kfree_large(const void *ptr);
  * @page_shift:        page_shift passed to vmap_range_noflush().
  *
  * KMSAN maps shadow and origin pages of @pages into contiguous ranges in
- * vmalloc metadata address range.
+ * vmalloc metadata address range. Returns 0 on success, callers must check
+ * for non-zero return value.
  */
-void kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
-                                   pgprot_t prot, struct page **pages,
-                                   unsigned int page_shift);
+int kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
+                                  pgprot_t prot, struct page **pages,
+                                  unsigned int page_shift);
 
 /**
  * kmsan_vunmap_kernel_range_noflush() - Notify KMSAN about a vunmap.
@@ -159,11 +160,12 @@ void kmsan_vunmap_range_noflush(unsigned long start, unsigned long end);
  * @page_shift:        page_shift argument passed to vmap_range_noflush().
  *
  * KMSAN creates new metadata pages for the physical pages mapped into the
- * virtual memory.
+ * virtual memory. Returns 0 on success, callers must check for non-zero return
+ * value.
  */
-void kmsan_ioremap_page_range(unsigned long addr, unsigned long end,
-                             phys_addr_t phys_addr, pgprot_t prot,
-                             unsigned int page_shift);
+int kmsan_ioremap_page_range(unsigned long addr, unsigned long end,
+                            phys_addr_t phys_addr, pgprot_t prot,
+                            unsigned int page_shift);
 
 /**
  * kmsan_iounmap_page_range() - Notify KMSAN about a iounmap_page_range() call.
@@ -281,12 +283,13 @@ static inline void kmsan_kfree_large(const void *ptr)
 {
 }
 
-static inline void kmsan_vmap_pages_range_noflush(unsigned long start,
-                                                 unsigned long end,
-                                                 pgprot_t prot,
-                                                 struct page **pages,
-                                                 unsigned int page_shift)
+static inline int kmsan_vmap_pages_range_noflush(unsigned long start,
+                                                unsigned long end,
+                                                pgprot_t prot,
+                                                struct page **pages,
+                                                unsigned int page_shift)
 {
+       return 0;
 }
 
 static inline void kmsan_vunmap_range_noflush(unsigned long start,
@@ -294,12 +297,12 @@ static inline void kmsan_vunmap_range_noflush(unsigned long start,
 {
 }
 
-static inline void kmsan_ioremap_page_range(unsigned long start,
-                                           unsigned long end,
-                                           phys_addr_t phys_addr,
-                                           pgprot_t prot,
-                                           unsigned int page_shift)
+static inline int kmsan_ioremap_page_range(unsigned long start,
+                                          unsigned long end,
+                                          phys_addr_t phys_addr, pgprot_t prot,
+                                          unsigned int page_shift)
 {
+       return 0;
 }
 
 static inline void kmsan_iounmap_page_range(unsigned long start,
index 8ada23756b0ec223b86eaa94945d070e3e7e9a16..a9adf75344bee024bf8fb02b13036046f9aabae5 100644 (file)
@@ -755,6 +755,7 @@ struct kvm {
        struct {
                spinlock_t        lock;
                struct list_head  items;
+               /* resampler_list update side is protected by resampler_lock. */
                struct list_head  resampler_list;
                struct mutex      resampler_lock;
        } irqfds;
@@ -1986,6 +1987,9 @@ int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
 #ifdef CONFIG_HAVE_KVM_IRQFD
 int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
 void kvm_irqfd_release(struct kvm *kvm);
+bool kvm_notify_irqfd_resampler(struct kvm *kvm,
+                               unsigned int irqchip,
+                               unsigned int pin);
 void kvm_irq_routing_update(struct kvm *);
 #else
 static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
@@ -1994,6 +1998,13 @@ static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
 }
 
 static inline void kvm_irqfd_release(struct kvm *kvm) {}
+
+static inline bool kvm_notify_irqfd_resampler(struct kvm *kvm,
+                                             unsigned int irqchip,
+                                             unsigned int pin)
+{
+       return false;
+}
 #endif
 
 #else
index dac047abdba7c5d571671da54f95a8c930307d67..8ad43692e3bbb459a75c3e33fd17fbd22b3d03e1 100644 (file)
@@ -31,7 +31,7 @@ struct kvm_kernel_irqfd_resampler {
        /*
         * Entry in list of kvm->irqfd.resampler_list.  Use for sharing
         * resamplers among irqfds on the same gsi.
-        * Accessed and modified under kvm->irqfds.resampler_lock
+        * RCU list modified under kvm->irqfds.resampler_lock
         */
        struct list_head link;
 };
index 9a6b55da8fd6442c895267128a02ee02682971ed..72831e35dca32d7412d2705fd38b00ac029d5927 100644 (file)
@@ -22,6 +22,7 @@
 #define        nlm4_fbig               cpu_to_be32(NLM_FBIG)
 #define        nlm4_failed             cpu_to_be32(NLM_FAILED)
 
+void   nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len);
 bool   nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool   nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
 bool   nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
index 1023f349af716a1fb7b1cadaff3224ae0b4bbdf7..b32256e9e94434e9189688ef4b5dde29e6369b84 100644 (file)
@@ -134,7 +134,8 @@ struct held_lock {
        unsigned int read:2;        /* see lock_acquire() comment */
        unsigned int check:1;       /* see lock_acquire() comment */
        unsigned int hardirqs_off:1;
-       unsigned int references:12;                                     /* 32 bits */
+       unsigned int sync:1;
+       unsigned int references:11;                                     /* 32 bits */
        unsigned int pin_count;
 };
 
@@ -268,6 +269,10 @@ extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 
 extern void lock_release(struct lockdep_map *lock, unsigned long ip);
 
+extern void lock_sync(struct lockdep_map *lock, unsigned int subclass,
+                     int read, int check, struct lockdep_map *nest_lock,
+                     unsigned long ip);
+
 /* lock_is_held_type() returns */
 #define LOCK_STATE_UNKNOWN     -1
 #define LOCK_STATE_NOT_HELD    0
@@ -554,6 +559,7 @@ do {                                                                        \
 #define lock_map_acquire_read(l)               lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_)
 #define lock_map_acquire_tryread(l)            lock_acquire_shared_recursive(l, 0, 1, NULL, _THIS_IP_)
 #define lock_map_release(l)                    lock_release(l, _THIS_IP_)
+#define lock_map_sync(l)                       lock_sync(l, 0, 0, 1, NULL, _THIS_IP_)
 
 #ifdef CONFIG_PROVE_LOCKING
 # define might_lock(lock)                                              \
index 094b76dc716489c77d7fcfdc936f32f954725676..6bb55e61e8e87fddb499360b6fe826ac7304f478 100644 (file)
@@ -381,7 +381,7 @@ LSM_HOOK(int, 0, key_alloc, struct key *key, const struct cred *cred,
 LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key)
 LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred,
         enum key_need_perm need_perm)
-LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **_buffer)
+LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer)
 #endif /* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT
index 6e156d2acffce446ffee035b620d83c657a827ee..ab2b2fafa4a459b4f03df8bedb611dc23c482f1e 100644 (file)
 #include <linux/init.h>
 #include <linux/rculist.h>
 
-/**
- * union security_list_options - Linux Security Module hook function list
- *
- * Security hooks for program execution operations.
- *
- * @bprm_creds_for_exec:
- *     If the setup in prepare_exec_creds did not setup @bprm->cred->security
- *     properly for executing @bprm->file, update the LSM's portion of
- *     @bprm->cred->security to be what commit_creds needs to install for the
- *     new program.  This hook may also optionally check permissions
- *     (e.g. for transitions between security domains).
- *     The hook must set @bprm->secureexec to 1 if AT_SECURE should be set to
- *     request libc enable secure mode.
- *     @bprm contains the linux_binprm structure.
- *     Return 0 if the hook is successful and permission is granted.
- * @bprm_creds_from_file:
- *     If @file is setpcap, suid, sgid or otherwise marked to change
- *     privilege upon exec, update @bprm->cred to reflect that change.
- *     This is called after finding the binary that will be executed.
- *     without an interpreter.  This ensures that the credentials will not
- *     be derived from a script that the binary will need to reopen, which
- *     when reopend may end up being a completely different file.  This
- *     hook may also optionally check permissions (e.g. for transitions
- *     between security domains).
- *     The hook must set @bprm->secureexec to 1 if AT_SECURE should be set to
- *     request libc enable secure mode.
- *     The hook must add to @bprm->per_clear any personality flags that
- *     should be cleared from current->personality.
- *     @bprm contains the linux_binprm structure.
- *     Return 0 if the hook is successful and permission is granted.
- * @bprm_check_security:
- *     This hook mediates the point when a search for a binary handler will
- *     begin.  It allows a check against the @bprm->cred->security value
- *     which was set in the preceding creds_for_exec call.  The argv list and
- *     envp list are reliably available in @bprm.  This hook may be called
- *     multiple times during a single execve.
- *     @bprm contains the linux_binprm structure.
- *     Return 0 if the hook is successful and permission is granted.
- * @bprm_committing_creds:
- *     Prepare to install the new security attributes of a process being
- *     transformed by an execve operation, based on the old credentials
- *     pointed to by @current->cred and the information set in @bprm->cred by
- *     the bprm_creds_for_exec hook.  @bprm points to the linux_binprm
- *     structure.  This hook is a good place to perform state changes on the
- *     process such as closing open file descriptors to which access will no
- *     longer be granted when the attributes are changed.  This is called
- *     immediately before commit_creds().
- * @bprm_committed_creds:
- *     Tidy up after the installation of the new security attributes of a
- *     process being transformed by an execve operation.  The new credentials
- *     have, by this point, been set to @current->cred.  @bprm points to the
- *     linux_binprm structure.  This hook is a good place to perform state
- *     changes on the process such as clearing out non-inheritable signal
- *     state.  This is called immediately after commit_creds().
- *
- * Security hooks for mount using fs_context.
- *     [See also Documentation/filesystems/mount_api.rst]
- *
- * @fs_context_dup:
- *     Allocate and attach a security structure to sc->security.  This pointer
- *     is initialised to NULL by the caller.
- *     @fc indicates the new filesystem context.
- *     @src_fc indicates the original filesystem context.
- *     Return 0 on success or a negative error code on failure.
- * @fs_context_parse_param:
- *     Userspace provided a parameter to configure a superblock.  The LSM may
- *     reject it with an error and may use it for itself, in which case it
- *     should return 0; otherwise it should return -ENOPARAM to pass it on to
- *     the filesystem.
- *     @fc indicates the filesystem context.
- *     @param The parameter.
- *
- * Security hooks for filesystem operations.
- *
- * @sb_alloc_security:
- *     Allocate and attach a security structure to the sb->s_security field.
- *     The s_security field is initialized to NULL when the structure is
- *     allocated.
- *     @sb contains the super_block structure to be modified.
- *     Return 0 if operation was successful.
- * @sb_delete:
- *     Release objects tied to a superblock (e.g. inodes).
- *     @sb contains the super_block structure being released.
- * @sb_free_security:
- *     Deallocate and clear the sb->s_security field.
- *     @sb contains the super_block structure to be modified.
- * @sb_free_mnt_opts:
- *     Free memory associated with @mnt_ops.
- * @sb_eat_lsm_opts:
- *     Eat (scan @orig options) and save them in @mnt_opts.
- *     Return 0 on success, negative values on failure.
- * @sb_statfs:
- *     Check permission before obtaining filesystem statistics for the @mnt
- *     mountpoint.
- *     @dentry is a handle on the superblock for the filesystem.
- *     Return 0 if permission is granted.
- * @sb_mount:
- *     Check permission before an object specified by @dev_name is mounted on
- *     the mount point named by @nd.  For an ordinary mount, @dev_name
- *     identifies a device if the file system type requires a device.  For a
- *     remount (@flags & MS_REMOUNT), @dev_name is irrelevant.  For a
- *     loopback/bind mount (@flags & MS_BIND), @dev_name identifies the
- *     pathname of the object being mounted.
- *     @dev_name contains the name for object being mounted.
- *     @path contains the path for mount point object.
- *     @type contains the filesystem type.
- *     @flags contains the mount flags.
- *     @data contains the filesystem-specific data.
- *     Return 0 if permission is granted.
- * @sb_mnt_opts_compat:
- *     Determine if the new mount options in @mnt_opts are allowed given
- *     the existing mounted filesystem at @sb.
- *     @sb superblock being compared.
- *     @mnt_opts new mount options.
- *     Return 0 if options are compatible.
- * @sb_remount:
- *     Extracts security system specific mount options and verifies no changes
- *     are being made to those options.
- *     @sb superblock being remounted.
- *     @data contains the filesystem-specific data.
- *     Return 0 if permission is granted.
- * @sb_kern_mount:
- *     Mount this @sb if allowed by permissions.
- *     Return 0 if permission is granted.
- * @sb_show_options:
- *     Show (print on @m) mount options for this @sb.
- *     Return 0 on success, negative values on failure.
- * @sb_umount:
- *     Check permission before the @mnt file system is unmounted.
- *     @mnt contains the mounted file system.
- *     @flags contains the unmount flags, e.g. MNT_FORCE.
- *     Return 0 if permission is granted.
- * @sb_pivotroot:
- *     Check permission before pivoting the root filesystem.
- *     @old_path contains the path for the new location of the
- *     current root (put_old).
- *     @new_path contains the path for the new root (new_root).
- *     Return 0 if permission is granted.
- * @sb_set_mnt_opts:
- *     Set the security relevant mount options used for a superblock
- *     @sb the superblock to set security mount options for.
- *     @opts binary data structure containing all lsm mount data.
- *     Return 0 on success, error on failure.
- * @sb_clone_mnt_opts:
- *     Copy all security options from a given superblock to another
- *     @oldsb old superblock which contain information to clone.
- *     @newsb new superblock which needs filled in.
- *     Return 0 on success, error on failure.
- * @move_mount:
- *     Check permission before a mount is moved.
- *     @from_path indicates the mount that is going to be moved.
- *     @to_path indicates the mountpoint that will be mounted upon.
- *     Return 0 if permission is granted.
- * @dentry_init_security:
- *     Compute a context for a dentry as the inode is not yet available
- *     since NFSv4 has no label backed by an EA anyway.
- *     @dentry dentry to use in calculating the context.
- *     @mode mode used to determine resource type.
- *     @name name of the last path component used to create file.
- *     @xattr_name pointer to place the pointer to security xattr name.
- *                 Caller does not have to free the resulting pointer. Its
- *                 a pointer to static string.
- *     @ctx pointer to place the pointer to the resulting context in.
- *     @ctxlen point to place the length of the resulting context.
- *     Return 0 on success, negative values on failure.
- * @dentry_create_files_as:
- *     Compute a context for a dentry as the inode is not yet available
- *     and set that context in passed in creds so that new files are
- *     created using that context. Context is calculated using the
- *     passed in creds and not the creds of the caller.
- *     @dentry dentry to use in calculating the context.
- *     @mode mode used to determine resource type.
- *     @name name of the last path component used to create file.
- *     @old creds which should be used for context calculation.
- *     @new creds to modify.
- *     Return 0 on success, error on failure.
- *
- *
- * Security hooks for inode operations.
- *
- * @inode_alloc_security:
- *     Allocate and attach a security structure to @inode->i_security.  The
- *     i_security field is initialized to NULL when the inode structure is
- *     allocated.
- *     @inode contains the inode structure.
- *     Return 0 if operation was successful.
- * @inode_free_security:
- *     @inode contains the inode structure.
- *     Deallocate the inode security structure and set @inode->i_security to
- *     NULL.
- * @inode_init_security:
- *     Obtain the security attribute name suffix and value to set on a newly
- *     created inode and set up the incore security field for the new inode.
- *     This hook is called by the fs code as part of the inode creation
- *     transaction and provides for atomic labeling of the inode, unlike
- *     the post_create/mkdir/... hooks called by the VFS.  The hook function
- *     is expected to allocate the name and value via kmalloc, with the caller
- *     being responsible for calling kfree after using them.
- *     If the security module does not use security attributes or does
- *     not wish to put a security attribute on this particular inode,
- *     then it should return -EOPNOTSUPP to skip this processing.
- *     @inode contains the inode structure of the newly created inode.
- *     @dir contains the inode structure of the parent directory.
- *     @qstr contains the last path component of the new object.
- *     @name will be set to the allocated name suffix (e.g. selinux).
- *     @value will be set to the allocated attribute value.
- *     @len will be set to the length of the value.
- *     Returns 0 if @name and @value have been successfully set,
- *     -EOPNOTSUPP if no security attribute is needed, or
- *     -ENOMEM on memory allocation failure.
- * @inode_init_security_anon:
- *      Set up the incore security field for the new anonymous inode
- *      and return whether the inode creation is permitted by the security
- *      module or not.
- *      @inode contains the inode structure.
- *      @name name of the anonymous inode class.
- *      @context_inode optional related inode.
- *     Returns 0 on success, -EACCES if the security module denies the
- *     creation of this inode, or another -errno upon other errors.
- * @inode_create:
- *     Check permission to create a regular file.
- *     @dir contains inode structure of the parent of the new file.
- *     @dentry contains the dentry structure for the file to be created.
- *     @mode contains the file mode of the file to be created.
- *     Return 0 if permission is granted.
- * @inode_link:
- *     Check permission before creating a new hard link to a file.
- *     @old_dentry contains the dentry structure for an existing
- *     link to the file.
- *     @dir contains the inode structure of the parent directory
- *     of the new link.
- *     @new_dentry contains the dentry structure for the new link.
- *     Return 0 if permission is granted.
- * @path_link:
- *     Check permission before creating a new hard link to a file.
- *     @old_dentry contains the dentry structure for an existing link
- *     to the file.
- *     @new_dir contains the path structure of the parent directory of
- *     the new link.
- *     @new_dentry contains the dentry structure for the new link.
- *     Return 0 if permission is granted.
- * @inode_unlink:
- *     Check the permission to remove a hard link to a file.
- *     @dir contains the inode structure of parent directory of the file.
- *     @dentry contains the dentry structure for file to be unlinked.
- *     Return 0 if permission is granted.
- * @path_unlink:
- *     Check the permission to remove a hard link to a file.
- *     @dir contains the path structure of parent directory of the file.
- *     @dentry contains the dentry structure for file to be unlinked.
- *     Return 0 if permission is granted.
- * @inode_symlink:
- *     Check the permission to create a symbolic link to a file.
- *     @dir contains the inode structure of parent directory of
- *     the symbolic link.
- *     @dentry contains the dentry structure of the symbolic link.
- *     @old_name contains the pathname of file.
- *     Return 0 if permission is granted.
- * @path_symlink:
- *     Check the permission to create a symbolic link to a file.
- *     @dir contains the path structure of parent directory of
- *     the symbolic link.
- *     @dentry contains the dentry structure of the symbolic link.
- *     @old_name contains the pathname of file.
- *     Return 0 if permission is granted.
- * @inode_mkdir:
- *     Check permissions to create a new directory in the existing directory
- *     associated with inode structure @dir.
- *     @dir contains the inode structure of parent of the directory
- *     to be created.
- *     @dentry contains the dentry structure of new directory.
- *     @mode contains the mode of new directory.
- *     Return 0 if permission is granted.
- * @path_mkdir:
- *     Check permissions to create a new directory in the existing directory
- *     associated with path structure @path.
- *     @dir contains the path structure of parent of the directory
- *     to be created.
- *     @dentry contains the dentry structure of new directory.
- *     @mode contains the mode of new directory.
- *     Return 0 if permission is granted.
- * @inode_rmdir:
- *     Check the permission to remove a directory.
- *     @dir contains the inode structure of parent of the directory
- *     to be removed.
- *     @dentry contains the dentry structure of directory to be removed.
- *     Return 0 if permission is granted.
- * @path_rmdir:
- *     Check the permission to remove a directory.
- *     @dir contains the path structure of parent of the directory to be
- *     removed.
- *     @dentry contains the dentry structure of directory to be removed.
- *     Return 0 if permission is granted.
- * @inode_mknod:
- *     Check permissions when creating a special file (or a socket or a fifo
- *     file created via the mknod system call).  Note that if mknod operation
- *     is being done for a regular file, then the create hook will be called
- *     and not this hook.
- *     @dir contains the inode structure of parent of the new file.
- *     @dentry contains the dentry structure of the new file.
- *     @mode contains the mode of the new file.
- *     @dev contains the device number.
- *     Return 0 if permission is granted.
- * @path_mknod:
- *     Check permissions when creating a file. Note that this hook is called
- *     even if mknod operation is being done for a regular file.
- *     @dir contains the path structure of parent of the new file.
- *     @dentry contains the dentry structure of the new file.
- *     @mode contains the mode of the new file.
- *     @dev contains the undecoded device number. Use new_decode_dev() to get
- *     the decoded device number.
- *     Return 0 if permission is granted.
- * @inode_rename:
- *     Check for permission to rename a file or directory.
- *     @old_dir contains the inode structure for parent of the old link.
- *     @old_dentry contains the dentry structure of the old link.
- *     @new_dir contains the inode structure for parent of the new link.
- *     @new_dentry contains the dentry structure of the new link.
- *     Return 0 if permission is granted.
- * @path_rename:
- *     Check for permission to rename a file or directory.
- *     @old_dir contains the path structure for parent of the old link.
- *     @old_dentry contains the dentry structure of the old link.
- *     @new_dir contains the path structure for parent of the new link.
- *     @new_dentry contains the dentry structure of the new link.
- *     @flags may contain rename options such as RENAME_EXCHANGE.
- *     Return 0 if permission is granted.
- * @path_chmod:
- *     Check for permission to change a mode of the file @path. The new
- *     mode is specified in @mode.
- *     @path contains the path structure of the file to change the mode.
- *     @mode contains the new DAC's permission, which is a bitmask of
- *     constants from <include/uapi/linux/stat.h>.
- *     Return 0 if permission is granted.
- * @path_chown:
- *     Check for permission to change owner/group of a file or directory.
- *     @path contains the path structure.
- *     @uid contains new owner's ID.
- *     @gid contains new group's ID.
- *     Return 0 if permission is granted.
- * @path_chroot:
- *     Check for permission to change root directory.
- *     @path contains the path structure.
- *     Return 0 if permission is granted.
- * @path_notify:
- *     Check permissions before setting a watch on events as defined by @mask,
- *     on an object at @path, whose type is defined by @obj_type.
- *     Return 0 if permission is granted.
- * @inode_readlink:
- *     Check the permission to read the symbolic link.
- *     @dentry contains the dentry structure for the file link.
- *     Return 0 if permission is granted.
- * @inode_follow_link:
- *     Check permission to follow a symbolic link when looking up a pathname.
- *     @dentry contains the dentry structure for the link.
- *     @inode contains the inode, which itself is not stable in RCU-walk.
- *     @rcu indicates whether we are in RCU-walk mode.
- *     Return 0 if permission is granted.
- * @inode_permission:
- *     Check permission before accessing an inode.  This hook is called by the
- *     existing Linux permission function, so a security module can use it to
- *     provide additional checking for existing Linux permission checks.
- *     Notice that this hook is called when a file is opened (as well as many
- *     other operations), whereas the file_security_ops permission hook is
- *     called when the actual read/write operations are performed.
- *     @inode contains the inode structure to check.
- *     @mask contains the permission mask.
- *     Return 0 if permission is granted.
- * @inode_setattr:
- *     Check permission before setting file attributes.  Note that the kernel
- *     call to notify_change is performed from several locations, whenever
- *     file attributes change (such as when a file is truncated, chown/chmod
- *     operations, transferring disk quotas, etc).
- *     @dentry contains the dentry structure for the file.
- *     @attr is the iattr structure containing the new file attributes.
- *     Return 0 if permission is granted.
- * @path_truncate:
- *     Check permission before truncating the file indicated by path.
- *     Note that truncation permissions may also be checked based on
- *     already opened files, using the @file_truncate hook.
- *     @path contains the path structure for the file.
- *     Return 0 if permission is granted.
- * @inode_getattr:
- *     Check permission before obtaining file attributes.
- *     @path contains the path structure for the file.
- *     Return 0 if permission is granted.
- * @inode_setxattr:
- *     Check permission before setting the extended attributes
- *     @value identified by @name for @dentry.
- *     Return 0 if permission is granted.
- * @inode_post_setxattr:
- *     Update inode security field after successful setxattr operation.
- *     @value identified by @name for @dentry.
- * @inode_getxattr:
- *     Check permission before obtaining the extended attributes
- *     identified by @name for @dentry.
- *     Return 0 if permission is granted.
- * @inode_listxattr:
- *     Check permission before obtaining the list of extended attribute
- *     names for @dentry.
- *     Return 0 if permission is granted.
- * @inode_removexattr:
- *     Check permission before removing the extended attribute
- *     identified by @name for @dentry.
- *     Return 0 if permission is granted.
- * @inode_set_acl:
- *     Check permission before setting posix acls
- *     The posix acls in @kacl are identified by @acl_name.
- *     Return 0 if permission is granted.
- * @inode_get_acl:
- *     Check permission before getting osix acls
- *     The posix acls are identified by @acl_name.
- *     Return 0 if permission is granted.
- * @inode_remove_acl:
- *     Check permission before removing posix acls
- *     The posix acls are identified by @acl_name.
- *     Return 0 if permission is granted.
- * @inode_getsecurity:
- *     Retrieve a copy of the extended attribute representation of the
- *     security label associated with @name for @inode via @buffer.  Note that
- *     @name is the remainder of the attribute name after the security prefix
- *     has been removed. @alloc is used to specify if the call should return a
- *     value via the buffer or just the value length.
- *     Return size of buffer on success.
- * @inode_setsecurity:
- *     Set the security label associated with @name for @inode from the
- *     extended attribute value @value.  @size indicates the size of the
- *     @value in bytes.  @flags may be XATTR_CREATE, XATTR_REPLACE, or 0.
- *     Note that @name is the remainder of the attribute name after the
- *     security. prefix has been removed.
- *     Return 0 on success.
- * @inode_listsecurity:
- *     Copy the extended attribute names for the security labels
- *     associated with @inode into @buffer.  The maximum size of @buffer
- *     is specified by @buffer_size.  @buffer may be NULL to request
- *     the size of the buffer required.
- *     Returns number of bytes used/required on success.
- * @inode_need_killpriv:
- *     Called when an inode has been changed.
- *     @dentry is the dentry being changed.
- *     Return <0 on error to abort the inode change operation.
- *     Return 0 if inode_killpriv does not need to be called.
- *     Return >0 if inode_killpriv does need to be called.
- * @inode_killpriv:
- *     The setuid bit is being removed.  Remove similar security labels.
- *     Called with the dentry->d_inode->i_mutex held.
- *     @idmap: idmap of the mount.
- *     @dentry is the dentry being changed.
- *     Return 0 on success.  If error is returned, then the operation
- *     causing setuid bit removal is failed.
- * @inode_getsecid:
- *     Get the secid associated with the node.
- *     @inode contains a pointer to the inode.
- *     @secid contains a pointer to the location where result will be saved.
- *     In case of failure, @secid will be set to zero.
- * @inode_copy_up:
- *     A file is about to be copied up from lower layer to upper layer of
- *     overlay filesystem. Security module can prepare a set of new creds
- *     and modify as need be and return new creds. Caller will switch to
- *     new creds temporarily to create new file and release newly allocated
- *     creds.
- *     @src indicates the union dentry of file that is being copied up.
- *     @new pointer to pointer to return newly allocated creds.
- *     Returns 0 on success or a negative error code on error.
- * @inode_copy_up_xattr:
- *     Filter the xattrs being copied up when a unioned file is copied
- *     up from a lower layer to the union/overlay layer.
- *     @name indicates the name of the xattr.
- *     Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if
- *     security module does not know about attribute or a negative error code
- *     to abort the copy up. Note that the caller is responsible for reading
- *     and writing the xattrs as this hook is merely a filter.
- * @d_instantiate:
- *     Fill in @inode security information for a @dentry if allowed.
- * @getprocattr:
- *     Read attribute @name for process @p and store it into @value if allowed.
- *     Return the length of @value on success, a negative value otherwise.
- * @setprocattr:
- *     Write (set) attribute @name to @value, size @size if allowed.
- *     Return written bytes on success, a negative value otherwise.
- *
- * Security hooks for kernfs node operations
- *
- * @kernfs_init_security:
- *     Initialize the security context of a newly created kernfs node based
- *     on its own and its parent's attributes.
- *     @kn_dir the parent kernfs node.
- *     @kn the new child kernfs node.
- *     Return 0 if permission is granted.
- *
- * Security hooks for file operations
- *
- * @file_permission:
- *     Check file permissions before accessing an open file.  This hook is
- *     called by various operations that read or write files.  A security
- *     module can use this hook to perform additional checking on these
- *     operations, e.g.  to revalidate permissions on use to support privilege
- *     bracketing or policy changes.  Notice that this hook is used when the
- *     actual read/write operations are performed, whereas the
- *     inode_security_ops hook is called when a file is opened (as well as
- *     many other operations).
- *     Caveat:  Although this hook can be used to revalidate permissions for
- *     various system call operations that read or write files, it does not
- *     address the revalidation of permissions for memory-mapped files.
- *     Security modules must handle this separately if they need such
- *     revalidation.
- *     @file contains the file structure being accessed.
- *     @mask contains the requested permissions.
- *     Return 0 if permission is granted.
- * @file_alloc_security:
- *     Allocate and attach a security structure to the file->f_security field.
- *     The security field is initialized to NULL when the structure is first
- *     created.
- *     @file contains the file structure to secure.
- *     Return 0 if the hook is successful and permission is granted.
- * @file_free_security:
- *     Deallocate and free any security structures stored in file->f_security.
- *     @file contains the file structure being modified.
- * @file_ioctl:
- *     @file contains the file structure.
- *     @cmd contains the operation to perform.
- *     @arg contains the operational arguments.
- *     Check permission for an ioctl operation on @file.  Note that @arg
- *     sometimes represents a user space pointer; in other cases, it may be a
- *     simple integer value.  When @arg represents a user space pointer, it
- *     should never be used by the security module.
- *     Return 0 if permission is granted.
- * @mmap_addr:
- *     Check permissions for a mmap operation at @addr.
- *     @addr contains virtual address that will be used for the operation.
- *     Return 0 if permission is granted.
- * @mmap_file:
- *     Check permissions for a mmap operation.  The @file may be NULL, e.g.
- *     if mapping anonymous memory.
- *     @file contains the file structure for file to map (may be NULL).
- *     @reqprot contains the protection requested by the application.
- *     @prot contains the protection that will be applied by the kernel.
- *     @flags contains the operational flags.
- *     Return 0 if permission is granted.
- * @file_mprotect:
- *     Check permissions before changing memory access permissions.
- *     @vma contains the memory region to modify.
- *     @reqprot contains the protection requested by the application.
- *     @prot contains the protection that will be applied by the kernel.
- *     Return 0 if permission is granted.
- * @file_lock:
- *     Check permission before performing file locking operations.
- *     Note the hook mediates both flock and fcntl style locks.
- *     @file contains the file structure.
- *     @cmd contains the posix-translated lock operation to perform
- *     (e.g. F_RDLCK, F_WRLCK).
- *     Return 0 if permission is granted.
- * @file_fcntl:
- *     Check permission before allowing the file operation specified by @cmd
- *     from being performed on the file @file.  Note that @arg sometimes
- *     represents a user space pointer; in other cases, it may be a simple
- *     integer value.  When @arg represents a user space pointer, it should
- *     never be used by the security module.
- *     @file contains the file structure.
- *     @cmd contains the operation to be performed.
- *     @arg contains the operational arguments.
- *     Return 0 if permission is granted.
- * @file_set_fowner:
- *     Save owner security information (typically from current->security) in
- *     file->f_security for later use by the send_sigiotask hook.
- *     @file contains the file structure to update.
- *     Return 0 on success.
- * @file_send_sigiotask:
- *     Check permission for the file owner @fown to send SIGIO or SIGURG to the
- *     process @tsk.  Note that this hook is sometimes called from interrupt.
- *     Note that the fown_struct, @fown, is never outside the context of a
- *     struct file, so the file structure (and associated security information)
- *     can always be obtained: container_of(fown, struct file, f_owner)
- *     @tsk contains the structure of task receiving signal.
- *     @fown contains the file owner information.
- *     @sig is the signal that will be sent.  When 0, kernel sends SIGIO.
- *     Return 0 if permission is granted.
- * @file_receive:
- *     This hook allows security modules to control the ability of a process
- *     to receive an open file descriptor via socket IPC.
- *     @file contains the file structure being received.
- *     Return 0 if permission is granted.
- * @file_truncate:
- *     Check permission before truncating a file, i.e. using ftruncate.
- *     Note that truncation permission may also be checked based on the path,
- *     using the @path_truncate hook.
- *     @file contains the file structure for the file.
- *     Return 0 if permission is granted.
- * @file_open:
- *     Save open-time permission checking state for later use upon
- *     file_permission, and recheck access if anything has changed
- *     since inode_permission.
- *     Return 0 if permission is granted.
- *
- * Security hooks for task operations.
- *
- * @task_alloc:
- *     @task task being allocated.
- *     @clone_flags contains the flags indicating what should be shared.
- *     Handle allocation of task-related resources.
- *     Returns a zero on success, negative values on failure.
- * @task_free:
- *     @task task about to be freed.
- *     Handle release of task-related resources. (Note that this can be called
- *     from interrupt context.)
- * @cred_alloc_blank:
- *     @cred points to the credentials.
- *     @gfp indicates the atomicity of any memory allocations.
- *     Only allocate sufficient memory and attach to @cred such that
- *     cred_transfer() will not get ENOMEM.
- *     Return 0 on success, negative values on failure.
- * @cred_free:
- *     @cred points to the credentials.
- *     Deallocate and clear the cred->security field in a set of credentials.
- * @cred_prepare:
- *     @new points to the new credentials.
- *     @old points to the original credentials.
- *     @gfp indicates the atomicity of any memory allocations.
- *     Prepare a new set of credentials by copying the data from the old set.
- *     Return 0 on success, negative values on failure.
- * @cred_transfer:
- *     @new points to the new credentials.
- *     @old points to the original credentials.
- *     Transfer data from original creds to new creds
- * @cred_getsecid:
- *     Retrieve the security identifier of the cred structure @c
- *     @c contains the credentials, secid will be placed into @secid.
- *     In case of failure, @secid will be set to zero.
- * @kernel_act_as:
- *     Set the credentials for a kernel service to act as (subjective context).
- *     @new points to the credentials to be modified.
- *     @secid specifies the security ID to be set.
- *     The current task must be the one that nominated @secid.
- *     Return 0 if successful.
- * @kernel_create_files_as:
- *     Set the file creation context in a set of credentials to be the same as
- *     the objective context of the specified inode.
- *     @new points to the credentials to be modified.
- *     @inode points to the inode to use as a reference.
- *     The current task must be the one that nominated @inode.
- *     Return 0 if successful.
- * @kernel_module_request:
- *     Ability to trigger the kernel to automatically upcall to userspace for
- *     userspace to load a kernel module with the given name.
- *     @kmod_name name of the module requested by the kernel.
- *     Return 0 if successful.
- * @kernel_load_data:
- *     Load data provided by userspace.
- *     @id kernel load data identifier.
- *     @contents if a subsequent @kernel_post_load_data will be called.
- *     Return 0 if permission is granted.
- * @kernel_post_load_data:
- *     Load data provided by a non-file source (usually userspace buffer).
- *     @buf pointer to buffer containing the data contents.
- *     @size length of the data contents.
- *     @id kernel load data identifier.
- *     @description a text description of what was loaded, @id-specific.
- *     Return 0 if permission is granted.
- *     This must be paired with a prior @kernel_load_data call that had
- *     @contents set to true.
- * @kernel_read_file:
- *     Read a file specified by userspace.
- *     @file contains the file structure pointing to the file being read
- *     by the kernel.
- *     @id kernel read file identifier.
- *     @contents if a subsequent @kernel_post_read_file will be called.
- *     Return 0 if permission is granted.
- * @kernel_post_read_file:
- *     Read a file specified by userspace.
- *     @file contains the file structure pointing to the file being read
- *     by the kernel.
- *     @buf pointer to buffer containing the file contents.
- *     @size length of the file contents.
- *     @id kernel read file identifier.
- *     This must be paired with a prior @kernel_read_file call that had
- *     @contents set to true.
- *     Return 0 if permission is granted.
- * @task_fix_setuid:
- *     Update the module's state after setting one or more of the user
- *     identity attributes of the current process.  The @flags parameter
- *     indicates which of the set*uid system calls invoked this hook.  If
- *     @new is the set of credentials that will be installed.  Modifications
- *     should be made to this rather than to @current->cred.
- *     @old is the set of credentials that are being replaced.
- *     @flags contains one of the LSM_SETID_* values.
- *     Return 0 on success.
- * @task_fix_setgid:
- *     Update the module's state after setting one or more of the group
- *     identity attributes of the current process.  The @flags parameter
- *     indicates which of the set*gid system calls invoked this hook.
- *     @new is the set of credentials that will be installed.  Modifications
- *     should be made to this rather than to @current->cred.
- *     @old is the set of credentials that are being replaced.
- *     @flags contains one of the LSM_SETID_* values.
- *     Return 0 on success.
- * @task_fix_setgroups:
- *     Update the module's state after setting the supplementary group
- *     identity attributes of the current process.
- *     @new is the set of credentials that will be installed.  Modifications
- *     should be made to this rather than to @current->cred.
- *     @old is the set of credentials that are being replaced.
- *     Return 0 on success.
- * @task_setpgid:
- *     Check permission before setting the process group identifier of the
- *     process @p to @pgid.
- *     @p contains the task_struct for process being modified.
- *     @pgid contains the new pgid.
- *     Return 0 if permission is granted.
- * @task_getpgid:
- *     Check permission before getting the process group identifier of the
- *     process @p.
- *     @p contains the task_struct for the process.
- *     Return 0 if permission is granted.
- * @task_getsid:
- *     Check permission before getting the session identifier of the process
- *     @p.
- *     @p contains the task_struct for the process.
- *     Return 0 if permission is granted.
- * @current_getsecid_subj:
- *     Retrieve the subjective security identifier of the current task and
- *     return it in @secid.
- *     In case of failure, @secid will be set to zero.
- * @task_getsecid_obj:
- *     Retrieve the objective security identifier of the task_struct in @p
- *     and return it in @secid.
- *     In case of failure, @secid will be set to zero.
- *
- * @task_setnice:
- *     Check permission before setting the nice value of @p to @nice.
- *     @p contains the task_struct of process.
- *     @nice contains the new nice value.
- *     Return 0 if permission is granted.
- * @task_setioprio:
- *     Check permission before setting the ioprio value of @p to @ioprio.
- *     @p contains the task_struct of process.
- *     @ioprio contains the new ioprio value.
- *     Return 0 if permission is granted.
- * @task_getioprio:
- *     Check permission before getting the ioprio value of @p.
- *     @p contains the task_struct of process.
- *     Return 0 if permission is granted.
- * @task_prlimit:
- *     Check permission before getting and/or setting the resource limits of
- *     another task.
- *     @cred points to the cred structure for the current task.
- *     @tcred points to the cred structure for the target task.
- *     @flags contains the LSM_PRLIMIT_* flag bits indicating whether the
- *     resource limits are being read, modified, or both.
- *     Return 0 if permission is granted.
- * @task_setrlimit:
- *     Check permission before setting the resource limits of process @p
- *     for @resource to @new_rlim.  The old resource limit values can
- *     be examined by dereferencing (p->signal->rlim + resource).
- *     @p points to the task_struct for the target task's group leader.
- *     @resource contains the resource whose limit is being set.
- *     @new_rlim contains the new limits for @resource.
- *     Return 0 if permission is granted.
- * @task_setscheduler:
- *     Check permission before setting scheduling policy and/or parameters of
- *     process @p.
- *     @p contains the task_struct for process.
- *     Return 0 if permission is granted.
- * @task_getscheduler:
- *     Check permission before obtaining scheduling information for process
- *     @p.
- *     @p contains the task_struct for process.
- *     Return 0 if permission is granted.
- * @task_movememory:
- *     Check permission before moving memory owned by process @p.
- *     @p contains the task_struct for process.
- *     Return 0 if permission is granted.
- * @task_kill:
- *     Check permission before sending signal @sig to @p.  @info can be NULL,
- *     the constant 1, or a pointer to a kernel_siginfo structure.  If @info is 1 or
- *     SI_FROMKERNEL(info) is true, then the signal should be viewed as coming
- *     from the kernel and should typically be permitted.
- *     SIGIO signals are handled separately by the send_sigiotask hook in
- *     file_security_ops.
- *     @p contains the task_struct for process.
- *     @info contains the signal information.
- *     @sig contains the signal value.
- *     @cred contains the cred of the process where the signal originated, or
- *     NULL if the current task is the originator.
- *     Return 0 if permission is granted.
- * @task_prctl:
- *     Check permission before performing a process control operation on the
- *     current process.
- *     @option contains the operation.
- *     @arg2 contains a argument.
- *     @arg3 contains a argument.
- *     @arg4 contains a argument.
- *     @arg5 contains a argument.
- *     Return -ENOSYS if no-one wanted to handle this op, any other value to
- *     cause prctl() to return immediately with that value.
- * @task_to_inode:
- *     Set the security attributes for an inode based on an associated task's
- *     security attributes, e.g. for /proc/pid inodes.
- *     @p contains the task_struct for the task.
- *     @inode contains the inode structure for the inode.
- * @userns_create:
- *     Check permission prior to creating a new user namespace.
- *     @cred points to prepared creds.
- *     Return 0 if successful, otherwise < 0 error code.
- *
- * Security hooks for Netlink messaging.
- *
- * @netlink_send:
- *     Save security information for a netlink message so that permission
- *     checking can be performed when the message is processed.  The security
- *     information can be saved using the eff_cap field of the
- *     netlink_skb_parms structure.  Also may be used to provide fine
- *     grained control over message transmission.
- *     @sk associated sock of task sending the message.
- *     @skb contains the sk_buff structure for the netlink message.
- *     Return 0 if the information was successfully saved and message
- *     is allowed to be transmitted.
- *
- * Security hooks for Unix domain networking.
- *
- * @unix_stream_connect:
- *     Check permissions before establishing a Unix domain stream connection
- *     between @sock and @other.
- *     @sock contains the sock structure.
- *     @other contains the peer sock structure.
- *     @newsk contains the new sock structure.
- *     Return 0 if permission is granted.
- * @unix_may_send:
- *     Check permissions before connecting or sending datagrams from @sock to
- *     @other.
- *     @sock contains the socket structure.
- *     @other contains the peer socket structure.
- *     Return 0 if permission is granted.
- *
- * The @unix_stream_connect and @unix_may_send hooks were necessary because
- * Linux provides an alternative to the conventional file name space for Unix
- * domain sockets.  Whereas binding and connecting to sockets in the file name
- * space is mediated by the typical file permissions (and caught by the mknod
- * and permission hooks in inode_security_ops), binding and connecting to
- * sockets in the abstract name space is completely unmediated.  Sufficient
- * control of Unix domain sockets in the abstract name space isn't possible
- * using only the socket layer hooks, since we need to know the actual target
- * socket, which is not looked up until we are inside the af_unix code.
- *
- * Security hooks for socket operations.
- *
- * @socket_create:
- *     Check permissions prior to creating a new socket.
- *     @family contains the requested protocol family.
- *     @type contains the requested communications type.
- *     @protocol contains the requested protocol.
- *     @kern set to 1 if a kernel socket.
- *     Return 0 if permission is granted.
- * @socket_post_create:
- *     This hook allows a module to update or allocate a per-socket security
- *     structure. Note that the security field was not added directly to the
- *     socket structure, but rather, the socket security information is stored
- *     in the associated inode.  Typically, the inode alloc_security hook will
- *     allocate and attach security information to
- *     SOCK_INODE(sock)->i_security.  This hook may be used to update the
- *     SOCK_INODE(sock)->i_security field with additional information that
- *     wasn't available when the inode was allocated.
- *     @sock contains the newly created socket structure.
- *     @family contains the requested protocol family.
- *     @type contains the requested communications type.
- *     @protocol contains the requested protocol.
- *     @kern set to 1 if a kernel socket.
- *     Return 0 if permission is granted.
- * @socket_socketpair:
- *     Check permissions before creating a fresh pair of sockets.
- *     @socka contains the first socket structure.
- *     @sockb contains the second socket structure.
- *     Return 0 if permission is granted and the connection was established.
- * @socket_bind:
- *     Check permission before socket protocol layer bind operation is
- *     performed and the socket @sock is bound to the address specified in the
- *     @address parameter.
- *     @sock contains the socket structure.
- *     @address contains the address to bind to.
- *     @addrlen contains the length of address.
- *     Return 0 if permission is granted.
- * @socket_connect:
- *     Check permission before socket protocol layer connect operation
- *     attempts to connect socket @sock to a remote address, @address.
- *     @sock contains the socket structure.
- *     @address contains the address of remote endpoint.
- *     @addrlen contains the length of address.
- *     Return 0 if permission is granted.
- * @socket_listen:
- *     Check permission before socket protocol layer listen operation.
- *     @sock contains the socket structure.
- *     @backlog contains the maximum length for the pending connection queue.
- *     Return 0 if permission is granted.
- * @socket_accept:
- *     Check permission before accepting a new connection.  Note that the new
- *     socket, @newsock, has been created and some information copied to it,
- *     but the accept operation has not actually been performed.
- *     @sock contains the listening socket structure.
- *     @newsock contains the newly created server socket for connection.
- *     Return 0 if permission is granted.
- * @socket_sendmsg:
- *     Check permission before transmitting a message to another socket.
- *     @sock contains the socket structure.
- *     @msg contains the message to be transmitted.
- *     @size contains the size of message.
- *     Return 0 if permission is granted.
- * @socket_recvmsg:
- *     Check permission before receiving a message from a socket.
- *     @sock contains the socket structure.
- *     @msg contains the message structure.
- *     @size contains the size of message structure.
- *     @flags contains the operational flags.
- *     Return 0 if permission is granted.
- * @socket_getsockname:
- *     Check permission before the local address (name) of the socket object
- *     @sock is retrieved.
- *     @sock contains the socket structure.
- *     Return 0 if permission is granted.
- * @socket_getpeername:
- *     Check permission before the remote address (name) of a socket object
- *     @sock is retrieved.
- *     @sock contains the socket structure.
- *     Return 0 if permission is granted.
- * @socket_getsockopt:
- *     Check permissions before retrieving the options associated with socket
- *     @sock.
- *     @sock contains the socket structure.
- *     @level contains the protocol level to retrieve option from.
- *     @optname contains the name of option to retrieve.
- *     Return 0 if permission is granted.
- * @socket_setsockopt:
- *     Check permissions before setting the options associated with socket
- *     @sock.
- *     @sock contains the socket structure.
- *     @level contains the protocol level to set options for.
- *     @optname contains the name of the option to set.
- *     Return 0 if permission is granted.
- * @socket_shutdown:
- *     Checks permission before all or part of a connection on the socket
- *     @sock is shut down.
- *     @sock contains the socket structure.
- *     @how contains the flag indicating how future sends and receives
- *     are handled.
- *     Return 0 if permission is granted.
- * @socket_sock_rcv_skb:
- *     Check permissions on incoming network packets.  This hook is distinct
- *     from Netfilter's IP input hooks since it is the first time that the
- *     incoming sk_buff @skb has been associated with a particular socket, @sk.
- *     Must not sleep inside this hook because some callers hold spinlocks.
- *     @sk contains the sock (not socket) associated with the incoming sk_buff.
- *     @skb contains the incoming network data.
- *     Return 0 if permission is granted.
- * @socket_getpeersec_stream:
- *     This hook allows the security module to provide peer socket security
- *     state for unix or connected tcp sockets to userspace via getsockopt
- *     SO_GETPEERSEC.  For tcp sockets this can be meaningful if the
- *     socket is associated with an ipsec SA.
- *     @sock is the local socket.
- *     @optval memory where the security state is to be copied.
- *     @optlen memory where the module should copy the actual length
- *     of the security state.
- *     @len as input is the maximum length to copy to userspace provided
- *     by the caller.
- *     Return 0 if all is well, otherwise, typical getsockopt return
- *     values.
- * @socket_getpeersec_dgram:
- *     This hook allows the security module to provide peer socket security
- *     state for udp sockets on a per-packet basis to userspace via
- *     getsockopt SO_GETPEERSEC. The application must first have indicated
- *     the IP_PASSSEC option via getsockopt. It can then retrieve the
- *     security state returned by this hook for a packet via the SCM_SECURITY
- *     ancillary message type.
- *     @sock contains the peer socket. May be NULL.
- *     @skb is the sk_buff for the packet being queried. May be NULL.
- *     @secid pointer to store the secid of the packet.
- *     Return 0 on success, error on failure.
- * @sk_alloc_security:
- *     Allocate and attach a security structure to the sk->sk_security field,
- *     which is used to copy security attributes between local stream sockets.
- *     Return 0 on success, error on failure.
- * @sk_free_security:
- *     Deallocate security structure.
- * @sk_clone_security:
- *     Clone/copy security structure.
- * @sk_getsecid:
- *     Retrieve the LSM-specific secid for the sock to enable caching
- *     of network authorizations.
- * @sock_graft:
- *     Sets the socket's isec sid to the sock's sid.
- * @inet_conn_request:
- *     Sets the openreq's sid to socket's sid with MLS portion taken
- *     from peer sid.
- *     Return 0 if permission is granted.
- * @inet_csk_clone:
- *     Sets the new child socket's sid to the openreq sid.
- * @inet_conn_established:
- *     Sets the connection's peersid to the secmark on skb.
- * @secmark_relabel_packet:
- *     Check if the process should be allowed to relabel packets to
- *     the given secid.
- *     Return 0 if permission is granted.
- * @secmark_refcount_inc:
- *     Tells the LSM to increment the number of secmark labeling rules loaded.
- * @secmark_refcount_dec:
- *     Tells the LSM to decrement the number of secmark labeling rules loaded.
- * @req_classify_flow:
- *     Sets the flow's sid to the openreq sid.
- * @tun_dev_alloc_security:
- *     This hook allows a module to allocate a security structure for a TUN
- *     device.
- *     @security pointer to a security structure pointer.
- *     Returns a zero on success, negative values on failure.
- * @tun_dev_free_security:
- *     This hook allows a module to free the security structure for a TUN
- *     device.
- *     @security pointer to the TUN device's security structure.
- * @tun_dev_create:
- *     Check permissions prior to creating a new TUN device.
- *     Return 0 if permission is granted.
- * @tun_dev_attach_queue:
- *     Check permissions prior to attaching to a TUN device queue.
- *     @security pointer to the TUN device's security structure.
- *     Return 0 if permission is granted.
- * @tun_dev_attach:
- *     This hook can be used by the module to update any security state
- *     associated with the TUN device's sock structure.
- *     @sk contains the existing sock structure.
- *     @security pointer to the TUN device's security structure.
- *     Return 0 if permission is granted.
- * @tun_dev_open:
- *     This hook can be used by the module to update any security state
- *     associated with the TUN device's security structure.
- *     @security pointer to the TUN devices's security structure.
- *     Return 0 if permission is granted.
- *
- * Security hooks for SCTP
- *
- * @sctp_assoc_request:
- *     Passes the @asoc and @chunk->skb of the association INIT packet to
- *     the security module.
- *     @asoc pointer to sctp association structure.
- *     @skb pointer to skbuff of association packet.
- *     Return 0 on success, error on failure.
- * @sctp_bind_connect:
- *     Validiate permissions required for each address associated with sock
- *     @sk. Depending on @optname, the addresses will be treated as either
- *     for a connect or bind service. The @addrlen is calculated on each
- *     ipv4 and ipv6 address using sizeof(struct sockaddr_in) or
- *     sizeof(struct sockaddr_in6).
- *     @sk pointer to sock structure.
- *     @optname name of the option to validate.
- *     @address list containing one or more ipv4/ipv6 addresses.
- *     @addrlen total length of address(s).
- *     Return 0 on success, error on failure.
- * @sctp_sk_clone:
- *     Called whenever a new socket is created by accept(2) (i.e. a TCP
- *     style socket) or when a socket is 'peeled off' e.g userspace
- *     calls sctp_peeloff(3).
- *     @asoc pointer to current sctp association structure.
- *     @sk pointer to current sock structure.
- *     @newsk pointer to new sock structure.
- * @sctp_assoc_established:
- *     Passes the @asoc and @chunk->skb of the association COOKIE_ACK packet
- *     to the security module.
- *     @asoc pointer to sctp association structure.
- *     @skb pointer to skbuff of association packet.
- *     Return 0 if permission is granted.
- *
- * Security hooks for Infiniband
- *
- * @ib_pkey_access:
- *     Check permission to access a pkey when modifing a QP.
- *     @subnet_prefix the subnet prefix of the port being used.
- *     @pkey the pkey to be accessed.
- *     @sec pointer to a security structure.
- *     Return 0 if permission is granted.
- * @ib_endport_manage_subnet:
- *     Check permissions to send and receive SMPs on a end port.
- *     @dev_name the IB device name (i.e. mlx4_0).
- *     @port_num the port number.
- *     @sec pointer to a security structure.
- *     Return 0 if permission is granted.
- * @ib_alloc_security:
- *     Allocate a security structure for Infiniband objects.
- *     @sec pointer to a security structure pointer.
- *     Returns 0 on success, non-zero on failure.
- * @ib_free_security:
- *     Deallocate an Infiniband security structure.
- *     @sec contains the security structure to be freed.
- *
- * Security hooks for XFRM operations.
- *
- * @xfrm_policy_alloc_security:
- *     @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
- *     Database used by the XFRM system.
- *     @sec_ctx contains the security context information being provided by
- *     the user-level policy update program (e.g., setkey).
- *     @gfp is to specify the context for the allocation.
- *     Allocate a security structure to the xp->security field; the security
- *     field is initialized to NULL when the xfrm_policy is allocated.
- *     Return 0 if operation was successful (memory to allocate, legal
- *     context).
- * @xfrm_policy_clone_security:
- *     @old_ctx contains an existing xfrm_sec_ctx.
- *     @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
- *     Allocate a security structure in new_ctxp that contains the
- *     information from the old_ctx structure.
- *     Return 0 if operation was successful (memory to allocate).
- * @xfrm_policy_free_security:
- *     @ctx contains the xfrm_sec_ctx.
- *     Deallocate xp->security.
- * @xfrm_policy_delete_security:
- *     @ctx contains the xfrm_sec_ctx.
- *     Authorize deletion of xp->security.
- *     Return 0 if permission is granted.
- * @xfrm_state_alloc:
- *     @x contains the xfrm_state being added to the Security Association
- *     Database by the XFRM system.
- *     @sec_ctx contains the security context information being provided by
- *     the user-level SA generation program (e.g., setkey or racoon).
- *     Allocate a security structure to the x->security field; the security
- *     field is initialized to NULL when the xfrm_state is allocated. Set the
- *     context to correspond to sec_ctx. Return 0 if operation was successful
- *     (memory to allocate, legal context).
- * @xfrm_state_alloc_acquire:
- *     @x contains the xfrm_state being added to the Security Association
- *     Database by the XFRM system.
- *     @polsec contains the policy's security context.
- *     @secid contains the secid from which to take the mls portion of the
- *     context.
- *     Allocate a security structure to the x->security field; the security
- *     field is initialized to NULL when the xfrm_state is allocated. Set the
- *     context to correspond to secid. Return 0 if operation was successful
- *     (memory to allocate, legal context).
- * @xfrm_state_free_security:
- *     @x contains the xfrm_state.
- *     Deallocate x->security.
- * @xfrm_state_delete_security:
- *     @x contains the xfrm_state.
- *     Authorize deletion of x->security.
- *     Return 0 if permission is granted.
- * @xfrm_policy_lookup:
- *     @ctx contains the xfrm_sec_ctx for which the access control is being
- *     checked.
- *     @fl_secid contains the flow security label that is used to authorize
- *     access to the policy xp.
- *     @dir contains the direction of the flow (input or output).
- *     Check permission when a flow selects a xfrm_policy for processing
- *     XFRMs on a packet.  The hook is called when selecting either a
- *     per-socket policy or a generic xfrm policy.
- *     Return 0 if permission is granted, -ESRCH otherwise, or -errno
- *     on other errors.
- * @xfrm_state_pol_flow_match:
- *     @x contains the state to match.
- *     @xp contains the policy to check for a match.
- *     @flic contains the flowi_common struct to check for a match.
- *     Return 1 if there is a match.
- * @xfrm_decode_session:
- *     @skb points to skb to decode.
- *     @secid points to the flow key secid to set.
- *     @ckall says if all xfrms used should be checked for same secid.
- *     Return 0 if ckall is zero or all xfrms used have the same secid.
- *
- * Security hooks affecting all Key Management operations
- *
- * @key_alloc:
- *     Permit allocation of a key and assign security data. Note that key does
- *     not have a serial number assigned at this point.
- *     @key points to the key.
- *     @flags is the allocation flags.
- *     Return 0 if permission is granted, -ve error otherwise.
- * @key_free:
- *     Notification of destruction; free security data.
- *     @key points to the key.
- *     No return value.
- * @key_permission:
- *     See whether a specific operational right is granted to a process on a
- *     key.
- *     @key_ref refers to the key (key pointer + possession attribute bit).
- *     @cred points to the credentials to provide the context against which to
- *     evaluate the security data on the key.
- *     @perm describes the combination of permissions required of this key.
- *     Return 0 if permission is granted, -ve error otherwise.
- * @key_getsecurity:
- *     Get a textual representation of the security context attached to a key
- *     for the purposes of honouring KEYCTL_GETSECURITY.  This function
- *     allocates the storage for the NUL-terminated string and the caller
- *     should free it.
- *     @key points to the key to be queried.
- *     @_buffer points to a pointer that should be set to point to the
- *     resulting string (if no label or an error occurs).
- *     Return the length of the string (including terminating NUL) or -ve if
- *     an error.
- *     May also return 0 (and a NULL buffer pointer) if there is no label.
- *
- * Security hooks affecting all System V IPC operations.
- *
- * @ipc_permission:
- *     Check permissions for access to IPC
- *     @ipcp contains the kernel IPC permission structure.
- *     @flag contains the desired (requested) permission set.
- *     Return 0 if permission is granted.
- * @ipc_getsecid:
- *     Get the secid associated with the ipc object.
- *     @ipcp contains the kernel IPC permission structure.
- *     @secid contains a pointer to the location where result will be saved.
- *     In case of failure, @secid will be set to zero.
- *
- * Security hooks for individual messages held in System V IPC message queues
- *
- * @msg_msg_alloc_security:
- *     Allocate and attach a security structure to the msg->security field.
- *     The security field is initialized to NULL when the structure is first
- *     created.
- *     @msg contains the message structure to be modified.
- *     Return 0 if operation was successful and permission is granted.
- * @msg_msg_free_security:
- *     Deallocate the security structure for this message.
- *     @msg contains the message structure to be modified.
- *
- * Security hooks for System V IPC Message Queues
- *
- * @msg_queue_alloc_security:
- *     Allocate and attach a security structure to the
- *     @perm->security field. The security field is initialized to
- *     NULL when the structure is first created.
- *     @perm contains the IPC permissions of the message queue.
- *     Return 0 if operation was successful and permission is granted.
- * @msg_queue_free_security:
- *     Deallocate security field @perm->security for the message queue.
- *     @perm contains the IPC permissions of the message queue.
- * @msg_queue_associate:
- *     Check permission when a message queue is requested through the
- *     msgget system call. This hook is only called when returning the
- *     message queue identifier for an existing message queue, not when a
- *     new message queue is created.
- *     @perm contains the IPC permissions of the message queue.
- *     @msqflg contains the operation control flags.
- *     Return 0 if permission is granted.
- * @msg_queue_msgctl:
- *     Check permission when a message control operation specified by @cmd
- *     is to be performed on the message queue with permissions @perm.
- *     The @perm may be NULL, e.g. for IPC_INFO or MSG_INFO.
- *     @perm contains the IPC permissions of the msg queue. May be NULL.
- *     @cmd contains the operation to be performed.
- *     Return 0 if permission is granted.
- * @msg_queue_msgsnd:
- *     Check permission before a message, @msg, is enqueued on the message
- *     queue with permissions @perm.
- *     @perm contains the IPC permissions of the message queue.
- *     @msg contains the message to be enqueued.
- *     @msqflg contains operational flags.
- *     Return 0 if permission is granted.
- * @msg_queue_msgrcv:
- *     Check permission before a message, @msg, is removed from the message
- *     queue. The @target task structure contains a pointer to the
- *     process that will be receiving the message (not equal to the current
- *     process when inline receives are being performed).
- *     @perm contains the IPC permissions of the message queue.
- *     @msg contains the message destination.
- *     @target contains the task structure for recipient process.
- *     @type contains the type of message requested.
- *     @mode contains the operational flags.
- *     Return 0 if permission is granted.
- *
- * Security hooks for System V Shared Memory Segments
- *
- * @shm_alloc_security:
- *     Allocate and attach a security structure to the @perm->security
- *     field. The security field is initialized to NULL when the structure is
- *     first created.
- *     @perm contains the IPC permissions of the shared memory structure.
- *     Return 0 if operation was successful and permission is granted.
- * @shm_free_security:
- *     Deallocate the security structure @perm->security for the memory segment.
- *     @perm contains the IPC permissions of the shared memory structure.
- * @shm_associate:
- *     Check permission when a shared memory region is requested through the
- *     shmget system call. This hook is only called when returning the shared
- *     memory region identifier for an existing region, not when a new shared
- *     memory region is created.
- *     @perm contains the IPC permissions of the shared memory structure.
- *     @shmflg contains the operation control flags.
- *     Return 0 if permission is granted.
- * @shm_shmctl:
- *     Check permission when a shared memory control operation specified by
- *     @cmd is to be performed on the shared memory region with permissions @perm.
- *     The @perm may be NULL, e.g. for IPC_INFO or SHM_INFO.
- *     @perm contains the IPC permissions of the shared memory structure.
- *     @cmd contains the operation to be performed.
- *     Return 0 if permission is granted.
- * @shm_shmat:
- *     Check permissions prior to allowing the shmat system call to attach the
- *     shared memory segment with permissions @perm to the data segment of the
- *     calling process. The attaching address is specified by @shmaddr.
- *     @perm contains the IPC permissions of the shared memory structure.
- *     @shmaddr contains the address to attach memory region to.
- *     @shmflg contains the operational flags.
- *     Return 0 if permission is granted.
- *
- * Security hooks for System V Semaphores
- *
- * @sem_alloc_security:
- *     Allocate and attach a security structure to the @perm->security
- *     field. The security field is initialized to NULL when the structure is
- *     first created.
- *     @perm contains the IPC permissions of the semaphore.
- *     Return 0 if operation was successful and permission is granted.
- * @sem_free_security:
- *     Deallocate security structure @perm->security for the semaphore.
- *     @perm contains the IPC permissions of the semaphore.
- * @sem_associate:
- *     Check permission when a semaphore is requested through the semget
- *     system call. This hook is only called when returning the semaphore
- *     identifier for an existing semaphore, not when a new one must be
- *     created.
- *     @perm contains the IPC permissions of the semaphore.
- *     @semflg contains the operation control flags.
- *     Return 0 if permission is granted.
- * @sem_semctl:
- *     Check permission when a semaphore operation specified by @cmd is to be
- *     performed on the semaphore. The @perm may be NULL, e.g. for
- *     IPC_INFO or SEM_INFO.
- *     @perm contains the IPC permissions of the semaphore. May be NULL.
- *     @cmd contains the operation to be performed.
- *     Return 0 if permission is granted.
- * @sem_semop:
- *     Check permissions before performing operations on members of the
- *     semaphore set. If the @alter flag is nonzero, the semaphore set
- *     may be modified.
- *     @perm contains the IPC permissions of the semaphore.
- *     @sops contains the operations to perform.
- *     @nsops contains the number of operations to perform.
- *     @alter contains the flag indicating whether changes are to be made.
- *     Return 0 if permission is granted.
- *
- * @binder_set_context_mgr:
- *     Check whether @mgr is allowed to be the binder context manager.
- *     @mgr contains the struct cred for the current binder process.
- *     Return 0 if permission is granted.
- * @binder_transaction:
- *     Check whether @from is allowed to invoke a binder transaction call
- *     to @to.
- *     @from contains the struct cred for the sending process.
- *     @to contains the struct cred for the receiving process.
- *     Return 0 if permission is granted.
- * @binder_transfer_binder:
- *     Check whether @from is allowed to transfer a binder reference to @to.
- *     @from contains the struct cred for the sending process.
- *     @to contains the struct cred for the receiving process.
- *     Return 0 if permission is granted.
- * @binder_transfer_file:
- *     Check whether @from is allowed to transfer @file to @to.
- *     @from contains the struct cred for the sending process.
- *     @file contains the struct file being transferred.
- *     @to contains the struct cred for the receiving process.
- *     Return 0 if permission is granted.
- *
- * @ptrace_access_check:
- *     Check permission before allowing the current process to trace the
- *     @child process.
- *     Security modules may also want to perform a process tracing check
- *     during an execve in the set_security or apply_creds hooks of
- *     tracing check during an execve in the bprm_set_creds hook of
- *     binprm_security_ops if the process is being traced and its security
- *     attributes would be changed by the execve.
- *     @child contains the task_struct structure for the target process.
- *     @mode contains the PTRACE_MODE flags indicating the form of access.
- *     Return 0 if permission is granted.
- * @ptrace_traceme:
- *     Check that the @parent process has sufficient permission to trace the
- *     current process before allowing the current process to present itself
- *     to the @parent process for tracing.
- *     @parent contains the task_struct structure for debugger process.
- *     Return 0 if permission is granted.
- * @capget:
- *     Get the @effective, @inheritable, and @permitted capability sets for
- *     the @target process.  The hook may also perform permission checking to
- *     determine if the current process is allowed to see the capability sets
- *     of the @target process.
- *     @target contains the task_struct structure for target process.
- *     @effective contains the effective capability set.
- *     @inheritable contains the inheritable capability set.
- *     @permitted contains the permitted capability set.
- *     Return 0 if the capability sets were successfully obtained.
- * @capset:
- *     Set the @effective, @inheritable, and @permitted capability sets for
- *     the current process.
- *     @new contains the new credentials structure for target process.
- *     @old contains the current credentials structure for target process.
- *     @effective contains the effective capability set.
- *     @inheritable contains the inheritable capability set.
- *     @permitted contains the permitted capability set.
- *     Return 0 and update @new if permission is granted.
- * @capable:
- *     Check whether the @tsk process has the @cap capability in the indicated
- *     credentials.
- *     @cred contains the credentials to use.
- *     @ns contains the user namespace we want the capability in.
- *     @cap contains the capability <include/linux/capability.h>.
- *     @opts contains options for the capable check <include/linux/security.h>.
- *     Return 0 if the capability is granted for @tsk.
- * @quotactl:
- *     Check whether the quotactl syscall is allowed for this @sb.
- *     Return 0 if permission is granted.
- * @quota_on:
- *     Check whether QUOTAON is allowed for this @dentry.
- *     Return 0 if permission is granted.
- * @syslog:
- *     Check permission before accessing the kernel message ring or changing
- *     logging to the console.
- *     See the syslog(2) manual page for an explanation of the @type values.
- *     @type contains the SYSLOG_ACTION_* constant from
- *     <include/linux/syslog.h>.
- *     Return 0 if permission is granted.
- * @settime:
- *     Check permission to change the system time.
- *     struct timespec64 is defined in <include/linux/time64.h> and timezone
- *     is defined in <include/linux/time.h>
- *     @ts contains new time.
- *     @tz contains new timezone.
- *     Return 0 if permission is granted.
- * @vm_enough_memory:
- *     Check permissions for allocating a new virtual mapping.
- *     @mm contains the mm struct it is being added to.
- *     @pages contains the number of pages.
- *     Return 0 if permission is granted by the LSM infrastructure to the
- *     caller. If all LSMs return a positive value, __vm_enough_memory() will
- *     be called with cap_sys_admin set. If at least one LSM returns 0 or
- *     negative, __vm_enough_memory() will be called with cap_sys_admin
- *     cleared.
- *
- * @ismaclabel:
- *     Check if the extended attribute specified by @name
- *     represents a MAC label. Returns 1 if name is a MAC
- *     attribute otherwise returns 0.
- *     @name full extended attribute name to check against
- *     LSM as a MAC label.
- *
- * @secid_to_secctx:
- *     Convert secid to security context.  If secdata is NULL the length of
- *     the result will be returned in seclen, but no secdata will be returned.
- *     This does mean that the length could change between calls to check the
- *     length and the next call which actually allocates and returns the
- *     secdata.
- *     @secid contains the security ID.
- *     @secdata contains the pointer that stores the converted security
- *     context.
- *     @seclen pointer which contains the length of the data.
- *     Return 0 on success, error on failure.
- * @secctx_to_secid:
- *     Convert security context to secid.
- *     @secid contains the pointer to the generated security ID.
- *     @secdata contains the security context.
- *     Return 0 on success, error on failure.
- *
- * @release_secctx:
- *     Release the security context.
- *     @secdata contains the security context.
- *     @seclen contains the length of the security context.
- *
- * Security hooks for Audit
- *
- * @audit_rule_init:
- *     Allocate and initialize an LSM audit rule structure.
- *     @field contains the required Audit action.
- *     Fields flags are defined in <include/linux/audit.h>
- *     @op contains the operator the rule uses.
- *     @rulestr contains the context where the rule will be applied to.
- *     @lsmrule contains a pointer to receive the result.
- *     Return 0 if @lsmrule has been successfully set,
- *     -EINVAL in case of an invalid rule.
- *
- * @audit_rule_known:
- *     Specifies whether given @krule contains any fields related to
- *     current LSM.
- *     @krule contains the audit rule of interest.
- *     Return 1 in case of relation found, 0 otherwise.
- *
- * @audit_rule_match:
- *     Determine if given @secid matches a rule previously approved
- *     by @audit_rule_known.
- *     @secid contains the security id in question.
- *     @field contains the field which relates to current LSM.
- *     @op contains the operator that will be used for matching.
- *     @lrule points to the audit rule that will be checked against.
- *     Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
- *
- * @audit_rule_free:
- *     Deallocate the LSM audit rule structure previously allocated by
- *     audit_rule_init.
- *     @lsmrule contains the allocated rule.
- *
- * @inode_invalidate_secctx:
- *     Notify the security module that it must revalidate the security context
- *     of an inode.
- *
- * @inode_notifysecctx:
- *     Notify the security module of what the security context of an inode
- *     should be.  Initializes the incore security context managed by the
- *     security module for this inode.  Example usage:  NFS client invokes
- *     this hook to initialize the security context in its incore inode to the
- *     value provided by the server for the file when the server returned the
- *     file's attributes to the client.
- *     Must be called with inode->i_mutex locked.
- *     @inode we wish to set the security context of.
- *     @ctx contains the string which we wish to set in the inode.
- *     @ctxlen contains the length of @ctx.
- *     Return 0 on success, error on failure.
- *
- * @inode_setsecctx:
- *     Change the security context of an inode.  Updates the
- *     incore security context managed by the security module and invokes the
- *     fs code as needed (via __vfs_setxattr_noperm) to update any backing
- *     xattrs that represent the context.  Example usage:  NFS server invokes
- *     this hook to change the security context in its incore inode and on the
- *     backing filesystem to a value provided by the client on a SETATTR
- *     operation.
- *     Must be called with inode->i_mutex locked.
- *     @dentry contains the inode we wish to set the security context of.
- *     @ctx contains the string which we wish to set in the inode.
- *     @ctxlen contains the length of @ctx.
- *     Return 0 on success, error on failure.
- *
- * @inode_getsecctx:
- *     On success, returns 0 and fills out @ctx and @ctxlen with the security
- *     context for the given @inode.
- *     @inode we wish to get the security context of.
- *     @ctx is a pointer in which to place the allocated security context.
- *     @ctxlen points to the place to put the length of @ctx.
- *     Return 0 on success, error on failure.
- *
- * Security hooks for the general notification queue:
- *
- * @post_notification:
- *     Check to see if a watch notification can be posted to a particular
- *     queue.
- *     @w_cred: The credentials of the whoever set the watch.
- *     @cred: The event-triggerer's credentials.
- *     @n: The notification being posted.
- *     Return 0 if permission is granted.
- *
- * @watch_key:
- *     Check to see if a process is allowed to watch for event notifications
- *     from a key or keyring.
- *     @key: The key to watch.
- *     Return 0 if permission is granted.
- *
- * Security hooks for using the eBPF maps and programs functionalities through
- * eBPF syscalls.
- *
- * @bpf:
- *     Do a initial check for all bpf syscalls after the attribute is copied
- *     into the kernel. The actual security module can implement their own
- *     rules to check the specific cmd they need.
- *     Return 0 if permission is granted.
- *
- * @bpf_map:
- *     Do a check when the kernel generate and return a file descriptor for
- *     eBPF maps.
- *     @map: bpf map that we want to access.
- *     @mask: the access flags.
- *     Return 0 if permission is granted.
- *
- * @bpf_prog:
- *     Do a check when the kernel generate and return a file descriptor for
- *     eBPF programs.
- *     @prog: bpf prog that userspace want to use.
- *     Return 0 if permission is granted.
- *
- * @bpf_map_alloc_security:
- *     Initialize the security field inside bpf map.
- *     Return 0 on success, error on failure.
- *
- * @bpf_map_free_security:
- *     Clean up the security information stored inside bpf map.
- *
- * @bpf_prog_alloc_security:
- *     Initialize the security field inside bpf program.
- *     Return 0 on success, error on failure.
- *
- * @bpf_prog_free_security:
- *     Clean up the security information stored inside bpf prog.
- *
- * @locked_down:
- *     Determine whether a kernel feature that potentially enables arbitrary
- *     code execution in kernel space should be permitted.
- *     @what: kernel feature being accessed.
- *     Return 0 if permission is granted.
- *
- * Security hooks for perf events
- *
- * @perf_event_open:
- *     Check whether the @type of perf_event_open syscall is allowed.
- *     Return 0 if permission is granted.
- * @perf_event_alloc:
- *     Allocate and save perf_event security info.
- *     Return 0 on success, error on failure.
- * @perf_event_free:
- *     Release (free) perf_event security info.
- * @perf_event_read:
- *     Read perf_event security info if allowed.
- *     Return 0 if permission is granted.
- * @perf_event_write:
- *     Write perf_event security info if allowed.
- *     Return 0 if permission is granted.
- *
- * Security hooks for io_uring
- *
- * @uring_override_creds:
- *     Check if the current task, executing an io_uring operation, is allowed
- *     to override it's credentials with @new.
- *     @new: the new creds to use.
- *     Return 0 if permission is granted.
- *
- * @uring_sqpoll:
- *     Check whether the current task is allowed to spawn a io_uring polling
- *     thread (IORING_SETUP_SQPOLL).
- *     Return 0 if permission is granted.
- *
- * @uring_cmd:
- *     Check whether the file_operations uring_cmd is allowed to run.
- *     Return 0 if permission is granted.
- *
- */
 union security_list_options {
        #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
        #include "lsm_hook_defs.h"
@@ -1716,6 +92,7 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count,
 enum lsm_order {
        LSM_ORDER_FIRST = -1,   /* This is only for capabilities. */
        LSM_ORDER_MUTABLE = 0,
+       LSM_ORDER_LAST = 1,     /* This is only for integrity. */
 };
 
 struct lsm_info {
@@ -1740,36 +117,6 @@ extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
                __used __section(".early_lsm_info.init")                \
                __aligned(sizeof(unsigned long))
 
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-/*
- * Assuring the safety of deleting a security module is up to
- * the security module involved. This may entail ordering the
- * module's hook list in a particular way, refusing to disable
- * the module once a policy is loaded or any number of other
- * actions better imagined than described.
- *
- * The name of the configuration option reflects the only module
- * that currently uses the mechanism. Any developer who thinks
- * disabling their module is a good idea needs to be at least as
- * careful as the SELinux team.
- */
-static inline void security_delete_hooks(struct security_hook_list *hooks,
-                                               int count)
-{
-       int i;
-
-       for (i = 0; i < count; i++)
-               hlist_del_rcu(&hooks[i].list);
-}
-#endif /* CONFIG_SECURITY_SELINUX_DISABLE */
-
-/* Currently required to handle SELinux runtime hook disable. */
-#ifdef CONFIG_SECURITY_WRITABLE_HOOKS
-#define __lsm_ro_after_init
-#else
-#define __lsm_ro_after_init    __ro_after_init
-#endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
-
 extern int lsm_inode_alloc(struct inode *inode);
 
 #endif /* ! __LINUX_LSM_HOOKS_H */
index 71b06ebad4024c429bf6b33cf3637e9e0c7fc61e..1db19a9d26e324a86ac0a5b9e4dfeea409ac1dfd 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/types.h>
 #include <rdma/ib_verbs.h>
 #include <linux/mlx5/mlx5_ifc.h>
+#include <linux/bitfield.h>
 
 #if defined(__LITTLE_ENDIAN)
 #define MLX5_SET_HOST_ENDIANNESS       0
@@ -980,14 +981,23 @@ enum {
 };
 
 enum {
-       CQE_RSS_HTYPE_IP        = 0x3 << 2,
+       CQE_RSS_HTYPE_IP        = GENMASK(3, 2),
        /* cqe->rss_hash_type[3:2] - IP destination selected for hash
         * (00 = none,  01 = IPv4, 10 = IPv6, 11 = Reserved)
         */
-       CQE_RSS_HTYPE_L4        = 0x3 << 6,
+       CQE_RSS_IP_NONE         = 0x0,
+       CQE_RSS_IPV4            = 0x1,
+       CQE_RSS_IPV6            = 0x2,
+       CQE_RSS_RESERVED        = 0x3,
+
+       CQE_RSS_HTYPE_L4        = GENMASK(7, 6),
        /* cqe->rss_hash_type[7:6] - L4 destination selected for hash
         * (00 = none, 01 = TCP. 10 = UDP, 11 = IPSEC.SPI
         */
+       CQE_RSS_L4_NONE         = 0x0,
+       CQE_RSS_L4_TCP          = 0x1,
+       CQE_RSS_L4_UDP          = 0x2,
+       CQE_RSS_L4_IPSEC        = 0x3,
 };
 
 enum {
index f33389b42209e472c7dd6245c96c9f6c4203b503..7e225e41d55b8b61a93b6ac6ad223e0d2b218b0c 100644 (file)
@@ -1211,11 +1211,6 @@ static inline bool mlx5_core_is_vf(const struct mlx5_core_dev *dev)
        return dev->coredev_type == MLX5_COREDEV_VF;
 }
 
-static inline bool mlx5_core_is_management_pf(const struct mlx5_core_dev *dev)
-{
-       return MLX5_CAP_GEN(dev, num_ports) == 1 && !MLX5_CAP_GEN(dev, native_port_num);
-}
-
 static inline bool mlx5_core_is_ecpf(const struct mlx5_core_dev *dev)
 {
        return dev->caps.embedded_cpu;
index 0722859c36478d92f06455c6841144a7bfe5d207..a57e6ae78e6569ef67058faa9e353175628de44c 100644 (file)
@@ -774,7 +774,8 @@ struct mm_struct {
        unsigned long cpu_bitmap[];
 };
 
-#define MM_MT_FLAGS    (MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN)
+#define MM_MT_FLAGS    (MT_FLAGS_ALLOC_RANGE | MT_FLAGS_LOCK_EXTERN | \
+                        MT_FLAGS_USE_RCU)
 extern struct mm_struct init_mm;
 
 /* Pointer magic because the dynamic array size confuses some compilers. */
index 6a14b7b117668ca2c8b1f914ecb49fb4311784ab..c35f04f636f15a2a034baedd0b60b0857b96f0e0 100644 (file)
@@ -297,9 +297,11 @@ struct hh_cache {
  * relationship HH alignment <= LL alignment.
  */
 #define LL_RESERVED_SPACE(dev) \
-       ((((dev)->hard_header_len+(dev)->needed_headroom)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
+       ((((dev)->hard_header_len + READ_ONCE((dev)->needed_headroom)) \
+         & ~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
 #define LL_RESERVED_SPACE_EXTRA(dev,extra) \
-       ((((dev)->hard_header_len+(dev)->needed_headroom+(extra))&~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
+       ((((dev)->hard_header_len + READ_ONCE((dev)->needed_headroom) + (extra)) \
+         & ~(HH_DATA_MOD - 1)) + HH_DATA_MOD)
 
 struct header_ops {
        int     (*create) (struct sk_buff *skb, struct net_device *dev,
@@ -1622,7 +1624,8 @@ struct net_device_ops {
 
 struct xdp_metadata_ops {
        int     (*xmo_rx_timestamp)(const struct xdp_md *ctx, u64 *timestamp);
-       int     (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash);
+       int     (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash,
+                              enum xdp_rss_hash_type *rss_type);
 };
 
 /**
index aef88c2d117366bfc0cab51264312a445cf585e3..2aba75145144c9f1a8ea0156c72460ffe9810044 100644 (file)
@@ -73,6 +73,9 @@ struct raw_notifier_head {
 
 struct srcu_notifier_head {
        struct mutex mutex;
+#ifdef CONFIG_TREE_SRCU
+       struct srcu_usage srcuu;
+#endif
        struct srcu_struct srcu;
        struct notifier_block __rcu *head;
 };
@@ -107,7 +110,7 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
        {                                                       \
                .mutex = __MUTEX_INITIALIZER(name.mutex),       \
                .head = NULL,                                   \
-               .srcu = __SRCU_STRUCT_INIT(name.srcu, pcpu),    \
+               .srcu = __SRCU_STRUCT_INIT(name.srcu, name.srcuu, pcpu), \
        }
 
 #define ATOMIC_NOTIFIER_HEAD(name)                             \
index 75470159a194d97fa91e208999217767dd3c9761..57ebe1267f7fbe96166e9c40621192330d6fcbc4 100644 (file)
@@ -115,8 +115,9 @@ struct nvme_tcp_icresp_pdu {
 struct nvme_tcp_term_pdu {
        struct nvme_tcp_hdr     hdr;
        __le16                  fes;
-       __le32                  fei;
-       __u8                    rsvd[8];
+       __le16                  feil;
+       __le16                  feiu;
+       __u8                    rsvd[10];
 };
 
 /**
index 4fad4aa245fb0621ee3adbec1793981ae54f1ea7..779507ac750b803db2c8a185d461e6114969b5b3 100644 (file)
@@ -812,6 +812,7 @@ enum nvme_opcode {
                nvme_opcode_name(nvme_cmd_compare),             \
                nvme_opcode_name(nvme_cmd_write_zeroes),        \
                nvme_opcode_name(nvme_cmd_dsm),                 \
+               nvme_opcode_name(nvme_cmd_verify),              \
                nvme_opcode_name(nvme_cmd_resv_register),       \
                nvme_opcode_name(nvme_cmd_resv_report),         \
                nvme_opcode_name(nvme_cmd_resv_acquire),        \
@@ -1144,10 +1145,14 @@ enum nvme_admin_opcode {
                nvme_admin_opcode_name(nvme_admin_ns_mgmt),             \
                nvme_admin_opcode_name(nvme_admin_activate_fw),         \
                nvme_admin_opcode_name(nvme_admin_download_fw),         \
+               nvme_admin_opcode_name(nvme_admin_dev_self_test),       \
                nvme_admin_opcode_name(nvme_admin_ns_attach),           \
                nvme_admin_opcode_name(nvme_admin_keep_alive),          \
                nvme_admin_opcode_name(nvme_admin_directive_send),      \
                nvme_admin_opcode_name(nvme_admin_directive_recv),      \
+               nvme_admin_opcode_name(nvme_admin_virtual_mgmt),        \
+               nvme_admin_opcode_name(nvme_admin_nvme_mi_send),        \
+               nvme_admin_opcode_name(nvme_admin_nvme_mi_recv),        \
                nvme_admin_opcode_name(nvme_admin_dbbuf),               \
                nvme_admin_opcode_name(nvme_admin_format_nvm),          \
                nvme_admin_opcode_name(nvme_admin_security_send),       \
index da633d34ab866bd92a693459a2a23b69de6940fb..8a52ef2e6fa6bb495313edad7026df3f1dedcb84 100644 (file)
 
 #if IS_ENABLED(CONFIG_OF_MDIO)
 bool of_mdiobus_child_is_phy(struct device_node *child);
-int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
-int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
-                            struct device_node *np);
+int __of_mdiobus_register(struct mii_bus *mdio, struct device_node *np,
+                         struct module *owner);
+
+static inline int of_mdiobus_register(struct mii_bus *mdio,
+                                     struct device_node *np)
+{
+       return __of_mdiobus_register(mdio, np, THIS_MODULE);
+}
+
+int __devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
+                              struct device_node *np, struct module *owner);
+
+static inline int devm_of_mdiobus_register(struct device *dev,
+                                          struct mii_bus *mdio,
+                                          struct device_node *np)
+{
+       return __devm_of_mdiobus_register(dev, mdio, np, THIS_MODULE);
+}
+
 struct mdio_device *of_mdio_find_device(struct device_node *np);
 struct phy_device *of_phy_find_device(struct device_node *phy_np);
 struct phy_device *
index 0acb8e1fb7afdc92b8d17c1216294d02f6fa19d9..853184a46411f46d9ac2337c19c58825b34184e1 100644 (file)
@@ -1066,12 +1066,6 @@ static inline void folio_cancel_dirty(struct folio *folio)
 bool folio_clear_dirty_for_io(struct folio *folio);
 bool clear_page_dirty_for_io(struct page *page);
 void folio_invalidate(struct folio *folio, size_t offset, size_t length);
-int __must_check folio_write_one(struct folio *folio);
-static inline int __must_check write_one_page(struct page *page)
-{
-       return folio_write_one(page_folio(page));
-}
-
 int __set_page_dirty_nobuffers(struct page *page);
 bool noop_dirty_folio(struct address_space *mapping, struct folio *folio);
 
index ed9b4df792b8858be22221ec77f24abafce9cc75..43765eaf2342c6996db747a14d9dcef89d6993e8 100644 (file)
@@ -34,6 +34,10 @@ struct pci_doe_mb;
  * @work: Used internally by the mailbox
  * @doe_mb: Used internally by the mailbox
  *
+ * Payloads are treated as opaque byte streams which are transmitted verbatim,
+ * without byte-swapping.  If payloads contain little-endian register values,
+ * the caller is responsible for conversion with cpu_to_le32() / le32_to_cpu().
+ *
  * The payload sizes and rv are specified in bytes with the following
  * restrictions concerning the protocol.
  *
@@ -45,9 +49,9 @@ struct pci_doe_mb;
  */
 struct pci_doe_task {
        struct pci_doe_protocol prot;
-       u32 *request_pl;
+       __le32 *request_pl;
        size_t request_pl_sz;
-       u32 *response_pl;
+       __le32 *response_pl;
        size_t response_pl_sz;
        int rv;
        void (*complete)(struct pci_doe_task *task);
index fafd8020c6d7f1f7a02b82199874d11b6b0870dd..a5dda515fcd1d4f7fe2cd4b6e384797c0083027d 100644 (file)
@@ -1438,6 +1438,7 @@ void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
                          unsigned int flags);
 struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
 void pci_bus_remove_resources(struct pci_bus *bus);
+void pci_bus_remove_resource(struct pci_bus *bus, struct resource *res);
 int devm_request_pci_bus_resources(struct device *dev,
                                   struct list_head *resources);
 
@@ -1623,6 +1624,8 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
                                              flags, NULL);
 }
 
+static inline bool pci_msix_can_alloc_dyn(struct pci_dev *dev)
+{ return false; }
 static inline struct msi_map pci_msix_alloc_irq_at(struct pci_dev *dev, unsigned int index,
                                                   const struct irq_affinity_desc *affdesc)
 {
index 521a733e21a920cc04a401788048143ecb64f236..75b73c83bc9d0d1074c9e0f67ad39776b12c5eb1 100644 (file)
@@ -45,7 +45,6 @@ void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
 void percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount,
                              s32 batch);
 s64 __percpu_counter_sum(struct percpu_counter *fbc);
-s64 percpu_counter_sum_all(struct percpu_counter *fbc);
 int __percpu_counter_compare(struct percpu_counter *fbc, s64 rhs, s32 batch);
 void percpu_counter_sync(struct percpu_counter *fbc);
 
@@ -196,11 +195,6 @@ static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
        return percpu_counter_read(fbc);
 }
 
-static inline s64 percpu_counter_sum_all(struct percpu_counter *fbc)
-{
-       return percpu_counter_read(fbc);
-}
-
 static inline bool percpu_counter_initialized(struct percpu_counter *fbc)
 {
        return true;
index 36bf0bbc8efa0cd33c73d96e08d5758bd8089b32..db7c0bd67559dc3e0af53a89df938b302eb2f97b 100644 (file)
@@ -1547,7 +1547,7 @@ int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id);
 struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
 struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
 struct phy_device *device_phy_find_device(struct device *dev);
-struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode);
+struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
 void phy_device_free(struct phy_device *phydev);
index c492c26202b5b89a535273ba16b5a86f25581997..637698ed5cb6cb00ce313adaee94f99ee6341429 100644 (file)
@@ -574,6 +574,7 @@ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
                               phy_interface_t iface,
                               const struct phylink_mac_ops *mac_ops);
 void phylink_destroy(struct phylink *);
+bool phylink_expects_phy(struct phylink *pl);
 
 int phylink_connect_phy(struct phylink *, struct phy_device *);
 int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
index 343abf22092e6b54a973dc6d457e06e317e6c9ed..b75de288a8c29ac47f10137078e094fe2a63fbe9 100644 (file)
@@ -80,6 +80,7 @@ extern struct pid *pidfd_pid(const struct file *file);
 struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags);
 struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags);
 int pidfd_create(struct pid *pid, unsigned int flags);
+int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret);
 
 static inline struct pid *get_pid(struct pid *pid)
 {
index 2c6e99ca48afcabb14c1800ff9ac4eb24c6edf7c..d607f51404fca063e4134bdba93bde6265be7d45 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/alarmtimer.h>
 #include <linux/timerqueue.h>
 
@@ -62,16 +63,18 @@ static inline int clockid_to_fd(const clockid_t clk)
  * cpu_timer - Posix CPU timer representation for k_itimer
  * @node:      timerqueue node to queue in the task/sig
  * @head:      timerqueue head on which this timer is queued
- * @task:      Pointer to target task
+ * @pid:       Pointer to target task PID
  * @elist:     List head for the expiry list
  * @firing:    Timer is currently firing
+ * @handling:  Pointer to the task which handles expiry
  */
 struct cpu_timer {
-       struct timerqueue_node  node;
-       struct timerqueue_head  *head;
-       struct pid              *pid;
-       struct list_head        elist;
-       int                     firing;
+       struct timerqueue_node          node;
+       struct timerqueue_head          *head;
+       struct pid                      *pid;
+       struct list_head                elist;
+       int                             firing;
+       struct task_struct __rcu        *handling;
 };
 
 static inline bool cpu_timer_enqueue(struct timerqueue_head *head,
@@ -135,10 +138,12 @@ struct posix_cputimers {
 /**
  * posix_cputimers_work - Container for task work based posix CPU timer expiry
  * @work:      The task work to be scheduled
+ * @mutex:     Mutex held around expiry in context of this task work
  * @scheduled:  @work has been scheduled already, no further processing
  */
 struct posix_cputimers_work {
        struct callback_head    work;
+       struct mutex            mutex;
        unsigned int            scheduled;
 };
 
index 21cc29b8a9e8d18000702316773d04a11d6d9ed9..0e65b3d634d9afd330ccfff3263142ffa1457aec 100644 (file)
@@ -106,6 +106,8 @@ struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap,
                              struct dentry *dentry, const char *acl_name);
 int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
                   const char *acl_name);
+int posix_acl_listxattr(struct inode *inode, char **buffer,
+                       ssize_t *remaining_size);
 #else
 static inline int posix_acl_chmod(struct mnt_idmap *idmap,
                                  struct dentry *dentry, umode_t mode)
@@ -153,6 +155,11 @@ static inline int vfs_remove_acl(struct mnt_idmap *idmap,
 {
        return -EOPNOTSUPP;
 }
+static inline int posix_acl_listxattr(struct inode *inode, char **buffer,
+                                     ssize_t *remaining_size)
+{
+       return 0;
+}
 #endif /* CONFIG_FS_POSIX_ACL */
 
 struct posix_acl *get_inode_acl(struct inode *inode, int type);
index 54cd7a14330dd5689a725f98fd0b787336b2a464..e86f3b731da25ced707633d252ccb62b14216598 100644 (file)
@@ -68,7 +68,8 @@ static inline int posix_acl_type(const char *name)
        return -1;
 }
 
-extern const struct xattr_handler posix_acl_access_xattr_handler;
-extern const struct xattr_handler posix_acl_default_xattr_handler;
+/* These are legacy handlers. Don't use them for new code. */
+extern const struct xattr_handler nop_posix_acl_access;
+extern const struct xattr_handler nop_posix_acl_default;
 
 #endif /* _POSIX_ACL_XATTR_H */
index 75807ecef880f1b12f690da75717e61600f50318..49539bc416cecb7b45bfd4f11df817cd11f2e791 100644 (file)
@@ -72,7 +72,6 @@ static inline int ns_alloc_inum(struct ns_common *ns)
 
 #define ns_free_inum(ns) proc_free_inum((ns)->inum)
 
-extern struct file *proc_ns_fget(int fd);
 #define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
 extern int ns_get_path(struct path *path, struct task_struct *task,
                        const struct proc_ns_operations *ns_ops);
index 92ad75549e9cdbabb78cd9c6cc7e4c2356cf850a..b6e6378dcbbd7070200a709e32fe7553d614d9f9 100644 (file)
@@ -25,7 +25,8 @@ void rtmsg_ifinfo_newnet(int type, struct net_device *dev, unsigned int change,
 struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
                                       unsigned change, u32 event,
                                       gfp_t flags, int *new_nsid,
-                                      int new_ifindex, u32 portid, u32 seq);
+                                      int new_ifindex, u32 portid,
+                                      const struct nlmsghdr *nlh);
 void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev,
                       gfp_t flags, u32 portid, const struct nlmsghdr *nlh);
 
index 63d242164b1a91af1fcb89c3cf6e146b32cda391..e1e605b1255b8c2ed1a78bdc517b8c51f1a344c2 100644 (file)
@@ -1729,7 +1729,7 @@ extern struct pid *cad_pid;
 #define PF_MEMALLOC            0x00000800      /* Allocating memory */
 #define PF_NPROC_EXCEEDED      0x00001000      /* set_user() noticed that RLIMIT_NPROC was exceeded */
 #define PF_USED_MATH           0x00002000      /* If unset the fpu must be initialized before use */
-#define PF__HOLE__00004000     0x00004000
+#define PF_USER_WORKER         0x00004000      /* Kernel thread cloned from userspace thread */
 #define PF_NOFREEZE            0x00008000      /* This thread should not be frozen */
 #define PF__HOLE__00010000     0x00010000
 #define PF_KSWAPD              0x00020000      /* I am kswapd */
index 357e0068497c162b097a18099922ae23a20c7015..537cbf9a2adeab8ef6bc372474ab63afe292d74d 100644 (file)
@@ -23,7 +23,13 @@ struct kernel_clone_args {
        int __user *pidfd;
        int __user *child_tid;
        int __user *parent_tid;
+       const char *name;
        int exit_signal;
+       u32 kthread:1;
+       u32 io_thread:1;
+       u32 user_worker:1;
+       u32 no_files:1;
+       u32 ignore_signals:1;
        unsigned long stack;
        unsigned long stack_size;
        unsigned long tls;
@@ -31,8 +37,6 @@ struct kernel_clone_args {
        /* Number of elements in *set_tid */
        size_t set_tid_size;
        int cgroup;
-       int io_thread;
-       int kthread;
        int idle;
        int (*fn)(void *);
        void *fn_arg;
@@ -89,9 +93,12 @@ extern void exit_files(struct task_struct *);
 extern void exit_itimers(struct task_struct *);
 
 extern pid_t kernel_clone(struct kernel_clone_args *kargs);
+struct task_struct *copy_process(struct pid *pid, int trace, int node,
+                                struct kernel_clone_args *args);
 struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node);
 struct task_struct *fork_idle(int);
-extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+extern pid_t kernel_thread(int (*fn)(void *), void *arg, const char *name,
+                           unsigned long flags);
 extern pid_t user_mode_thread(int (*fn)(void *), void *arg, unsigned long flags);
 extern long kernel_wait4(pid_t, int __user *, int, struct rusage *);
 int kernel_wait(pid_t pid, int *stat);
diff --git a/include/linux/sched/vhost_task.h b/include/linux/sched/vhost_task.h
new file mode 100644 (file)
index 0000000..6123c10
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_VHOST_TASK_H
+#define _LINUX_VHOST_TASK_H
+
+#include <linux/completion.h>
+
+struct task_struct;
+
+struct vhost_task {
+       int (*fn)(void *data);
+       void *data;
+       struct completion exited;
+       unsigned long flags;
+       struct task_struct *task;
+};
+
+struct vhost_task *vhost_task_create(int (*fn)(void *), void *arg,
+                                    const char *name);
+void vhost_task_start(struct vhost_task *vtsk);
+void vhost_task_stop(struct vhost_task *vtsk);
+bool vhost_task_should_stop(struct vhost_task *vtsk);
+
+#endif
index 5984d0d550b41bc1b134b63b67af46b4653eb710..e2734e9e44d5c7a4145712aa29b1bd163e598a12 100644 (file)
@@ -68,7 +68,7 @@ struct watch_notification;
 /* If capable is being called by a setid function */
 #define CAP_OPT_INSETID BIT(2)
 
-/* LSM Agnostic defines for fs_context::lsm_flags */
+/* LSM Agnostic defines for security_sb_set_mnt_opts() flags */
 #define SECURITY_LSM_NATIVE_LABELS     1
 
 struct ctl_table;
@@ -336,9 +336,6 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 int security_inode_init_security_anon(struct inode *inode,
                                      const struct qstr *name,
                                      const struct inode *context_inode);
-int security_old_inode_init_security(struct inode *inode, struct inode *dir,
-                                    const struct qstr *qstr, const char **name,
-                                    void **value, size_t *len);
 int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode);
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry);
@@ -778,15 +775,6 @@ static inline int security_inode_init_security_anon(struct inode *inode,
        return 0;
 }
 
-static inline int security_old_inode_init_security(struct inode *inode,
-                                                  struct inode *dir,
-                                                  const struct qstr *qstr,
-                                                  const char **name,
-                                                  void **value, size_t *len)
-{
-       return -EOPNOTSUPP;
-}
-
 static inline int security_inode_create(struct inode *dir,
                                         struct dentry *dentry,
                                         umode_t mode)
index 52b98f9666a2fc676ea51cee559c75d24c8a9e11..ef06a195b3c2bc588f485364d3a6bd86f992dec5 100644 (file)
@@ -557,7 +557,7 @@ int sfp_get_module_eeprom_by_page(struct sfp_bus *bus,
 void sfp_upstream_start(struct sfp_bus *bus);
 void sfp_upstream_stop(struct sfp_bus *bus);
 void sfp_bus_put(struct sfp_bus *bus);
-struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode);
+struct sfp_bus *sfp_bus_find_fwnode(const struct fwnode_handle *fwnode);
 int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
                         const struct sfp_upstream_ops *ops);
 void sfp_bus_del_upstream(struct sfp_bus *bus);
@@ -619,7 +619,8 @@ static inline void sfp_bus_put(struct sfp_bus *bus)
 {
 }
 
-static inline struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
+static inline struct sfp_bus *
+sfp_bus_find_fwnode(const struct fwnode_handle *fwnode)
 {
        return NULL;
 }
index ff7ad331fb8259fd06c07913dfa197d7ac448390..dbcaac8b696653e07961a94715ab63009295b21b 100644 (file)
@@ -294,6 +294,7 @@ struct nf_bridge_info {
        u8                      pkt_otherhost:1;
        u8                      in_prerouting:1;
        u8                      bridged_dnat:1;
+       u8                      sabotage_in_done:1;
        __u16                   frag_max_size;
        struct net_device       *physindev;
 
@@ -4712,7 +4713,7 @@ static inline void nf_reset_ct(struct sk_buff *skb)
 
 static inline void nf_reset_trace(struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || IS_ENABLED(CONFIG_NF_TABLES)
        skb->nf_trace = 0;
 #endif
 }
@@ -4732,7 +4733,7 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
        dst->_nfct = src->_nfct;
        nf_conntrack_get(skb_nfct(src));
 #endif
-#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || IS_ENABLED(CONFIG_NF_TABLES)
        if (copy)
                dst->nf_trace = src->nf_trace;
 #endif
index 2b498f4f394649551ecc0783aa57e566004429bb..649955d2cf5cdd89de731d4b402d7bda22e0f93c 100644 (file)
@@ -27,6 +27,8 @@ struct cmdq_client {
        struct mbox_chan *chan;
 };
 
+#if IS_ENABLED(CONFIG_MTK_CMDQ)
+
 /**
  * cmdq_dev_get_client_reg() - parse cmdq client reg from the device
  *                            node of CMDQ client
@@ -277,4 +279,116 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt);
  */
 int cmdq_pkt_flush_async(struct cmdq_pkt *pkt);
 
+#else /* IS_ENABLED(CONFIG_MTK_CMDQ) */
+
+static inline int cmdq_dev_get_client_reg(struct device *dev,
+                                         struct cmdq_client_reg *client_reg, int idx)
+{
+       return -ENODEV;
+}
+
+static inline struct cmdq_client *cmdq_mbox_create(struct device *dev, int index)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline void cmdq_mbox_destroy(struct cmdq_client *client) { }
+
+static inline  struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline void cmdq_pkt_destroy(struct cmdq_pkt *pkt) { }
+
+static inline int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys,
+                                     u16 offset, u32 value, u32 mask)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_read_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
+                                 u16 addr_low, u16 reg_idx)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
+                                  u16 addr_low, u16 src_reg_idx)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s_mask(struct cmdq_pkt *pkt, u16 high_addr_reg_idx,
+                                       u16 addr_low, u16 src_reg_idx, u32 mask)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
+                                        u16 addr_low, u32 value)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_write_s_mask_value(struct cmdq_pkt *pkt, u8 high_addr_reg_idx,
+                                             u16 addr_low, u32 value, u32 mask)
+{
+       return -ENOENT;
+}
+
+static inline int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event, bool clear)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_set_event(struct cmdq_pkt *pkt, u16 event)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_poll(struct cmdq_pkt *pkt, u8 subsys,
+                               u16 offset, u32 value)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_poll_mask(struct cmdq_pkt *pkt, u8 subsys,
+                                    u16 offset, u32 value, u32 mask)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_assign(struct cmdq_pkt *pkt, u16 reg_idx, u32 value)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
+{
+       return -EINVAL;
+}
+
+static inline int cmdq_pkt_flush_async(struct cmdq_pkt *pkt)
+{
+       return -EINVAL;
+}
+
+#endif /* IS_ENABLED(CONFIG_MTK_CMDQ) */
+
 #endif /* __MTK_CMDQ_H__ */
index dc2963a0a0f7ea71def09bf8d0b1b6ba6ed01a1f..37544ea6286d87dcf7f399bf0d413df3bd097774 100644 (file)
@@ -99,4 +99,10 @@ void mtk_mmsys_mixer_in_config(struct device *dev, int idx, bool alpha_sel, u16
 void mtk_mmsys_mixer_in_channel_swap(struct device *dev, int idx, bool channel_swap,
                                     struct cmdq_pkt *cmdq_pkt);
 
+void mtk_mmsys_vpp_rsz_merge_config(struct device *dev, u32 id, bool enable,
+                                   struct cmdq_pkt *cmdq_pkt);
+
+void mtk_mmsys_vpp_rsz_dcm_config(struct device *dev, bool enable,
+                                 struct cmdq_pkt *cmdq_pkt);
+
 #endif /* __MTK_MMSYS_H */
index b335c2837cd8b074503c3d7f67862f4d546b88b6..635218e3ac68a268f5b04fb7ad8e4d2d6eb51484 100644 (file)
@@ -22,6 +22,41 @@ enum mtk_mutex_mod_index {
        MUTEX_MOD_IDX_MDP_CCORR0,
        MUTEX_MOD_IDX_MDP_HDR0,
        MUTEX_MOD_IDX_MDP_COLOR0,
+       MUTEX_MOD_IDX_MDP_RDMA1,
+       MUTEX_MOD_IDX_MDP_RDMA2,
+       MUTEX_MOD_IDX_MDP_RDMA3,
+       MUTEX_MOD_IDX_MDP_STITCH0,
+       MUTEX_MOD_IDX_MDP_FG0,
+       MUTEX_MOD_IDX_MDP_FG1,
+       MUTEX_MOD_IDX_MDP_FG2,
+       MUTEX_MOD_IDX_MDP_FG3,
+       MUTEX_MOD_IDX_MDP_HDR1,
+       MUTEX_MOD_IDX_MDP_HDR2,
+       MUTEX_MOD_IDX_MDP_HDR3,
+       MUTEX_MOD_IDX_MDP_AAL1,
+       MUTEX_MOD_IDX_MDP_AAL2,
+       MUTEX_MOD_IDX_MDP_AAL3,
+       MUTEX_MOD_IDX_MDP_RSZ2,
+       MUTEX_MOD_IDX_MDP_RSZ3,
+       MUTEX_MOD_IDX_MDP_MERGE2,
+       MUTEX_MOD_IDX_MDP_MERGE3,
+       MUTEX_MOD_IDX_MDP_TDSHP1,
+       MUTEX_MOD_IDX_MDP_TDSHP2,
+       MUTEX_MOD_IDX_MDP_TDSHP3,
+       MUTEX_MOD_IDX_MDP_COLOR1,
+       MUTEX_MOD_IDX_MDP_COLOR2,
+       MUTEX_MOD_IDX_MDP_COLOR3,
+       MUTEX_MOD_IDX_MDP_OVL0,
+       MUTEX_MOD_IDX_MDP_OVL1,
+       MUTEX_MOD_IDX_MDP_PAD0,
+       MUTEX_MOD_IDX_MDP_PAD1,
+       MUTEX_MOD_IDX_MDP_PAD2,
+       MUTEX_MOD_IDX_MDP_PAD3,
+       MUTEX_MOD_IDX_MDP_TCC0,
+       MUTEX_MOD_IDX_MDP_TCC1,
+       MUTEX_MOD_IDX_MDP_WROT1,
+       MUTEX_MOD_IDX_MDP_WROT2,
+       MUTEX_MOD_IDX_MDP_WROT3,
 
        MUTEX_MOD_IDX_MAX               /* ALWAYS keep at the end */
 };
index 400213daa461d5998e106871065529c2f87ab92a..c55a0bc8cb0e908f41f04d746fb6d00cf49938e7 100644 (file)
@@ -245,12 +245,22 @@ struct geni_se {
 /* SE_HW_PARAM_0 fields */
 #define TX_FIFO_WIDTH_MSK              GENMASK(29, 24)
 #define TX_FIFO_WIDTH_SHFT             24
+/*
+ * For QUP HW Version >= 3.10 Tx fifo depth support is increased
+ * to 256bytes and corresponding bits are 16 to 23
+ */
+#define TX_FIFO_DEPTH_MSK_256_BYTES    GENMASK(23, 16)
 #define TX_FIFO_DEPTH_MSK              GENMASK(21, 16)
 #define TX_FIFO_DEPTH_SHFT             16
 
 /* SE_HW_PARAM_1 fields */
 #define RX_FIFO_WIDTH_MSK              GENMASK(29, 24)
 #define RX_FIFO_WIDTH_SHFT             24
+/*
+ * For QUP HW Version >= 3.10 Rx fifo depth support is increased
+ * to 256bytes and corresponding bits are 16 to 23
+ */
+#define RX_FIFO_DEPTH_MSK_256_BYTES    GENMASK(23, 16)
 #define RX_FIFO_DEPTH_MSK              GENMASK(21, 16)
 #define RX_FIFO_DEPTH_SHFT             16
 
@@ -391,7 +401,8 @@ static inline void geni_se_abort_s_cmd(struct geni_se *se)
 
 /**
  * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine
- * @se:        Pointer to the concerned serial engine.
+ * based on QUP HW version
+ * @se: Pointer to the concerned serial engine.
  *
  * This function is used to get the depth i.e. number of elements in the
  * TX fifo of the serial engine.
@@ -400,11 +411,20 @@ static inline void geni_se_abort_s_cmd(struct geni_se *se)
  */
 static inline u32 geni_se_get_tx_fifo_depth(struct geni_se *se)
 {
-       u32 val;
+       u32 val, hw_version, hw_major, hw_minor, tx_fifo_depth_mask;
+
+       hw_version = geni_se_get_qup_hw_version(se);
+       hw_major = GENI_SE_VERSION_MAJOR(hw_version);
+       hw_minor = GENI_SE_VERSION_MINOR(hw_version);
+
+       if ((hw_major == 3 && hw_minor >= 10) || hw_major > 3)
+               tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK_256_BYTES;
+       else
+               tx_fifo_depth_mask = TX_FIFO_DEPTH_MSK;
 
        val = readl_relaxed(se->base + SE_HW_PARAM_0);
 
-       return (val & TX_FIFO_DEPTH_MSK) >> TX_FIFO_DEPTH_SHFT;
+       return (val & tx_fifo_depth_mask) >> TX_FIFO_DEPTH_SHFT;
 }
 
 /**
@@ -427,7 +447,8 @@ static inline u32 geni_se_get_tx_fifo_width(struct geni_se *se)
 
 /**
  * geni_se_get_rx_fifo_depth() - Get the RX fifo depth of the serial engine
- * @se:        Pointer to the concerned serial engine.
+ * based on QUP HW version
+ * @se: Pointer to the concerned serial engine.
  *
  * This function is used to get the depth i.e. number of elements in the
  * RX fifo of the serial engine.
@@ -436,11 +457,20 @@ static inline u32 geni_se_get_tx_fifo_width(struct geni_se *se)
  */
 static inline u32 geni_se_get_rx_fifo_depth(struct geni_se *se)
 {
-       u32 val;
+       u32 val, hw_version, hw_major, hw_minor, rx_fifo_depth_mask;
+
+       hw_version = geni_se_get_qup_hw_version(se);
+       hw_major = GENI_SE_VERSION_MAJOR(hw_version);
+       hw_minor = GENI_SE_VERSION_MINOR(hw_version);
+
+       if ((hw_major == 3 && hw_minor >= 10) || hw_major > 3)
+               rx_fifo_depth_mask = RX_FIFO_DEPTH_MSK_256_BYTES;
+       else
+               rx_fifo_depth_mask = RX_FIFO_DEPTH_MSK;
 
        val = readl_relaxed(se->base + SE_HW_PARAM_1);
 
-       return (val & RX_FIFO_DEPTH_MSK) >> RX_FIFO_DEPTH_SHFT;
+       return (val & rx_fifo_depth_mask) >> RX_FIFO_DEPTH_SHFT;
 }
 
 void geni_se_init(struct geni_se *se, u32 rx_wm, u32 rx_rfr);
index ad1fd718169d9750fe07b3a05623398c95bfdb19..423220e66026252630bfd065bfd08bd4ab05b457 100644 (file)
@@ -120,7 +120,7 @@ struct llcc_edac_reg_offset {
 
 /**
  * struct llcc_drv_data - Data associated with the llcc driver
- * @regmap: regmap associated with the llcc device
+ * @regmaps: regmaps associated with the llcc device
  * @bcast_regmap: regmap associated with llcc broadcast offset
  * @cfg: pointer to the data structure for slice configuration
  * @edac_reg_offset: Offset of the LLCC EDAC registers
@@ -129,12 +129,11 @@ struct llcc_edac_reg_offset {
  * @max_slices: max slices as read from device tree
  * @num_banks: Number of llcc banks
  * @bitmap: Bit map to track the active slice ids
- * @offsets: Pointer to the bank offsets array
  * @ecc_irq: interrupt for llcc cache error detection and reporting
  * @version: Indicates the LLCC version
  */
 struct llcc_drv_data {
-       struct regmap *regmap;
+       struct regmap **regmaps;
        struct regmap *bcast_regmap;
        const struct llcc_slice_config *cfg;
        const struct llcc_edac_reg_offset *edac_reg_offset;
@@ -143,7 +142,6 @@ struct llcc_drv_data {
        u32 max_slices;
        u32 num_banks;
        unsigned long *bitmap;
-       u32 *offsets;
        int ecc_irq;
        u32 version;
 };
index 74796cd7e7a9d20d2cf5d3c50c66fc422e0832da..41c4b26fb1c1949f08b59426192813cfe10a3c9f 100644 (file)
@@ -102,6 +102,32 @@ static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
        return lock_is_held(&ssp->dep_map);
 }
 
+/*
+ * Annotations provide deadlock detection for SRCU.
+ *
+ * Similar to other lockdep annotations, except there is an additional
+ * srcu_lock_sync(), which is basically an empty *write*-side critical section,
+ * see lock_sync() for more information.
+ */
+
+/* Annotates a srcu_read_lock() */
+static inline void srcu_lock_acquire(struct lockdep_map *map)
+{
+       lock_map_acquire_read(map);
+}
+
+/* Annotates a srcu_read_lock() */
+static inline void srcu_lock_release(struct lockdep_map *map)
+{
+       lock_map_release(map);
+}
+
+/* Annotates a synchronize_srcu() */
+static inline void srcu_lock_sync(struct lockdep_map *map)
+{
+       lock_map_sync(map);
+}
+
 #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
@@ -109,6 +135,10 @@ static inline int srcu_read_lock_held(const struct srcu_struct *ssp)
        return 1;
 }
 
+#define srcu_lock_acquire(m) do { } while (0)
+#define srcu_lock_release(m) do { } while (0)
+#define srcu_lock_sync(m) do { } while (0)
+
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 #define SRCU_NMI_UNKNOWN       0x0
@@ -182,7 +212,7 @@ static inline int srcu_read_lock(struct srcu_struct *ssp) __acquires(ssp)
 
        srcu_check_nmi_safety(ssp, false);
        retval = __srcu_read_lock(ssp);
-       rcu_lock_acquire(&(ssp)->dep_map);
+       srcu_lock_acquire(&(ssp)->dep_map);
        return retval;
 }
 
@@ -254,7 +284,7 @@ static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)
 {
        WARN_ON_ONCE(idx & ~0x1);
        srcu_check_nmi_safety(ssp, false);
-       rcu_lock_release(&(ssp)->dep_map);
+       srcu_lock_release(&(ssp)->dep_map);
        __srcu_read_unlock(ssp, idx);
 }
 
index 5aa5e0faf6a121a2770e6362cf368ce3efceefc7..ebd72491af99246cae9287b2c8a27e40ccb4c540 100644 (file)
@@ -31,7 +31,7 @@ struct srcu_struct {
 
 void srcu_drive_gp(struct work_struct *wp);
 
-#define __SRCU_STRUCT_INIT(name, __ignored)                            \
+#define __SRCU_STRUCT_INIT(name, __ignored, ___ignored)                        \
 {                                                                      \
        .srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq),        \
        .srcu_cb_tail = &name.srcu_cb_head,                             \
@@ -44,9 +44,9 @@ void srcu_drive_gp(struct work_struct *wp);
  * Tree SRCU, which needs some per-CPU data.
  */
 #define DEFINE_SRCU(name) \
-       struct srcu_struct name = __SRCU_STRUCT_INIT(name, name)
+       struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name)
 #define DEFINE_STATIC_SRCU(name) \
-       static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name)
+       static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name, name)
 
 void synchronize_srcu(struct srcu_struct *ssp);
 
index 558057b517b74cf5892d85ba95872f15ad42e1ce..8f3f72480e78b0d467167c777592e6472e3485e7 100644 (file)
@@ -58,9 +58,9 @@ struct srcu_node {
 };
 
 /*
- * Per-SRCU-domain structure, similar in function to rcu_state.
+ * Per-SRCU-domain structure, update-side data linked from srcu_struct.
  */
-struct srcu_struct {
+struct srcu_usage {
        struct srcu_node *node;                 /* Combining tree. */
        struct srcu_node *level[RCU_NUM_LVLS + 1];
                                                /* First node at each level. */
@@ -68,7 +68,6 @@ struct srcu_struct {
        struct mutex srcu_cb_mutex;             /* Serialize CB preparation. */
        spinlock_t __private lock;              /* Protect counters and size state. */
        struct mutex srcu_gp_mutex;             /* Serialize GP work. */
-       unsigned int srcu_idx;                  /* Current rdr array element. */
        unsigned long srcu_gp_seq;              /* Grace-period seq #. */
        unsigned long srcu_gp_seq_needed;       /* Latest gp_seq needed. */
        unsigned long srcu_gp_seq_needed_exp;   /* Furthest future exp GP. */
@@ -77,7 +76,6 @@ struct srcu_struct {
        unsigned long srcu_size_jiffies;        /* Current contention-measurement interval. */
        unsigned long srcu_n_lock_retries;      /* Contention events in current interval. */
        unsigned long srcu_n_exp_nodelay;       /* # expedited no-delays in current GP phase. */
-       struct srcu_data __percpu *sda;         /* Per-CPU srcu_data array. */
        bool sda_is_static;                     /* May ->sda be passed to free_percpu()? */
        unsigned long srcu_barrier_seq;         /* srcu_barrier seq #. */
        struct mutex srcu_barrier_mutex;        /* Serialize barrier ops. */
@@ -89,32 +87,68 @@ struct srcu_struct {
        unsigned long reschedule_jiffies;
        unsigned long reschedule_count;
        struct delayed_work work;
+       struct srcu_struct *srcu_ssp;
+};
+
+/*
+ * Per-SRCU-domain structure, similar in function to rcu_state.
+ */
+struct srcu_struct {
+       unsigned int srcu_idx;                  /* Current rdr array element. */
+       struct srcu_data __percpu *sda;         /* Per-CPU srcu_data array. */
        struct lockdep_map dep_map;
+       struct srcu_usage *srcu_sup;            /* Update-side data. */
 };
 
-/* Values for size state variable (->srcu_size_state). */
-#define SRCU_SIZE_SMALL                0
-#define SRCU_SIZE_ALLOC                1
-#define SRCU_SIZE_WAIT_BARRIER 2
-#define SRCU_SIZE_WAIT_CALL    3
-#define SRCU_SIZE_WAIT_CBS1    4
-#define SRCU_SIZE_WAIT_CBS2    5
-#define SRCU_SIZE_WAIT_CBS3    6
-#define SRCU_SIZE_WAIT_CBS4    7
-#define SRCU_SIZE_BIG          8
+// Values for size state variable (->srcu_size_state).  Once the state
+// has been set to SRCU_SIZE_ALLOC, the grace-period code advances through
+// this state machine one step per grace period until the SRCU_SIZE_BIG state
+// is reached.  Otherwise, the state machine remains in the SRCU_SIZE_SMALL
+// state indefinitely.
+#define SRCU_SIZE_SMALL                0       // No srcu_node combining tree, ->node == NULL
+#define SRCU_SIZE_ALLOC                1       // An srcu_node tree is being allocated, initialized,
+                                       //  and then referenced by ->node.  It will not be used.
+#define SRCU_SIZE_WAIT_BARRIER 2       // The srcu_node tree starts being used by everything
+                                       //  except call_srcu(), especially by srcu_barrier().
+                                       //  By the end of this state, all CPUs and threads
+                                       //  are aware of this tree's existence.
+#define SRCU_SIZE_WAIT_CALL    3       // The srcu_node tree starts being used by call_srcu().
+                                       //  By the end of this state, all of the call_srcu()
+                                       //  invocations that were running on a non-boot CPU
+                                       //  and using the boot CPU's callback queue will have
+                                       //  completed.
+#define SRCU_SIZE_WAIT_CBS1    4       // Don't trust the ->srcu_have_cbs[] grace-period
+#define SRCU_SIZE_WAIT_CBS2    5       //  sequence elements or the ->srcu_data_have_cbs[]
+#define SRCU_SIZE_WAIT_CBS3    6       //  CPU-bitmask elements until all four elements of
+#define SRCU_SIZE_WAIT_CBS4    7       //  each array have been initialized.
+#define SRCU_SIZE_BIG          8       // The srcu_node combining tree is fully initialized
+                                       //  and all aspects of it are being put to use.
 
 /* Values for state variable (bottom bits of ->srcu_gp_seq). */
 #define SRCU_STATE_IDLE                0
 #define SRCU_STATE_SCAN1       1
 #define SRCU_STATE_SCAN2       2
 
-#define __SRCU_STRUCT_INIT(name, pcpu_name)                            \
-{                                                                      \
-       .sda = &pcpu_name,                                              \
-       .lock = __SPIN_LOCK_UNLOCKED(name.lock),                        \
-       .srcu_gp_seq_needed = -1UL,                                     \
-       .work = __DELAYED_WORK_INITIALIZER(name.work, NULL, 0),         \
-       __SRCU_DEP_MAP_INIT(name)                                       \
+#define __SRCU_USAGE_INIT(name)                                                                        \
+{                                                                                              \
+       .lock = __SPIN_LOCK_UNLOCKED(name.lock),                                                \
+       .srcu_gp_seq_needed = -1UL,                                                             \
+       .work = __DELAYED_WORK_INITIALIZER(name.work, NULL, 0),                                 \
+}
+
+#define __SRCU_STRUCT_INIT_COMMON(name, usage_name)                                            \
+       .srcu_sup = &usage_name,                                                                \
+       __SRCU_DEP_MAP_INIT(name)
+
+#define __SRCU_STRUCT_INIT_MODULE(name, usage_name)                                            \
+{                                                                                              \
+       __SRCU_STRUCT_INIT_COMMON(name, usage_name)                                             \
+}
+
+#define __SRCU_STRUCT_INIT(name, usage_name, pcpu_name)                                                \
+{                                                                                              \
+       .sda = &pcpu_name,                                                                      \
+       __SRCU_STRUCT_INIT_COMMON(name, usage_name)                                             \
 }
 
 /*
@@ -137,16 +171,18 @@ struct srcu_struct {
  * See include/linux/percpu-defs.h for the rules on per-CPU variables.
  */
 #ifdef MODULE
-# define __DEFINE_SRCU(name, is_static)                                        \
-       is_static struct srcu_struct name;                              \
-       extern struct srcu_struct * const __srcu_struct_##name;         \
-       struct srcu_struct * const __srcu_struct_##name                 \
+# define __DEFINE_SRCU(name, is_static)                                                                \
+       static struct srcu_usage name##_srcu_usage = __SRCU_USAGE_INIT(name##_srcu_usage);      \
+       is_static struct srcu_struct name = __SRCU_STRUCT_INIT_MODULE(name, name##_srcu_usage); \
+       extern struct srcu_struct * const __srcu_struct_##name;                                 \
+       struct srcu_struct * const __srcu_struct_##name                                         \
                __section("___srcu_struct_ptrs") = &name
 #else
-# define __DEFINE_SRCU(name, is_static)                                        \
-       static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data);      \
-       is_static struct srcu_struct name =                             \
-               __SRCU_STRUCT_INIT(name, name##_srcu_data)
+# define __DEFINE_SRCU(name, is_static)                                                                \
+       static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data);                              \
+       static struct srcu_usage name##_srcu_usage = __SRCU_USAGE_INIT(name##_srcu_usage);      \
+       is_static struct srcu_struct name =                                                     \
+               __SRCU_STRUCT_INIT(name, name##_srcu_usage, name##_srcu_data)
 #endif
 #define DEFINE_SRCU(name)              __DEFINE_SRCU(name, /* not static */)
 #define DEFINE_STATIC_SRCU(name)       __DEFINE_SRCU(name, static)
index a152678b82b714bd53f59764a8772627c8e25a05..a2414c18748370f40c0e8d99c0056e56103a26af 100644 (file)
@@ -215,7 +215,7 @@ struct plat_stmmacenet_data {
        int unicast_filter_entries;
        int tx_fifo_size;
        int rx_fifo_size;
-       u32 addr64;
+       u32 host_dma_width;
        u32 rx_queues_to_use;
        u32 tx_queues_to_use;
        u8 rx_sched_algorithm;
index a0ae443fb7df60e6812a846ebac8806e8157d53f..641ca8880995ea694aae9c4496ad4310e1f77ff5 100644 (file)
@@ -22,6 +22,12 @@ int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
 #define clear_syscall_work_syscall_user_dispatch(tsk) \
        clear_task_syscall_work(tsk, SYSCALL_USER_DISPATCH)
 
+int syscall_user_dispatch_get_config(struct task_struct *task, unsigned long size,
+                                    void __user *data);
+
+int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long size,
+                                    void __user *data);
+
 #else
 struct syscall_user_dispatch {};
 
@@ -35,6 +41,18 @@ static inline void clear_syscall_work_syscall_user_dispatch(struct task_struct *
 {
 }
 
+static inline int syscall_user_dispatch_get_config(struct task_struct *task,
+                                                  unsigned long size, void __user *data)
+{
+       return -EINVAL;
+}
+
+static inline int syscall_user_dispatch_set_config(struct task_struct *task,
+                                                  unsigned long size, void __user *data)
+{
+       return -EINVAL;
+}
+
 #endif /* CONFIG_GENERIC_ENTRY */
 
 #endif /* _SYSCALL_USER_DISPATCH_H */
index 8ba8b5be5567511dfecf4386de133af14e359807..c1ef5fc60a3cba54d640a3e77dc419506801f42c 100644 (file)
@@ -70,11 +70,16 @@ static inline void sysfb_disable(void)
 #ifdef CONFIG_EFI
 
 extern struct efifb_dmi_info efifb_dmi_list[];
-void sysfb_apply_efi_quirks(struct platform_device *pd);
+void sysfb_apply_efi_quirks(void);
+void sysfb_set_efifb_fwnode(struct platform_device *pd);
 
 #else /* CONFIG_EFI */
 
-static inline void sysfb_apply_efi_quirks(struct platform_device *pd)
+static inline void sysfb_apply_efi_quirks(void)
+{
+}
+
+static inline void sysfb_set_efifb_fwnode(struct platform_device *pd)
 {
 }
 
index 2bb4bf33f4f32df80449108f53aaa7c193a75fb2..13c6aaed18df3e2f63a9da830f448e7575988c73 100644 (file)
@@ -384,6 +384,7 @@ devm_thermal_of_cooling_device_register(struct device *dev,
                                struct device_node *np,
                                char *type, void *devdata,
                                const struct thermal_cooling_device_ops *ops);
+void thermal_cooling_device_update(struct thermal_cooling_device *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
 struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name);
 int thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp);
index bfd571f18cfdc9c474139234aeceaa4244ebb1b1..9459fef5b85736d0c895a5643ae0d87feabbb41d 100644 (file)
@@ -216,6 +216,7 @@ extern void tick_nohz_dep_set_signal(struct task_struct *tsk,
                                     enum tick_dep_bits bit);
 extern void tick_nohz_dep_clear_signal(struct signal_struct *signal,
                                       enum tick_dep_bits bit);
+extern bool tick_nohz_cpu_hotpluggable(unsigned int cpu);
 
 /*
  * The below are tick_nohz_[set,clear]_dep() wrappers that optimize off-cases
@@ -280,6 +281,7 @@ static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
 
 static inline void tick_nohz_dep_set_cpu(int cpu, enum tick_dep_bits bit) { }
 static inline void tick_nohz_dep_clear_cpu(int cpu, enum tick_dep_bits bit) { }
+static inline bool tick_nohz_cpu_hotpluggable(unsigned int cpu) { return true; }
 
 static inline void tick_dep_set(enum tick_dep_bits bit) { }
 static inline void tick_dep_clear(enum tick_dep_bits bit) { }
index e299f29375bb7f1e55789adca45b45e31bebde84..6811e43c1b5c2afed0bad0a2e7469e8573916eb9 100644 (file)
@@ -242,12 +242,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
  * not add unwanted padding between the beginning of the section and the
  * structure. Force alignment to the same alignment as the section start.
  *
- * When lockdep is enabled, we make sure to always do the RCU portions of
- * the tracepoint code, regardless of whether tracing is on. However,
- * don't check if the condition is false, due to interaction with idle
- * instrumentation. This lets us find RCU issues triggered with tracepoints
- * even when this tracepoint is off. This code has no purpose other than
- * poking RCU a bit.
+ * When lockdep is enabled, we make sure to always test if RCU is
+ * "watching" regardless if the tracepoint is enabled or not. Tracepoints
+ * require RCU to be active, and it should always warn at the tracepoint
+ * site if it is not watching, as it will need to be active when the
+ * tracepoint is enabled.
  */
 #define __DECLARE_TRACE(name, proto, args, cond, data_proto)           \
        extern int __traceiter_##name(data_proto);                      \
@@ -260,9 +259,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                                TP_ARGS(args),                          \
                                TP_CONDITION(cond), 0);                 \
                if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) {             \
-                       rcu_read_lock_sched_notrace();                  \
-                       rcu_dereference_sched(__tracepoint_##name.funcs);\
-                       rcu_read_unlock_sched_notrace();                \
+                       WARN_ON_ONCE(!rcu_is_watching());               \
                }                                                       \
        }                                                               \
        __DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args),          \
index 27e3fd942960978b3bf1e461eb893f0c827a3f0f..ed35f4427a0ad48a9db9b941163b80f95c6fb4f9 100644 (file)
@@ -49,14 +49,35 @@ struct iov_iter {
                size_t iov_offset;
                int last_offset;
        };
-       size_t count;
+       /*
+        * Hack alert: overlay ubuf_iovec with iovec + count, so
+        * that the members resolve correctly regardless of the type
+        * of iterator used. This means that you can use:
+        *
+        * &iter->__ubuf_iovec or iter->__iov
+        *
+        * interchangably for the user_backed cases, hence simplifying
+        * some of the cases that need to deal with both.
+        */
        union {
-               const struct iovec *iov;
-               const struct kvec *kvec;
-               const struct bio_vec *bvec;
-               struct xarray *xarray;
-               struct pipe_inode_info *pipe;
-               void __user *ubuf;
+               /*
+                * This really should be a const, but we cannot do that without
+                * also modifying any of the zero-filling iter init functions.
+                * Leave it non-const for now, but it should be treated as such.
+                */
+               struct iovec __ubuf_iovec;
+               struct {
+                       union {
+                               /* use iter_iov() to get the current vec */
+                               const struct iovec *__iov;
+                               const struct kvec *kvec;
+                               const struct bio_vec *bvec;
+                               struct xarray *xarray;
+                               struct pipe_inode_info *pipe;
+                               void __user *ubuf;
+                       };
+                       size_t count;
+               };
        };
        union {
                unsigned long nr_segs;
@@ -68,6 +89,16 @@ struct iov_iter {
        };
 };
 
+static inline const struct iovec *iter_iov(const struct iov_iter *iter)
+{
+       if (iter->iter_type == ITER_UBUF)
+               return (const struct iovec *) &iter->__ubuf_iovec;
+       return iter->__iov;
+}
+
+#define iter_iov_addr(iter)    (iter_iov(iter)->iov_base + (iter)->iov_offset)
+#define iter_iov_len(iter)     (iter_iov(iter)->iov_len - (iter)->iov_offset)
+
 static inline enum iter_type iov_iter_type(const struct iov_iter *i)
 {
        return i->iter_type;
@@ -143,15 +174,6 @@ static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
        return ret;
 }
 
-static inline struct iovec iov_iter_iovec(const struct iov_iter *iter)
-{
-       return (struct iovec) {
-               .iov_base = iter->iov->iov_base + iter->iov_offset,
-               .iov_len = min(iter->count,
-                              iter->iov->iov_len - iter->iov_offset),
-       };
-}
-
 size_t copy_page_from_iter_atomic(struct page *page, unsigned offset,
                                  size_t bytes, struct iov_iter *i);
 void iov_iter_advance(struct iov_iter *i, size_t bytes);
@@ -359,7 +381,8 @@ static inline void iov_iter_ubuf(struct iov_iter *i, unsigned int direction,
                .user_backed = true,
                .data_source = direction,
                .ubuf = buf,
-               .count = count
+               .count = count,
+               .nr_segs = 1
        };
 }
 /* Flags for iov_iter_get/extract_pages*() */
index 6af72461397d425e9f99f33148450f06d6a9103e..d591ef59aa98efed1f6cda7d54a21f94ed828bc4 100644 (file)
@@ -47,6 +47,22 @@ struct xattr_handler {
                   size_t size, int flags);
 };
 
+/**
+ * xattr_handler_can_list - check whether xattr can be listed
+ * @handler: handler for this type of xattr
+ * @dentry: dentry whose inode xattr to list
+ *
+ * Determine whether the xattr associated with @dentry can be listed given
+ * @handler.
+ *
+ * Return: true if xattr can be listed, false if not.
+ */
+static inline bool xattr_handler_can_list(const struct xattr_handler *handler,
+                                         struct dentry *dentry)
+{
+       return handler && (!handler->list || handler->list(dentry));
+}
+
 const char *xattr_full_name(const struct xattr_handler *, const char *);
 
 struct xattr {
@@ -78,7 +94,7 @@ int vfs_getxattr_alloc(struct mnt_idmap *idmap,
                       struct dentry *dentry, const char *name,
                       char **xattr_value, size_t size, gfp_t flags);
 
-int xattr_supported_namespace(struct inode *inode, const char *prefix);
+int xattr_supports_user_prefix(struct inode *inode);
 
 static inline const char *xattr_prefix(const struct xattr_handler *handler)
 {
@@ -109,5 +125,6 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
                          char *buffer, size_t size);
 void simple_xattr_add(struct simple_xattrs *xattrs,
                      struct simple_xattr *new_xattr);
+int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name);
 
 #endif /* _LINUX_XATTR_H */
index 7254edfba4c9c43fd0ea2f6f44fe1b2d2083d2e4..d5311ceb21c62f30d302ecf8aa4ac16bc2edc062 100644 (file)
@@ -954,6 +954,7 @@ enum {
        HCI_CONN_STK_ENCRYPT,
        HCI_CONN_AUTH_INITIATOR,
        HCI_CONN_DROP,
+       HCI_CONN_CANCEL,
        HCI_CONN_PARAM_REMOVAL_PEND,
        HCI_CONN_NEW_LINK_KEY,
        HCI_CONN_SCANNING,
@@ -1613,6 +1614,7 @@ void hci_conn_add_sysfs(struct hci_conn *conn);
 void hci_conn_del_sysfs(struct hci_conn *conn);
 
 #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
+#define GET_HCIDEV_DEV(hdev) ((hdev)->dev.parent)
 
 /* ----- LMP capabilities ----- */
 #define lmp_encrypt_capable(dev)   ((dev)->features[0][0] & LMP_ENCRYPT)
index ea36ab7f9e724bd3650d7502c969ab1b8ba2f7ba..c3843239517d539c15985f38b4887a888c940d9d 100644 (file)
@@ -761,13 +761,17 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
 #if IS_ENABLED(CONFIG_IPV6)
 static inline int bond_get_targets_ip6(struct in6_addr *targets, struct in6_addr *ip)
 {
+       struct in6_addr mcaddr;
        int i;
 
-       for (i = 0; i < BOND_MAX_NS_TARGETS; i++)
-               if (ipv6_addr_equal(&targets[i], ip))
+       for (i = 0; i < BOND_MAX_NS_TARGETS; i++) {
+               addrconf_addr_solict_mult(&targets[i], &mcaddr);
+               if ((ipv6_addr_equal(&targets[i], ip)) ||
+                   (ipv6_addr_equal(&mcaddr, ip)))
                        return i;
                else if (ipv6_addr_any(&targets[i]))
                        break;
+       }
 
        return -1;
 }
index 9430128aae991144f6e24d7b373a04153d6e3f0e..1b8e305bb54aec82f71a79755ae166ed64387838 100644 (file)
@@ -1085,6 +1085,10 @@ struct nft_chain {
 };
 
 int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain);
+int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
+                        const struct nft_set_iter *iter,
+                        struct nft_set_elem *elem);
+int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
 
 enum nft_chain_types {
        NFT_CHAIN_T_DEFAULT = 0,
index 2c004c20ed996d1dbe07f2c8d25edd2ce03cca03..3af5289fdead9aa5eb517171a6bd5b4f63fe7390 100644 (file)
@@ -37,7 +37,7 @@ int raw_rcv(struct sock *, struct sk_buff *);
 struct raw_hashinfo {
        spinlock_t lock;
 
-       struct hlist_nulls_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned;
+       struct hlist_head ht[RAW_HTABLE_SIZE] ____cacheline_aligned;
 };
 
 static inline u32 raw_hashfunc(const struct net *net, u32 proto)
@@ -51,7 +51,7 @@ static inline void raw_hashinfo_init(struct raw_hashinfo *hashinfo)
 
        spin_lock_init(&hashinfo->lock);
        for (i = 0; i < RAW_HTABLE_SIZE; i++)
-               INIT_HLIST_NULLS_HEAD(&hashinfo->ht[i], i);
+               INIT_HLIST_HEAD(&hashinfo->ht[i]);
 }
 
 #ifdef CONFIG_PROC_FS
index d517bfac937b0a2bda248f594750fbb0c9a082ab..76aa748e792374abc91166561c072b18833e1a63 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/skbuff.h> /* skb_shared_info */
 #include <uapi/linux/netdev.h>
+#include <linux/bitfield.h>
 
 /**
  * DOC: XDP RX-queue information
@@ -425,15 +426,67 @@ XDP_METADATA_KFUNC_xxx
 MAX_XDP_METADATA_KFUNC,
 };
 
+enum xdp_rss_hash_type {
+       /* First part: Individual bits for L3/L4 types */
+       XDP_RSS_L3_IPV4         = BIT(0),
+       XDP_RSS_L3_IPV6         = BIT(1),
+
+       /* The fixed (L3) IPv4 and IPv6 headers can both be followed by
+        * variable/dynamic headers, IPv4 called Options and IPv6 called
+        * Extension Headers. HW RSS type can contain this info.
+        */
+       XDP_RSS_L3_DYNHDR       = BIT(2),
+
+       /* When RSS hash covers L4 then drivers MUST set XDP_RSS_L4 bit in
+        * addition to the protocol specific bit.  This ease interaction with
+        * SKBs and avoids reserving a fixed mask for future L4 protocol bits.
+        */
+       XDP_RSS_L4              = BIT(3), /* L4 based hash, proto can be unknown */
+       XDP_RSS_L4_TCP          = BIT(4),
+       XDP_RSS_L4_UDP          = BIT(5),
+       XDP_RSS_L4_SCTP         = BIT(6),
+       XDP_RSS_L4_IPSEC        = BIT(7), /* L4 based hash include IPSEC SPI */
+
+       /* Second part: RSS hash type combinations used for driver HW mapping */
+       XDP_RSS_TYPE_NONE            = 0,
+       XDP_RSS_TYPE_L2              = XDP_RSS_TYPE_NONE,
+
+       XDP_RSS_TYPE_L3_IPV4         = XDP_RSS_L3_IPV4,
+       XDP_RSS_TYPE_L3_IPV6         = XDP_RSS_L3_IPV6,
+       XDP_RSS_TYPE_L3_IPV4_OPT     = XDP_RSS_L3_IPV4 | XDP_RSS_L3_DYNHDR,
+       XDP_RSS_TYPE_L3_IPV6_EX      = XDP_RSS_L3_IPV6 | XDP_RSS_L3_DYNHDR,
+
+       XDP_RSS_TYPE_L4_ANY          = XDP_RSS_L4,
+       XDP_RSS_TYPE_L4_IPV4_TCP     = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_TCP,
+       XDP_RSS_TYPE_L4_IPV4_UDP     = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_UDP,
+       XDP_RSS_TYPE_L4_IPV4_SCTP    = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_SCTP,
+       XDP_RSS_TYPE_L4_IPV4_IPSEC   = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_IPSEC,
+
+       XDP_RSS_TYPE_L4_IPV6_TCP     = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_TCP,
+       XDP_RSS_TYPE_L4_IPV6_UDP     = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_UDP,
+       XDP_RSS_TYPE_L4_IPV6_SCTP    = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_SCTP,
+       XDP_RSS_TYPE_L4_IPV6_IPSEC   = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_IPSEC,
+
+       XDP_RSS_TYPE_L4_IPV6_TCP_EX  = XDP_RSS_TYPE_L4_IPV6_TCP  | XDP_RSS_L3_DYNHDR,
+       XDP_RSS_TYPE_L4_IPV6_UDP_EX  = XDP_RSS_TYPE_L4_IPV6_UDP  | XDP_RSS_L3_DYNHDR,
+       XDP_RSS_TYPE_L4_IPV6_SCTP_EX = XDP_RSS_TYPE_L4_IPV6_SCTP | XDP_RSS_L3_DYNHDR,
+};
+
 #ifdef CONFIG_NET
 u32 bpf_xdp_metadata_kfunc_id(int id);
 bool bpf_dev_bound_kfunc_id(u32 btf_id);
+void xdp_set_features_flag(struct net_device *dev, xdp_features_t val);
 void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg);
 void xdp_features_clear_redirect_target(struct net_device *dev);
 #else
 static inline u32 bpf_xdp_metadata_kfunc_id(int id) { return 0; }
 static inline bool bpf_dev_bound_kfunc_id(u32 btf_id) { return false; }
 
+static inline void
+xdp_set_features_flag(struct net_device *dev, xdp_features_t val)
+{
+}
+
 static inline void
 xdp_features_set_redirect_target(struct net_device *dev, bool support_sg)
 {
@@ -445,4 +498,9 @@ xdp_features_clear_redirect_target(struct net_device *dev)
 }
 #endif
 
+static inline void xdp_clear_features_flag(struct net_device *dev)
+{
+       xdp_set_features_flag(dev, 0);
+}
+
 #endif /* __LINUX_NET_XDP_H__ */
index de310f21406c546f7d8d0819e56ef4a9a4ec7ea4..f10a008e5bfa1408b4836465015c9c3ac984cb32 100644 (file)
@@ -145,6 +145,7 @@ struct scsi_device {
        const char * model;             /* ... after scan; point to static string */
        const char * rev;               /* ... "nullnullnullnull" before scan */
 
+#define SCSI_DEFAULT_VPD_LEN   255     /* default SCSI VPD page size (max) */
        struct scsi_vpd __rcu *vpd_pg0;
        struct scsi_vpd __rcu *vpd_pg83;
        struct scsi_vpd __rcu *vpd_pg80;
@@ -215,6 +216,7 @@ struct scsi_device {
                                         * creation time */
        unsigned ignore_media_change:1; /* Ignore MEDIA CHANGE on resume */
        unsigned silence_suspend:1;     /* Do not print runtime PM related messages */
+       unsigned no_vpd_size:1;         /* No VPD size reported in header */
 
        unsigned int queue_stopped;     /* request queue is quiesced */
        bool offline_already;           /* Device offline message logged */
index 5d14adae21c78903188052187076eeec9644188a..6b548dc2c49654c95aa9e213692e2931395701e6 100644 (file)
@@ -32,7 +32,8 @@
 #define BLIST_IGN_MEDIA_CHANGE ((__force blist_flags_t)(1ULL << 11))
 /* do not do automatic start on add */
 #define BLIST_NOSTARTONADD     ((__force blist_flags_t)(1ULL << 12))
-#define __BLIST_UNUSED_13      ((__force blist_flags_t)(1ULL << 13))
+/* do not ask for VPD page size first on some broken targets */
+#define BLIST_NO_VPD_SIZE      ((__force blist_flags_t)(1ULL << 13))
 #define __BLIST_UNUSED_14      ((__force blist_flags_t)(1ULL << 14))
 #define __BLIST_UNUSED_15      ((__force blist_flags_t)(1ULL << 15))
 #define __BLIST_UNUSED_16      ((__force blist_flags_t)(1ULL << 16))
@@ -74,8 +75,7 @@
 #define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \
                               (__force blist_flags_t) \
                               ((__force __u64)__BLIST_LAST_USED - 1ULL)))
-#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_13 | \
-                            __BLIST_UNUSED_14 | \
+#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_14 | \
                             __BLIST_UNUSED_15 | \
                             __BLIST_UNUSED_16 | \
                             __BLIST_UNUSED_24 | \
diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
new file mode 100644 (file)
index 0000000..5870a94
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef __QCOM_ICE_H__
+#define __QCOM_ICE_H__
+
+#include <linux/types.h>
+
+struct qcom_ice;
+
+enum qcom_ice_crypto_key_size {
+       QCOM_ICE_CRYPTO_KEY_SIZE_INVALID        = 0x0,
+       QCOM_ICE_CRYPTO_KEY_SIZE_128            = 0x1,
+       QCOM_ICE_CRYPTO_KEY_SIZE_192            = 0x2,
+       QCOM_ICE_CRYPTO_KEY_SIZE_256            = 0x3,
+       QCOM_ICE_CRYPTO_KEY_SIZE_512            = 0x4,
+};
+
+enum qcom_ice_crypto_alg {
+       QCOM_ICE_CRYPTO_ALG_AES_XTS             = 0x0,
+       QCOM_ICE_CRYPTO_ALG_BITLOCKER_AES_CBC   = 0x1,
+       QCOM_ICE_CRYPTO_ALG_AES_ECB             = 0x2,
+       QCOM_ICE_CRYPTO_ALG_ESSIV_AES_CBC       = 0x3,
+};
+
+int qcom_ice_enable(struct qcom_ice *ice);
+int qcom_ice_resume(struct qcom_ice *ice);
+int qcom_ice_suspend(struct qcom_ice *ice);
+int qcom_ice_program_key(struct qcom_ice *ice,
+                        u8 algorithm_id, u8 key_size,
+                        const u8 crypto_key[], u8 data_unit_size,
+                        int slot);
+int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
+struct qcom_ice *of_qcom_ice_get(struct device *dev);
+#endif /* __QCOM_ICE_H__ */
index cf4a0d28b178b356c730b1c591cc73bc1f73deba..71dbe8bfa7db23e0d72383e2f09f2c03075aa5b4 100644 (file)
@@ -71,8 +71,8 @@ TRACE_EVENT(erofs_fill_inode,
        TP_fast_assign(
                __entry->dev            = inode->i_sb->s_dev;
                __entry->nid            = EROFS_I(inode)->nid;
-               __entry->blkaddr        = erofs_blknr(erofs_iloc(inode));
-               __entry->ofs            = erofs_blkoff(erofs_iloc(inode));
+               __entry->blkaddr        = erofs_blknr(inode->i_sb, erofs_iloc(inode));
+               __entry->ofs            = erofs_blkoff(inode->i_sb, erofs_iloc(inode));
        ),
 
        TP_printk("dev = (%d,%d), nid = %llu, blkaddr %u ofs %u",
index 1322d34a5dfc17cdcdc26eee30b0c497a4a4fe91..99cbc5949e3cd0ae13f72eff9efdf88eed2c1df6 100644 (file)
@@ -512,7 +512,7 @@ TRACE_EVENT(f2fs_truncate_partial_nodes,
        TP_STRUCT__entry(
                __field(dev_t,  dev)
                __field(ino_t,  ino)
-               __field(nid_t,  nid[3])
+               __array(nid_t,  nid, 3)
                __field(int,    depth)
                __field(int,    err)
        ),
index eeceafaaea4c1ca74cf026a966c253331cd980d8..a07b4607b66359856f958381e42373a1f903c95e 100644 (file)
@@ -160,6 +160,53 @@ DEFINE_EVENT(softirq, softirq_raise,
        TP_ARGS(vec_nr)
 );
 
+DECLARE_EVENT_CLASS(tasklet,
+
+       TP_PROTO(struct tasklet_struct *t, void *func),
+
+       TP_ARGS(t, func),
+
+       TP_STRUCT__entry(
+               __field(        void *, tasklet)
+               __field(        void *, func)
+       ),
+
+       TP_fast_assign(
+               __entry->tasklet = t;
+               __entry->func = func;
+       ),
+
+       TP_printk("tasklet=%ps function=%ps", __entry->tasklet, __entry->func)
+);
+
+/**
+ * tasklet_entry - called immediately before the tasklet is run
+ * @t: tasklet pointer
+ * @func: tasklet callback or function being run
+ *
+ * Used to find individual tasklet execution time
+ */
+DEFINE_EVENT(tasklet, tasklet_entry,
+
+       TP_PROTO(struct tasklet_struct *t, void *func),
+
+       TP_ARGS(t, func)
+);
+
+/**
+ * tasklet_exit - called immediately after the tasklet is run
+ * @t: tasklet pointer
+ * @func: tasklet callback or function being run
+ *
+ * Used to find individual tasklet execution time
+ */
+DEFINE_EVENT(tasklet, tasklet_exit,
+
+       TP_PROTO(struct tasklet_struct *t, void *func),
+
+       TP_ARGS(t, func)
+);
+
 #endif /*  _TRACE_IRQ_H */
 
 /* This part must be outside protection */
index 216de5f0362101d8adf9f9e231f03c086951df0d..f8d61485de16deadad88d6062676d2374f1079e5 100644 (file)
@@ -35,7 +35,7 @@ TRACE_EVENT(vm_unmapped_area,
                __entry->align_offset = info->align_offset;
        ),
 
-       TP_printk("addr=0x%lx err=%ld total_vm=0x%lx flags=0x%lx len=0x%lx lo=0x%lx hi=0x%lx mask=0x%lx ofs=0x%lx\n",
+       TP_printk("addr=0x%lx err=%ld total_vm=0x%lx flags=0x%lx len=0x%lx lo=0x%lx hi=0x%lx mask=0x%lx ofs=0x%lx",
                IS_ERR_VALUE(__entry->addr) ? 0 : __entry->addr,
                IS_ERR_VALUE(__entry->addr) ? __entry->addr : 0,
                __entry->total_vm, __entry->flags, __entry->length,
@@ -110,7 +110,7 @@ TRACE_EVENT(exit_mmap,
                       __entry->mt              = &mm->mm_mt;
        ),
 
-       TP_printk("mt_mod %p, DESTROY\n",
+       TP_printk("mt_mod %p, DESTROY",
                  __entry->mt
        )
 );
index 90b2fb0292cb1525d7ecd1f82f10b163804f7ee0..2ef9c719772afbd6002c4b658c3dcaaa99da1246 100644 (file)
@@ -768,7 +768,7 @@ TRACE_EVENT_RCU(rcu_torture_read,
        TP_ARGS(rcutorturename, rhp, secs, c_old, c),
 
        TP_STRUCT__entry(
-               __field(char, rcutorturename[RCUTORTURENAME_LEN])
+               __array(char, rcutorturename, RCUTORTURENAME_LEN)
                __field(struct rcu_head *, rhp)
                __field(unsigned long, secs)
                __field(unsigned long, c_old)
@@ -776,9 +776,7 @@ TRACE_EVENT_RCU(rcu_torture_read,
        ),
 
        TP_fast_assign(
-               strncpy(__entry->rcutorturename, rcutorturename,
-                       RCUTORTURENAME_LEN);
-               __entry->rcutorturename[RCUTORTURENAME_LEN - 1] = 0;
+               strscpy(__entry->rcutorturename, rcutorturename, RCUTORTURENAME_LEN);
                __entry->rhp = rhp;
                __entry->secs = secs;
                __entry->c_old = c_old;
index 2e713a7d9aa3a45c11c551d038d8ea4d087017d6..3e8619c72f774589592ff6149f93746f0b48eca7 100644 (file)
@@ -371,7 +371,8 @@ TRACE_EVENT(itimer_expire,
                tick_dep_name(PERF_EVENTS)              \
                tick_dep_name(SCHED)                    \
                tick_dep_name(CLOCK_UNSTABLE)           \
-               tick_dep_name_end(RCU)
+               tick_dep_name(RCU)                      \
+               tick_dep_name_end(RCU_EXP)
 
 #undef tick_dep_name
 #undef tick_dep_mask_name
index ac5c24d3beeb24950996b07803ced5ccda09ca6f..e30a13be46ba560eaac1d11eb8e4843faf176891 100644 (file)
@@ -9,17 +9,30 @@
 #undef __entry
 #define __entry entry
 
+/*
+ * Fields should never declare an array: i.e. __field(int, arr[5])
+ * If they do, it will cause issues in parsing and possibly corrupt the
+ * events. To prevent that from happening, test the sizeof() a fictitious
+ * type called "struct _test_no_array_##item" which will fail if "item"
+ * contains array elements (like "arr[5]").
+ *
+ * If you hit this, use __array(int, arr, 5) instead.
+ */
 #undef __field
-#define __field(type, item)
+#define __field(type, item)                                    \
+       { (void)sizeof(struct _test_no_array_##item *); }
 
 #undef __field_ext
-#define __field_ext(type, item, filter_type)
+#define __field_ext(type, item, filter_type)                   \
+       { (void)sizeof(struct _test_no_array_##item *); }
 
 #undef __field_struct
-#define __field_struct(type, item)
+#define __field_struct(type, item)                             \
+       { (void)sizeof(struct _test_no_array_##item *); }
 
 #undef __field_struct_ext
-#define __field_struct_ext(type, item, filter_type)
+#define __field_struct_ext(type, item, filter_type)            \
+       { (void)sizeof(struct _test_no_array_##item *); }
 
 #undef __array
 #define __array(type, item, len)
index 1ecdb911add8de3b16f4b05dff630a0ca47285d1..80f37a0d40d7d4efefe406f73598f0f150bd9973 100644 (file)
@@ -91,7 +91,6 @@
 
 /* a horrid kludge trying to make sure that this will fail on old kernels */
 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
-#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)      
 
 #ifndef O_NDELAY
 #define O_NDELAY       O_NONBLOCK
index 5041c3598493874ce15b554d03e04df4f3c518d3..b5cd3e7b3775a61690ce5998b6fe379de34b9e01 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/fou.yaml */
 /* YNL-GEN uapi header */
index f3223f9646913cc9539a66b9ee6a10ced108f954..81d09ef9aa50e902d92baed031f07e32b8f2e07c 100644 (file)
@@ -130,21 +130,37 @@ struct landlock_path_beneath_attr {
  * - %LANDLOCK_ACCESS_FS_MAKE_BLOCK: Create (or rename or link) a block device.
  * - %LANDLOCK_ACCESS_FS_MAKE_SYM: Create (or rename or link) a symbolic link.
  * - %LANDLOCK_ACCESS_FS_REFER: Link or rename a file from or to a different
- *   directory (i.e. reparent a file hierarchy).  This access right is
- *   available since the second version of the Landlock ABI.  This is also the
- *   only access right which is always considered handled by any ruleset in
- *   such a way that reparenting a file hierarchy is always denied by default.
- *   To avoid privilege escalation, it is not enough to add a rule with this
- *   access right.  When linking or renaming a file, the destination directory
- *   hierarchy must also always have the same or a superset of restrictions of
- *   the source hierarchy.  If it is not the case, or if the domain doesn't
- *   handle this access right, such actions are denied by default with errno
- *   set to ``EXDEV``.  Linking also requires a ``LANDLOCK_ACCESS_FS_MAKE_*``
- *   access right on the destination directory, and renaming also requires a
- *   ``LANDLOCK_ACCESS_FS_REMOVE_*`` access right on the source's (file or
- *   directory) parent.  Otherwise, such actions are denied with errno set to
- *   ``EACCES``.  The ``EACCES`` errno prevails over ``EXDEV`` to let user space
- *   efficiently deal with an unrecoverable error.
+ *   directory (i.e. reparent a file hierarchy).
+ *
+ *   This access right is available since the second version of the Landlock
+ *   ABI.
+ *
+ *   This is the only access right which is denied by default by any ruleset,
+ *   even if the right is not specified as handled at ruleset creation time.
+ *   The only way to make a ruleset grant this right is to explicitly allow it
+ *   for a specific directory by adding a matching rule to the ruleset.
+ *
+ *   In particular, when using the first Landlock ABI version, Landlock will
+ *   always deny attempts to reparent files between different directories.
+ *
+ *   In addition to the source and destination directories having the
+ *   %LANDLOCK_ACCESS_FS_REFER access right, the attempted link or rename
+ *   operation must meet the following constraints:
+ *
+ *   * The reparented file may not gain more access rights in the destination
+ *     directory than it previously had in the source directory.  If this is
+ *     attempted, the operation results in an ``EXDEV`` error.
+ *
+ *   * When linking or renaming, the ``LANDLOCK_ACCESS_FS_MAKE_*`` right for the
+ *     respective file type must be granted for the destination directory.
+ *     Otherwise, the operation results in an ``EACCES`` error.
+ *
+ *   * When renaming, the ``LANDLOCK_ACCESS_FS_REMOVE_*`` right for the
+ *     respective file type must be granted for the source directory.  Otherwise,
+ *     the operation results in an ``EACCES`` error.
+ *
+ *   If multiple requirements are not met, the ``EACCES`` error code takes
+ *   precedence over ``EXDEV``.
  *
  * .. warning::
  *
index 8c4e3e536c04285e155617cde126f2c4fce10e08..639524b59930bfcabcd0d352048a3fd4aa1da08b 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/netdev.yaml */
 /* YNL-GEN uapi header */
@@ -33,6 +33,8 @@ enum netdev_xdp_act {
        NETDEV_XDP_ACT_HW_OFFLOAD = 16,
        NETDEV_XDP_ACT_RX_SG = 32,
        NETDEV_XDP_ACT_NDO_XMIT_SG = 64,
+
+       NETDEV_XDP_ACT_MASK = 127,
 };
 
 enum {
index 91b4c63d5cbf4f5f319aa5e342172ae1aa7aa9dd..1c9da485318f93fe50e11a47f284d8fe81106066 100644 (file)
@@ -36,6 +36,13 @@ enum {
  * SEV Firmware status code
  */
 typedef enum {
+       /*
+        * This error code is not in the SEV spec. Its purpose is to convey that
+        * there was an error that prevented the SEV firmware from being called.
+        * The SEV API error codes are 16 bits, so the -1 value will not overlap
+        * with possible values from the specification.
+        */
+       SEV_RET_NO_FW_CALL = -1,
        SEV_RET_SUCCESS = 0,
        SEV_RET_INVALID_PLATFORM_STATE,
        SEV_RET_INVALID_GUEST_STATE,
index 195ae64a8c871254b7f181a0396cce3e1cdeca6c..72c038fc71d093514e010fdc4a833cb95285053e 100644 (file)
@@ -112,6 +112,36 @@ struct ptrace_rseq_configuration {
        __u32 pad;
 };
 
+#define PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG 0x4210
+#define PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG 0x4211
+
+/*
+ * struct ptrace_sud_config - Per-task configuration for Syscall User Dispatch
+ * @mode:      One of PR_SYS_DISPATCH_ON or PR_SYS_DISPATCH_OFF
+ * @selector:  Tracees user virtual address of SUD selector
+ * @offset:    SUD exclusion area (virtual address)
+ * @len:       Length of SUD exclusion area
+ *
+ * Used to get/set the syscall user dispatch configuration for a tracee.
+ * Selector is optional (may be NULL), and if invalid will produce
+ * a SIGSEGV in the tracee upon first access.
+ *
+ * If mode is PR_SYS_DISPATCH_ON, syscall dispatch will be enabled. If
+ * PR_SYS_DISPATCH_OFF, syscall dispatch will be disabled and all other
+ * parameters must be 0.  The value in *selector (if not null), also determines
+ * whether syscall dispatch will occur.
+ *
+ * The Syscall User Dispatch Exclusion area described by offset/len is the
+ * virtual address space from which syscalls will not produce a user
+ * dispatch.
+ */
+struct ptrace_sud_config {
+       __u64 mode;
+       __u64 selector;
+       __u64 offset;
+       __u64 len;
+};
+
 /*
  * These values are stored in task->ptrace_message
  * by ptrace_stop to describe the current syscall-stop.
index 25a0af57dd5ed3c204897f8da892a4c378bf5c08..51c13cf9c5aee4a2d1ab33c1a89043383d67b9cf 100644 (file)
@@ -789,6 +789,7 @@ enum {
        TCA_ROOT_FLAGS,
        TCA_ROOT_COUNT,
        TCA_ROOT_TIME_DELTA, /* in msecs */
+       TCA_ROOT_EXT_WARN_MSG,
        __TCA_ROOT_MAX,
 #define        TCA_ROOT_MAX (__TCA_ROOT_MAX - 1)
 };
index 256aaeff7e654e85011a2cebd5bbd7c86ed40a9c..2aa39112cf8dd37e3ee265f6128973c8698145df 100644 (file)
@@ -52,8 +52,14 @@ struct snp_guest_request_ioctl {
        __u64 req_data;
        __u64 resp_data;
 
-       /* firmware error code on failure (see psp-sev.h) */
-       __u64 fw_err;
+       /* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */
+       union {
+               __u64 exitinfo2;
+               struct {
+                       __u32 fw_error;
+                       __u32 vmm_error;
+               };
+       };
 };
 
 struct snp_ext_report_req {
@@ -77,4 +83,12 @@ struct snp_ext_report_req {
 /* Get SNP extended report as defined in the GHCB specification version 2. */
 #define SNP_GET_EXT_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x2, struct snp_guest_request_ioctl)
 
+/* Guest message request EXIT_INFO_2 constants */
+#define SNP_GUEST_FW_ERR_MASK          GENMASK_ULL(31, 0)
+#define SNP_GUEST_VMM_ERR_SHIFT                32
+#define SNP_GUEST_VMM_ERR(x)           (((u64)x) << SNP_GUEST_VMM_ERR_SHIFT)
+
+#define SNP_GUEST_VMM_ERR_INVALID_LEN  1
+#define SNP_GUEST_VMM_ERR_BUSY         2
+
 #endif /* __UAPI_LINUX_SEV_GUEST_H_ */
index 5af2a0300bb9d59a48beba17b79964af76985590..3744e4da1b2a7d1121b6873a3839ed962fa4898f 100644 (file)
@@ -140,11 +140,11 @@ struct virtio_blk_config {
 
        /* Zoned block device characteristics (if VIRTIO_BLK_F_ZONED) */
        struct virtio_blk_zoned_characteristics {
-               __le32 zone_sectors;
-               __le32 max_open_zones;
-               __le32 max_active_zones;
-               __le32 max_append_sectors;
-               __le32 write_granularity;
+               __virtio32 zone_sectors;
+               __virtio32 max_open_zones;
+               __virtio32 max_active_zones;
+               __virtio32 max_append_sectors;
+               __virtio32 write_granularity;
                __u8 model;
                __u8 unused2[3];
        } zoned;
@@ -241,11 +241,11 @@ struct virtio_blk_outhdr {
  */
 struct virtio_blk_zone_descriptor {
        /* Zone capacity */
-       __le64 z_cap;
+       __virtio64 z_cap;
        /* The starting sector of the zone */
-       __le64 z_start;
+       __virtio64 z_start;
        /* Zone write pointer position in sectors */
-       __le64 z_wp;
+       __virtio64 z_wp;
        /* Zone type */
        __u8 z_type;
        /* Zone state */
@@ -254,7 +254,7 @@ struct virtio_blk_zone_descriptor {
 };
 
 struct virtio_blk_zone_report {
-       __le64 nr_zones;
+       __virtio64 nr_zones;
        __u8 reserved[56];
        struct virtio_blk_zone_descriptor zones[];
 };
index 25aab8ec4f86be11780176b250c915ca73865b98..431c3afb2ce0f2048d6a50e77d90121ad8557239 100644 (file)
@@ -979,7 +979,6 @@ struct ufs_hba {
        struct completion *uic_async_done;
 
        enum ufshcd_state ufshcd_state;
-       bool logical_unit_scan_finished;
        u32 eh_flags;
        u32 intr_mask;
        u16 ee_ctrl_mask;
index 655d92e803e1498d35b9a96e2c2a7c645c6ba726..79a443c65ea93c0f93696aa83711ce64b138615b 100644 (file)
@@ -483,6 +483,8 @@ struct xenpf_symdata {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_symdata);
 
+#define XENPF_get_dom0_console 64
+
 struct xen_platform_op {
        uint32_t cmd;
        uint32_t interface_version; /* XENPF_INTERFACE_VERSION */
@@ -506,6 +508,7 @@ struct xen_platform_op {
                struct xenpf_mem_hotadd        mem_add;
                struct xenpf_core_parking      core_parking;
                struct xenpf_symdata           symdata;
+               struct dom0_vga_console_info   dom0_console;
                uint8_t                        pad[128];
        } u;
 };
index 1fb5f313d18f0fa93739348c575b547be801ee40..c88bb30a8b0b026285d7905c812da9ee27e7bfff 100644 (file)
@@ -890,18 +890,14 @@ config CC_IMPLICIT_FALLTHROUGH
        default "-Wimplicit-fallthrough=5" if CC_IS_GCC && $(cc-option,-Wimplicit-fallthrough=5)
        default "-Wimplicit-fallthrough" if CC_IS_CLANG && $(cc-option,-Wunreachable-code-fallthrough)
 
-# Currently, disable gcc-11,12 array-bounds globally.
-# We may want to target only particular configurations some day.
+# Currently, disable gcc-11+ array-bounds globally.
+# It's still broken in gcc-13, so no upper bound yet.
 config GCC11_NO_ARRAY_BOUNDS
        def_bool y
 
-config GCC12_NO_ARRAY_BOUNDS
-       def_bool y
-
 config CC_NO_ARRAY_BOUNDS
        bool
-       default y if CC_IS_GCC && GCC_VERSION >= 110000 && GCC_VERSION < 120000 && GCC11_NO_ARRAY_BOUNDS
-       default y if CC_IS_GCC && GCC_VERSION >= 120000 && GCC_VERSION < 130000 && GCC12_NO_ARRAY_BOUNDS
+       default y if CC_IS_GCC && GCC_VERSION >= 110000 && GCC11_NO_ARRAY_BOUNDS
 
 #
 # For architectures that know their GCC __int128 support is sound
index f6c112e30bd47d9363086ea6f2154b1c7e2a0ccf..e7a01c2ccd1b0c33f795dd94a0c58ab57092bb93 100644 (file)
@@ -60,15 +60,8 @@ static void __init error(char *x)
                message = x;
 }
 
-static void panic_show_mem(const char *fmt, ...)
-{
-       va_list args;
-
-       show_mem(0, NULL);
-       va_start(args, fmt);
-       panic(fmt, args);
-       va_end(args);
-}
+#define panic_show_mem(fmt, ...) \
+       ({ show_mem(0, NULL); panic(fmt, ##__VA_ARGS__); })
 
 /* link hash */
 
index 4425d1783d5c21e8f1da703e503a5edc37a3d93f..c62f0c8811d773421113ebd0b5e5e939b0834db4 100644 (file)
@@ -156,7 +156,7 @@ static char *extra_init_args;
 
 #ifdef CONFIG_BOOT_CONFIG
 /* Is bootconfig on command line? */
-static bool bootconfig_found = IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE);
+static bool bootconfig_found;
 static size_t initargs_offs;
 #else
 # define bootconfig_found false
@@ -429,7 +429,7 @@ static void __init setup_boot_config(void)
        err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
                         bootconfig_params);
 
-       if (IS_ERR(err) || !bootconfig_found)
+       if (IS_ERR(err) || !(bootconfig_found || IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE)))
                return;
 
        /* parse_args() stops at the next param of '--' and returns an address */
@@ -437,7 +437,11 @@ static void __init setup_boot_config(void)
                initargs_offs = err - tmp_cmdline;
 
        if (!data) {
-               pr_err("'bootconfig' found on command line, but no bootconfig found\n");
+               /* If user intended to use bootconfig, show an error level message */
+               if (bootconfig_found)
+                       pr_err("'bootconfig' found on command line, but no bootconfig found\n");
+               else
+                       pr_info("No bootconfig data provided, so skipping bootconfig");
                return;
        }
 
@@ -707,7 +711,7 @@ noinline void __ref rest_init(void)
        rcu_read_unlock();
 
        numa_default_policy();
-       pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
+       pid = kernel_thread(kthreadd, NULL, NULL, CLONE_FS | CLONE_FILES);
        rcu_read_lock();
        kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
        rcu_read_unlock();
@@ -1088,14 +1092,6 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
         */
        locking_selftest();
 
-       /*
-        * This needs to be called before any devices perform DMA
-        * operations that might use the SWIOTLB bounce buffers. It will
-        * mark the bounce buffers as decrypted so that their usage will
-        * not cause "plain-text" data to be decrypted when accessed.
-        */
-       mem_encrypt_init();
-
 #ifdef CONFIG_BLK_DEV_INITRD
        if (initrd_start && !initrd_below_start_ok &&
            page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
@@ -1112,6 +1108,17 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void)
                late_time_init();
        sched_clock_init();
        calibrate_delay();
+
+       /*
+        * This needs to be called before any devices perform DMA
+        * operations that might use the SWIOTLB bounce buffers. It will
+        * mark the bounce buffers as decrypted so that their usage will
+        * not cause "plain-text" data to be decrypted when accessed. It
+        * must be called after late_time_init() so that Hyper-V x86/x64
+        * hypercalls work when the SWIOTLB bounce buffers are decrypted.
+        */
+       mem_encrypt_init();
+
        pid_idr_init();
        anon_vma_init();
 #ifdef CONFIG_X86
index 729793ae97127a0d83c2df9864bcfe10130eee00..c2cde88aeed53f6e8d31438a83c10677a70d43f3 100644 (file)
@@ -27,6 +27,7 @@ static inline struct io_cache_entry *io_alloc_cache_get(struct io_alloc_cache *c
                struct hlist_node *node = cache->list.first;
 
                hlist_del(node);
+               cache->nr_cached--;
                return container_of(node, struct io_cache_entry, node);
        }
 
index 68dfc6936aa7250181a981dba6bb58e1ba6115d3..b80614e7d605112507363644c510d6312b65259d 100644 (file)
@@ -19,6 +19,9 @@ static int io_file_bitmap_get(struct io_ring_ctx *ctx)
        unsigned long nr = ctx->file_alloc_end;
        int ret;
 
+       if (!table->bitmap)
+               return -ENFILE;
+
        do {
                ret = find_next_zero_bit(table->bitmap, nr, table->alloc_hint);
                if (ret != nr)
index 722624b6d0dcae61b64c3966260ddc3cae814616..4a865f0e85d0b8116c6ef3bd37b5f6db4af29835 100644 (file)
@@ -998,7 +998,7 @@ static void __io_req_complete_post(struct io_kiocb *req)
 
 void io_req_complete_post(struct io_kiocb *req, unsigned issue_flags)
 {
-       if (req->ctx->task_complete && (issue_flags & IO_URING_F_IOWQ)) {
+       if (req->ctx->task_complete && req->ctx->submitter_task != current) {
                req->io_task_work.func = io_req_task_complete;
                io_req_task_work_add(req);
        } else if (!(issue_flags & IO_URING_F_UNLOCKED) ||
@@ -2789,8 +2789,8 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
        io_eventfd_unregister(ctx);
        io_alloc_cache_free(&ctx->apoll_cache, io_apoll_cache_free);
        io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free);
-       mutex_unlock(&ctx->uring_lock);
        io_destroy_buffers(ctx);
+       mutex_unlock(&ctx->uring_lock);
        if (ctx->sq_creds)
                put_cred(ctx->sq_creds);
        if (ctx->submitter_task)
index 3002dc827195916b160fce8376de009feb86f3c5..a90c820ce99e12e5e72d37dee4fefd2d24665c3a 100644 (file)
@@ -228,17 +228,18 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx,
                return i;
        }
 
-       /* the head kbuf is the list itself */
+       /* protects io_buffers_cache */
+       lockdep_assert_held(&ctx->uring_lock);
+
        while (!list_empty(&bl->buf_list)) {
                struct io_buffer *nxt;
 
                nxt = list_first_entry(&bl->buf_list, struct io_buffer, list);
-               list_del(&nxt->list);
+               list_move(&nxt->list, &ctx->io_buffers_cache);
                if (++i == nbufs)
                        return i;
                cond_resched();
        }
-       i++;
 
        return i;
 }
index 8803c0979e2a91345d5dc1c29da1686a224c241d..85fd7ce5f05b85f10fc8ab91af8b428629356140 100644 (file)
@@ -202,7 +202,7 @@ static int io_msg_install_complete(struct io_kiocb *req, unsigned int issue_flag
         * completes with -EOVERFLOW, then the sender must ensure that a
         * later IORING_OP_MSG_RING delivers the message.
         */
-       if (!io_post_aux_cqe(target_ctx, msg->user_data, msg->len, 0))
+       if (!io_post_aux_cqe(target_ctx, msg->user_data, ret, 0))
                ret = -EOVERFLOW;
 out_unlock:
        io_double_unlock_ctx(target_ctx);
@@ -229,6 +229,8 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
        struct io_ring_ctx *ctx = req->ctx;
        struct file *src_file = msg->src_file;
 
+       if (msg->len)
+               return -EINVAL;
        if (target_ctx == ctx)
                return -EINVAL;
        if (target_ctx->flags & IORING_SETUP_R_DISABLED)
index b7f190ca528e6e259eb2b072d7a16aaba98848cb..89e839013837ffd34947076ae7e9be54e1b1cfc7 100644 (file)
@@ -47,6 +47,7 @@ struct io_connect {
        struct sockaddr __user          *addr;
        int                             addr_len;
        bool                            in_progress;
+       bool                            seen_econnaborted;
 };
 
 struct io_sr_msg {
@@ -183,8 +184,8 @@ static int io_setup_async_msg(struct io_kiocb *req,
                async_msg->msg.msg_name = &async_msg->addr;
        /* if were using fast_iov, set it to the new one */
        if (iter_is_iovec(&kmsg->msg.msg_iter) && !kmsg->free_iov) {
-               size_t fast_idx = kmsg->msg.msg_iter.iov - kmsg->fast_iov;
-               async_msg->msg.msg_iter.iov = &async_msg->fast_iov[fast_idx];
+               size_t fast_idx = iter_iov(&kmsg->msg.msg_iter) - kmsg->fast_iov;
+               async_msg->msg.msg_iter.__iov = &async_msg->fast_iov[fast_idx];
        }
 
        return -EAGAIN;
@@ -1424,7 +1425,7 @@ int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 
        conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
        conn->addr_len =  READ_ONCE(sqe->addr2);
-       conn->in_progress = false;
+       conn->in_progress = conn->seen_econnaborted = false;
        return 0;
 }
 
@@ -1461,18 +1462,24 @@ int io_connect(struct io_kiocb *req, unsigned int issue_flags)
 
        ret = __sys_connect_file(req->file, &io->address,
                                        connect->addr_len, file_flags);
-       if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
+       if ((ret == -EAGAIN || ret == -EINPROGRESS || ret == -ECONNABORTED)
+           && force_nonblock) {
                if (ret == -EINPROGRESS) {
                        connect->in_progress = true;
-               } else {
-                       if (req_has_async_data(req))
-                               return -EAGAIN;
-                       if (io_alloc_async_data(req)) {
-                               ret = -ENOMEM;
+                       return -EAGAIN;
+               }
+               if (ret == -ECONNABORTED) {
+                       if (connect->seen_econnaborted)
                                goto out;
-                       }
-                       memcpy(req->async_data, &__io, sizeof(__io));
+                       connect->seen_econnaborted = true;
+               }
+               if (req_has_async_data(req))
+                       return -EAGAIN;
+               if (io_alloc_async_data(req)) {
+                       ret = -ENOMEM;
+                       goto out;
                }
+               memcpy(req->async_data, &__io, sizeof(__io));
                return -EAGAIN;
        }
        if (ret == -ERESTARTSYS)
index 795facbd0e9f174ab4af7bbd1444b4eaedeb29da..55306e801081376acb380487fed2308e09a0f1d9 100644 (file)
@@ -726,6 +726,7 @@ int io_arm_poll_handler(struct io_kiocb *req, unsigned issue_flags)
        apoll = io_req_alloc_apoll(req, issue_flags);
        if (!apoll)
                return IO_APOLL_ABORTED;
+       req->flags &= ~(REQ_F_SINGLE_POLL | REQ_F_DOUBLE_POLL);
        req->flags |= REQ_F_POLLED;
        ipt.pt._qproc = io_async_queue_proc;
 
index 056f40946ff68ff8d2d72781c5bdc9e3e303cea4..7a43aed8e395cb4d22885e0800bf193c862f0b1f 100644 (file)
@@ -410,7 +410,7 @@ __cold static int io_rsrc_data_alloc(struct io_ring_ctx *ctx,
                                     unsigned nr, struct io_rsrc_data **pdata)
 {
        struct io_rsrc_data *data;
-       int ret = -ENOMEM;
+       int ret = 0;
        unsigned i;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -794,6 +794,7 @@ void __io_sqe_files_unregister(struct io_ring_ctx *ctx)
        }
 #endif
        io_free_file_tables(&ctx->file_table);
+       io_file_table_set_alloc_range(ctx, 0, 0);
        io_rsrc_data_free(ctx->file_data);
        ctx->file_data = NULL;
        ctx->nr_user_files = 0;
@@ -1235,7 +1236,13 @@ static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov,
                        }
                }
                if (folio) {
-                       folio_put_refs(folio, nr_pages - 1);
+                       /*
+                        * The pages are bound to the folio, it doesn't
+                        * actually unpin them but drops all but one reference,
+                        * which is usually put down by io_buffer_unmap().
+                        * Note, needs a better helper.
+                        */
+                       unpin_user_pages(&pages[1], nr_pages - 1);
                        nr_pages = 1;
                }
        }
index 2b8743645efcbd5d29709fbd2ecff2b6d51e86f3..f27f4975217d94ada42a3474fe5da0b04285eb3c 100644 (file)
@@ -144,15 +144,13 @@ static inline void io_req_set_rsrc_node(struct io_kiocb *req,
                                        unsigned int issue_flags)
 {
        if (!req->rsrc_node) {
-               req->rsrc_node = ctx->rsrc_node;
+               io_ring_submit_lock(ctx, issue_flags);
 
-               if (!(issue_flags & IO_URING_F_UNLOCKED)) {
-                       lockdep_assert_held(&ctx->uring_lock);
+               lockdep_assert_held(&ctx->uring_lock);
 
-                       io_charge_rsrc_node(ctx);
-               } else {
-                       percpu_ref_get(&req->rsrc_node->refs);
-               }
+               req->rsrc_node = ctx->rsrc_node;
+               io_charge_rsrc_node(ctx);
+               io_ring_submit_unlock(ctx, issue_flags);
        }
 }
 
index 4c233910e20097e2833c9e3a6c2f78995c2b7947..f33ba6f282474c2e24f589b42aa30530b1f7c3f0 100644 (file)
@@ -447,26 +447,25 @@ static ssize_t loop_rw_iter(int ddir, struct io_rw *rw, struct iov_iter *iter)
        ppos = io_kiocb_ppos(kiocb);
 
        while (iov_iter_count(iter)) {
-               struct iovec iovec;
+               void __user *addr;
+               size_t len;
                ssize_t nr;
 
                if (iter_is_ubuf(iter)) {
-                       iovec.iov_base = iter->ubuf + iter->iov_offset;
-                       iovec.iov_len = iov_iter_count(iter);
+                       addr = iter->ubuf + iter->iov_offset;
+                       len = iov_iter_count(iter);
                } else if (!iov_iter_is_bvec(iter)) {
-                       iovec = iov_iter_iovec(iter);
+                       addr = iter_iov_addr(iter);
+                       len = iter_iov_len(iter);
                } else {
-                       iovec.iov_base = u64_to_user_ptr(rw->addr);
-                       iovec.iov_len = rw->len;
+                       addr = u64_to_user_ptr(rw->addr);
+                       len = rw->len;
                }
 
-               if (ddir == READ) {
-                       nr = file->f_op->read(file, iovec.iov_base,
-                                             iovec.iov_len, ppos);
-               } else {
-                       nr = file->f_op->write(file, iovec.iov_base,
-                                              iovec.iov_len, ppos);
-               }
+               if (ddir == READ)
+                       nr = file->f_op->read(file, addr, len, ppos);
+               else
+                       nr = file->f_op->write(file, addr, len, ppos);
 
                if (nr < 0) {
                        if (!ret)
@@ -482,7 +481,7 @@ static ssize_t loop_rw_iter(int ddir, struct io_rw *rw, struct iov_iter *iter)
                        if (!rw->len)
                                break;
                }
-               if (nr != iovec.iov_len)
+               if (nr != len)
                        break;
        }
 
@@ -503,10 +502,10 @@ static void io_req_map_rw(struct io_kiocb *req, const struct iovec *iovec,
        if (!iovec) {
                unsigned iov_off = 0;
 
-               io->s.iter.iov = io->s.fast_iov;
-               if (iter->iov != fast_iov) {
-                       iov_off = iter->iov - fast_iov;
-                       io->s.iter.iov += iov_off;
+               io->s.iter.__iov = io->s.fast_iov;
+               if (iter->__iov != fast_iov) {
+                       iov_off = iter_iov(iter) - fast_iov;
+                       io->s.iter.__iov += iov_off;
                }
                if (io->s.fast_iov != fast_iov)
                        memcpy(io->s.fast_iov + iov_off, fast_iov + iov_off,
index 0119d3f1a55698a9958d26d9baadb68e3028141a..9db4bc1f521a3162d3480000cdc82e9a1aacfe62 100644 (file)
@@ -233,7 +233,6 @@ static int io_sq_thread(void *data)
                set_cpus_allowed_ptr(current, cpumask_of(sqd->sq_cpu));
        else
                set_cpus_allowed_ptr(current, cpu_online_mask);
-       current->flags |= PF_NO_SETAFFINITY;
 
        mutex_lock(&sqd->lock);
        while (1) {
index 2e4c483075d331f70b2dafa11797e8f7c3fac757..9a1dee5718724a109461560b39fc789132d6a13b 100644 (file)
 static void io_uring_cmd_work(struct io_kiocb *req, bool *locked)
 {
        struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
+       unsigned issue_flags = *locked ? 0 : IO_URING_F_UNLOCKED;
 
-       ioucmd->task_work_cb(ioucmd);
+       ioucmd->task_work_cb(ioucmd, issue_flags);
 }
 
 void io_uring_cmd_complete_in_task(struct io_uring_cmd *ioucmd,
-                       void (*task_work_cb)(struct io_uring_cmd *))
+                       void (*task_work_cb)(struct io_uring_cmd *, unsigned))
 {
        struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
 
@@ -42,7 +43,8 @@ static inline void io_req_set_cqe32_extra(struct io_kiocb *req,
  * Called by consumers of io_uring_cmd, if they originally returned
  * -EIOCBQUEUED upon receiving the command.
  */
-void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2)
+void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2,
+                      unsigned issue_flags)
 {
        struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
 
@@ -56,7 +58,7 @@ void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2)
                /* order with io_iopoll_req_issued() checking ->iopoll_complete */
                smp_store_release(&req->iopoll_completed, 1);
        else
-               io_req_complete_post(req, 0);
+               io_req_complete_post(req, issue_flags);
 }
 EXPORT_SYMBOL_GPL(io_uring_cmd_done);
 
index 10ef068f598d5db37a00f951f057c90b61e04326..6fc72b3afbde10c420317764fd12e0ec77446711 100644 (file)
@@ -15,6 +15,7 @@ obj-y     = fork.o exec_domain.o panic.o \
 obj-$(CONFIG_USERMODE_DRIVER) += usermode_driver.o
 obj-$(CONFIG_MODULES) += kmod.o
 obj-$(CONFIG_MULTIUSER) += groups.o
+obj-$(CONFIG_VHOST_TASK) += vhost_task.o
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace internal ftrace files
index 05f4c66c9089f69a40365651d5d490bcb40313bf..85720311cc6747f3c3e1d1fef0005ecf0eacbed0 100644 (file)
@@ -84,16 +84,13 @@ void bpf_inode_storage_free(struct inode *inode)
 static void *bpf_fd_inode_storage_lookup_elem(struct bpf_map *map, void *key)
 {
        struct bpf_local_storage_data *sdata;
-       struct file *f;
-       int fd;
+       struct fd f = fdget_raw(*(int *)key);
 
-       fd = *(int *)key;
-       f = fget_raw(fd);
-       if (!f)
+       if (!f.file)
                return ERR_PTR(-EBADF);
 
-       sdata = inode_storage_lookup(f->f_inode, map, true);
-       fput(f);
+       sdata = inode_storage_lookup(file_inode(f.file), map, true);
+       fdput(f);
        return sdata ? sdata->data : NULL;
 }
 
@@ -101,22 +98,19 @@ static int bpf_fd_inode_storage_update_elem(struct bpf_map *map, void *key,
                                         void *value, u64 map_flags)
 {
        struct bpf_local_storage_data *sdata;
-       struct file *f;
-       int fd;
+       struct fd f = fdget_raw(*(int *)key);
 
-       fd = *(int *)key;
-       f = fget_raw(fd);
-       if (!f)
+       if (!f.file)
                return -EBADF;
-       if (!inode_storage_ptr(f->f_inode)) {
-               fput(f);
+       if (!inode_storage_ptr(file_inode(f.file))) {
+               fdput(f);
                return -EBADF;
        }
 
-       sdata = bpf_local_storage_update(f->f_inode,
+       sdata = bpf_local_storage_update(file_inode(f.file),
                                         (struct bpf_local_storage_map *)map,
                                         value, map_flags, GFP_ATOMIC);
-       fput(f);
+       fdput(f);
        return PTR_ERR_OR_ZERO(sdata);
 }
 
@@ -135,16 +129,14 @@ static int inode_storage_delete(struct inode *inode, struct bpf_map *map)
 
 static int bpf_fd_inode_storage_delete_elem(struct bpf_map *map, void *key)
 {
-       struct file *f;
-       int fd, err;
+       struct fd f = fdget_raw(*(int *)key);
+       int err;
 
-       fd = *(int *)key;
-       f = fget_raw(fd);
-       if (!f)
+       if (!f.file)
                return -EBADF;
 
-       err = inode_storage_delete(f->f_inode, map);
-       fput(f);
+       err = inode_storage_delete(file_inode(f.file), map);
+       fdput(f);
        return err;
 }
 
index b297e9f60ca1015ec0d788b54f6381b2e9140d6a..e2d256c820723ffb7f2264fc45bfcbc841036974 100644 (file)
@@ -972,7 +972,7 @@ static int __init bpf_jit_charge_init(void)
 {
        /* Only used as heuristic here to derive limit. */
        bpf_jit_limit_max = bpf_jit_alloc_exec_limit();
-       bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2,
+       bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 1,
                                            PAGE_SIZE), LONG_MAX);
        return 0;
 }
index 272563a0b7702a98f4060be952b85570934e210c..767e8930b0bd5da90cdde093461c7442257b2666 100644 (file)
@@ -2967,6 +2967,21 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx,
                        }
                } else if (opcode == BPF_EXIT) {
                        return -ENOTSUPP;
+               } else if (BPF_SRC(insn->code) == BPF_X) {
+                       if (!(*reg_mask & (dreg | sreg)))
+                               return 0;
+                       /* dreg <cond> sreg
+                        * Both dreg and sreg need precision before
+                        * this insn. If only sreg was marked precise
+                        * before it would be equally necessary to
+                        * propagate it to dreg.
+                        */
+                       *reg_mask |= (sreg | dreg);
+                        /* else dreg <cond> K
+                         * Only dreg still needs precision before
+                         * this insn, so for the K-based conditional
+                         * there is nothing new to be marked.
+                         */
                }
        } else if (class == BPF_LD) {
                if (!(*reg_mask & dreg))
@@ -3826,6 +3841,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
                                                continue;
                                        if (type == STACK_MISC)
                                                continue;
+                                       if (type == STACK_INVALID && env->allow_uninit_stack)
+                                               continue;
                                        verbose(env, "invalid read from stack off %d+%d size %d\n",
                                                off, i, size);
                                        return -EACCES;
@@ -3863,6 +3880,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
                                continue;
                        if (type == STACK_ZERO)
                                continue;
+                       if (type == STACK_INVALID && env->allow_uninit_stack)
+                               continue;
                        verbose(env, "invalid read from stack off %d+%d size %d\n",
                                off, i, size);
                        return -EACCES;
@@ -5754,7 +5773,8 @@ static int check_stack_range_initialized(
                stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE];
                if (*stype == STACK_MISC)
                        goto mark;
-               if (*stype == STACK_ZERO) {
+               if ((*stype == STACK_ZERO) ||
+                   (*stype == STACK_INVALID && env->allow_uninit_stack)) {
                        if (clobber) {
                                /* helper can write anything into the stack */
                                *stype = STACK_MISC;
@@ -13936,6 +13956,10 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
                if (old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_INVALID)
                        continue;
 
+               if (env->allow_uninit_stack &&
+                   old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_MISC)
+                       continue;
+
                /* explored stack has more populated slots than current stack
                 * and these slots were used
                 */
index 935e8121b21e67063d32c839b0d3a340b9915176..4b249f81c6933b2499c1f968972211973ba4a087 100644 (file)
@@ -6856,14 +6856,12 @@ EXPORT_SYMBOL_GPL(cgroup_get_from_path);
 struct cgroup *cgroup_v1v2_get_from_fd(int fd)
 {
        struct cgroup *cgrp;
-       struct file *f;
-
-       f = fget_raw(fd);
-       if (!f)
+       struct fd f = fdget_raw(fd);
+       if (!f.file)
                return ERR_PTR(-EBADF);
 
-       cgrp = cgroup_v1v2_get_from_file(f);
-       fput(f);
+       cgrp = cgroup_v1v2_get_from_file(f.file);
+       fdput(f);
        return cgrp;
 }
 
index 636f1c682ac07a86668b186e808c5b1b98f70a6b..505d86b166426e46dd3549683c7b74d614d02af7 100644 (file)
@@ -1513,7 +1513,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
        spin_unlock_irq(&callback_lock);
 
        if (adding || deleting)
-               update_tasks_cpumask(parent, tmp->new_cpus);
+               update_tasks_cpumask(parent, tmp->addmask);
 
        /*
         * Set or clear CS_SCHED_LOAD_BALANCE when partcmd_update, if necessary.
@@ -1770,10 +1770,13 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
        /*
         * Use the cpumasks in trialcs for tmpmasks when they are pointers
         * to allocated cpumasks.
+        *
+        * Note that update_parent_subparts_cpumask() uses only addmask &
+        * delmask, but not new_cpus.
         */
        tmp.addmask  = trialcs->subparts_cpus;
        tmp.delmask  = trialcs->effective_cpus;
-       tmp.new_cpus = trialcs->cpus_allowed;
+       tmp.new_cpus = NULL;
 #endif
 
        retval = validate_change(cs, trialcs);
@@ -1838,6 +1841,11 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
        }
        spin_unlock_irq(&callback_lock);
 
+#ifdef CONFIG_CPUMASK_OFFSTACK
+       /* Now trialcs->cpus_allowed is available */
+       tmp.new_cpus = trialcs->cpus_allowed;
+#endif
+
        /* effective_cpus will be updated here */
        update_cpumasks_hier(cs, &tmp, false);
 
@@ -2445,6 +2453,20 @@ static int fmeter_getrate(struct fmeter *fmp)
 
 static struct cpuset *cpuset_attach_old_cs;
 
+/*
+ * Check to see if a cpuset can accept a new task
+ * For v1, cpus_allowed and mems_allowed can't be empty.
+ * For v2, effective_cpus can't be empty.
+ * Note that in v1, effective_cpus = cpus_allowed.
+ */
+static int cpuset_can_attach_check(struct cpuset *cs)
+{
+       if (cpumask_empty(cs->effective_cpus) ||
+          (!is_in_v2_mode() && nodes_empty(cs->mems_allowed)))
+               return -ENOSPC;
+       return 0;
+}
+
 /* Called by cgroups to determine if a cpuset is usable; cpuset_rwsem held */
 static int cpuset_can_attach(struct cgroup_taskset *tset)
 {
@@ -2459,16 +2481,9 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
 
        percpu_down_write(&cpuset_rwsem);
 
-       /* allow moving tasks into an empty cpuset if on default hierarchy */
-       ret = -ENOSPC;
-       if (!is_in_v2_mode() &&
-           (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
-               goto out_unlock;
-
-       /*
-        * Task cannot be moved to a cpuset with empty effective cpus.
-        */
-       if (cpumask_empty(cs->effective_cpus))
+       /* Check to see if task is allowed in the cpuset */
+       ret = cpuset_can_attach_check(cs);
+       if (ret)
                goto out_unlock;
 
        cgroup_taskset_for_each(task, css, tset) {
@@ -2485,7 +2500,6 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
         * changes which zero cpus/mems_allowed.
         */
        cs->attach_in_progress++;
-       ret = 0;
 out_unlock:
        percpu_up_write(&cpuset_rwsem);
        return ret;
@@ -2494,25 +2508,47 @@ out_unlock:
 static void cpuset_cancel_attach(struct cgroup_taskset *tset)
 {
        struct cgroup_subsys_state *css;
+       struct cpuset *cs;
 
        cgroup_taskset_first(tset, &css);
+       cs = css_cs(css);
 
        percpu_down_write(&cpuset_rwsem);
-       css_cs(css)->attach_in_progress--;
+       cs->attach_in_progress--;
+       if (!cs->attach_in_progress)
+               wake_up(&cpuset_attach_wq);
        percpu_up_write(&cpuset_rwsem);
 }
 
 /*
- * Protected by cpuset_rwsem.  cpus_attach is used only by cpuset_attach()
+ * Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach_task()
  * but we can't allocate it dynamically there.  Define it global and
  * allocate from cpuset_init().
  */
 static cpumask_var_t cpus_attach;
+static nodemask_t cpuset_attach_nodemask_to;
+
+static void cpuset_attach_task(struct cpuset *cs, struct task_struct *task)
+{
+       percpu_rwsem_assert_held(&cpuset_rwsem);
+
+       if (cs != &top_cpuset)
+               guarantee_online_cpus(task, cpus_attach);
+       else
+               cpumask_andnot(cpus_attach, task_cpu_possible_mask(task),
+                              cs->subparts_cpus);
+       /*
+        * can_attach beforehand should guarantee that this doesn't
+        * fail.  TODO: have a better way to handle failure here
+        */
+       WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
+
+       cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
+       cpuset_update_task_spread_flags(cs, task);
+}
 
 static void cpuset_attach(struct cgroup_taskset *tset)
 {
-       /* static buf protected by cpuset_rwsem */
-       static nodemask_t cpuset_attach_nodemask_to;
        struct task_struct *task;
        struct task_struct *leader;
        struct cgroup_subsys_state *css;
@@ -2543,20 +2579,8 @@ static void cpuset_attach(struct cgroup_taskset *tset)
 
        guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
 
-       cgroup_taskset_for_each(task, css, tset) {
-               if (cs != &top_cpuset)
-                       guarantee_online_cpus(task, cpus_attach);
-               else
-                       cpumask_copy(cpus_attach, task_cpu_possible_mask(task));
-               /*
-                * can_attach beforehand should guarantee that this doesn't
-                * fail.  TODO: have a better way to handle failure here
-                */
-               WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
-
-               cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
-               cpuset_update_task_spread_flags(cs, task);
-       }
+       cgroup_taskset_for_each(task, css, tset)
+               cpuset_attach_task(cs, task);
 
        /*
         * Change mm for all threadgroup leaders. This is expensive and may
@@ -3247,6 +3271,68 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
        percpu_up_write(&cpuset_rwsem);
 }
 
+/*
+ * In case the child is cloned into a cpuset different from its parent,
+ * additional checks are done to see if the move is allowed.
+ */
+static int cpuset_can_fork(struct task_struct *task, struct css_set *cset)
+{
+       struct cpuset *cs = css_cs(cset->subsys[cpuset_cgrp_id]);
+       bool same_cs;
+       int ret;
+
+       rcu_read_lock();
+       same_cs = (cs == task_cs(current));
+       rcu_read_unlock();
+
+       if (same_cs)
+               return 0;
+
+       lockdep_assert_held(&cgroup_mutex);
+       percpu_down_write(&cpuset_rwsem);
+
+       /* Check to see if task is allowed in the cpuset */
+       ret = cpuset_can_attach_check(cs);
+       if (ret)
+               goto out_unlock;
+
+       ret = task_can_attach(task, cs->effective_cpus);
+       if (ret)
+               goto out_unlock;
+
+       ret = security_task_setscheduler(task);
+       if (ret)
+               goto out_unlock;
+
+       /*
+        * Mark attach is in progress.  This makes validate_change() fail
+        * changes which zero cpus/mems_allowed.
+        */
+       cs->attach_in_progress++;
+out_unlock:
+       percpu_up_write(&cpuset_rwsem);
+       return ret;
+}
+
+static void cpuset_cancel_fork(struct task_struct *task, struct css_set *cset)
+{
+       struct cpuset *cs = css_cs(cset->subsys[cpuset_cgrp_id]);
+       bool same_cs;
+
+       rcu_read_lock();
+       same_cs = (cs == task_cs(current));
+       rcu_read_unlock();
+
+       if (same_cs)
+               return;
+
+       percpu_down_write(&cpuset_rwsem);
+       cs->attach_in_progress--;
+       if (!cs->attach_in_progress)
+               wake_up(&cpuset_attach_wq);
+       percpu_up_write(&cpuset_rwsem);
+}
+
 /*
  * Make sure the new task conform to the current state of its parent,
  * which could have been changed by cpuset just after it inherits the
@@ -3254,11 +3340,33 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css)
  */
 static void cpuset_fork(struct task_struct *task)
 {
-       if (task_css_is_root(task, cpuset_cgrp_id))
+       struct cpuset *cs;
+       bool same_cs;
+
+       rcu_read_lock();
+       cs = task_cs(task);
+       same_cs = (cs == task_cs(current));
+       rcu_read_unlock();
+
+       if (same_cs) {
+               if (cs == &top_cpuset)
+                       return;
+
+               set_cpus_allowed_ptr(task, current->cpus_ptr);
+               task->mems_allowed = current->mems_allowed;
                return;
+       }
+
+       /* CLONE_INTO_CGROUP */
+       percpu_down_write(&cpuset_rwsem);
+       guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
+       cpuset_attach_task(cs, task);
+
+       cs->attach_in_progress--;
+       if (!cs->attach_in_progress)
+               wake_up(&cpuset_attach_wq);
 
-       set_cpus_allowed_ptr(task, current->cpus_ptr);
-       task->mems_allowed = current->mems_allowed;
+       percpu_up_write(&cpuset_rwsem);
 }
 
 struct cgroup_subsys cpuset_cgrp_subsys = {
@@ -3271,6 +3379,8 @@ struct cgroup_subsys cpuset_cgrp_subsys = {
        .attach         = cpuset_attach,
        .post_attach    = cpuset_post_attach,
        .bind           = cpuset_bind,
+       .can_fork       = cpuset_can_fork,
+       .cancel_fork    = cpuset_cancel_fork,
        .fork           = cpuset_fork,
        .legacy_cftypes = legacy_files,
        .dfl_cftypes    = dfl_files,
index 1b6b21851e9d47daa3456123d604ab4d5e0f3b9c..936473203a6b511c2fa095a04ba219282913ab6a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/freezer.h>
 #include <linux/seq_file.h>
 #include <linux/mutex.h>
+#include <linux/cpu.h>
 
 /*
  * A cgroup is freezing if any FREEZING flags are set.  FREEZING_SELF is
@@ -350,7 +351,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze,
 
        if (freeze) {
                if (!(freezer->state & CGROUP_FREEZING))
-                       static_branch_inc(&freezer_active);
+                       static_branch_inc_cpuslocked(&freezer_active);
                freezer->state |= state;
                freeze_cgroup(freezer);
        } else {
@@ -361,7 +362,7 @@ static void freezer_apply_state(struct freezer *freezer, bool freeze,
                if (!(freezer->state & CGROUP_FREEZING)) {
                        freezer->state &= ~CGROUP_FROZEN;
                        if (was_freezing)
-                               static_branch_dec(&freezer_active);
+                               static_branch_dec_cpuslocked(&freezer_active);
                        unfreeze_cgroup(freezer);
                }
        }
@@ -379,6 +380,7 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
 {
        struct cgroup_subsys_state *pos;
 
+       cpus_read_lock();
        /*
         * Update all its descendants in pre-order traversal.  Each
         * descendant will try to inherit its parent's FREEZING state as
@@ -407,6 +409,7 @@ static void freezer_change_state(struct freezer *freezer, bool freeze)
        }
        rcu_read_unlock();
        mutex_unlock(&freezer_mutex);
+       cpus_read_unlock();
 }
 
 static ssize_t freezer_write(struct kernfs_open_file *of,
index 831f1f472bb814c945006f996d978c545e7a8759..0a2b4967e3334ca54003725c0aec38fd169c435e 100644 (file)
@@ -457,9 +457,7 @@ static void root_cgroup_cputime(struct cgroup_base_stat *bstat)
        struct task_cputime *cputime = &bstat->cputime;
        int i;
 
-       cputime->stime = 0;
-       cputime->utime = 0;
-       cputime->sum_exec_runtime = 0;
+       memset(bstat, 0, sizeof(*bstat));
        for_each_possible_cpu(i) {
                struct kernel_cpustat kcpustat;
                u64 *cpustat = kcpustat.cpustat;
index 55551989d9da50215c2c0954d55baa2a83bc03a9..fb50f29d9b361db607391c0228c9ee9a6f713b38 100644 (file)
@@ -152,7 +152,7 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t,  pid, unsigned int, len,
        if (len & (sizeof(compat_ulong_t)-1))
                return -EINVAL;
 
-       if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
                return -ENOMEM;
 
        ret = sched_getaffinity(pid, mask);
index 03e3251cd9d2b63daceebcf99dfa4c9971dadfe2..dac42a2ad5883c16b851dc94c53d17c638a91b66 100644 (file)
@@ -623,10 +623,10 @@ static int swiotlb_do_find_slots(struct device *dev, int area_index,
                phys_to_dma_unencrypted(dev, mem->start) & boundary_mask;
        unsigned long max_slots = get_max_slots(boundary_mask);
        unsigned int iotlb_align_mask =
-               dma_get_min_align_mask(dev) & ~(IO_TLB_SIZE - 1);
+               dma_get_min_align_mask(dev) | alloc_align_mask;
        unsigned int nslots = nr_slots(alloc_size), stride;
-       unsigned int index, wrap, count = 0, i;
        unsigned int offset = swiotlb_align_offset(dev, orig_addr);
+       unsigned int index, slots_checked, count = 0, i;
        unsigned long flags;
        unsigned int slot_base;
        unsigned int slot_index;
@@ -634,30 +634,35 @@ static int swiotlb_do_find_slots(struct device *dev, int area_index,
        BUG_ON(!nslots);
        BUG_ON(area_index >= mem->nareas);
 
+       /*
+        * For allocations of PAGE_SIZE or larger only look for page aligned
+        * allocations.
+        */
+       if (alloc_size >= PAGE_SIZE)
+               iotlb_align_mask |= ~PAGE_MASK;
+       iotlb_align_mask &= ~(IO_TLB_SIZE - 1);
+
        /*
         * For mappings with an alignment requirement don't bother looping to
-        * unaligned slots once we found an aligned one.  For allocations of
-        * PAGE_SIZE or larger only look for page aligned allocations.
+        * unaligned slots once we found an aligned one.
         */
        stride = (iotlb_align_mask >> IO_TLB_SHIFT) + 1;
-       if (alloc_size >= PAGE_SIZE)
-               stride = max(stride, stride << (PAGE_SHIFT - IO_TLB_SHIFT));
-       stride = max(stride, (alloc_align_mask >> IO_TLB_SHIFT) + 1);
 
        spin_lock_irqsave(&area->lock, flags);
        if (unlikely(nslots > mem->area_nslabs - area->used))
                goto not_found;
 
        slot_base = area_index * mem->area_nslabs;
-       index = wrap = wrap_area_index(mem, ALIGN(area->index, stride));
+       index = area->index;
 
-       do {
+       for (slots_checked = 0; slots_checked < mem->area_nslabs; ) {
                slot_index = slot_base + index;
 
                if (orig_addr &&
                    (slot_addr(tbl_dma_addr, slot_index) &
                     iotlb_align_mask) != (orig_addr & iotlb_align_mask)) {
                        index = wrap_area_index(mem, index + 1);
+                       slots_checked++;
                        continue;
                }
 
@@ -673,7 +678,8 @@ static int swiotlb_do_find_slots(struct device *dev, int area_index,
                                goto found;
                }
                index = wrap_area_index(mem, index + stride);
-       } while (index != wrap);
+               slots_checked += stride;
+       }
 
 not_found:
        spin_unlock_irqrestore(&area->lock, flags);
@@ -693,10 +699,7 @@ found:
        /*
         * Update the indices to avoid searching in the next round.
         */
-       if (index + nslots < mem->area_nslabs)
-               area->index = index + nslots;
-       else
-               area->index = 0;
+       area->index = wrap_area_index(mem, index + nslots);
        area->used += nslots;
        spin_unlock_irqrestore(&area->lock, flags);
        return slot_index;
index 846add8394c4159c8e5accb77ecc10e463519e3b..be61332c66b54a02b37d7a1847001b23a82d910e 100644 (file)
@@ -21,7 +21,7 @@ static __always_inline void __enter_from_user_mode(struct pt_regs *regs)
        arch_enter_from_user_mode(regs);
        lockdep_hardirqs_off(CALLER_ADDR0);
 
-       CT_WARN_ON(ct_state() != CONTEXT_USER);
+       CT_WARN_ON(__ct_state() != CONTEXT_USER);
        user_exit_irqoff();
 
        instrumentation_begin();
@@ -192,13 +192,14 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
 
 static void exit_to_user_mode_prepare(struct pt_regs *regs)
 {
-       unsigned long ti_work = read_thread_flags();
+       unsigned long ti_work;
 
        lockdep_assert_irqs_disabled();
 
        /* Flush pending rcuog wakeup before the last need_resched() check */
        tick_nohz_user_enter_prepare();
 
+       ti_work = read_thread_flags();
        if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK))
                ti_work = exit_to_user_mode_loop(regs, ti_work);
 
index 0b6379adff6bdd4327ace5ae7029cfd24369e825..5340c5aa89e7dd33f30a3543e4f73bfc08ea5a4e 100644 (file)
@@ -4,6 +4,7 @@
  */
 #include <linux/sched.h>
 #include <linux/prctl.h>
+#include <linux/ptrace.h>
 #include <linux/syscall_user_dispatch.h>
 #include <linux/uaccess.h>
 #include <linux/signal.h>
@@ -68,8 +69,9 @@ bool syscall_user_dispatch(struct pt_regs *regs)
        return true;
 }
 
-int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
-                             unsigned long len, char __user *selector)
+static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned long mode,
+                                         unsigned long offset, unsigned long len,
+                                         char __user *selector)
 {
        switch (mode) {
        case PR_SYS_DISPATCH_OFF:
@@ -86,7 +88,16 @@ int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
                if (offset && offset + len <= offset)
                        return -EINVAL;
 
-               if (selector && !access_ok(selector, sizeof(*selector)))
+               /*
+                * access_ok() will clear memory tags for tagged addresses
+                * if current has memory tagging enabled.
+
+                * To enable a tracer to set a tracees selector the
+                * selector address must be untagged for access_ok(),
+                * otherwise an untagged tracer will always fail to set a
+                * tagged tracees selector.
+                */
+               if (selector && !access_ok(untagged_addr(selector), sizeof(*selector)))
                        return -EFAULT;
 
                break;
@@ -94,15 +105,60 @@ int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
                return -EINVAL;
        }
 
-       current->syscall_dispatch.selector = selector;
-       current->syscall_dispatch.offset = offset;
-       current->syscall_dispatch.len = len;
-       current->syscall_dispatch.on_dispatch = false;
+       task->syscall_dispatch.selector = selector;
+       task->syscall_dispatch.offset = offset;
+       task->syscall_dispatch.len = len;
+       task->syscall_dispatch.on_dispatch = false;
 
        if (mode == PR_SYS_DISPATCH_ON)
-               set_syscall_work(SYSCALL_USER_DISPATCH);
+               set_task_syscall_work(task, SYSCALL_USER_DISPATCH);
+       else
+               clear_task_syscall_work(task, SYSCALL_USER_DISPATCH);
+
+       return 0;
+}
+
+int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
+                             unsigned long len, char __user *selector)
+{
+       return task_set_syscall_user_dispatch(current, mode, offset, len, selector);
+}
+
+int syscall_user_dispatch_get_config(struct task_struct *task, unsigned long size,
+                                    void __user *data)
+{
+       struct syscall_user_dispatch *sd = &task->syscall_dispatch;
+       struct ptrace_sud_config cfg;
+
+       if (size != sizeof(cfg))
+               return -EINVAL;
+
+       if (test_task_syscall_work(task, SYSCALL_USER_DISPATCH))
+               cfg.mode = PR_SYS_DISPATCH_ON;
        else
-               clear_syscall_work(SYSCALL_USER_DISPATCH);
+               cfg.mode = PR_SYS_DISPATCH_OFF;
+
+       cfg.offset = sd->offset;
+       cfg.len = sd->len;
+       cfg.selector = (__u64)(uintptr_t)sd->selector;
+
+       if (copy_to_user(data, &cfg, sizeof(cfg)))
+               return -EFAULT;
 
        return 0;
 }
+
+int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long size,
+                                    void __user *data)
+{
+       struct ptrace_sud_config cfg;
+
+       if (size != sizeof(cfg))
+               return -EINVAL;
+
+       if (copy_from_user(&cfg, data, sizeof(cfg)))
+               return -EFAULT;
+
+       return task_set_syscall_user_dispatch(task, cfg.mode, cfg.offset, cfg.len,
+                                             (char __user *)(uintptr_t)cfg.selector);
+}
index f79fd8b87f75edc22453a47dee8c9b14855e8eeb..435815d3be3f8104cee70f8330bcc7058e38402b 100644 (file)
@@ -2163,7 +2163,7 @@ static void perf_group_detach(struct perf_event *event)
                /* Inherit group flags from the previous leader */
                sibling->group_caps = event->group_caps;
 
-               if (!RB_EMPTY_NODE(&event->group_node)) {
+               if (sibling->attach_state & PERF_ATTACH_CONTEXT) {
                        add_event_to_groups(sibling, event->ctx);
 
                        if (sibling->state == PERF_EVENT_STATE_ACTIVE)
@@ -3872,7 +3872,7 @@ ctx_sched_in(struct perf_event_context *ctx, enum event_type_t event_type)
        if (likely(!ctx->nr_events))
                return;
 
-       if (is_active ^ EVENT_TIME) {
+       if (!(is_active & EVENT_TIME)) {
                /* start ctx time */
                __update_context_time(ctx, false);
                perf_cgroup_set_timestamp(cpuctx);
@@ -9187,7 +9187,7 @@ static void perf_event_bpf_output(struct perf_event *event, void *data)
 
        perf_event_header__init_id(&bpf_event->event_id.header,
                                   &sample, event);
-       ret = perf_output_begin(&handle, data, event,
+       ret = perf_output_begin(&handle, &sample, event,
                                bpf_event->event_id.header.size);
        if (ret)
                return;
@@ -12173,7 +12173,7 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event)
        /*
         * If its not a per-cpu rb, it must be the same task.
         */
-       if (output_event->cpu == -1 && output_event->ctx != event->ctx)
+       if (output_event->cpu == -1 && output_event->hw.target != event->hw.target)
                goto out;
 
        /*
@@ -12893,12 +12893,14 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
        __perf_pmu_remove(src_ctx, src_cpu, pmu, &src_ctx->pinned_groups, &events);
        __perf_pmu_remove(src_ctx, src_cpu, pmu, &src_ctx->flexible_groups, &events);
 
-       /*
-        * Wait for the events to quiesce before re-instating them.
-        */
-       synchronize_rcu();
+       if (!list_empty(&events)) {
+               /*
+                * Wait for the events to quiesce before re-instating them.
+                */
+               synchronize_rcu();
 
-       __perf_pmu_install(dst_ctx, dst_cpu, pmu, &events);
+               __perf_pmu_install(dst_ctx, dst_cpu, pmu, &events);
+       }
 
        mutex_unlock(&dst_ctx->mutex);
        mutex_unlock(&src_ctx->mutex);
index d8cda4c6de6c705051ffa2c14aa83a68c989da2f..bfe73db1c26c21c0ea8fe775fe90a3d3c475bb36 100644 (file)
@@ -617,6 +617,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
        if (retval)
                goto out;
 
+       mt_clear_in_rcu(vmi.mas.tree);
        for_each_vma(old_vmi, mpnt) {
                struct file *file;
 
@@ -700,6 +701,8 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
        retval = arch_dup_mmap(oldmm, mm);
 loop_out:
        vma_iter_free(&vmi);
+       if (!retval)
+               mt_set_in_rcu(vmi.mas.tree);
 out:
        mmap_write_unlock(mm);
        flush_tlb_mm(oldmm);
@@ -755,11 +758,6 @@ static void check_mm(struct mm_struct *mm)
        for (i = 0; i < NR_MM_COUNTERS; i++) {
                long x = percpu_counter_sum(&mm->rss_stat[i]);
 
-               if (likely(!x))
-                       continue;
-
-               /* Making sure this is not due to race with CPU offlining. */
-               x = percpu_counter_sum_all(&mm->rss_stat[i]);
                if (unlikely(x))
                        pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n",
                                 mm, resident_page_types[i], x);
@@ -1176,6 +1174,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
 fail_pcpu:
        while (i > 0)
                percpu_counter_destroy(&mm->rss_stat[--i]);
+       destroy_context(mm);
 fail_nocontext:
        mm_free_pgd(mm);
 fail_nopgd:
@@ -1627,7 +1626,8 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
        return 0;
 }
 
-static int copy_files(unsigned long clone_flags, struct task_struct *tsk)
+static int copy_files(unsigned long clone_flags, struct task_struct *tsk,
+                     int no_files)
 {
        struct files_struct *oldf, *newf;
        int error = 0;
@@ -1639,6 +1639,11 @@ static int copy_files(unsigned long clone_flags, struct task_struct *tsk)
        if (!oldf)
                goto out;
 
+       if (no_files) {
+               tsk->files = NULL;
+               goto out;
+       }
+
        if (clone_flags & CLONE_FILES) {
                atomic_inc(&oldf->count);
                goto out;
@@ -1956,6 +1961,91 @@ const struct file_operations pidfd_fops = {
 #endif
 };
 
+/**
+ * __pidfd_prepare - allocate a new pidfd_file and reserve a pidfd
+ * @pid:   the struct pid for which to create a pidfd
+ * @flags: flags of the new @pidfd
+ * @pidfd: the pidfd to return
+ *
+ * Allocate a new file that stashes @pid and reserve a new pidfd number in the
+ * caller's file descriptor table. The pidfd is reserved but not installed yet.
+
+ * The helper doesn't perform checks on @pid which makes it useful for pidfds
+ * created via CLONE_PIDFD where @pid has no task attached when the pidfd and
+ * pidfd file are prepared.
+ *
+ * If this function returns successfully the caller is responsible to either
+ * call fd_install() passing the returned pidfd and pidfd file as arguments in
+ * order to install the pidfd into its file descriptor table or they must use
+ * put_unused_fd() and fput() on the returned pidfd and pidfd file
+ * respectively.
+ *
+ * This function is useful when a pidfd must already be reserved but there
+ * might still be points of failure afterwards and the caller wants to ensure
+ * that no pidfd is leaked into its file descriptor table.
+ *
+ * Return: On success, a reserved pidfd is returned from the function and a new
+ *         pidfd file is returned in the last argument to the function. On
+ *         error, a negative error code is returned from the function and the
+ *         last argument remains unchanged.
+ */
+static int __pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret)
+{
+       int pidfd;
+       struct file *pidfd_file;
+
+       if (flags & ~(O_NONBLOCK | O_RDWR | O_CLOEXEC))
+               return -EINVAL;
+
+       pidfd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
+       if (pidfd < 0)
+               return pidfd;
+
+       pidfd_file = anon_inode_getfile("[pidfd]", &pidfd_fops, pid,
+                                       flags | O_RDWR | O_CLOEXEC);
+       if (IS_ERR(pidfd_file)) {
+               put_unused_fd(pidfd);
+               return PTR_ERR(pidfd_file);
+       }
+       get_pid(pid); /* held by pidfd_file now */
+       *ret = pidfd_file;
+       return pidfd;
+}
+
+/**
+ * pidfd_prepare - allocate a new pidfd_file and reserve a pidfd
+ * @pid:   the struct pid for which to create a pidfd
+ * @flags: flags of the new @pidfd
+ * @pidfd: the pidfd to return
+ *
+ * Allocate a new file that stashes @pid and reserve a new pidfd number in the
+ * caller's file descriptor table. The pidfd is reserved but not installed yet.
+ *
+ * The helper verifies that @pid is used as a thread group leader.
+ *
+ * If this function returns successfully the caller is responsible to either
+ * call fd_install() passing the returned pidfd and pidfd file as arguments in
+ * order to install the pidfd into its file descriptor table or they must use
+ * put_unused_fd() and fput() on the returned pidfd and pidfd file
+ * respectively.
+ *
+ * This function is useful when a pidfd must already be reserved but there
+ * might still be points of failure afterwards and the caller wants to ensure
+ * that no pidfd is leaked into its file descriptor table.
+ *
+ * Return: On success, a reserved pidfd is returned from the function and a new
+ *         pidfd file is returned in the last argument to the function. On
+ *         error, a negative error code is returned from the function and the
+ *         last argument remains unchanged.
+ */
+int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret)
+{
+       if (!pid || !pid_has_task(pid, PIDTYPE_TGID))
+               return -EINVAL;
+
+       return __pidfd_prepare(pid, flags, ret);
+}
+
 static void __delayed_free_task(struct rcu_head *rhp)
 {
        struct task_struct *tsk = container_of(rhp, struct task_struct, rcu);
@@ -2010,7 +2100,7 @@ static void rv_task_fork(struct task_struct *p)
  * parts of the process environment (as per the clone
  * flags). The actual kick-off is left to the caller.
  */
-static __latent_entropy struct task_struct *copy_process(
+__latent_entropy struct task_struct *copy_process(
                                        struct pid *pid,
                                        int trace,
                                        int node,
@@ -2103,6 +2193,8 @@ static __latent_entropy struct task_struct *copy_process(
        p->flags &= ~PF_KTHREAD;
        if (args->kthread)
                p->flags |= PF_KTHREAD;
+       if (args->user_worker)
+               p->flags |= PF_USER_WORKER;
        if (args->io_thread) {
                /*
                 * Mark us an IO worker, and block any signal that isn't
@@ -2112,6 +2204,9 @@ static __latent_entropy struct task_struct *copy_process(
                siginitsetinv(&p->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
        }
 
+       if (args->name)
+               strscpy_pad(p->comm, args->name, sizeof(p->comm));
+
        p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? args->child_tid : NULL;
        /*
         * Clear TID on mm_release()?
@@ -2254,7 +2349,7 @@ static __latent_entropy struct task_struct *copy_process(
        retval = copy_semundo(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_security;
-       retval = copy_files(clone_flags, p);
+       retval = copy_files(clone_flags, p, args->no_files);
        if (retval)
                goto bad_fork_cleanup_semundo;
        retval = copy_fs(clone_flags, p);
@@ -2279,6 +2374,9 @@ static __latent_entropy struct task_struct *copy_process(
        if (retval)
                goto bad_fork_cleanup_io;
 
+       if (args->ignore_signals)
+               ignore_signals(p);
+
        stackleak_task_init(p);
 
        if (pid != &init_struct_pid) {
@@ -2296,21 +2394,12 @@ static __latent_entropy struct task_struct *copy_process(
         * if the fd table isn't shared).
         */
        if (clone_flags & CLONE_PIDFD) {
-               retval = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
+               /* Note that no task has been attached to @pid yet. */
+               retval = __pidfd_prepare(pid, O_RDWR | O_CLOEXEC, &pidfile);
                if (retval < 0)
                        goto bad_fork_free_pid;
-
                pidfd = retval;
 
-               pidfile = anon_inode_getfile("[pidfd]", &pidfd_fops, pid,
-                                             O_RDWR | O_CLOEXEC);
-               if (IS_ERR(pidfile)) {
-                       put_unused_fd(pidfd);
-                       retval = PTR_ERR(pidfile);
-                       goto bad_fork_free_pid;
-               }
-               get_pid(pid);   /* held by pidfile now */
-
                retval = put_user(pidfd, args->pidfd);
                if (retval)
                        goto bad_fork_put_pidfd;
@@ -2627,6 +2716,7 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
                .fn             = fn,
                .fn_arg         = arg,
                .io_thread      = 1,
+               .user_worker    = 1,
        };
 
        return copy_process(NULL, 0, node, &args);
@@ -2730,7 +2820,8 @@ pid_t kernel_clone(struct kernel_clone_args *args)
 /*
  * Create a kernel thread.
  */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+pid_t kernel_thread(int (*fn)(void *), void *arg, const char *name,
+                   unsigned long flags)
 {
        struct kernel_clone_args args = {
                .flags          = ((lower_32_bits(flags) | CLONE_VM |
@@ -2738,6 +2829,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
                .exit_signal    = (lower_32_bits(flags) & CSIGNAL),
                .fn             = fn,
                .fn_arg         = arg,
+               .name           = name,
                .kthread        = 1,
        };
 
index 8ce75495e04f137ec48f8259d2b3444a3e1c8281..d2742af0f0fd870124c8fa189c102e8f330ff4d9 100644 (file)
@@ -189,9 +189,12 @@ void irq_set_thread_affinity(struct irq_desc *desc)
 {
        struct irqaction *action;
 
-       for_each_action_of_desc(desc, action)
+       for_each_action_of_desc(desc, action) {
                if (action->thread)
                        set_bit(IRQTF_AFFINITY, &action->thread_flags);
+               if (action->secondary && action->secondary->thread)
+                       set_bit(IRQTF_AFFINITY, &action->secondary->thread_flags);
+       }
 }
 
 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
index 8cf70f068d92d31fda0d147782d55760c6854b5a..a45f3dfc8d14169ae3ea4ee875897213f81236be 100644 (file)
@@ -16,6 +16,6 @@ obj-y := core.o debugfs.o report.o
 KCSAN_INSTRUMENT_BARRIERS_selftest.o := y
 obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o
 
-CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer
+CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -fno-omit-frame-pointer
 CFLAGS_kcsan_test.o += $(DISABLE_STRUCTLEAK_PLUGIN)
 obj-$(CONFIG_KCSAN_KUNIT_TEST) += kcsan_test.o
index 54d077e1a2dc7ba80be3662c32a065dcc42d9836..5a60cc52adc0c508602b54bc691fd091f2da3beb 100644 (file)
@@ -337,11 +337,20 @@ static void delay_access(int type)
  */
 static __always_inline u64 read_instrumented_memory(const volatile void *ptr, size_t size)
 {
+       /*
+        * In the below we don't necessarily need the read of the location to
+        * be atomic, and we don't use READ_ONCE(), since all we need for race
+        * detection is to observe 2 different values.
+        *
+        * Furthermore, on certain architectures (such as arm64), READ_ONCE()
+        * may turn into more complex instructions than a plain load that cannot
+        * do unaligned accesses.
+        */
        switch (size) {
-       case 1:  return READ_ONCE(*(const u8 *)ptr);
-       case 2:  return READ_ONCE(*(const u16 *)ptr);
-       case 4:  return READ_ONCE(*(const u32 *)ptr);
-       case 8:  return READ_ONCE(*(const u64 *)ptr);
+       case 1:  return *(const volatile u8 *)ptr;
+       case 2:  return *(const volatile u16 *)ptr;
+       case 4:  return *(const volatile u32 *)ptr;
+       case 8:  return *(const volatile u64 *)ptr;
        default: return 0; /* Ignore; we do not diff the values. */
        }
 }
index 7e6751b29101e5ca4050aa512b922ab05ddfc5e2..4bc6e0971ec93ce9322f5743b3d7c8b43a76b9b0 100644 (file)
@@ -38,6 +38,7 @@ struct task_struct *kthreadd_task;
 struct kthread_create_info
 {
        /* Information passed to kthread() from kthreadd. */
+       char *full_name;
        int (*threadfn)(void *data);
        void *data;
        int node;
@@ -343,10 +344,12 @@ static int kthread(void *_create)
        /* Release the structure when caller killed by a fatal signal. */
        done = xchg(&create->done, NULL);
        if (!done) {
+               kfree(create->full_name);
                kfree(create);
                kthread_exit(-EINTR);
        }
 
+       self->full_name = create->full_name;
        self->threadfn = threadfn;
        self->data = data;
 
@@ -396,11 +399,13 @@ static void create_kthread(struct kthread_create_info *create)
        current->pref_node_fork = create->node;
 #endif
        /* We want our own signal handler (we take no signals by default). */
-       pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
+       pid = kernel_thread(kthread, create, create->full_name,
+                           CLONE_FS | CLONE_FILES | SIGCHLD);
        if (pid < 0) {
                /* Release the structure when caller killed by a fatal signal. */
                struct completion *done = xchg(&create->done, NULL);
 
+               kfree(create->full_name);
                if (!done) {
                        kfree(create);
                        return;
@@ -427,6 +432,11 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
        create->data = data;
        create->node = node;
        create->done = &done;
+       create->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
+       if (!create->full_name) {
+               task = ERR_PTR(-ENOMEM);
+               goto free_create;
+       }
 
        spin_lock(&kthread_create_lock);
        list_add_tail(&create->list, &kthread_create_list);
@@ -453,26 +463,7 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
                wait_for_completion(&done);
        }
        task = create->result;
-       if (!IS_ERR(task)) {
-               char name[TASK_COMM_LEN];
-               va_list aq;
-               int len;
-
-               /*
-                * task is already visible to other tasks, so updating
-                * COMM must be protected.
-                */
-               va_copy(aq, args);
-               len = vsnprintf(name, sizeof(name), namefmt, aq);
-               va_end(aq);
-               if (len >= TASK_COMM_LEN) {
-                       struct kthread *kthread = to_kthread(task);
-
-                       /* leave it truncated when out of memory. */
-                       kthread->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
-               }
-               set_task_comm(task, name);
-       }
+free_create:
        kfree(create);
        return task;
 }
index 50d4863974e7a218a3c4b855d3934712c80c614a..dcd1d5bfc1e077a57da1253d0eaab90e61100bd2 100644 (file)
@@ -1881,6 +1881,8 @@ print_circular_lock_scenario(struct held_lock *src,
        struct lock_class *source = hlock_class(src);
        struct lock_class *target = hlock_class(tgt);
        struct lock_class *parent = prt->class;
+       int src_read = src->read;
+       int tgt_read = tgt->read;
 
        /*
         * A direct locking problem where unsafe_class lock is taken
@@ -1908,7 +1910,10 @@ print_circular_lock_scenario(struct held_lock *src,
        printk(" Possible unsafe locking scenario:\n\n");
        printk("       CPU0                    CPU1\n");
        printk("       ----                    ----\n");
-       printk("  lock(");
+       if (tgt_read != 0)
+               printk("  rlock(");
+       else
+               printk("  lock(");
        __print_lock_name(target);
        printk(KERN_CONT ");\n");
        printk("                               lock(");
@@ -1917,7 +1922,12 @@ print_circular_lock_scenario(struct held_lock *src,
        printk("                               lock(");
        __print_lock_name(target);
        printk(KERN_CONT ");\n");
-       printk("  lock(");
+       if (src_read != 0)
+               printk("  rlock(");
+       else if (src->sync)
+               printk("  sync(");
+       else
+               printk("  lock(");
        __print_lock_name(source);
        printk(KERN_CONT ");\n");
        printk("\n *** DEADLOCK ***\n\n");
@@ -4531,7 +4541,13 @@ mark_usage(struct task_struct *curr, struct held_lock *hlock, int check)
                                        return 0;
                }
        }
-       if (!hlock->hardirqs_off) {
+
+       /*
+        * For lock_sync(), don't mark the ENABLED usage, since lock_sync()
+        * creates no critical section and no extra dependency can be introduced
+        * by interrupts
+        */
+       if (!hlock->hardirqs_off && !hlock->sync) {
                if (hlock->read) {
                        if (!mark_lock(curr, hlock,
                                        LOCK_ENABLED_HARDIRQ_READ))
@@ -4910,7 +4926,7 @@ static int __lock_is_held(const struct lockdep_map *lock, int read);
 static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
                          int trylock, int read, int check, int hardirqs_off,
                          struct lockdep_map *nest_lock, unsigned long ip,
-                         int references, int pin_count)
+                         int references, int pin_count, int sync)
 {
        struct task_struct *curr = current;
        struct lock_class *class = NULL;
@@ -4961,7 +4977,8 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 
        class_idx = class - lock_classes;
 
-       if (depth) { /* we're holding locks */
+       if (depth && !sync) {
+               /* we're holding locks and the new held lock is not a sync */
                hlock = curr->held_locks + depth - 1;
                if (hlock->class_idx == class_idx && nest_lock) {
                        if (!references)
@@ -4995,6 +5012,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        hlock->trylock = trylock;
        hlock->read = read;
        hlock->check = check;
+       hlock->sync = !!sync;
        hlock->hardirqs_off = !!hardirqs_off;
        hlock->references = references;
 #ifdef CONFIG_LOCK_STAT
@@ -5056,6 +5074,10 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        if (!validate_chain(curr, hlock, chain_head, chain_key))
                return 0;
 
+       /* For lock_sync(), we are done here since no actual critical section */
+       if (hlock->sync)
+               return 1;
+
        curr->curr_chain_key = chain_key;
        curr->lockdep_depth++;
        check_chain_key(curr);
@@ -5197,7 +5219,7 @@ static int reacquire_held_locks(struct task_struct *curr, unsigned int depth,
                                    hlock->read, hlock->check,
                                    hlock->hardirqs_off,
                                    hlock->nest_lock, hlock->acquire_ip,
-                                   hlock->references, hlock->pin_count)) {
+                                   hlock->references, hlock->pin_count, 0)) {
                case 0:
                        return 1;
                case 1:
@@ -5667,7 +5689,7 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 
        lockdep_recursion_inc();
        __lock_acquire(lock, subclass, trylock, read, check,
-                      irqs_disabled_flags(flags), nest_lock, ip, 0, 0);
+                      irqs_disabled_flags(flags), nest_lock, ip, 0, 0, 0);
        lockdep_recursion_finish();
        raw_local_irq_restore(flags);
 }
@@ -5693,6 +5715,34 @@ void lock_release(struct lockdep_map *lock, unsigned long ip)
 }
 EXPORT_SYMBOL_GPL(lock_release);
 
+/*
+ * lock_sync() - A special annotation for synchronize_{s,}rcu()-like API.
+ *
+ * No actual critical section is created by the APIs annotated with this: these
+ * APIs are used to wait for one or multiple critical sections (on other CPUs
+ * or threads), and it means that calling these APIs inside these critical
+ * sections is potential deadlock.
+ */
+void lock_sync(struct lockdep_map *lock, unsigned subclass, int read,
+              int check, struct lockdep_map *nest_lock, unsigned long ip)
+{
+       unsigned long flags;
+
+       if (unlikely(!lockdep_enabled()))
+               return;
+
+       raw_local_irq_save(flags);
+       check_flags(flags);
+
+       lockdep_recursion_inc();
+       __lock_acquire(lock, subclass, 0, read, check,
+                      irqs_disabled_flags(flags), nest_lock, ip, 0, 0, 1);
+       check_chain_key(current);
+       lockdep_recursion_finish();
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(lock_sync);
+
 noinstr int lock_is_held_type(const struct lockdep_map *lock, int read)
 {
        unsigned long flags;
index f04b1978899dda4185697b6d2d69bbdf02c1ea38..153ddc4c47eff1dd35599b1b3390a4959a693409 100644 (file)
@@ -51,8 +51,11 @@ torture_param(int, rt_boost, 2,
 torture_param(int, rt_boost_factor, 50, "A factor determining how often rt-boost happens.");
 torture_param(int, verbose, 1,
             "Enable verbose debugging printk()s");
+torture_param(int, nested_locks, 0, "Number of nested locks (max = 8)");
+/* Going much higher trips "BUG: MAX_LOCKDEP_CHAIN_HLOCKS too low!" errors */
+#define MAX_NESTED_LOCKS 8
 
-static char *torture_type = "spin_lock";
+static char *torture_type = IS_ENABLED(CONFIG_PREEMPT_RT) ? "raw_spin_lock" : "spin_lock";
 module_param(torture_type, charp, 0444);
 MODULE_PARM_DESC(torture_type,
                 "Type of lock to torture (spin_lock, spin_lock_irq, mutex_lock, ...)");
@@ -79,10 +82,12 @@ static void lock_torture_cleanup(void);
 struct lock_torture_ops {
        void (*init)(void);
        void (*exit)(void);
+       int (*nested_lock)(int tid, u32 lockset);
        int (*writelock)(int tid);
        void (*write_delay)(struct torture_random_state *trsp);
        void (*task_boost)(struct torture_random_state *trsp);
        void (*writeunlock)(int tid);
+       void (*nested_unlock)(int tid, u32 lockset);
        int (*readlock)(int tid);
        void (*read_delay)(struct torture_random_state *trsp);
        void (*readunlock)(int tid);
@@ -252,6 +257,59 @@ static struct lock_torture_ops spin_lock_irq_ops = {
        .name           = "spin_lock_irq"
 };
 
+static DEFINE_RAW_SPINLOCK(torture_raw_spinlock);
+
+static int torture_raw_spin_lock_write_lock(int tid __maybe_unused)
+__acquires(torture_raw_spinlock)
+{
+       raw_spin_lock(&torture_raw_spinlock);
+       return 0;
+}
+
+static void torture_raw_spin_lock_write_unlock(int tid __maybe_unused)
+__releases(torture_raw_spinlock)
+{
+       raw_spin_unlock(&torture_raw_spinlock);
+}
+
+static struct lock_torture_ops raw_spin_lock_ops = {
+       .writelock      = torture_raw_spin_lock_write_lock,
+       .write_delay    = torture_spin_lock_write_delay,
+       .task_boost     = torture_rt_boost,
+       .writeunlock    = torture_raw_spin_lock_write_unlock,
+       .readlock       = NULL,
+       .read_delay     = NULL,
+       .readunlock     = NULL,
+       .name           = "raw_spin_lock"
+};
+
+static int torture_raw_spin_lock_write_lock_irq(int tid __maybe_unused)
+__acquires(torture_raw_spinlock)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&torture_raw_spinlock, flags);
+       cxt.cur_ops->flags = flags;
+       return 0;
+}
+
+static void torture_raw_spin_lock_write_unlock_irq(int tid __maybe_unused)
+__releases(torture_raw_spinlock)
+{
+       raw_spin_unlock_irqrestore(&torture_raw_spinlock, cxt.cur_ops->flags);
+}
+
+static struct lock_torture_ops raw_spin_lock_irq_ops = {
+       .writelock      = torture_raw_spin_lock_write_lock_irq,
+       .write_delay    = torture_spin_lock_write_delay,
+       .task_boost     = torture_rt_boost,
+       .writeunlock    = torture_raw_spin_lock_write_unlock_irq,
+       .readlock       = NULL,
+       .read_delay     = NULL,
+       .readunlock     = NULL,
+       .name           = "raw_spin_lock_irq"
+};
+
 static DEFINE_RWLOCK(torture_rwlock);
 
 static int torture_rwlock_write_lock(int tid __maybe_unused)
@@ -365,6 +423,28 @@ static struct lock_torture_ops rw_lock_irq_ops = {
 };
 
 static DEFINE_MUTEX(torture_mutex);
+static struct mutex torture_nested_mutexes[MAX_NESTED_LOCKS];
+static struct lock_class_key nested_mutex_keys[MAX_NESTED_LOCKS];
+
+static void torture_mutex_init(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_NESTED_LOCKS; i++)
+               __mutex_init(&torture_nested_mutexes[i], __func__,
+                            &nested_mutex_keys[i]);
+}
+
+static int torture_mutex_nested_lock(int tid __maybe_unused,
+                                    u32 lockset)
+{
+       int i;
+
+       for (i = 0; i < nested_locks; i++)
+               if (lockset & (1 << i))
+                       mutex_lock(&torture_nested_mutexes[i]);
+       return 0;
+}
 
 static int torture_mutex_lock(int tid __maybe_unused)
 __acquires(torture_mutex)
@@ -393,11 +473,24 @@ __releases(torture_mutex)
        mutex_unlock(&torture_mutex);
 }
 
+static void torture_mutex_nested_unlock(int tid __maybe_unused,
+                                       u32 lockset)
+{
+       int i;
+
+       for (i = nested_locks - 1; i >= 0; i--)
+               if (lockset & (1 << i))
+                       mutex_unlock(&torture_nested_mutexes[i]);
+}
+
 static struct lock_torture_ops mutex_lock_ops = {
+       .init           = torture_mutex_init,
+       .nested_lock    = torture_mutex_nested_lock,
        .writelock      = torture_mutex_lock,
        .write_delay    = torture_mutex_delay,
        .task_boost     = torture_rt_boost,
        .writeunlock    = torture_mutex_unlock,
+       .nested_unlock  = torture_mutex_nested_unlock,
        .readlock       = NULL,
        .read_delay     = NULL,
        .readunlock     = NULL,
@@ -504,6 +597,28 @@ static struct lock_torture_ops ww_mutex_lock_ops = {
 
 #ifdef CONFIG_RT_MUTEXES
 static DEFINE_RT_MUTEX(torture_rtmutex);
+static struct rt_mutex torture_nested_rtmutexes[MAX_NESTED_LOCKS];
+static struct lock_class_key nested_rtmutex_keys[MAX_NESTED_LOCKS];
+
+static void torture_rtmutex_init(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_NESTED_LOCKS; i++)
+               __rt_mutex_init(&torture_nested_rtmutexes[i], __func__,
+                               &nested_rtmutex_keys[i]);
+}
+
+static int torture_rtmutex_nested_lock(int tid __maybe_unused,
+                                      u32 lockset)
+{
+       int i;
+
+       for (i = 0; i < nested_locks; i++)
+               if (lockset & (1 << i))
+                       rt_mutex_lock(&torture_nested_rtmutexes[i]);
+       return 0;
+}
 
 static int torture_rtmutex_lock(int tid __maybe_unused)
 __acquires(torture_rtmutex)
@@ -545,11 +660,24 @@ static void torture_rt_boost_rtmutex(struct torture_random_state *trsp)
        __torture_rt_boost(trsp);
 }
 
+static void torture_rtmutex_nested_unlock(int tid __maybe_unused,
+                                         u32 lockset)
+{
+       int i;
+
+       for (i = nested_locks - 1; i >= 0; i--)
+               if (lockset & (1 << i))
+                       rt_mutex_unlock(&torture_nested_rtmutexes[i]);
+}
+
 static struct lock_torture_ops rtmutex_lock_ops = {
+       .init           = torture_rtmutex_init,
+       .nested_lock    = torture_rtmutex_nested_lock,
        .writelock      = torture_rtmutex_lock,
        .write_delay    = torture_rtmutex_delay,
        .task_boost     = torture_rt_boost_rtmutex,
        .writeunlock    = torture_rtmutex_unlock,
+       .nested_unlock  = torture_rtmutex_nested_unlock,
        .readlock       = NULL,
        .read_delay     = NULL,
        .readunlock     = NULL,
@@ -684,6 +812,8 @@ static int lock_torture_writer(void *arg)
        struct lock_stress_stats *lwsp = arg;
        int tid = lwsp - cxt.lwsa;
        DEFINE_TORTURE_RANDOM(rand);
+       u32 lockset_mask;
+       bool skip_main_lock;
 
        VERBOSE_TOROUT_STRING("lock_torture_writer task started");
        set_user_nice(current, MAX_NICE);
@@ -692,19 +822,40 @@ static int lock_torture_writer(void *arg)
                if ((torture_random(&rand) & 0xfffff) == 0)
                        schedule_timeout_uninterruptible(1);
 
-               cxt.cur_ops->task_boost(&rand);
-               cxt.cur_ops->writelock(tid);
-               if (WARN_ON_ONCE(lock_is_write_held))
-                       lwsp->n_lock_fail++;
-               lock_is_write_held = true;
-               if (WARN_ON_ONCE(atomic_read(&lock_is_read_held)))
-                       lwsp->n_lock_fail++; /* rare, but... */
+               lockset_mask = torture_random(&rand);
+               /*
+                * When using nested_locks, we want to occasionally
+                * skip the main lock so we can avoid always serializing
+                * the lock chains on that central lock. By skipping the
+                * main lock occasionally, we can create different
+                * contention patterns (allowing for multiple disjoint
+                * blocked trees)
+                */
+               skip_main_lock = (nested_locks &&
+                                !(torture_random(&rand) % 100));
 
-               lwsp->n_lock_acquired++;
+               cxt.cur_ops->task_boost(&rand);
+               if (cxt.cur_ops->nested_lock)
+                       cxt.cur_ops->nested_lock(tid, lockset_mask);
+
+               if (!skip_main_lock) {
+                       cxt.cur_ops->writelock(tid);
+                       if (WARN_ON_ONCE(lock_is_write_held))
+                               lwsp->n_lock_fail++;
+                       lock_is_write_held = true;
+                       if (WARN_ON_ONCE(atomic_read(&lock_is_read_held)))
+                               lwsp->n_lock_fail++; /* rare, but... */
+
+                       lwsp->n_lock_acquired++;
+               }
                cxt.cur_ops->write_delay(&rand);
-               lock_is_write_held = false;
-               WRITE_ONCE(last_lock_release, jiffies);
-               cxt.cur_ops->writeunlock(tid);
+               if (!skip_main_lock) {
+                       lock_is_write_held = false;
+                       WRITE_ONCE(last_lock_release, jiffies);
+                       cxt.cur_ops->writeunlock(tid);
+               }
+               if (cxt.cur_ops->nested_unlock)
+                       cxt.cur_ops->nested_unlock(tid, lockset_mask);
 
                stutter_wait("lock_torture_writer");
        } while (!torture_must_stop());
@@ -845,11 +996,11 @@ lock_torture_print_module_parms(struct lock_torture_ops *cur_ops,
                                const char *tag)
 {
        pr_alert("%s" TORTURE_FLAG
-                "--- %s%s: nwriters_stress=%d nreaders_stress=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n",
+                "--- %s%s: nwriters_stress=%d nreaders_stress=%d nested_locks=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n",
                 torture_type, tag, cxt.debug_lock ? " [debug]": "",
-                cxt.nrealwriters_stress, cxt.nrealreaders_stress, stat_interval,
-                verbose, shuffle_interval, stutter, shutdown_secs,
-                onoff_interval, onoff_holdoff);
+                cxt.nrealwriters_stress, cxt.nrealreaders_stress,
+                nested_locks, stat_interval, verbose, shuffle_interval,
+                stutter, shutdown_secs, onoff_interval, onoff_holdoff);
 }
 
 static void lock_torture_cleanup(void)
@@ -919,6 +1070,7 @@ static int __init lock_torture_init(void)
        static struct lock_torture_ops *torture_ops[] = {
                &lock_busted_ops,
                &spin_lock_ops, &spin_lock_irq_ops,
+               &raw_spin_lock_ops, &raw_spin_lock_irq_ops,
                &rw_lock_ops, &rw_lock_irq_ops,
                &mutex_lock_ops,
                &ww_mutex_lock_ops,
@@ -1068,6 +1220,10 @@ static int __init lock_torture_init(void)
                }
        }
 
+       /* cap nested_locks to MAX_NESTED_LOCKS */
+       if (nested_locks > MAX_NESTED_LOCKS)
+               nested_locks = MAX_NESTED_LOCKS;
+
        if (cxt.cur_ops->readlock) {
                reader_tasks = kcalloc(cxt.nrealreaders_stress,
                                       sizeof(reader_tasks[0]),
index 29dc253d03af7c1c6f5f2c47694b842ac744fdab..93cca6e698600ac798a8968b95b1e94ae9380126 100644 (file)
@@ -659,7 +659,7 @@ static int __init test_ww_mutex_init(void)
        if (ret)
                return ret;
 
-       ret = stress(4095, hweight32(STRESS_ALL)*ncpus, STRESS_ALL);
+       ret = stress(2047, hweight32(STRESS_ALL)*ncpus, STRESS_ALL);
        if (ret)
                return ret;
 
index a487ff24129b8ea5f4c343eade407dae82fc4f52..80d9c6d77a452648045c7dfd21e375ca01b46a3c 100644 (file)
@@ -545,21 +545,20 @@ static void commit_nsset(struct nsset *nsset)
 
 SYSCALL_DEFINE2(setns, int, fd, int, flags)
 {
-       struct file *file;
+       struct fd f = fdget(fd);
        struct ns_common *ns = NULL;
        struct nsset nsset = {};
        int err = 0;
 
-       file = fget(fd);
-       if (!file)
+       if (!f.file)
                return -EBADF;
 
-       if (proc_ns_file(file)) {
-               ns = get_proc_ns(file_inode(file));
+       if (proc_ns_file(f.file)) {
+               ns = get_proc_ns(file_inode(f.file));
                if (flags && (ns->ops->type != flags))
                        err = -EINVAL;
                flags = ns->ops->type;
-       } else if (!IS_ERR(pidfd_pid(file))) {
+       } else if (!IS_ERR(pidfd_pid(f.file))) {
                err = check_setns_flags(flags);
        } else {
                err = -EINVAL;
@@ -571,17 +570,17 @@ SYSCALL_DEFINE2(setns, int, fd, int, flags)
        if (err)
                goto out;
 
-       if (proc_ns_file(file))
+       if (proc_ns_file(f.file))
                err = validate_ns(&nsset, ns);
        else
-               err = validate_nsset(&nsset, file->private_data);
+               err = validate_nsset(&nsset, f.file->private_data);
        if (!err) {
                commit_nsset(&nsset);
                perf_event_namespaces(current);
        }
        put_nsset(&nsset);
 out:
-       fput(file);
+       fdput(f);
        return err;
 }
 
index 3fbc5e46b72173cf216850ea85afc24ace98fd3c..f93954a0384d3889fb6d52de977562d10be1a012 100644 (file)
@@ -594,20 +594,15 @@ struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags)
  */
 int pidfd_create(struct pid *pid, unsigned int flags)
 {
-       int fd;
-
-       if (!pid || !pid_has_task(pid, PIDTYPE_TGID))
-               return -EINVAL;
+       int pidfd;
+       struct file *pidfd_file;
 
-       if (flags & ~(O_NONBLOCK | O_RDWR | O_CLOEXEC))
-               return -EINVAL;
-
-       fd = anon_inode_getfd("[pidfd]", &pidfd_fops, get_pid(pid),
-                             flags | O_RDWR | O_CLOEXEC);
-       if (fd < 0)
-               put_pid(pid);
+       pidfd = pidfd_prepare(pid, flags, &pidfd_file);
+       if (pidfd < 0)
+               return pidfd;
 
-       return fd;
+       fd_install(pidfd, pidfd_file);
+       return pidfd;
 }
 
 /**
index 0786450074c13b787fec9a58072c49ec972e3aad..443057bee87cb7469990f3ad1d6abe09a42c22f3 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/compat.h>
 #include <linux/sched/signal.h>
 #include <linux/minmax.h>
+#include <linux/syscall_user_dispatch.h>
 
 #include <asm/syscall.h>       /* for syscall_get_* */
 
@@ -1259,6 +1260,14 @@ int ptrace_request(struct task_struct *child, long request,
                break;
 #endif
 
+       case PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG:
+               ret = syscall_user_dispatch_set_config(child, addr, datavp);
+               break;
+
+       case PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG:
+               ret = syscall_user_dispatch_get_config(child, addr, datavp);
+               break;
+
        default:
                break;
        }
index ab62074174c32d184d51d13cd158bdb30d3da6cb..9071182b1284bb97bce2c062724bb81d897d97f1 100644 (file)
@@ -53,9 +53,6 @@ config RCU_EXPERT
 
          Say N if you are unsure.
 
-config SRCU
-       def_bool y
-
 config TINY_SRCU
        bool
        default y if TINY_RCU
index 115616ac3bfa6d1cb83bd0efdf823f64df3ab855..4a1b9622598be4193c0b758f6728dc8153d86208 100644 (file)
 
 /*
  * Grace-period counter management.
+ *
+ * The two least significant bits contain the control flags.
+ * The most significant bits contain the grace-period sequence counter.
+ *
+ * When both control flags are zero, no grace period is in progress.
+ * When either bit is non-zero, a grace period has started and is in
+ * progress. When the grace period completes, the control flags are reset
+ * to 0 and the grace-period sequence counter is incremented.
+ *
+ * However some specific RCU usages make use of custom values.
+ *
+ * SRCU special control values:
+ *
+ *     SRCU_SNP_INIT_SEQ       :       Invalid/init value set when SRCU node
+ *                                     is initialized.
+ *
+ *     SRCU_STATE_IDLE         :       No SRCU gp is in progress
+ *
+ *     SRCU_STATE_SCAN1        :       State set by rcu_seq_start(). Indicates
+ *                                     we are scanning the readers on the slot
+ *                                     defined as inactive (there might well
+ *                                     be pending readers that will use that
+ *                                     index, but their number is bounded).
+ *
+ *     SRCU_STATE_SCAN2        :       State set manually via rcu_seq_set_state()
+ *                                     Indicates we are flipping the readers
+ *                                     index and then scanning the readers on the
+ *                                     slot newly designated as inactive (again,
+ *                                     the number of pending readers that will use
+ *                                     this inactive index is bounded).
+ *
+ * RCU polled GP special control value:
+ *
+ *     RCU_GET_STATE_COMPLETED :       State value indicating an already-completed
+ *                                     polled GP has completed.  This value covers
+ *                                     both the state and the counter of the
+ *                                     grace-period sequence number.
  */
 
 #define RCU_SEQ_CTR_SHIFT      2
@@ -341,11 +378,13 @@ extern void rcu_init_geometry(void);
  * specified state structure (for SRCU) or the only rcu_state structure
  * (for RCU).
  */
-#define srcu_for_each_node_breadth_first(sp, rnp) \
+#define _rcu_for_each_node_breadth_first(sp, rnp) \
        for ((rnp) = &(sp)->node[0]; \
             (rnp) < &(sp)->node[rcu_num_nodes]; (rnp)++)
 #define rcu_for_each_node_breadth_first(rnp) \
-       srcu_for_each_node_breadth_first(&rcu_state, rnp)
+       _rcu_for_each_node_breadth_first(&rcu_state, rnp)
+#define srcu_for_each_node_breadth_first(ssp, rnp) \
+       _rcu_for_each_node_breadth_first(ssp->srcu_sup, rnp)
 
 /*
  * Scan the leaves of the rcu_node hierarchy for the rcu_state structure.
index 91fb5905a008ff243039e4d967d76deb187537ec..e82ec9f9a5d80c71682760730b239c26d9252efa 100644 (file)
@@ -631,8 +631,7 @@ static int compute_real(int n)
 static int
 rcu_scale_shutdown(void *arg)
 {
-       wait_event(shutdown_wq,
-                  atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters);
+       wait_event_idle(shutdown_wq, atomic_read(&n_rcu_scale_writer_finished) >= nrealwriters);
        smp_mb(); /* Wake before output. */
        rcu_scale_cleanup();
        kernel_power_off();
@@ -716,7 +715,7 @@ kfree_scale_thread(void *arg)
                        // is tested.
                        if ((kfree_rcu_test_single && !kfree_rcu_test_double) ||
                                        (kfree_rcu_test_both && torture_random(&tr) & 0x800))
-                               kfree_rcu(alloc_ptr);
+                               kfree_rcu_mightsleep(alloc_ptr);
                        else
                                kfree_rcu(alloc_ptr, rh);
                }
@@ -771,8 +770,8 @@ kfree_scale_cleanup(void)
 static int
 kfree_scale_shutdown(void *arg)
 {
-       wait_event(shutdown_wq,
-                  atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads);
+       wait_event_idle(shutdown_wq,
+                       atomic_read(&n_kfree_scale_thread_ended) >= kfree_nrealthreads);
 
        smp_mb(); /* Wake before output. */
 
index 8e6c023212cb314555514f568a18fb4b6898caad..147551c23baf03e273fcf0380678d8a5e3822a72 100644 (file)
@@ -119,7 +119,9 @@ torture_param(int, stutter, 5, "Number of seconds to run/halt test");
 torture_param(int, test_boost, 1, "Test RCU prio boost: 0=no, 1=maybe, 2=yes.");
 torture_param(int, test_boost_duration, 4, "Duration of each boost test, seconds.");
 torture_param(int, test_boost_interval, 7, "Interval between boost tests, seconds.");
+torture_param(int, test_nmis, 0, "End-test NMI tests, 0 to disable.");
 torture_param(bool, test_no_idle_hz, true, "Test support for tickless idle CPUs");
+torture_param(int, test_srcu_lockdep, 0, "Test specified SRCU deadlock scenario.");
 torture_param(int, verbose, 1, "Enable verbose debugging printk()s");
 
 static char *torture_type = "rcu";
@@ -179,7 +181,6 @@ static atomic_t n_rcu_torture_mbchk_tries;
 static atomic_t n_rcu_torture_error;
 static long n_rcu_torture_barrier_error;
 static long n_rcu_torture_boost_ktrerror;
-static long n_rcu_torture_boost_rterror;
 static long n_rcu_torture_boost_failure;
 static long n_rcu_torture_boosts;
 static atomic_long_t n_rcu_torture_timers;
@@ -2194,12 +2195,11 @@ rcu_torture_stats_print(void)
                atomic_read(&n_rcu_torture_alloc),
                atomic_read(&n_rcu_torture_alloc_fail),
                atomic_read(&n_rcu_torture_free));
-       pr_cont("rtmbe: %d rtmbkf: %d/%d rtbe: %ld rtbke: %ld rtbre: %ld ",
+       pr_cont("rtmbe: %d rtmbkf: %d/%d rtbe: %ld rtbke: %ld ",
                atomic_read(&n_rcu_torture_mberror),
                atomic_read(&n_rcu_torture_mbchk_fail), atomic_read(&n_rcu_torture_mbchk_tries),
                n_rcu_torture_barrier_error,
-               n_rcu_torture_boost_ktrerror,
-               n_rcu_torture_boost_rterror);
+               n_rcu_torture_boost_ktrerror);
        pr_cont("rtbf: %ld rtb: %ld nt: %ld ",
                n_rcu_torture_boost_failure,
                n_rcu_torture_boosts,
@@ -2217,15 +2217,13 @@ rcu_torture_stats_print(void)
        if (atomic_read(&n_rcu_torture_mberror) ||
            atomic_read(&n_rcu_torture_mbchk_fail) ||
            n_rcu_torture_barrier_error || n_rcu_torture_boost_ktrerror ||
-           n_rcu_torture_boost_rterror || n_rcu_torture_boost_failure ||
-           i > 1) {
+           n_rcu_torture_boost_failure || i > 1) {
                pr_cont("%s", "!!! ");
                atomic_inc(&n_rcu_torture_error);
                WARN_ON_ONCE(atomic_read(&n_rcu_torture_mberror));
                WARN_ON_ONCE(atomic_read(&n_rcu_torture_mbchk_fail));
                WARN_ON_ONCE(n_rcu_torture_barrier_error);  // rcu_barrier()
                WARN_ON_ONCE(n_rcu_torture_boost_ktrerror); // no boost kthread
-               WARN_ON_ONCE(n_rcu_torture_boost_rterror); // can't set RT prio
                WARN_ON_ONCE(n_rcu_torture_boost_failure); // boost failed (TIMER_SOFTIRQ RT prio?)
                WARN_ON_ONCE(i > 1); // Too-short grace period
        }
@@ -2358,7 +2356,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
                 "n_barrier_cbs=%d "
                 "onoff_interval=%d onoff_holdoff=%d "
                 "read_exit_delay=%d read_exit_burst=%d "
-                "nocbs_nthreads=%d nocbs_toggle=%d\n",
+                "nocbs_nthreads=%d nocbs_toggle=%d "
+                "test_nmis=%d\n",
                 torture_type, tag, nrealreaders, nfakewriters,
                 stat_interval, verbose, test_no_idle_hz, shuffle_interval,
                 stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter,
@@ -2369,7 +2368,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag)
                 n_barrier_cbs,
                 onoff_interval, onoff_holdoff,
                 read_exit_delay, read_exit_burst,
-                nocbs_nthreads, nocbs_toggle);
+                nocbs_nthreads, nocbs_toggle,
+                test_nmis);
 }
 
 static int rcutorture_booster_cleanup(unsigned int cpu)
@@ -3273,6 +3273,29 @@ static void rcu_torture_read_exit_cleanup(void)
        torture_stop_kthread(rcutorture_read_exit, read_exit_task);
 }
 
+static void rcutorture_test_nmis(int n)
+{
+#if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)
+       int cpu;
+       int dumpcpu;
+       int i;
+
+       for (i = 0; i < n; i++) {
+               preempt_disable();
+               cpu = smp_processor_id();
+               dumpcpu = cpu + 1;
+               if (dumpcpu >= nr_cpu_ids)
+                       dumpcpu = 0;
+               pr_alert("%s: CPU %d invoking dump_cpu_task(%d)\n", __func__, cpu, dumpcpu);
+               dump_cpu_task(dumpcpu);
+               preempt_enable();
+               schedule_timeout_uninterruptible(15 * HZ);
+       }
+#else // #if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)
+       WARN_ONCE(n, "Non-zero rcutorture.test_nmis=%d permitted only when rcutorture is built in.\n", test_nmis);
+#endif // #else // #if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST)
+}
+
 static enum cpuhp_state rcutor_hp;
 
 static void
@@ -3297,6 +3320,8 @@ rcu_torture_cleanup(void)
                return;
        }
 
+       rcutorture_test_nmis(test_nmis);
+
        if (cur_ops->gp_kthread_dbg)
                cur_ops->gp_kthread_dbg();
        rcu_torture_read_exit_cleanup();
@@ -3463,6 +3488,188 @@ static void rcutorture_sync(void)
                cur_ops->sync();
 }
 
+static DEFINE_MUTEX(mut0);
+static DEFINE_MUTEX(mut1);
+static DEFINE_MUTEX(mut2);
+static DEFINE_MUTEX(mut3);
+static DEFINE_MUTEX(mut4);
+static DEFINE_MUTEX(mut5);
+static DEFINE_MUTEX(mut6);
+static DEFINE_MUTEX(mut7);
+static DEFINE_MUTEX(mut8);
+static DEFINE_MUTEX(mut9);
+
+static DECLARE_RWSEM(rwsem0);
+static DECLARE_RWSEM(rwsem1);
+static DECLARE_RWSEM(rwsem2);
+static DECLARE_RWSEM(rwsem3);
+static DECLARE_RWSEM(rwsem4);
+static DECLARE_RWSEM(rwsem5);
+static DECLARE_RWSEM(rwsem6);
+static DECLARE_RWSEM(rwsem7);
+static DECLARE_RWSEM(rwsem8);
+static DECLARE_RWSEM(rwsem9);
+
+DEFINE_STATIC_SRCU(srcu0);
+DEFINE_STATIC_SRCU(srcu1);
+DEFINE_STATIC_SRCU(srcu2);
+DEFINE_STATIC_SRCU(srcu3);
+DEFINE_STATIC_SRCU(srcu4);
+DEFINE_STATIC_SRCU(srcu5);
+DEFINE_STATIC_SRCU(srcu6);
+DEFINE_STATIC_SRCU(srcu7);
+DEFINE_STATIC_SRCU(srcu8);
+DEFINE_STATIC_SRCU(srcu9);
+
+static int srcu_lockdep_next(const char *f, const char *fl, const char *fs, const char *fu, int i,
+                            int cyclelen, int deadlock)
+{
+       int j = i + 1;
+
+       if (j >= cyclelen)
+               j = deadlock ? 0 : -1;
+       if (j >= 0)
+               pr_info("%s: %s(%d), %s(%d), %s(%d)\n", f, fl, i, fs, j, fu, i);
+       else
+               pr_info("%s: %s(%d), %s(%d)\n", f, fl, i, fu, i);
+       return j;
+}
+
+// Test lockdep on SRCU-based deadlock scenarios.
+static void rcu_torture_init_srcu_lockdep(void)
+{
+       int cyclelen;
+       int deadlock;
+       bool err = false;
+       int i;
+       int j;
+       int idx;
+       struct mutex *muts[] = { &mut0, &mut1, &mut2, &mut3, &mut4,
+                                &mut5, &mut6, &mut7, &mut8, &mut9 };
+       struct rw_semaphore *rwsems[] = { &rwsem0, &rwsem1, &rwsem2, &rwsem3, &rwsem4,
+                                         &rwsem5, &rwsem6, &rwsem7, &rwsem8, &rwsem9 };
+       struct srcu_struct *srcus[] = { &srcu0, &srcu1, &srcu2, &srcu3, &srcu4,
+                                       &srcu5, &srcu6, &srcu7, &srcu8, &srcu9 };
+       int testtype;
+
+       if (!test_srcu_lockdep)
+               return;
+
+       deadlock = test_srcu_lockdep / 1000;
+       testtype = (test_srcu_lockdep / 10) % 100;
+       cyclelen = test_srcu_lockdep % 10;
+       WARN_ON_ONCE(ARRAY_SIZE(muts) != ARRAY_SIZE(srcus));
+       if (WARN_ONCE(deadlock != !!deadlock,
+                     "%s: test_srcu_lockdep=%d and deadlock digit %d must be zero or one.\n",
+                     __func__, test_srcu_lockdep, deadlock))
+               err = true;
+       if (WARN_ONCE(cyclelen <= 0,
+                     "%s: test_srcu_lockdep=%d and cycle-length digit %d must be greater than zero.\n",
+                     __func__, test_srcu_lockdep, cyclelen))
+               err = true;
+       if (err)
+               goto err_out;
+
+       if (testtype == 0) {
+               pr_info("%s: test_srcu_lockdep = %05d: SRCU %d-way %sdeadlock.\n",
+                       __func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
+               if (deadlock && cyclelen == 1)
+                       pr_info("%s: Expect hang.\n", __func__);
+               for (i = 0; i < cyclelen; i++) {
+                       j = srcu_lockdep_next(__func__, "srcu_read_lock", "synchronize_srcu",
+                                             "srcu_read_unlock", i, cyclelen, deadlock);
+                       idx = srcu_read_lock(srcus[i]);
+                       if (j >= 0)
+                               synchronize_srcu(srcus[j]);
+                       srcu_read_unlock(srcus[i], idx);
+               }
+               return;
+       }
+
+       if (testtype == 1) {
+               pr_info("%s: test_srcu_lockdep = %05d: SRCU/mutex %d-way %sdeadlock.\n",
+                       __func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
+               for (i = 0; i < cyclelen; i++) {
+                       pr_info("%s: srcu_read_lock(%d), mutex_lock(%d), mutex_unlock(%d), srcu_read_unlock(%d)\n",
+                               __func__, i, i, i, i);
+                       idx = srcu_read_lock(srcus[i]);
+                       mutex_lock(muts[i]);
+                       mutex_unlock(muts[i]);
+                       srcu_read_unlock(srcus[i], idx);
+
+                       j = srcu_lockdep_next(__func__, "mutex_lock", "synchronize_srcu",
+                                             "mutex_unlock", i, cyclelen, deadlock);
+                       mutex_lock(muts[i]);
+                       if (j >= 0)
+                               synchronize_srcu(srcus[j]);
+                       mutex_unlock(muts[i]);
+               }
+               return;
+       }
+
+       if (testtype == 2) {
+               pr_info("%s: test_srcu_lockdep = %05d: SRCU/rwsem %d-way %sdeadlock.\n",
+                       __func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
+               for (i = 0; i < cyclelen; i++) {
+                       pr_info("%s: srcu_read_lock(%d), down_read(%d), up_read(%d), srcu_read_unlock(%d)\n",
+                               __func__, i, i, i, i);
+                       idx = srcu_read_lock(srcus[i]);
+                       down_read(rwsems[i]);
+                       up_read(rwsems[i]);
+                       srcu_read_unlock(srcus[i], idx);
+
+                       j = srcu_lockdep_next(__func__, "down_write", "synchronize_srcu",
+                                             "up_write", i, cyclelen, deadlock);
+                       down_write(rwsems[i]);
+                       if (j >= 0)
+                               synchronize_srcu(srcus[j]);
+                       up_write(rwsems[i]);
+               }
+               return;
+       }
+
+#ifdef CONFIG_TASKS_TRACE_RCU
+       if (testtype == 3) {
+               pr_info("%s: test_srcu_lockdep = %05d: SRCU and Tasks Trace RCU %d-way %sdeadlock.\n",
+                       __func__, test_srcu_lockdep, cyclelen, deadlock ? "" : "non-");
+               if (deadlock && cyclelen == 1)
+                       pr_info("%s: Expect hang.\n", __func__);
+               for (i = 0; i < cyclelen; i++) {
+                       char *fl = i == 0 ? "rcu_read_lock_trace" : "srcu_read_lock";
+                       char *fs = i == cyclelen - 1 ? "synchronize_rcu_tasks_trace"
+                                                    : "synchronize_srcu";
+                       char *fu = i == 0 ? "rcu_read_unlock_trace" : "srcu_read_unlock";
+
+                       j = srcu_lockdep_next(__func__, fl, fs, fu, i, cyclelen, deadlock);
+                       if (i == 0)
+                               rcu_read_lock_trace();
+                       else
+                               idx = srcu_read_lock(srcus[i]);
+                       if (j >= 0) {
+                               if (i == cyclelen - 1)
+                                       synchronize_rcu_tasks_trace();
+                               else
+                                       synchronize_srcu(srcus[j]);
+                       }
+                       if (i == 0)
+                               rcu_read_unlock_trace();
+                       else
+                               srcu_read_unlock(srcus[i], idx);
+               }
+               return;
+       }
+#endif // #ifdef CONFIG_TASKS_TRACE_RCU
+
+err_out:
+       pr_info("%s: test_srcu_lockdep = %05d does nothing.\n", __func__, test_srcu_lockdep);
+       pr_info("%s: test_srcu_lockdep = DNNL.\n", __func__);
+       pr_info("%s: D: Deadlock if nonzero.\n", __func__);
+       pr_info("%s: NN: Test number, 0=SRCU, 1=SRCU/mutex, 2=SRCU/rwsem, 3=SRCU/Tasks Trace RCU.\n", __func__);
+       pr_info("%s: L: Cycle length.\n", __func__);
+       if (!IS_ENABLED(CONFIG_TASKS_TRACE_RCU))
+               pr_info("%s: NN=3 disallowed because kernel is built with CONFIG_TASKS_TRACE_RCU=n\n", __func__);
+}
+
 static int __init
 rcu_torture_init(void)
 {
@@ -3501,9 +3708,17 @@ rcu_torture_init(void)
                pr_alert("rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n");
                fqs_duration = 0;
        }
+       if (nocbs_nthreads != 0 && (cur_ops != &rcu_ops ||
+                                   !IS_ENABLED(CONFIG_RCU_NOCB_CPU))) {
+               pr_alert("rcu-torture types: %s and CONFIG_RCU_NOCB_CPU=%d, nocb toggle disabled.\n",
+                        cur_ops->name, IS_ENABLED(CONFIG_RCU_NOCB_CPU));
+               nocbs_nthreads = 0;
+       }
        if (cur_ops->init)
                cur_ops->init();
 
+       rcu_torture_init_srcu_lockdep();
+
        if (nreaders >= 0) {
                nrealreaders = nreaders;
        } else {
@@ -3540,7 +3755,6 @@ rcu_torture_init(void)
        atomic_set(&n_rcu_torture_error, 0);
        n_rcu_torture_barrier_error = 0;
        n_rcu_torture_boost_ktrerror = 0;
-       n_rcu_torture_boost_rterror = 0;
        n_rcu_torture_boost_failure = 0;
        n_rcu_torture_boosts = 0;
        for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
index afa3e1a2f6902c41c1c094efe09181e510a58142..1970ce5f22d405bc075015f5b8a4ec1f1635d1ee 100644 (file)
@@ -1031,7 +1031,7 @@ ref_scale_cleanup(void)
 static int
 ref_scale_shutdown(void *arg)
 {
-       wait_event(shutdown_wq, shutdown_start);
+       wait_event_idle(shutdown_wq, shutdown_start);
 
        smp_mb(); // Wake before output.
        ref_scale_cleanup();
index b12fb0cec44d61708302ebf388e2fdbcd2d58399..336af24e0fe358a71209120786ffa1d0255d63f6 100644 (file)
@@ -197,6 +197,8 @@ void synchronize_srcu(struct srcu_struct *ssp)
 {
        struct rcu_synchronize rs;
 
+       srcu_lock_sync(&ssp->dep_map);
+
        RCU_LOCKDEP_WARN(lockdep_is_held(ssp) ||
                        lock_is_held(&rcu_bh_lock_map) ||
                        lock_is_held(&rcu_lock_map) ||
index ab4ee58af84bfcfaf6890a6650b40117be09bfb0..20d7a238d675a8ece4b0ca1751944f176a38b305 100644 (file)
@@ -103,7 +103,7 @@ do {                                                                                \
 
 #define spin_trylock_irqsave_rcu_node(p, flags)                                        \
 ({                                                                             \
-       bool ___locked = spin_trylock_irqsave(&ACCESS_PRIVATE(p, lock), flags); \
+       bool ___locked = spin_trylock_irqsave(&ACCESS_PRIVATE(p, lock), flags); \
                                                                                \
        if (___locked)                                                          \
                smp_mb__after_unlock_lock();                                    \
@@ -135,8 +135,8 @@ static void init_srcu_struct_data(struct srcu_struct *ssp)
                spin_lock_init(&ACCESS_PRIVATE(sdp, lock));
                rcu_segcblist_init(&sdp->srcu_cblist);
                sdp->srcu_cblist_invoking = false;
-               sdp->srcu_gp_seq_needed = ssp->srcu_gp_seq;
-               sdp->srcu_gp_seq_needed_exp = ssp->srcu_gp_seq;
+               sdp->srcu_gp_seq_needed = ssp->srcu_sup->srcu_gp_seq;
+               sdp->srcu_gp_seq_needed_exp = ssp->srcu_sup->srcu_gp_seq;
                sdp->mynode = NULL;
                sdp->cpu = cpu;
                INIT_WORK(&sdp->work, srcu_invoke_callbacks);
@@ -173,14 +173,14 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
 
        /* Initialize geometry if it has not already been initialized. */
        rcu_init_geometry();
-       ssp->node = kcalloc(rcu_num_nodes, sizeof(*ssp->node), gfp_flags);
-       if (!ssp->node)
+       ssp->srcu_sup->node = kcalloc(rcu_num_nodes, sizeof(*ssp->srcu_sup->node), gfp_flags);
+       if (!ssp->srcu_sup->node)
                return false;
 
        /* Work out the overall tree geometry. */
-       ssp->level[0] = &ssp->node[0];
+       ssp->srcu_sup->level[0] = &ssp->srcu_sup->node[0];
        for (i = 1; i < rcu_num_lvls; i++)
-               ssp->level[i] = ssp->level[i - 1] + num_rcu_lvl[i - 1];
+               ssp->srcu_sup->level[i] = ssp->srcu_sup->level[i - 1] + num_rcu_lvl[i - 1];
        rcu_init_levelspread(levelspread, num_rcu_lvl);
 
        /* Each pass through this loop initializes one srcu_node structure. */
@@ -195,17 +195,17 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
                snp->srcu_gp_seq_needed_exp = SRCU_SNP_INIT_SEQ;
                snp->grplo = -1;
                snp->grphi = -1;
-               if (snp == &ssp->node[0]) {
+               if (snp == &ssp->srcu_sup->node[0]) {
                        /* Root node, special case. */
                        snp->srcu_parent = NULL;
                        continue;
                }
 
                /* Non-root node. */
-               if (snp == ssp->level[level + 1])
+               if (snp == ssp->srcu_sup->level[level + 1])
                        level++;
-               snp->srcu_parent = ssp->level[level - 1] +
-                                  (snp - ssp->level[level]) /
+               snp->srcu_parent = ssp->srcu_sup->level[level - 1] +
+                                  (snp - ssp->srcu_sup->level[level]) /
                                   levelspread[level - 1];
        }
 
@@ -214,7 +214,7 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
         * leaves of the srcu_node tree.
         */
        level = rcu_num_lvls - 1;
-       snp_first = ssp->level[level];
+       snp_first = ssp->srcu_sup->level[level];
        for_each_possible_cpu(cpu) {
                sdp = per_cpu_ptr(ssp->sda, cpu);
                sdp->mynode = &snp_first[cpu / levelspread[level]];
@@ -225,7 +225,7 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
                }
                sdp->grpmask = 1 << (cpu - sdp->mynode->grplo);
        }
-       smp_store_release(&ssp->srcu_size_state, SRCU_SIZE_WAIT_BARRIER);
+       smp_store_release(&ssp->srcu_sup->srcu_size_state, SRCU_SIZE_WAIT_BARRIER);
        return true;
 }
 
@@ -236,36 +236,47 @@ static bool init_srcu_struct_nodes(struct srcu_struct *ssp, gfp_t gfp_flags)
  */
 static int init_srcu_struct_fields(struct srcu_struct *ssp, bool is_static)
 {
-       ssp->srcu_size_state = SRCU_SIZE_SMALL;
-       ssp->node = NULL;
-       mutex_init(&ssp->srcu_cb_mutex);
-       mutex_init(&ssp->srcu_gp_mutex);
+       if (!is_static)
+               ssp->srcu_sup = kzalloc(sizeof(*ssp->srcu_sup), GFP_KERNEL);
+       if (!ssp->srcu_sup)
+               return -ENOMEM;
+       if (!is_static)
+               spin_lock_init(&ACCESS_PRIVATE(ssp->srcu_sup, lock));
+       ssp->srcu_sup->srcu_size_state = SRCU_SIZE_SMALL;
+       ssp->srcu_sup->node = NULL;
+       mutex_init(&ssp->srcu_sup->srcu_cb_mutex);
+       mutex_init(&ssp->srcu_sup->srcu_gp_mutex);
        ssp->srcu_idx = 0;
-       ssp->srcu_gp_seq = 0;
-       ssp->srcu_barrier_seq = 0;
-       mutex_init(&ssp->srcu_barrier_mutex);
-       atomic_set(&ssp->srcu_barrier_cpu_cnt, 0);
-       INIT_DELAYED_WORK(&ssp->work, process_srcu);
-       ssp->sda_is_static = is_static;
+       ssp->srcu_sup->srcu_gp_seq = 0;
+       ssp->srcu_sup->srcu_barrier_seq = 0;
+       mutex_init(&ssp->srcu_sup->srcu_barrier_mutex);
+       atomic_set(&ssp->srcu_sup->srcu_barrier_cpu_cnt, 0);
+       INIT_DELAYED_WORK(&ssp->srcu_sup->work, process_srcu);
+       ssp->srcu_sup->sda_is_static = is_static;
        if (!is_static)
                ssp->sda = alloc_percpu(struct srcu_data);
-       if (!ssp->sda)
+       if (!ssp->sda) {
+               if (!is_static)
+                       kfree(ssp->srcu_sup);
                return -ENOMEM;
+       }
        init_srcu_struct_data(ssp);
-       ssp->srcu_gp_seq_needed_exp = 0;
-       ssp->srcu_last_gp_end = ktime_get_mono_fast_ns();
-       if (READ_ONCE(ssp->srcu_size_state) == SRCU_SIZE_SMALL && SRCU_SIZING_IS_INIT()) {
+       ssp->srcu_sup->srcu_gp_seq_needed_exp = 0;
+       ssp->srcu_sup->srcu_last_gp_end = ktime_get_mono_fast_ns();
+       if (READ_ONCE(ssp->srcu_sup->srcu_size_state) == SRCU_SIZE_SMALL && SRCU_SIZING_IS_INIT()) {
                if (!init_srcu_struct_nodes(ssp, GFP_ATOMIC)) {
-                       if (!ssp->sda_is_static) {
+                       if (!ssp->srcu_sup->sda_is_static) {
                                free_percpu(ssp->sda);
                                ssp->sda = NULL;
+                               kfree(ssp->srcu_sup);
                                return -ENOMEM;
                        }
                } else {
-                       WRITE_ONCE(ssp->srcu_size_state, SRCU_SIZE_BIG);
+                       WRITE_ONCE(ssp->srcu_sup->srcu_size_state, SRCU_SIZE_BIG);
                }
        }
-       smp_store_release(&ssp->srcu_gp_seq_needed, 0); /* Init done. */
+       ssp->srcu_sup->srcu_ssp = ssp;
+       smp_store_release(&ssp->srcu_sup->srcu_gp_seq_needed, 0); /* Init done. */
        return 0;
 }
 
@@ -277,7 +288,6 @@ int __init_srcu_struct(struct srcu_struct *ssp, const char *name,
        /* Don't re-initialize a lock while it is held. */
        debug_check_no_locks_freed((void *)ssp, sizeof(*ssp));
        lockdep_init_map(&ssp->dep_map, name, key, 0);
-       spin_lock_init(&ACCESS_PRIVATE(ssp, lock));
        return init_srcu_struct_fields(ssp, false);
 }
 EXPORT_SYMBOL_GPL(__init_srcu_struct);
@@ -294,7 +304,6 @@ EXPORT_SYMBOL_GPL(__init_srcu_struct);
  */
 int init_srcu_struct(struct srcu_struct *ssp)
 {
-       spin_lock_init(&ACCESS_PRIVATE(ssp, lock));
        return init_srcu_struct_fields(ssp, false);
 }
 EXPORT_SYMBOL_GPL(init_srcu_struct);
@@ -306,8 +315,8 @@ EXPORT_SYMBOL_GPL(init_srcu_struct);
  */
 static void __srcu_transition_to_big(struct srcu_struct *ssp)
 {
-       lockdep_assert_held(&ACCESS_PRIVATE(ssp, lock));
-       smp_store_release(&ssp->srcu_size_state, SRCU_SIZE_ALLOC);
+       lockdep_assert_held(&ACCESS_PRIVATE(ssp->srcu_sup, lock));
+       smp_store_release(&ssp->srcu_sup->srcu_size_state, SRCU_SIZE_ALLOC);
 }
 
 /*
@@ -318,15 +327,15 @@ static void srcu_transition_to_big(struct srcu_struct *ssp)
        unsigned long flags;
 
        /* Double-checked locking on ->srcu_size-state. */
-       if (smp_load_acquire(&ssp->srcu_size_state) != SRCU_SIZE_SMALL)
+       if (smp_load_acquire(&ssp->srcu_sup->srcu_size_state) != SRCU_SIZE_SMALL)
                return;
-       spin_lock_irqsave_rcu_node(ssp, flags);
-       if (smp_load_acquire(&ssp->srcu_size_state) != SRCU_SIZE_SMALL) {
-               spin_unlock_irqrestore_rcu_node(ssp, flags);
+       spin_lock_irqsave_rcu_node(ssp->srcu_sup, flags);
+       if (smp_load_acquire(&ssp->srcu_sup->srcu_size_state) != SRCU_SIZE_SMALL) {
+               spin_unlock_irqrestore_rcu_node(ssp->srcu_sup, flags);
                return;
        }
        __srcu_transition_to_big(ssp);
-       spin_unlock_irqrestore_rcu_node(ssp, flags);
+       spin_unlock_irqrestore_rcu_node(ssp->srcu_sup, flags);
 }
 
 /*
@@ -337,14 +346,14 @@ static void spin_lock_irqsave_check_contention(struct srcu_struct *ssp)
 {
        unsigned long j;
 
-       if (!SRCU_SIZING_IS_CONTEND() || ssp->srcu_size_state)
+       if (!SRCU_SIZING_IS_CONTEND() || ssp->srcu_sup->srcu_size_state)
                return;
        j = jiffies;
-       if (ssp->srcu_size_jiffies != j) {
-               ssp->srcu_size_jiffies = j;
-               ssp->srcu_n_lock_retries = 0;
+       if (ssp->srcu_sup->srcu_size_jiffies != j) {
+               ssp->srcu_sup->srcu_size_jiffies = j;
+               ssp->srcu_sup->srcu_n_lock_retries = 0;
        }
-       if (++ssp->srcu_n_lock_retries <= small_contention_lim)
+       if (++ssp->srcu_sup->srcu_n_lock_retries <= small_contention_lim)
                return;
        __srcu_transition_to_big(ssp);
 }
@@ -361,9 +370,9 @@ static void spin_lock_irqsave_sdp_contention(struct srcu_data *sdp, unsigned lon
 
        if (spin_trylock_irqsave_rcu_node(sdp, *flags))
                return;
-       spin_lock_irqsave_rcu_node(ssp, *flags);
+       spin_lock_irqsave_rcu_node(ssp->srcu_sup, *flags);
        spin_lock_irqsave_check_contention(ssp);
-       spin_unlock_irqrestore_rcu_node(ssp, *flags);
+       spin_unlock_irqrestore_rcu_node(ssp->srcu_sup, *flags);
        spin_lock_irqsave_rcu_node(sdp, *flags);
 }
 
@@ -375,9 +384,9 @@ static void spin_lock_irqsave_sdp_contention(struct srcu_data *sdp, unsigned lon
  */
 static void spin_lock_irqsave_ssp_contention(struct srcu_struct *ssp, unsigned long *flags)
 {
-       if (spin_trylock_irqsave_rcu_node(ssp, *flags))
+       if (spin_trylock_irqsave_rcu_node(ssp->srcu_sup, *flags))
                return;
-       spin_lock_irqsave_rcu_node(ssp, *flags);
+       spin_lock_irqsave_rcu_node(ssp->srcu_sup, *flags);
        spin_lock_irqsave_check_contention(ssp);
 }
 
@@ -394,15 +403,15 @@ static void check_init_srcu_struct(struct srcu_struct *ssp)
        unsigned long flags;
 
        /* The smp_load_acquire() pairs with the smp_store_release(). */
-       if (!rcu_seq_state(smp_load_acquire(&ssp->srcu_gp_seq_needed))) /*^^^*/
+       if (!rcu_seq_state(smp_load_acquire(&ssp->srcu_sup->srcu_gp_seq_needed))) /*^^^*/
                return; /* Already initialized. */
-       spin_lock_irqsave_rcu_node(ssp, flags);
-       if (!rcu_seq_state(ssp->srcu_gp_seq_needed)) {
-               spin_unlock_irqrestore_rcu_node(ssp, flags);
+       spin_lock_irqsave_rcu_node(ssp->srcu_sup, flags);
+       if (!rcu_seq_state(ssp->srcu_sup->srcu_gp_seq_needed)) {
+               spin_unlock_irqrestore_rcu_node(ssp->srcu_sup, flags);
                return;
        }
        init_srcu_struct_fields(ssp, true);
-       spin_unlock_irqrestore_rcu_node(ssp, flags);
+       spin_unlock_irqrestore_rcu_node(ssp->srcu_sup, flags);
 }
 
 /*
@@ -607,17 +616,18 @@ static unsigned long srcu_get_delay(struct srcu_struct *ssp)
        unsigned long gpstart;
        unsigned long j;
        unsigned long jbase = SRCU_INTERVAL;
+       struct srcu_usage *sup = ssp->srcu_sup;
 
-       if (ULONG_CMP_LT(READ_ONCE(ssp->srcu_gp_seq), READ_ONCE(ssp->srcu_gp_seq_needed_exp)))
+       if (ULONG_CMP_LT(READ_ONCE(sup->srcu_gp_seq), READ_ONCE(sup->srcu_gp_seq_needed_exp)))
                jbase = 0;
-       if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq))) {
+       if (rcu_seq_state(READ_ONCE(sup->srcu_gp_seq))) {
                j = jiffies - 1;
-               gpstart = READ_ONCE(ssp->srcu_gp_start);
+               gpstart = READ_ONCE(sup->srcu_gp_start);
                if (time_after(j, gpstart))
                        jbase += j - gpstart;
                if (!jbase) {
-                       WRITE_ONCE(ssp->srcu_n_exp_nodelay, READ_ONCE(ssp->srcu_n_exp_nodelay) + 1);
-                       if (READ_ONCE(ssp->srcu_n_exp_nodelay) > srcu_max_nodelay_phase)
+                       WRITE_ONCE(sup->srcu_n_exp_nodelay, READ_ONCE(sup->srcu_n_exp_nodelay) + 1);
+                       if (READ_ONCE(sup->srcu_n_exp_nodelay) > srcu_max_nodelay_phase)
                                jbase = 1;
                }
        }
@@ -634,12 +644,13 @@ static unsigned long srcu_get_delay(struct srcu_struct *ssp)
 void cleanup_srcu_struct(struct srcu_struct *ssp)
 {
        int cpu;
+       struct srcu_usage *sup = ssp->srcu_sup;
 
        if (WARN_ON(!srcu_get_delay(ssp)))
                return; /* Just leak it! */
        if (WARN_ON(srcu_readers_active(ssp)))
                return; /* Just leak it! */
-       flush_delayed_work(&ssp->work);
+       flush_delayed_work(&sup->work);
        for_each_possible_cpu(cpu) {
                struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu);
 
@@ -648,21 +659,23 @@ void cleanup_srcu_struct(struct srcu_struct *ssp)
                if (WARN_ON(rcu_segcblist_n_cbs(&sdp->srcu_cblist)))
                        return; /* Forgot srcu_barrier(), so just leak it! */
        }
-       if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) ||
-           WARN_ON(rcu_seq_current(&ssp->srcu_gp_seq) != ssp->srcu_gp_seq_needed) ||
+       if (WARN_ON(rcu_seq_state(READ_ONCE(sup->srcu_gp_seq)) != SRCU_STATE_IDLE) ||
+           WARN_ON(rcu_seq_current(&sup->srcu_gp_seq) != sup->srcu_gp_seq_needed) ||
            WARN_ON(srcu_readers_active(ssp))) {
                pr_info("%s: Active srcu_struct %p read state: %d gp state: %lu/%lu\n",
-                       __func__, ssp, rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)),
-                       rcu_seq_current(&ssp->srcu_gp_seq), ssp->srcu_gp_seq_needed);
+                       __func__, ssp, rcu_seq_state(READ_ONCE(sup->srcu_gp_seq)),
+                       rcu_seq_current(&sup->srcu_gp_seq), sup->srcu_gp_seq_needed);
                return; /* Caller forgot to stop doing call_srcu()? */
        }
-       if (!ssp->sda_is_static) {
+       kfree(sup->node);
+       sup->node = NULL;
+       sup->srcu_size_state = SRCU_SIZE_SMALL;
+       if (!sup->sda_is_static) {
                free_percpu(ssp->sda);
                ssp->sda = NULL;
+               kfree(sup);
+               ssp->srcu_sup = NULL;
        }
-       kfree(ssp->node);
-       ssp->node = NULL;
-       ssp->srcu_size_state = SRCU_SIZE_SMALL;
 }
 EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
 
@@ -760,23 +773,23 @@ static void srcu_gp_start(struct srcu_struct *ssp)
        struct srcu_data *sdp;
        int state;
 
-       if (smp_load_acquire(&ssp->srcu_size_state) < SRCU_SIZE_WAIT_BARRIER)
+       if (smp_load_acquire(&ssp->srcu_sup->srcu_size_state) < SRCU_SIZE_WAIT_BARRIER)
                sdp = per_cpu_ptr(ssp->sda, get_boot_cpu_id());
        else
                sdp = this_cpu_ptr(ssp->sda);
-       lockdep_assert_held(&ACCESS_PRIVATE(ssp, lock));
-       WARN_ON_ONCE(ULONG_CMP_GE(ssp->srcu_gp_seq, ssp->srcu_gp_seq_needed));
+       lockdep_assert_held(&ACCESS_PRIVATE(ssp->srcu_sup, lock));
+       WARN_ON_ONCE(ULONG_CMP_GE(ssp->srcu_sup->srcu_gp_seq, ssp->srcu_sup->srcu_gp_seq_needed));
        spin_lock_rcu_node(sdp);  /* Interrupts already disabled. */
        rcu_segcblist_advance(&sdp->srcu_cblist,
-                             rcu_seq_current(&ssp->srcu_gp_seq));
+                             rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq));
        (void)rcu_segcblist_accelerate(&sdp->srcu_cblist,
-                                      rcu_seq_snap(&ssp->srcu_gp_seq));
+                                      rcu_seq_snap(&ssp->srcu_sup->srcu_gp_seq));
        spin_unlock_rcu_node(sdp);  /* Interrupts remain disabled. */
-       WRITE_ONCE(ssp->srcu_gp_start, jiffies);
-       WRITE_ONCE(ssp->srcu_n_exp_nodelay, 0);
+       WRITE_ONCE(ssp->srcu_sup->srcu_gp_start, jiffies);
+       WRITE_ONCE(ssp->srcu_sup->srcu_n_exp_nodelay, 0);
        smp_mb(); /* Order prior store to ->srcu_gp_seq_needed vs. GP start. */
-       rcu_seq_start(&ssp->srcu_gp_seq);
-       state = rcu_seq_state(ssp->srcu_gp_seq);
+       rcu_seq_start(&ssp->srcu_sup->srcu_gp_seq);
+       state = rcu_seq_state(ssp->srcu_sup->srcu_gp_seq);
        WARN_ON_ONCE(state != SRCU_STATE_SCAN1);
 }
 
@@ -849,28 +862,29 @@ static void srcu_gp_end(struct srcu_struct *ssp)
        unsigned long sgsne;
        struct srcu_node *snp;
        int ss_state;
+       struct srcu_usage *sup = ssp->srcu_sup;
 
        /* Prevent more than one additional grace period. */
-       mutex_lock(&ssp->srcu_cb_mutex);
+       mutex_lock(&sup->srcu_cb_mutex);
 
        /* End the current grace period. */
-       spin_lock_irq_rcu_node(ssp);
-       idx = rcu_seq_state(ssp->srcu_gp_seq);
+       spin_lock_irq_rcu_node(sup);
+       idx = rcu_seq_state(sup->srcu_gp_seq);
        WARN_ON_ONCE(idx != SRCU_STATE_SCAN2);
-       if (ULONG_CMP_LT(READ_ONCE(ssp->srcu_gp_seq), READ_ONCE(ssp->srcu_gp_seq_needed_exp)))
+       if (ULONG_CMP_LT(READ_ONCE(sup->srcu_gp_seq), READ_ONCE(sup->srcu_gp_seq_needed_exp)))
                cbdelay = 0;
 
-       WRITE_ONCE(ssp->srcu_last_gp_end, ktime_get_mono_fast_ns());
-       rcu_seq_end(&ssp->srcu_gp_seq);
-       gpseq = rcu_seq_current(&ssp->srcu_gp_seq);
-       if (ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, gpseq))
-               WRITE_ONCE(ssp->srcu_gp_seq_needed_exp, gpseq);
-       spin_unlock_irq_rcu_node(ssp);
-       mutex_unlock(&ssp->srcu_gp_mutex);
+       WRITE_ONCE(sup->srcu_last_gp_end, ktime_get_mono_fast_ns());
+       rcu_seq_end(&sup->srcu_gp_seq);
+       gpseq = rcu_seq_current(&sup->srcu_gp_seq);
+       if (ULONG_CMP_LT(sup->srcu_gp_seq_needed_exp, gpseq))
+               WRITE_ONCE(sup->srcu_gp_seq_needed_exp, gpseq);
+       spin_unlock_irq_rcu_node(sup);
+       mutex_unlock(&sup->srcu_gp_mutex);
        /* A new grace period can start at this point.  But only one. */
 
        /* Initiate callback invocation as needed. */
-       ss_state = smp_load_acquire(&ssp->srcu_size_state);
+       ss_state = smp_load_acquire(&sup->srcu_size_state);
        if (ss_state < SRCU_SIZE_WAIT_BARRIER) {
                srcu_schedule_cbs_sdp(per_cpu_ptr(ssp->sda, get_boot_cpu_id()),
                                        cbdelay);
@@ -879,7 +893,7 @@ static void srcu_gp_end(struct srcu_struct *ssp)
                srcu_for_each_node_breadth_first(ssp, snp) {
                        spin_lock_irq_rcu_node(snp);
                        cbs = false;
-                       last_lvl = snp >= ssp->level[rcu_num_lvls - 1];
+                       last_lvl = snp >= sup->level[rcu_num_lvls - 1];
                        if (last_lvl)
                                cbs = ss_state < SRCU_SIZE_BIG || snp->srcu_have_cbs[idx] == gpseq;
                        snp->srcu_have_cbs[idx] = gpseq;
@@ -911,18 +925,18 @@ static void srcu_gp_end(struct srcu_struct *ssp)
                }
 
        /* Callback initiation done, allow grace periods after next. */
-       mutex_unlock(&ssp->srcu_cb_mutex);
+       mutex_unlock(&sup->srcu_cb_mutex);
 
        /* Start a new grace period if needed. */
-       spin_lock_irq_rcu_node(ssp);
-       gpseq = rcu_seq_current(&ssp->srcu_gp_seq);
+       spin_lock_irq_rcu_node(sup);
+       gpseq = rcu_seq_current(&sup->srcu_gp_seq);
        if (!rcu_seq_state(gpseq) &&
-           ULONG_CMP_LT(gpseq, ssp->srcu_gp_seq_needed)) {
+           ULONG_CMP_LT(gpseq, sup->srcu_gp_seq_needed)) {
                srcu_gp_start(ssp);
-               spin_unlock_irq_rcu_node(ssp);
+               spin_unlock_irq_rcu_node(sup);
                srcu_reschedule(ssp, 0);
        } else {
-               spin_unlock_irq_rcu_node(ssp);
+               spin_unlock_irq_rcu_node(sup);
        }
 
        /* Transition to big if needed. */
@@ -930,7 +944,7 @@ static void srcu_gp_end(struct srcu_struct *ssp)
                if (ss_state == SRCU_SIZE_ALLOC)
                        init_srcu_struct_nodes(ssp, GFP_KERNEL);
                else
-                       smp_store_release(&ssp->srcu_size_state, ss_state + 1);
+                       smp_store_release(&sup->srcu_size_state, ss_state + 1);
        }
 }
 
@@ -950,7 +964,7 @@ static void srcu_funnel_exp_start(struct srcu_struct *ssp, struct srcu_node *snp
        if (snp)
                for (; snp != NULL; snp = snp->srcu_parent) {
                        sgsne = READ_ONCE(snp->srcu_gp_seq_needed_exp);
-                       if (WARN_ON_ONCE(rcu_seq_done(&ssp->srcu_gp_seq, s)) ||
+                       if (WARN_ON_ONCE(rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, s)) ||
                            (!srcu_invl_snp_seq(sgsne) && ULONG_CMP_GE(sgsne, s)))
                                return;
                        spin_lock_irqsave_rcu_node(snp, flags);
@@ -963,9 +977,9 @@ static void srcu_funnel_exp_start(struct srcu_struct *ssp, struct srcu_node *snp
                        spin_unlock_irqrestore_rcu_node(snp, flags);
                }
        spin_lock_irqsave_ssp_contention(ssp, &flags);
-       if (ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, s))
-               WRITE_ONCE(ssp->srcu_gp_seq_needed_exp, s);
-       spin_unlock_irqrestore_rcu_node(ssp, flags);
+       if (ULONG_CMP_LT(ssp->srcu_sup->srcu_gp_seq_needed_exp, s))
+               WRITE_ONCE(ssp->srcu_sup->srcu_gp_seq_needed_exp, s);
+       spin_unlock_irqrestore_rcu_node(ssp->srcu_sup, flags);
 }
 
 /*
@@ -990,9 +1004,10 @@ static void srcu_funnel_gp_start(struct srcu_struct *ssp, struct srcu_data *sdp,
        struct srcu_node *snp;
        struct srcu_node *snp_leaf;
        unsigned long snp_seq;
+       struct srcu_usage *sup = ssp->srcu_sup;
 
        /* Ensure that snp node tree is fully initialized before traversing it */
-       if (smp_load_acquire(&ssp->srcu_size_state) < SRCU_SIZE_WAIT_BARRIER)
+       if (smp_load_acquire(&sup->srcu_size_state) < SRCU_SIZE_WAIT_BARRIER)
                snp_leaf = NULL;
        else
                snp_leaf = sdp->mynode;
@@ -1000,7 +1015,7 @@ static void srcu_funnel_gp_start(struct srcu_struct *ssp, struct srcu_data *sdp,
        if (snp_leaf)
                /* Each pass through the loop does one level of the srcu_node tree. */
                for (snp = snp_leaf; snp != NULL; snp = snp->srcu_parent) {
-                       if (WARN_ON_ONCE(rcu_seq_done(&ssp->srcu_gp_seq, s)) && snp != snp_leaf)
+                       if (WARN_ON_ONCE(rcu_seq_done(&sup->srcu_gp_seq, s)) && snp != snp_leaf)
                                return; /* GP already done and CBs recorded. */
                        spin_lock_irqsave_rcu_node(snp, flags);
                        snp_seq = snp->srcu_have_cbs[idx];
@@ -1027,20 +1042,20 @@ static void srcu_funnel_gp_start(struct srcu_struct *ssp, struct srcu_data *sdp,
 
        /* Top of tree, must ensure the grace period will be started. */
        spin_lock_irqsave_ssp_contention(ssp, &flags);
-       if (ULONG_CMP_LT(ssp->srcu_gp_seq_needed, s)) {
+       if (ULONG_CMP_LT(sup->srcu_gp_seq_needed, s)) {
                /*
                 * Record need for grace period s.  Pair with load
                 * acquire setting up for initialization.
                 */
-               smp_store_release(&ssp->srcu_gp_seq_needed, s); /*^^^*/
+               smp_store_release(&sup->srcu_gp_seq_needed, s); /*^^^*/
        }
-       if (!do_norm && ULONG_CMP_LT(ssp->srcu_gp_seq_needed_exp, s))
-               WRITE_ONCE(ssp->srcu_gp_seq_needed_exp, s);
+       if (!do_norm && ULONG_CMP_LT(sup->srcu_gp_seq_needed_exp, s))
+               WRITE_ONCE(sup->srcu_gp_seq_needed_exp, s);
 
        /* If grace period not already in progress, start it. */
-       if (!WARN_ON_ONCE(rcu_seq_done(&ssp->srcu_gp_seq, s)) &&
-           rcu_seq_state(ssp->srcu_gp_seq) == SRCU_STATE_IDLE) {
-               WARN_ON_ONCE(ULONG_CMP_GE(ssp->srcu_gp_seq, ssp->srcu_gp_seq_needed));
+       if (!WARN_ON_ONCE(rcu_seq_done(&sup->srcu_gp_seq, s)) &&
+           rcu_seq_state(sup->srcu_gp_seq) == SRCU_STATE_IDLE) {
+               WARN_ON_ONCE(ULONG_CMP_GE(sup->srcu_gp_seq, sup->srcu_gp_seq_needed));
                srcu_gp_start(ssp);
 
                // And how can that list_add() in the "else" clause
@@ -1049,12 +1064,12 @@ static void srcu_funnel_gp_start(struct srcu_struct *ssp, struct srcu_data *sdp,
                // can only be executed during early boot when there is only
                // the one boot CPU running with interrupts still disabled.
                if (likely(srcu_init_done))
-                       queue_delayed_work(rcu_gp_wq, &ssp->work,
+                       queue_delayed_work(rcu_gp_wq, &sup->work,
                                           !!srcu_get_delay(ssp));
-               else if (list_empty(&ssp->work.work.entry))
-                       list_add(&ssp->work.work.entry, &srcu_boot_list);
+               else if (list_empty(&sup->work.work.entry))
+                       list_add(&sup->work.work.entry, &srcu_boot_list);
        }
-       spin_unlock_irqrestore_rcu_node(ssp, flags);
+       spin_unlock_irqrestore_rcu_node(sup, flags);
 }
 
 /*
@@ -1085,16 +1100,36 @@ static bool try_check_zero(struct srcu_struct *ssp, int idx, int trycount)
 static void srcu_flip(struct srcu_struct *ssp)
 {
        /*
-        * Ensure that if this updater saw a given reader's increment
-        * from __srcu_read_lock(), that reader was using an old value
-        * of ->srcu_idx.  Also ensure that if a given reader sees the
-        * new value of ->srcu_idx, this updater's earlier scans cannot
-        * have seen that reader's increments (which is OK, because this
-        * grace period need not wait on that reader).
+        * Because the flip of ->srcu_idx is executed only if the
+        * preceding call to srcu_readers_active_idx_check() found that
+        * the ->srcu_unlock_count[] and ->srcu_lock_count[] sums matched
+        * and because that summing uses atomic_long_read(), there is
+        * ordering due to a control dependency between that summing and
+        * the WRITE_ONCE() in this call to srcu_flip().  This ordering
+        * ensures that if this updater saw a given reader's increment from
+        * __srcu_read_lock(), that reader was using a value of ->srcu_idx
+        * from before the previous call to srcu_flip(), which should be
+        * quite rare.  This ordering thus helps forward progress because
+        * the grace period could otherwise be delayed by additional
+        * calls to __srcu_read_lock() using that old (soon to be new)
+        * value of ->srcu_idx.
+        *
+        * This sum-equality check and ordering also ensures that if
+        * a given call to __srcu_read_lock() uses the new value of
+        * ->srcu_idx, this updater's earlier scans cannot have seen
+        * that reader's increments, which is all to the good, because
+        * this grace period need not wait on that reader.  After all,
+        * if those earlier scans had seen that reader, there would have
+        * been a sum mismatch and this code would not be reached.
+        *
+        * This means that the following smp_mb() is redundant, but
+        * it stays until either (1) Compilers learn about this sort of
+        * control dependency or (2) Some production workload running on
+        * a production system is unduly delayed by this slowpath smp_mb().
         */
        smp_mb(); /* E */  /* Pairs with B and C. */
 
-       WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1);
+       WRITE_ONCE(ssp->srcu_idx, ssp->srcu_idx + 1); // Flip the counter.
 
        /*
         * Ensure that if the updater misses an __srcu_read_unlock()
@@ -1154,18 +1189,18 @@ static bool srcu_might_be_idle(struct srcu_struct *ssp)
 
        /* First, see if enough time has passed since the last GP. */
        t = ktime_get_mono_fast_ns();
-       tlast = READ_ONCE(ssp->srcu_last_gp_end);
+       tlast = READ_ONCE(ssp->srcu_sup->srcu_last_gp_end);
        if (exp_holdoff == 0 ||
            time_in_range_open(t, tlast, tlast + exp_holdoff))
                return false; /* Too soon after last GP. */
 
        /* Next, check for probable idleness. */
-       curseq = rcu_seq_current(&ssp->srcu_gp_seq);
+       curseq = rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq);
        smp_mb(); /* Order ->srcu_gp_seq with ->srcu_gp_seq_needed. */
-       if (ULONG_CMP_LT(curseq, READ_ONCE(ssp->srcu_gp_seq_needed)))
+       if (ULONG_CMP_LT(curseq, READ_ONCE(ssp->srcu_sup->srcu_gp_seq_needed)))
                return false; /* Grace period in progress, so not idle. */
        smp_mb(); /* Order ->srcu_gp_seq with prior access. */
-       if (curseq != rcu_seq_current(&ssp->srcu_gp_seq))
+       if (curseq != rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq))
                return false; /* GP # changed, so not idle. */
        return true; /* With reasonable probability, idle! */
 }
@@ -1199,7 +1234,7 @@ static unsigned long srcu_gp_start_if_needed(struct srcu_struct *ssp,
         * sequence number cannot wrap around in the meantime.
         */
        idx = __srcu_read_lock_nmisafe(ssp);
-       ss_state = smp_load_acquire(&ssp->srcu_size_state);
+       ss_state = smp_load_acquire(&ssp->srcu_sup->srcu_size_state);
        if (ss_state < SRCU_SIZE_WAIT_CALL)
                sdp = per_cpu_ptr(ssp->sda, get_boot_cpu_id());
        else
@@ -1208,8 +1243,8 @@ static unsigned long srcu_gp_start_if_needed(struct srcu_struct *ssp,
        if (rhp)
                rcu_segcblist_enqueue(&sdp->srcu_cblist, rhp);
        rcu_segcblist_advance(&sdp->srcu_cblist,
-                             rcu_seq_current(&ssp->srcu_gp_seq));
-       s = rcu_seq_snap(&ssp->srcu_gp_seq);
+                             rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq));
+       s = rcu_seq_snap(&ssp->srcu_sup->srcu_gp_seq);
        (void)rcu_segcblist_accelerate(&sdp->srcu_cblist, s);
        if (ULONG_CMP_LT(sdp->srcu_gp_seq_needed, s)) {
                sdp->srcu_gp_seq_needed = s;
@@ -1307,6 +1342,8 @@ static void __synchronize_srcu(struct srcu_struct *ssp, bool do_norm)
 {
        struct rcu_synchronize rcu;
 
+       srcu_lock_sync(&ssp->dep_map);
+
        RCU_LOCKDEP_WARN(lockdep_is_held(ssp) ||
                         lock_is_held(&rcu_bh_lock_map) ||
                         lock_is_held(&rcu_lock_map) ||
@@ -1420,7 +1457,7 @@ unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp)
        // Any prior manipulation of SRCU-protected data must happen
        // before the load from ->srcu_gp_seq.
        smp_mb();
-       return rcu_seq_snap(&ssp->srcu_gp_seq);
+       return rcu_seq_snap(&ssp->srcu_sup->srcu_gp_seq);
 }
 EXPORT_SYMBOL_GPL(get_state_synchronize_srcu);
 
@@ -1467,7 +1504,7 @@ EXPORT_SYMBOL_GPL(start_poll_synchronize_srcu);
  */
 bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)
 {
-       if (!rcu_seq_done(&ssp->srcu_gp_seq, cookie))
+       if (!rcu_seq_done(&ssp->srcu_sup->srcu_gp_seq, cookie))
                return false;
        // Ensure that the end of the SRCU grace period happens before
        // any subsequent code that the caller might execute.
@@ -1486,8 +1523,8 @@ static void srcu_barrier_cb(struct rcu_head *rhp)
 
        sdp = container_of(rhp, struct srcu_data, srcu_barrier_head);
        ssp = sdp->ssp;
-       if (atomic_dec_and_test(&ssp->srcu_barrier_cpu_cnt))
-               complete(&ssp->srcu_barrier_completion);
+       if (atomic_dec_and_test(&ssp->srcu_sup->srcu_barrier_cpu_cnt))
+               complete(&ssp->srcu_sup->srcu_barrier_completion);
 }
 
 /*
@@ -1501,13 +1538,13 @@ static void srcu_barrier_cb(struct rcu_head *rhp)
 static void srcu_barrier_one_cpu(struct srcu_struct *ssp, struct srcu_data *sdp)
 {
        spin_lock_irq_rcu_node(sdp);
-       atomic_inc(&ssp->srcu_barrier_cpu_cnt);
+       atomic_inc(&ssp->srcu_sup->srcu_barrier_cpu_cnt);
        sdp->srcu_barrier_head.func = srcu_barrier_cb;
        debug_rcu_head_queue(&sdp->srcu_barrier_head);
        if (!rcu_segcblist_entrain(&sdp->srcu_cblist,
                                   &sdp->srcu_barrier_head)) {
                debug_rcu_head_unqueue(&sdp->srcu_barrier_head);
-               atomic_dec(&ssp->srcu_barrier_cpu_cnt);
+               atomic_dec(&ssp->srcu_sup->srcu_barrier_cpu_cnt);
        }
        spin_unlock_irq_rcu_node(sdp);
 }
@@ -1520,23 +1557,23 @@ void srcu_barrier(struct srcu_struct *ssp)
 {
        int cpu;
        int idx;
-       unsigned long s = rcu_seq_snap(&ssp->srcu_barrier_seq);
+       unsigned long s = rcu_seq_snap(&ssp->srcu_sup->srcu_barrier_seq);
 
        check_init_srcu_struct(ssp);
-       mutex_lock(&ssp->srcu_barrier_mutex);
-       if (rcu_seq_done(&ssp->srcu_barrier_seq, s)) {
+       mutex_lock(&ssp->srcu_sup->srcu_barrier_mutex);
+       if (rcu_seq_done(&ssp->srcu_sup->srcu_barrier_seq, s)) {
                smp_mb(); /* Force ordering following return. */
-               mutex_unlock(&ssp->srcu_barrier_mutex);
+               mutex_unlock(&ssp->srcu_sup->srcu_barrier_mutex);
                return; /* Someone else did our work for us. */
        }
-       rcu_seq_start(&ssp->srcu_barrier_seq);
-       init_completion(&ssp->srcu_barrier_completion);
+       rcu_seq_start(&ssp->srcu_sup->srcu_barrier_seq);
+       init_completion(&ssp->srcu_sup->srcu_barrier_completion);
 
        /* Initial count prevents reaching zero until all CBs are posted. */
-       atomic_set(&ssp->srcu_barrier_cpu_cnt, 1);
+       atomic_set(&ssp->srcu_sup->srcu_barrier_cpu_cnt, 1);
 
        idx = __srcu_read_lock_nmisafe(ssp);
-       if (smp_load_acquire(&ssp->srcu_size_state) < SRCU_SIZE_WAIT_BARRIER)
+       if (smp_load_acquire(&ssp->srcu_sup->srcu_size_state) < SRCU_SIZE_WAIT_BARRIER)
                srcu_barrier_one_cpu(ssp, per_cpu_ptr(ssp->sda, get_boot_cpu_id()));
        else
                for_each_possible_cpu(cpu)
@@ -1544,12 +1581,12 @@ void srcu_barrier(struct srcu_struct *ssp)
        __srcu_read_unlock_nmisafe(ssp, idx);
 
        /* Remove the initial count, at which point reaching zero can happen. */
-       if (atomic_dec_and_test(&ssp->srcu_barrier_cpu_cnt))
-               complete(&ssp->srcu_barrier_completion);
-       wait_for_completion(&ssp->srcu_barrier_completion);
+       if (atomic_dec_and_test(&ssp->srcu_sup->srcu_barrier_cpu_cnt))
+               complete(&ssp->srcu_sup->srcu_barrier_completion);
+       wait_for_completion(&ssp->srcu_sup->srcu_barrier_completion);
 
-       rcu_seq_end(&ssp->srcu_barrier_seq);
-       mutex_unlock(&ssp->srcu_barrier_mutex);
+       rcu_seq_end(&ssp->srcu_sup->srcu_barrier_seq);
+       mutex_unlock(&ssp->srcu_sup->srcu_barrier_mutex);
 }
 EXPORT_SYMBOL_GPL(srcu_barrier);
 
@@ -1575,7 +1612,7 @@ static void srcu_advance_state(struct srcu_struct *ssp)
 {
        int idx;
 
-       mutex_lock(&ssp->srcu_gp_mutex);
+       mutex_lock(&ssp->srcu_sup->srcu_gp_mutex);
 
        /*
         * Because readers might be delayed for an extended period after
@@ -1587,39 +1624,39 @@ static void srcu_advance_state(struct srcu_struct *ssp)
         * The load-acquire ensures that we see the accesses performed
         * by the prior grace period.
         */
-       idx = rcu_seq_state(smp_load_acquire(&ssp->srcu_gp_seq)); /* ^^^ */
+       idx = rcu_seq_state(smp_load_acquire(&ssp->srcu_sup->srcu_gp_seq)); /* ^^^ */
        if (idx == SRCU_STATE_IDLE) {
-               spin_lock_irq_rcu_node(ssp);
-               if (ULONG_CMP_GE(ssp->srcu_gp_seq, ssp->srcu_gp_seq_needed)) {
-                       WARN_ON_ONCE(rcu_seq_state(ssp->srcu_gp_seq));
-                       spin_unlock_irq_rcu_node(ssp);
-                       mutex_unlock(&ssp->srcu_gp_mutex);
+               spin_lock_irq_rcu_node(ssp->srcu_sup);
+               if (ULONG_CMP_GE(ssp->srcu_sup->srcu_gp_seq, ssp->srcu_sup->srcu_gp_seq_needed)) {
+                       WARN_ON_ONCE(rcu_seq_state(ssp->srcu_sup->srcu_gp_seq));
+                       spin_unlock_irq_rcu_node(ssp->srcu_sup);
+                       mutex_unlock(&ssp->srcu_sup->srcu_gp_mutex);
                        return;
                }
-               idx = rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq));
+               idx = rcu_seq_state(READ_ONCE(ssp->srcu_sup->srcu_gp_seq));
                if (idx == SRCU_STATE_IDLE)
                        srcu_gp_start(ssp);
-               spin_unlock_irq_rcu_node(ssp);
+               spin_unlock_irq_rcu_node(ssp->srcu_sup);
                if (idx != SRCU_STATE_IDLE) {
-                       mutex_unlock(&ssp->srcu_gp_mutex);
+                       mutex_unlock(&ssp->srcu_sup->srcu_gp_mutex);
                        return; /* Someone else started the grace period. */
                }
        }
 
-       if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) == SRCU_STATE_SCAN1) {
+       if (rcu_seq_state(READ_ONCE(ssp->srcu_sup->srcu_gp_seq)) == SRCU_STATE_SCAN1) {
                idx = 1 ^ (ssp->srcu_idx & 1);
                if (!try_check_zero(ssp, idx, 1)) {
-                       mutex_unlock(&ssp->srcu_gp_mutex);
+                       mutex_unlock(&ssp->srcu_sup->srcu_gp_mutex);
                        return; /* readers present, retry later. */
                }
                srcu_flip(ssp);
-               spin_lock_irq_rcu_node(ssp);
-               rcu_seq_set_state(&ssp->srcu_gp_seq, SRCU_STATE_SCAN2);
-               ssp->srcu_n_exp_nodelay = 0;
-               spin_unlock_irq_rcu_node(ssp);
+               spin_lock_irq_rcu_node(ssp->srcu_sup);
+               rcu_seq_set_state(&ssp->srcu_sup->srcu_gp_seq, SRCU_STATE_SCAN2);
+               ssp->srcu_sup->srcu_n_exp_nodelay = 0;
+               spin_unlock_irq_rcu_node(ssp->srcu_sup);
        }
 
-       if (rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) == SRCU_STATE_SCAN2) {
+       if (rcu_seq_state(READ_ONCE(ssp->srcu_sup->srcu_gp_seq)) == SRCU_STATE_SCAN2) {
 
                /*
                 * SRCU read-side critical sections are normally short,
@@ -1627,10 +1664,10 @@ static void srcu_advance_state(struct srcu_struct *ssp)
                 */
                idx = 1 ^ (ssp->srcu_idx & 1);
                if (!try_check_zero(ssp, idx, 2)) {
-                       mutex_unlock(&ssp->srcu_gp_mutex);
+                       mutex_unlock(&ssp->srcu_sup->srcu_gp_mutex);
                        return; /* readers present, retry later. */
                }
-               ssp->srcu_n_exp_nodelay = 0;
+               ssp->srcu_sup->srcu_n_exp_nodelay = 0;
                srcu_gp_end(ssp);  /* Releases ->srcu_gp_mutex. */
        }
 }
@@ -1656,7 +1693,7 @@ static void srcu_invoke_callbacks(struct work_struct *work)
        rcu_cblist_init(&ready_cbs);
        spin_lock_irq_rcu_node(sdp);
        rcu_segcblist_advance(&sdp->srcu_cblist,
-                             rcu_seq_current(&ssp->srcu_gp_seq));
+                             rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq));
        if (sdp->srcu_cblist_invoking ||
            !rcu_segcblist_ready_cbs(&sdp->srcu_cblist)) {
                spin_unlock_irq_rcu_node(sdp);
@@ -1684,7 +1721,7 @@ static void srcu_invoke_callbacks(struct work_struct *work)
        spin_lock_irq_rcu_node(sdp);
        rcu_segcblist_add_len(&sdp->srcu_cblist, -len);
        (void)rcu_segcblist_accelerate(&sdp->srcu_cblist,
-                                      rcu_seq_snap(&ssp->srcu_gp_seq));
+                                      rcu_seq_snap(&ssp->srcu_sup->srcu_gp_seq));
        sdp->srcu_cblist_invoking = false;
        more = rcu_segcblist_ready_cbs(&sdp->srcu_cblist);
        spin_unlock_irq_rcu_node(sdp);
@@ -1700,20 +1737,20 @@ static void srcu_reschedule(struct srcu_struct *ssp, unsigned long delay)
 {
        bool pushgp = true;
 
-       spin_lock_irq_rcu_node(ssp);
-       if (ULONG_CMP_GE(ssp->srcu_gp_seq, ssp->srcu_gp_seq_needed)) {
-               if (!WARN_ON_ONCE(rcu_seq_state(ssp->srcu_gp_seq))) {
+       spin_lock_irq_rcu_node(ssp->srcu_sup);
+       if (ULONG_CMP_GE(ssp->srcu_sup->srcu_gp_seq, ssp->srcu_sup->srcu_gp_seq_needed)) {
+               if (!WARN_ON_ONCE(rcu_seq_state(ssp->srcu_sup->srcu_gp_seq))) {
                        /* All requests fulfilled, time to go idle. */
                        pushgp = false;
                }
-       } else if (!rcu_seq_state(ssp->srcu_gp_seq)) {
+       } else if (!rcu_seq_state(ssp->srcu_sup->srcu_gp_seq)) {
                /* Outstanding request and no GP.  Start one. */
                srcu_gp_start(ssp);
        }
-       spin_unlock_irq_rcu_node(ssp);
+       spin_unlock_irq_rcu_node(ssp->srcu_sup);
 
        if (pushgp)
-               queue_delayed_work(rcu_gp_wq, &ssp->work, delay);
+               queue_delayed_work(rcu_gp_wq, &ssp->srcu_sup->work, delay);
 }
 
 /*
@@ -1724,22 +1761,24 @@ static void process_srcu(struct work_struct *work)
        unsigned long curdelay;
        unsigned long j;
        struct srcu_struct *ssp;
+       struct srcu_usage *sup;
 
-       ssp = container_of(work, struct srcu_struct, work.work);
+       sup = container_of(work, struct srcu_usage, work.work);
+       ssp = sup->srcu_ssp;
 
        srcu_advance_state(ssp);
        curdelay = srcu_get_delay(ssp);
        if (curdelay) {
-               WRITE_ONCE(ssp->reschedule_count, 0);
+               WRITE_ONCE(sup->reschedule_count, 0);
        } else {
                j = jiffies;
-               if (READ_ONCE(ssp->reschedule_jiffies) == j) {
-                       WRITE_ONCE(ssp->reschedule_count, READ_ONCE(ssp->reschedule_count) + 1);
-                       if (READ_ONCE(ssp->reschedule_count) > srcu_max_nodelay)
+               if (READ_ONCE(sup->reschedule_jiffies) == j) {
+                       WRITE_ONCE(sup->reschedule_count, READ_ONCE(sup->reschedule_count) + 1);
+                       if (READ_ONCE(sup->reschedule_count) > srcu_max_nodelay)
                                curdelay = 1;
                } else {
-                       WRITE_ONCE(ssp->reschedule_count, 1);
-                       WRITE_ONCE(ssp->reschedule_jiffies, j);
+                       WRITE_ONCE(sup->reschedule_count, 1);
+                       WRITE_ONCE(sup->reschedule_jiffies, j);
                }
        }
        srcu_reschedule(ssp, curdelay);
@@ -1752,7 +1791,7 @@ void srcutorture_get_gp_data(enum rcutorture_type test_type,
        if (test_type != SRCU_FLAVOR)
                return;
        *flags = 0;
-       *gp_seq = rcu_seq_current(&ssp->srcu_gp_seq);
+       *gp_seq = rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq);
 }
 EXPORT_SYMBOL_GPL(srcutorture_get_gp_data);
 
@@ -1774,14 +1813,14 @@ void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf)
        int cpu;
        int idx;
        unsigned long s0 = 0, s1 = 0;
-       int ss_state = READ_ONCE(ssp->srcu_size_state);
+       int ss_state = READ_ONCE(ssp->srcu_sup->srcu_size_state);
        int ss_state_idx = ss_state;
 
        idx = ssp->srcu_idx & 0x1;
        if (ss_state < 0 || ss_state >= ARRAY_SIZE(srcu_size_state_name))
                ss_state_idx = ARRAY_SIZE(srcu_size_state_name) - 1;
        pr_alert("%s%s Tree SRCU g%ld state %d (%s)",
-                tt, tf, rcu_seq_current(&ssp->srcu_gp_seq), ss_state,
+                tt, tf, rcu_seq_current(&ssp->srcu_sup->srcu_gp_seq), ss_state,
                 srcu_size_state_name[ss_state_idx]);
        if (!ssp->sda) {
                // Called after cleanup_srcu_struct(), perhaps.
@@ -1838,7 +1877,7 @@ early_initcall(srcu_bootup_announce);
 
 void __init srcu_init(void)
 {
-       struct srcu_struct *ssp;
+       struct srcu_usage *sup;
 
        /* Decide on srcu_struct-size strategy. */
        if (SRCU_SIZING_IS(SRCU_SIZING_AUTO)) {
@@ -1858,12 +1897,13 @@ void __init srcu_init(void)
         */
        srcu_init_done = true;
        while (!list_empty(&srcu_boot_list)) {
-               ssp = list_first_entry(&srcu_boot_list, struct srcu_struct,
+               sup = list_first_entry(&srcu_boot_list, struct srcu_usage,
                                      work.work.entry);
-               list_del_init(&ssp->work.work.entry);
-               if (SRCU_SIZING_IS(SRCU_SIZING_INIT) && ssp->srcu_size_state == SRCU_SIZE_SMALL)
-                       ssp->srcu_size_state = SRCU_SIZE_ALLOC;
-               queue_work(rcu_gp_wq, &ssp->work.work);
+               list_del_init(&sup->work.work.entry);
+               if (SRCU_SIZING_IS(SRCU_SIZING_INIT) &&
+                   sup->srcu_size_state == SRCU_SIZE_SMALL)
+                       sup->srcu_size_state = SRCU_SIZE_ALLOC;
+               queue_work(rcu_gp_wq, &sup->work.work);
        }
 }
 
@@ -1873,13 +1913,14 @@ void __init srcu_init(void)
 static int srcu_module_coming(struct module *mod)
 {
        int i;
+       struct srcu_struct *ssp;
        struct srcu_struct **sspp = mod->srcu_struct_ptrs;
-       int ret;
 
        for (i = 0; i < mod->num_srcu_structs; i++) {
-               ret = init_srcu_struct(*(sspp++));
-               if (WARN_ON_ONCE(ret))
-                       return ret;
+               ssp = *(sspp++);
+               ssp->sda = alloc_percpu(struct srcu_data);
+               if (WARN_ON_ONCE(!ssp->sda))
+                       return -ENOMEM;
        }
        return 0;
 }
@@ -1888,10 +1929,17 @@ static int srcu_module_coming(struct module *mod)
 static void srcu_module_going(struct module *mod)
 {
        int i;
+       struct srcu_struct *ssp;
        struct srcu_struct **sspp = mod->srcu_struct_ptrs;
 
-       for (i = 0; i < mod->num_srcu_structs; i++)
-               cleanup_srcu_struct(*(sspp++));
+       for (i = 0; i < mod->num_srcu_structs; i++) {
+               ssp = *(sspp++);
+               if (!rcu_seq_state(smp_load_acquire(&ssp->srcu_sup->srcu_gp_seq_needed)) &&
+                   !WARN_ON_ONCE(!ssp->srcu_sup->sda_is_static))
+                       cleanup_srcu_struct(ssp);
+               if (!WARN_ON(srcu_readers_active(ssp)))
+                       free_percpu(ssp->sda);
+       }
 }
 
 /* Handle one module, either coming or going. */
index bfb5e1549f2b22d510758840df48467c59b5dc93..5f4fc8184dd0b5db02ed1cae4c9ec5e260786107 100644 (file)
@@ -136,8 +136,16 @@ static struct rcu_tasks rt_name =                                                  \
        .kname = #rt_name,                                                              \
 }
 
+#ifdef CONFIG_TASKS_RCU
 /* Track exiting tasks in order to allow them to be waited for. */
 DEFINE_STATIC_SRCU(tasks_rcu_exit_srcu);
+#endif
+
+#ifdef CONFIG_TASKS_RCU
+/* Report delay in synchronize_srcu() completion in rcu_tasks_postscan(). */
+static void tasks_rcu_exit_srcu_stall(struct timer_list *unused);
+static DEFINE_TIMER(tasks_rcu_exit_srcu_stall_timer, tasks_rcu_exit_srcu_stall);
+#endif
 
 /* Avoid IPIing CPUs early in the grace period. */
 #define RCU_TASK_IPI_DELAY (IS_ENABLED(CONFIG_TASKS_TRACE_RCU_READ_MB) ? HZ / 2 : 0)
@@ -830,6 +838,13 @@ static void rcu_tasks_pertask(struct task_struct *t, struct list_head *hop)
 /* Processing between scanning taskslist and draining the holdout list. */
 static void rcu_tasks_postscan(struct list_head *hop)
 {
+       int rtsi = READ_ONCE(rcu_task_stall_info);
+
+       if (!IS_ENABLED(CONFIG_TINY_RCU)) {
+               tasks_rcu_exit_srcu_stall_timer.expires = jiffies + rtsi;
+               add_timer(&tasks_rcu_exit_srcu_stall_timer);
+       }
+
        /*
         * Exiting tasks may escape the tasklist scan. Those are vulnerable
         * until their final schedule() with TASK_DEAD state. To cope with
@@ -848,6 +863,9 @@ static void rcu_tasks_postscan(struct list_head *hop)
         * call to synchronize_rcu().
         */
        synchronize_srcu(&tasks_rcu_exit_srcu);
+
+       if (!IS_ENABLED(CONFIG_TINY_RCU))
+               del_timer_sync(&tasks_rcu_exit_srcu_stall_timer);
 }
 
 /* See if tasks are still holding out, complain if so. */
@@ -923,6 +941,21 @@ static void rcu_tasks_postgp(struct rcu_tasks *rtp)
 void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func);
 DEFINE_RCU_TASKS(rcu_tasks, rcu_tasks_wait_gp, call_rcu_tasks, "RCU Tasks");
 
+static void tasks_rcu_exit_srcu_stall(struct timer_list *unused)
+{
+#ifndef CONFIG_TINY_RCU
+       int rtsi;
+
+       rtsi = READ_ONCE(rcu_task_stall_info);
+       pr_info("%s: %s grace period number %lu (since boot) gp_state: %s is %lu jiffies old.\n",
+               __func__, rcu_tasks.kname, rcu_tasks.tasks_gp_seq,
+               tasks_gp_state_getname(&rcu_tasks), jiffies - rcu_tasks.gp_jiffies);
+       pr_info("Please check any exiting tasks stuck between calls to exit_tasks_rcu_start() and exit_tasks_rcu_finish()\n");
+       tasks_rcu_exit_srcu_stall_timer.expires = jiffies + rtsi;
+       add_timer(&tasks_rcu_exit_srcu_stall_timer);
+#endif // #ifndef CONFIG_TINY_RCU
+}
+
 /**
  * call_rcu_tasks() - Queue an RCU for invocation task-based grace period
  * @rhp: structure to be used for queueing the RCU updates.
index 8e880c09ab59ed0fab53abd7954e60eaaa2c25f2..f52ff7241041666e0bef539351ad24c0ca326926 100644 (file)
@@ -640,6 +640,7 @@ void __rcu_irq_enter_check_tick(void)
        }
        raw_spin_unlock_rcu_node(rdp->mynode);
 }
+NOKPROBE_SYMBOL(__rcu_irq_enter_check_tick);
 #endif /* CONFIG_NO_HZ_FULL */
 
 /*
@@ -1955,7 +1956,6 @@ rcu_report_qs_rdp(struct rcu_data *rdp)
 {
        unsigned long flags;
        unsigned long mask;
-       bool needwake = false;
        bool needacc = false;
        struct rcu_node *rnp;
 
@@ -1987,7 +1987,12 @@ rcu_report_qs_rdp(struct rcu_data *rdp)
                 * NOCB kthreads have their own way to deal with that...
                 */
                if (!rcu_rdp_is_offloaded(rdp)) {
-                       needwake = rcu_accelerate_cbs(rnp, rdp);
+                       /*
+                        * The current GP has not yet ended, so it
+                        * should not be possible for rcu_accelerate_cbs()
+                        * to return true.  So complain, but don't awaken.
+                        */
+                       WARN_ON_ONCE(rcu_accelerate_cbs(rnp, rdp));
                } else if (!rcu_segcblist_completely_offloaded(&rdp->cblist)) {
                        /*
                         * ...but NOCB kthreads may miss or delay callbacks acceleration
@@ -1999,8 +2004,6 @@ rcu_report_qs_rdp(struct rcu_data *rdp)
                rcu_disable_urgency_upon_qs(rdp);
                rcu_report_qs_rnp(mask, rnp, rnp->gp_seq, flags);
                /* ^^^ Released rnp->lock */
-               if (needwake)
-                       rcu_gp_kthread_wake();
 
                if (needacc) {
                        rcu_nocb_lock_irqsave(rdp, flags);
@@ -2131,6 +2134,8 @@ static void rcu_do_batch(struct rcu_data *rdp)
                                break;
                        }
                } else {
+                       // In rcuoc context, so no worries about depriving
+                       // other softirq vectors of CPU cycles.
                        local_bh_enable();
                        lockdep_assert_irqs_enabled();
                        cond_resched_tasks_rcu_qs();
@@ -3024,6 +3029,18 @@ need_offload_krc(struct kfree_rcu_cpu *krcp)
        return !!READ_ONCE(krcp->head);
 }
 
+static bool
+need_wait_for_krwp_work(struct kfree_rcu_cpu_work *krwp)
+{
+       int i;
+
+       for (i = 0; i < FREE_N_CHANNELS; i++)
+               if (!list_empty(&krwp->bulk_head_free[i]))
+                       return true;
+
+       return !!krwp->head_free;
+}
+
 static int krc_count(struct kfree_rcu_cpu *krcp)
 {
        int sum = atomic_read(&krcp->head_count);
@@ -3107,15 +3124,14 @@ static void kfree_rcu_monitor(struct work_struct *work)
        for (i = 0; i < KFREE_N_BATCHES; i++) {
                struct kfree_rcu_cpu_work *krwp = &(krcp->krw_arr[i]);
 
-               // Try to detach bulk_head or head and attach it over any
-               // available corresponding free channel. It can be that
-               // a previous RCU batch is in progress, it means that
-               // immediately to queue another one is not possible so
-               // in that case the monitor work is rearmed.
-               if ((!list_empty(&krcp->bulk_head[0]) && list_empty(&krwp->bulk_head_free[0])) ||
-                       (!list_empty(&krcp->bulk_head[1]) && list_empty(&krwp->bulk_head_free[1])) ||
-                               (READ_ONCE(krcp->head) && !krwp->head_free)) {
+               // Try to detach bulk_head or head and attach it, only when
+               // all channels are free.  Any channel is not free means at krwp
+               // there is on-going rcu work to handle krwp's free business.
+               if (need_wait_for_krwp_work(krwp))
+                       continue;
 
+               // kvfree_rcu_drain_ready() might handle this krcp, if so give up.
+               if (need_offload_krc(krcp)) {
                        // Channel 1 corresponds to the SLAB-pointer bulk path.
                        // Channel 2 corresponds to vmalloc-pointer bulk path.
                        for (j = 0; j < FREE_N_CHANNELS; j++) {
@@ -4940,9 +4956,8 @@ void __init rcu_init(void)
        else
                qovld_calc = qovld;
 
-       // Kick-start any polled grace periods that started early.
-       if (!(per_cpu_ptr(&rcu_data, cpu)->mynode->exp_seq_poll_rq & 0x1))
-               (void)start_poll_synchronize_rcu_expedited();
+       // Kick-start in case any polled grace periods started early.
+       (void)start_poll_synchronize_rcu_expedited();
 
        rcu_test_sync_prims();
 }
index 249c2967d9e6c0ba7197997885523506365f9649..3b7abb58157df63b839e7d37752208db12a15a8b 100644 (file)
@@ -594,6 +594,7 @@ static void synchronize_rcu_expedited_wait(void)
        struct rcu_data *rdp;
        struct rcu_node *rnp;
        struct rcu_node *rnp_root = rcu_get_root();
+       unsigned long flags;
 
        trace_rcu_exp_grace_period(rcu_state.name, rcu_exp_gp_seq_endval(), TPS("startwait"));
        jiffies_stall = rcu_exp_jiffies_till_stall_check();
@@ -602,17 +603,17 @@ static void synchronize_rcu_expedited_wait(void)
                if (synchronize_rcu_expedited_wait_once(1))
                        return;
                rcu_for_each_leaf_node(rnp) {
+                       raw_spin_lock_irqsave_rcu_node(rnp, flags);
                        mask = READ_ONCE(rnp->expmask);
                        for_each_leaf_node_cpu_mask(rnp, cpu, mask) {
                                rdp = per_cpu_ptr(&rcu_data, cpu);
                                if (rdp->rcu_forced_tick_exp)
                                        continue;
                                rdp->rcu_forced_tick_exp = true;
-                               preempt_disable();
                                if (cpu_online(cpu))
                                        tick_dep_set_cpu(cpu, TICK_DEP_BIT_RCU_EXP);
-                               preempt_enable();
                        }
+                       raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                }
                j = READ_ONCE(jiffies_till_first_fqs);
                if (synchronize_rcu_expedited_wait_once(j + HZ))
@@ -802,9 +803,11 @@ static int rcu_print_task_exp_stall(struct rcu_node *rnp)
        int ndetected = 0;
        struct task_struct *t;
 
-       if (!READ_ONCE(rnp->exp_tasks))
-               return 0;
        raw_spin_lock_irqsave_rcu_node(rnp, flags);
+       if (!rnp->exp_tasks) {
+               raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
+               return 0;
+       }
        t = list_entry(rnp->exp_tasks->prev,
                       struct task_struct, rcu_node_entry);
        list_for_each_entry_continue(t, &rnp->blkd_tasks, rcu_node_entry) {
@@ -1065,9 +1068,10 @@ unsigned long start_poll_synchronize_rcu_expedited(void)
        if (rcu_init_invoked())
                raw_spin_lock_irqsave(&rnp->exp_poll_lock, flags);
        if (!poll_state_synchronize_rcu(s)) {
-               rnp->exp_seq_poll_rq = s;
-               if (rcu_init_invoked())
+               if (rcu_init_invoked()) {
+                       rnp->exp_seq_poll_rq = s;
                        queue_work(rcu_gp_wq, &rnp->exp_poll_wq);
+               }
        }
        if (rcu_init_invoked())
                raw_spin_unlock_irqrestore(&rnp->exp_poll_lock, flags);
index 9e1c8caec5ceb983a0422954c0383a191643b3c2..f2280616f9d51bdac29f94fc2381696af790ec7a 100644 (file)
@@ -1312,6 +1312,7 @@ int rcu_nocb_cpu_offload(int cpu)
 }
 EXPORT_SYMBOL_GPL(rcu_nocb_cpu_offload);
 
+#ifdef CONFIG_RCU_LAZY
 static unsigned long
 lazy_rcu_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
 {
@@ -1360,6 +1361,7 @@ static struct shrinker lazy_rcu_shrinker = {
        .batch = 0,
        .seeks = DEFAULT_SEEKS,
 };
+#endif // #ifdef CONFIG_RCU_LAZY
 
 void __init rcu_init_nohz(void)
 {
@@ -1391,8 +1393,10 @@ void __init rcu_init_nohz(void)
        if (!rcu_state.nocb_is_setup)
                return;
 
+#ifdef CONFIG_RCU_LAZY
        if (register_shrinker(&lazy_rcu_shrinker, "rcu-lazy"))
                pr_err("Failed to register lazy_rcu shrinker!\n");
+#endif // #ifdef CONFIG_RCU_LAZY
 
        if (!cpumask_subset(rcu_nocb_mask, cpu_possible_mask)) {
                pr_info("\tNote: kernel parameter 'rcu_nocbs=', 'nohz_full', or 'isolcpus=' contains nonexistent CPUs.\n");
index af017e038b482f47b0783efe6c089b1c5c9bfab0..0d18c3969f90400e5c91e1e0132268dcff5feb65 100644 (file)
@@ -2084,6 +2084,9 @@ static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
 
 void activate_task(struct rq *rq, struct task_struct *p, int flags)
 {
+       if (task_on_rq_migrating(p))
+               flags |= ENQUEUE_MIGRATED;
+
        enqueue_task(rq, p, flags);
 
        p->on_rq = TASK_ON_RQ_QUEUED;
@@ -8414,14 +8417,14 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
        if (len & (sizeof(unsigned long)-1))
                return -EINVAL;
 
-       if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
                return -ENOMEM;
 
        ret = sched_getaffinity(pid, mask);
        if (ret == 0) {
                unsigned int retlen = min(len, cpumask_size());
 
-               if (copy_to_user(user_mask_ptr, mask, retlen))
+               if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
                        ret = -EFAULT;
                else
                        ret = retlen;
index 7a1b1f855b9635e75282913850b70ffba2006322..5f6587d94c1dd692d2d0cbcf64151e66e690de55 100644 (file)
@@ -4648,11 +4648,33 @@ static void check_spread(struct cfs_rq *cfs_rq, struct sched_entity *se)
 #endif
 }
 
+static inline bool entity_is_long_sleeper(struct sched_entity *se)
+{
+       struct cfs_rq *cfs_rq;
+       u64 sleep_time;
+
+       if (se->exec_start == 0)
+               return false;
+
+       cfs_rq = cfs_rq_of(se);
+
+       sleep_time = rq_clock_task(rq_of(cfs_rq));
+
+       /* Happen while migrating because of clock task divergence */
+       if (sleep_time <= se->exec_start)
+               return false;
+
+       sleep_time -= se->exec_start;
+       if (sleep_time > ((1ULL << 63) / scale_load_down(NICE_0_LOAD)))
+               return true;
+
+       return false;
+}
+
 static void
 place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
 {
        u64 vruntime = cfs_rq->min_vruntime;
-       u64 sleep_time;
 
        /*
         * The 'current' period is already promised to the current tasks,
@@ -4684,13 +4706,24 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
 
        /*
         * Pull vruntime of the entity being placed to the base level of
-        * cfs_rq, to prevent boosting it if placed backwards.  If the entity
-        * slept for a long time, don't even try to compare its vruntime with
-        * the base as it may be too far off and the comparison may get
-        * inversed due to s64 overflow.
-        */
-       sleep_time = rq_clock_task(rq_of(cfs_rq)) - se->exec_start;
-       if ((s64)sleep_time > 60LL * NSEC_PER_SEC)
+        * cfs_rq, to prevent boosting it if placed backwards.
+        * However, min_vruntime can advance much faster than real time, with
+        * the extreme being when an entity with the minimal weight always runs
+        * on the cfs_rq. If the waking entity slept for a long time, its
+        * vruntime difference from min_vruntime may overflow s64 and their
+        * comparison may get inversed, so ignore the entity's original
+        * vruntime in that case.
+        * The maximal vruntime speedup is given by the ratio of normal to
+        * minimal weight: scale_load_down(NICE_0_LOAD) / MIN_SHARES.
+        * When placing a migrated waking entity, its exec_start has been set
+        * from a different rq. In order to take into account a possible
+        * divergence between new and prev rq's clocks task because of irq and
+        * stolen time, we take an additional margin.
+        * So, cutting off on the sleep time of
+        *     2^63 / scale_load_down(NICE_0_LOAD) ~ 104 days
+        * should be safe.
+        */
+       if (entity_is_long_sleeper(se))
                se->vruntime = vruntime;
        else
                se->vruntime = max_vruntime(se->vruntime, vruntime);
@@ -4770,6 +4803,9 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 
        if (flags & ENQUEUE_WAKEUP)
                place_entity(cfs_rq, se, 0);
+       /* Entity has migrated, no longer consider this task hot */
+       if (flags & ENQUEUE_MIGRATED)
+               se->exec_start = 0;
 
        check_schedstat_required();
        update_stats_enqueue_fair(cfs_rq, se, flags);
@@ -7657,9 +7693,6 @@ static void migrate_task_rq_fair(struct task_struct *p, int new_cpu)
        /* Tell new CPU we are migrated */
        se->avg.last_update_time = 0;
 
-       /* We have migrated, no longer consider this task hot */
-       se->exec_start = 0;
-
        update_scan_period(p, new_cpu);
 }
 
@@ -10205,6 +10238,16 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
 
                sds->avg_load = (sds->total_load * SCHED_CAPACITY_SCALE) /
                                sds->total_capacity;
+
+               /*
+                * If the local group is more loaded than the average system
+                * load, don't try to pull any tasks.
+                */
+               if (local->avg_load >= sds->avg_load) {
+                       env->imbalance = 0;
+                       return;
+               }
+
        }
 
        /*
index 8cb28f1df29411bcc4d25e0e845aafdf28d914e9..8f6330f0e9ca35856088c0d6dafe445dfc72686f 100644 (file)
@@ -1003,8 +1003,7 @@ static void complete_signal(int sig, struct task_struct *p, enum pid_type type)
        /*
         * Now find a thread we can wake up to take the signal off the queue.
         *
-        * If the main thread wants the signal, it gets first crack.
-        * Probably the least surprising to the average bear.
+        * Try the suggested task first (may or may not be the main thread).
         */
        if (wants_signal(sig, p))
                t = p;
@@ -1970,8 +1969,24 @@ int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
 
        ret = -1;
        rcu_read_lock();
+
+       /*
+        * This function is used by POSIX timers to deliver a timer signal.
+        * Where type is PIDTYPE_PID (such as for timers with SIGEV_THREAD_ID
+        * set), the signal must be delivered to the specific thread (queues
+        * into t->pending).
+        *
+        * Where type is not PIDTYPE_PID, signals must be delivered to the
+        * process. In this case, prefer to deliver to current if it is in
+        * the same thread group as the target process, which avoids
+        * unnecessarily waking up a potentially idle task.
+        */
        t = pid_task(pid, type);
-       if (!t || !likely(lock_task_sighand(t, &flags)))
+       if (!t)
+               goto ret;
+       if (type != PIDTYPE_PID && same_thread_group(t, current))
+               t = current;
+       if (!likely(lock_task_sighand(t, &flags)))
                goto ret;
 
        ret = 1; /* the signal is ignored */
index c8a6913c067d9307c0f208196c047a2bfc9197bb..1b725510dd0fa81e7cdcf25c65e335459b7b904e 100644 (file)
@@ -793,10 +793,15 @@ static void tasklet_action_common(struct softirq_action *a,
                if (tasklet_trylock(t)) {
                        if (!atomic_read(&t->count)) {
                                if (tasklet_clear_sched(t)) {
-                                       if (t->use_callback)
+                                       if (t->use_callback) {
+                                               trace_tasklet_entry(t, t->callback);
                                                t->callback(t);
-                                       else
+                                               trace_tasklet_exit(t, t->callback);
+                                       } else {
+                                               trace_tasklet_entry(t, t->func);
                                                t->func(t->data);
+                                               trace_tasklet_exit(t, t->func);
+                                       }
                                }
                                tasklet_unlock(t);
                                continue;
index 495cd87d9bf41b718e4b9acdf7b549a971c8d032..351de791630205d0000a5c354a2f9b0ff2e5c39a 100644 (file)
@@ -664,6 +664,7 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
        struct cred *new;
        int retval;
        kuid_t kruid, keuid, ksuid;
+       bool ruid_new, euid_new, suid_new;
 
        kruid = make_kuid(ns, ruid);
        keuid = make_kuid(ns, euid);
@@ -678,25 +679,29 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
        if ((suid != (uid_t) -1) && !uid_valid(ksuid))
                return -EINVAL;
 
+       old = current_cred();
+
+       /* check for no-op */
+       if ((ruid == (uid_t) -1 || uid_eq(kruid, old->uid)) &&
+           (euid == (uid_t) -1 || (uid_eq(keuid, old->euid) &&
+                                   uid_eq(keuid, old->fsuid))) &&
+           (suid == (uid_t) -1 || uid_eq(ksuid, old->suid)))
+               return 0;
+
+       ruid_new = ruid != (uid_t) -1        && !uid_eq(kruid, old->uid) &&
+                  !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid);
+       euid_new = euid != (uid_t) -1        && !uid_eq(keuid, old->uid) &&
+                  !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid);
+       suid_new = suid != (uid_t) -1        && !uid_eq(ksuid, old->uid) &&
+                  !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid);
+       if ((ruid_new || euid_new || suid_new) &&
+           !ns_capable_setid(old->user_ns, CAP_SETUID))
+               return -EPERM;
+
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
 
-       old = current_cred();
-
-       retval = -EPERM;
-       if (!ns_capable_setid(old->user_ns, CAP_SETUID)) {
-               if (ruid != (uid_t) -1        && !uid_eq(kruid, old->uid) &&
-                   !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
-                       goto error;
-               if (euid != (uid_t) -1        && !uid_eq(keuid, old->uid) &&
-                   !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))
-                       goto error;
-               if (suid != (uid_t) -1        && !uid_eq(ksuid, old->uid) &&
-                   !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))
-                       goto error;
-       }
-
        if (ruid != (uid_t) -1) {
                new->uid = kruid;
                if (!uid_eq(kruid, old->uid)) {
@@ -761,6 +766,7 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
        struct cred *new;
        int retval;
        kgid_t krgid, kegid, ksgid;
+       bool rgid_new, egid_new, sgid_new;
 
        krgid = make_kgid(ns, rgid);
        kegid = make_kgid(ns, egid);
@@ -773,23 +779,28 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
        if ((sgid != (gid_t) -1) && !gid_valid(ksgid))
                return -EINVAL;
 
+       old = current_cred();
+
+       /* check for no-op */
+       if ((rgid == (gid_t) -1 || gid_eq(krgid, old->gid)) &&
+           (egid == (gid_t) -1 || (gid_eq(kegid, old->egid) &&
+                                   gid_eq(kegid, old->fsgid))) &&
+           (sgid == (gid_t) -1 || gid_eq(ksgid, old->sgid)))
+               return 0;
+
+       rgid_new = rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
+                  !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid);
+       egid_new = egid != (gid_t) -1        && !gid_eq(kegid, old->gid) &&
+                  !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid);
+       sgid_new = sgid != (gid_t) -1        && !gid_eq(ksgid, old->gid) &&
+                  !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid);
+       if ((rgid_new || egid_new || sgid_new) &&
+           !ns_capable_setid(old->user_ns, CAP_SETGID))
+               return -EPERM;
+
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
-       old = current_cred();
-
-       retval = -EPERM;
-       if (!ns_capable_setid(old->user_ns, CAP_SETGID)) {
-               if (rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
-                   !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
-                       goto error;
-               if (egid != (gid_t) -1        && !gid_eq(kegid, old->gid) &&
-                   !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid))
-                       goto error;
-               if (sgid != (gid_t) -1        && !gid_eq(ksgid, old->gid) &&
-                   !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid))
-                       goto error;
-       }
 
        if (rgid != (gid_t) -1)
                new->gid = krgid;
index 2f5e9b34022c51b1cfed38ee0ddbeb93c2ea4a4e..e9c6f9d0e42ce42e837e9d83c046031ff797a4f8 100644 (file)
@@ -846,6 +846,8 @@ static u64 collect_timerqueue(struct timerqueue_head *head,
                        return expires;
 
                ctmr->firing = 1;
+               /* See posix_cpu_timer_wait_running() */
+               rcu_assign_pointer(ctmr->handling, current);
                cpu_timer_dequeue(ctmr);
                list_add_tail(&ctmr->elist, firing);
        }
@@ -1161,7 +1163,49 @@ static void handle_posix_cpu_timers(struct task_struct *tsk);
 #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK
 static void posix_cpu_timers_work(struct callback_head *work)
 {
+       struct posix_cputimers_work *cw = container_of(work, typeof(*cw), work);
+
+       mutex_lock(&cw->mutex);
        handle_posix_cpu_timers(current);
+       mutex_unlock(&cw->mutex);
+}
+
+/*
+ * Invoked from the posix-timer core when a cancel operation failed because
+ * the timer is marked firing. The caller holds rcu_read_lock(), which
+ * protects the timer and the task which is expiring it from being freed.
+ */
+static void posix_cpu_timer_wait_running(struct k_itimer *timr)
+{
+       struct task_struct *tsk = rcu_dereference(timr->it.cpu.handling);
+
+       /* Has the handling task completed expiry already? */
+       if (!tsk)
+               return;
+
+       /* Ensure that the task cannot go away */
+       get_task_struct(tsk);
+       /* Now drop the RCU protection so the mutex can be locked */
+       rcu_read_unlock();
+       /* Wait on the expiry mutex */
+       mutex_lock(&tsk->posix_cputimers_work.mutex);
+       /* Release it immediately again. */
+       mutex_unlock(&tsk->posix_cputimers_work.mutex);
+       /* Drop the task reference. */
+       put_task_struct(tsk);
+       /* Relock RCU so the callsite is balanced */
+       rcu_read_lock();
+}
+
+static void posix_cpu_timer_wait_running_nsleep(struct k_itimer *timr)
+{
+       /* Ensure that timr->it.cpu.handling task cannot go away */
+       rcu_read_lock();
+       spin_unlock_irq(&timr->it_lock);
+       posix_cpu_timer_wait_running(timr);
+       rcu_read_unlock();
+       /* @timr is on stack and is valid */
+       spin_lock_irq(&timr->it_lock);
 }
 
 /*
@@ -1177,6 +1221,7 @@ void clear_posix_cputimers_work(struct task_struct *p)
               sizeof(p->posix_cputimers_work.work));
        init_task_work(&p->posix_cputimers_work.work,
                       posix_cpu_timers_work);
+       mutex_init(&p->posix_cputimers_work.mutex);
        p->posix_cputimers_work.scheduled = false;
 }
 
@@ -1255,6 +1300,18 @@ static inline void __run_posix_cpu_timers(struct task_struct *tsk)
        lockdep_posixtimer_exit();
 }
 
+static void posix_cpu_timer_wait_running(struct k_itimer *timr)
+{
+       cpu_relax();
+}
+
+static void posix_cpu_timer_wait_running_nsleep(struct k_itimer *timr)
+{
+       spin_unlock_irq(&timr->it_lock);
+       cpu_relax();
+       spin_lock_irq(&timr->it_lock);
+}
+
 static inline bool posix_cpu_timers_work_scheduled(struct task_struct *tsk)
 {
        return false;
@@ -1363,6 +1420,8 @@ static void handle_posix_cpu_timers(struct task_struct *tsk)
                 */
                if (likely(cpu_firing >= 0))
                        cpu_timer_fire(timer);
+               /* See posix_cpu_timer_wait_running() */
+               rcu_assign_pointer(timer->it.cpu.handling, NULL);
                spin_unlock(&timer->it_lock);
        }
 }
@@ -1497,23 +1556,16 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
                expires = cpu_timer_getexpires(&timer.it.cpu);
                error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);
                if (!error) {
-                       /*
-                        * Timer is now unarmed, deletion can not fail.
-                        */
+                       /* Timer is now unarmed, deletion can not fail. */
                        posix_cpu_timer_del(&timer);
+               } else {
+                       while (error == TIMER_RETRY) {
+                               posix_cpu_timer_wait_running_nsleep(&timer);
+                               error = posix_cpu_timer_del(&timer);
+                       }
                }
-               spin_unlock_irq(&timer.it_lock);
 
-               while (error == TIMER_RETRY) {
-                       /*
-                        * We need to handle case when timer was or is in the
-                        * middle of firing. In other cases we already freed
-                        * resources.
-                        */
-                       spin_lock_irq(&timer.it_lock);
-                       error = posix_cpu_timer_del(&timer);
-                       spin_unlock_irq(&timer.it_lock);
-               }
+               spin_unlock_irq(&timer.it_lock);
 
                if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
                        /*
@@ -1623,6 +1675,7 @@ const struct k_clock clock_posix_cpu = {
        .timer_del              = posix_cpu_timer_del,
        .timer_get              = posix_cpu_timer_get,
        .timer_rearm            = posix_cpu_timer_rearm,
+       .timer_wait_running     = posix_cpu_timer_wait_running,
 };
 
 const struct k_clock clock_process = {
index 0c8a87a11b39df91a8aa297d3852d957e98a37ac..808a247205a9a8875ac443da02f8065907d6b8c0 100644 (file)
@@ -846,6 +846,10 @@ static struct k_itimer *timer_wait_running(struct k_itimer *timer,
        rcu_read_lock();
        unlock_timer(timer, *flags);
 
+       /*
+        * kc->timer_wait_running() might drop RCU lock. So @timer
+        * cannot be touched anymore after the function returns!
+        */
        if (!WARN_ON_ONCE(!kc->timer_wait_running))
                kc->timer_wait_running(timer);
 
index 46789356f856eb31ed156479694625059172c599..65b8658da829eb6dbe955e41fb71dece4966d40b 100644 (file)
@@ -218,9 +218,19 @@ static void tick_setup_device(struct tick_device *td,
                 * this cpu:
                 */
                if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) {
+                       ktime_t next_p;
+                       u32 rem;
+
                        tick_do_timer_cpu = cpu;
 
-                       tick_next_period = ktime_get();
+                       next_p = ktime_get();
+                       div_u64_rem(next_p, TICK_NSEC, &rem);
+                       if (rem) {
+                               next_p -= rem;
+                               next_p += TICK_NSEC;
+                       }
+
+                       tick_next_period = next_p;
 #ifdef CONFIG_NO_HZ_FULL
                        /*
                         * The boot CPU may be nohz_full, in which case set
index b0e3c9205946f7e8503c574ce6d1e133b9d94412..52254679ec4898d356d1be2e3b1d0d3ecc5dba76 100644 (file)
@@ -281,6 +281,11 @@ static bool check_tick_dependency(atomic_t *dep)
                return true;
        }
 
+       if (val & TICK_DEP_MASK_RCU_EXP) {
+               trace_tick_stop(0, TICK_DEP_MASK_RCU_EXP);
+               return true;
+       }
+
        return false;
 }
 
@@ -527,7 +532,7 @@ void __init tick_nohz_full_setup(cpumask_var_t cpumask)
        tick_nohz_full_running = true;
 }
 
-static int tick_nohz_cpu_down(unsigned int cpu)
+bool tick_nohz_cpu_hotpluggable(unsigned int cpu)
 {
        /*
         * The tick_do_timer_cpu CPU handles housekeeping duty (unbound
@@ -535,8 +540,13 @@ static int tick_nohz_cpu_down(unsigned int cpu)
         * CPUs. It must remain online when nohz full is enabled.
         */
        if (tick_nohz_full_running && tick_do_timer_cpu == cpu)
-               return -EBUSY;
-       return 0;
+               return false;
+       return true;
+}
+
+static int tick_nohz_cpu_down(unsigned int cpu)
+{
+       return tick_nohz_cpu_hotpluggable(cpu) ? 0 : -EBUSY;
 }
 
 void __init tick_nohz_init(void)
@@ -637,43 +647,67 @@ static void tick_nohz_update_jiffies(ktime_t now)
        touch_softlockup_watchdog_sched();
 }
 
-/*
- * Updates the per-CPU time idle statistics counters
- */
-static void
-update_ts_time_stats(int cpu, struct tick_sched *ts, ktime_t now, u64 *last_update_time)
+static void tick_nohz_stop_idle(struct tick_sched *ts, ktime_t now)
 {
        ktime_t delta;
 
-       if (ts->idle_active) {
-               delta = ktime_sub(now, ts->idle_entrytime);
-               if (nr_iowait_cpu(cpu) > 0)
-                       ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta);
-               else
-                       ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
-               ts->idle_entrytime = now;
-       }
+       if (WARN_ON_ONCE(!ts->idle_active))
+               return;
 
-       if (last_update_time)
-               *last_update_time = ktime_to_us(now);
+       delta = ktime_sub(now, ts->idle_entrytime);
 
-}
+       write_seqcount_begin(&ts->idle_sleeptime_seq);
+       if (nr_iowait_cpu(smp_processor_id()) > 0)
+               ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta);
+       else
+               ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta);
 
-static void tick_nohz_stop_idle(struct tick_sched *ts, ktime_t now)
-{
-       update_ts_time_stats(smp_processor_id(), ts, now, NULL);
+       ts->idle_entrytime = now;
        ts->idle_active = 0;
+       write_seqcount_end(&ts->idle_sleeptime_seq);
 
        sched_clock_idle_wakeup_event();
 }
 
 static void tick_nohz_start_idle(struct tick_sched *ts)
 {
+       write_seqcount_begin(&ts->idle_sleeptime_seq);
        ts->idle_entrytime = ktime_get();
        ts->idle_active = 1;
+       write_seqcount_end(&ts->idle_sleeptime_seq);
+
        sched_clock_idle_sleep_event();
 }
 
+static u64 get_cpu_sleep_time_us(struct tick_sched *ts, ktime_t *sleeptime,
+                                bool compute_delta, u64 *last_update_time)
+{
+       ktime_t now, idle;
+       unsigned int seq;
+
+       if (!tick_nohz_active)
+               return -1;
+
+       now = ktime_get();
+       if (last_update_time)
+               *last_update_time = ktime_to_us(now);
+
+       do {
+               seq = read_seqcount_begin(&ts->idle_sleeptime_seq);
+
+               if (ts->idle_active && compute_delta) {
+                       ktime_t delta = ktime_sub(now, ts->idle_entrytime);
+
+                       idle = ktime_add(*sleeptime, delta);
+               } else {
+                       idle = *sleeptime;
+               }
+       } while (read_seqcount_retry(&ts->idle_sleeptime_seq, seq));
+
+       return ktime_to_us(idle);
+
+}
+
 /**
  * get_cpu_idle_time_us - get the total idle time of a CPU
  * @cpu: CPU number to query
@@ -681,7 +715,10 @@ static void tick_nohz_start_idle(struct tick_sched *ts)
  * counters if NULL.
  *
  * Return the cumulative idle time (since boot) for a given
- * CPU, in microseconds.
+ * CPU, in microseconds. Note this is partially broken due to
+ * the counter of iowait tasks that can be remotely updated without
+ * any synchronization. Therefore it is possible to observe backward
+ * values within two consecutive reads.
  *
  * This time is measured via accounting rather than sampling,
  * and is as accurate as ktime_get() is.
@@ -691,27 +728,9 @@ static void tick_nohz_start_idle(struct tick_sched *ts)
 u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
 {
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
-       ktime_t now, idle;
-
-       if (!tick_nohz_active)
-               return -1;
-
-       now = ktime_get();
-       if (last_update_time) {
-               update_ts_time_stats(cpu, ts, now, last_update_time);
-               idle = ts->idle_sleeptime;
-       } else {
-               if (ts->idle_active && !nr_iowait_cpu(cpu)) {
-                       ktime_t delta = ktime_sub(now, ts->idle_entrytime);
-
-                       idle = ktime_add(ts->idle_sleeptime, delta);
-               } else {
-                       idle = ts->idle_sleeptime;
-               }
-       }
-
-       return ktime_to_us(idle);
 
+       return get_cpu_sleep_time_us(ts, &ts->idle_sleeptime,
+                                    !nr_iowait_cpu(cpu), last_update_time);
 }
 EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
 
@@ -722,7 +741,10 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
  * counters if NULL.
  *
  * Return the cumulative iowait time (since boot) for a given
- * CPU, in microseconds.
+ * CPU, in microseconds. Note this is partially broken due to
+ * the counter of iowait tasks that can be remotely updated without
+ * any synchronization. Therefore it is possible to observe backward
+ * values within two consecutive reads.
  *
  * This time is measured via accounting rather than sampling,
  * and is as accurate as ktime_get() is.
@@ -732,26 +754,9 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
 u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
 {
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
-       ktime_t now, iowait;
-
-       if (!tick_nohz_active)
-               return -1;
-
-       now = ktime_get();
-       if (last_update_time) {
-               update_ts_time_stats(cpu, ts, now, last_update_time);
-               iowait = ts->iowait_sleeptime;
-       } else {
-               if (ts->idle_active && nr_iowait_cpu(cpu) > 0) {
-                       ktime_t delta = ktime_sub(now, ts->idle_entrytime);
 
-                       iowait = ktime_add(ts->iowait_sleeptime, delta);
-               } else {
-                       iowait = ts->iowait_sleeptime;
-               }
-       }
-
-       return ktime_to_us(iowait);
+       return get_cpu_sleep_time_us(ts, &ts->iowait_sleeptime,
+                                    nr_iowait_cpu(cpu), last_update_time);
 }
 EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
 
@@ -1084,10 +1089,16 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
        return true;
 }
 
-static void __tick_nohz_idle_stop_tick(struct tick_sched *ts)
+/**
+ * tick_nohz_idle_stop_tick - stop the idle tick from the idle task
+ *
+ * When the next event is more than a tick into the future, stop the idle tick
+ */
+void tick_nohz_idle_stop_tick(void)
 {
-       ktime_t expires;
+       struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
        int cpu = smp_processor_id();
+       ktime_t expires;
 
        /*
         * If tick_nohz_get_sleep_length() ran tick_nohz_next_event(), the
@@ -1119,16 +1130,6 @@ static void __tick_nohz_idle_stop_tick(struct tick_sched *ts)
        }
 }
 
-/**
- * tick_nohz_idle_stop_tick - stop the idle tick from the idle task
- *
- * When the next event is more than a tick into the future, stop the idle tick
- */
-void tick_nohz_idle_stop_tick(void)
-{
-       __tick_nohz_idle_stop_tick(this_cpu_ptr(&tick_cpu_sched));
-}
-
 void tick_nohz_idle_retain_tick(void)
 {
        tick_nohz_retain_tick(this_cpu_ptr(&tick_cpu_sched));
index 504649513399ba3feed83a1f55f87ef1cb255aa5..5ed5a9d41d5a7a9489f954635b64a5bf04c0cf6e 100644 (file)
@@ -22,65 +22,82 @@ enum tick_nohz_mode {
 
 /**
  * struct tick_sched - sched tick emulation and no idle tick control/stats
- * @sched_timer:       hrtimer to schedule the periodic tick in high
- *                     resolution mode
- * @check_clocks:      Notification mechanism about clocksource changes
- * @nohz_mode:         Mode - one state of tick_nohz_mode
+ *
  * @inidle:            Indicator that the CPU is in the tick idle mode
  * @tick_stopped:      Indicator that the idle tick has been stopped
  * @idle_active:       Indicator that the CPU is actively in the tick idle mode;
  *                     it is reset during irq handling phases.
- * @do_timer_lst:      CPU was the last one doing do_timer before going idle
+ * @do_timer_last:     CPU was the last one doing do_timer before going idle
  * @got_idle_tick:     Tick timer function has run with @inidle set
+ * @stalled_jiffies:   Number of stalled jiffies detected across ticks
+ * @last_tick_jiffies: Value of jiffies seen on last tick
+ * @sched_timer:       hrtimer to schedule the periodic tick in high
+ *                     resolution mode
  * @last_tick:         Store the last tick expiry time when the tick
  *                     timer is modified for nohz sleeps. This is necessary
  *                     to resume the tick timer operation in the timeline
  *                     when the CPU returns from nohz sleep.
  * @next_tick:         Next tick to be fired when in dynticks mode.
  * @idle_jiffies:      jiffies at the entry to idle for idle time accounting
+ * @idle_waketime:     Time when the idle was interrupted
+ * @idle_entrytime:    Time when the idle call was entered
+ * @nohz_mode:         Mode - one state of tick_nohz_mode
+ * @last_jiffies:      Base jiffies snapshot when next event was last computed
+ * @timer_expires_base:        Base time clock monotonic for @timer_expires
+ * @timer_expires:     Anticipated timer expiration time (in case sched tick is stopped)
+ * @next_timer:                Expiry time of next expiring timer for debugging purpose only
+ * @idle_expires:      Next tick in idle, for debugging purpose only
  * @idle_calls:                Total number of idle calls
  * @idle_sleeps:       Number of idle calls, where the sched tick was stopped
- * @idle_entrytime:    Time when the idle call was entered
- * @idle_waketime:     Time when the idle was interrupted
  * @idle_exittime:     Time when the idle state was left
  * @idle_sleeptime:    Sum of the time slept in idle with sched tick stopped
  * @iowait_sleeptime:  Sum of the time slept in idle with sched tick stopped, with IO outstanding
- * @timer_expires:     Anticipated timer expiration time (in case sched tick is stopped)
- * @timer_expires_base:        Base time clock monotonic for @timer_expires
- * @next_timer:                Expiry time of next expiring timer for debugging purpose only
  * @tick_dep_mask:     Tick dependency mask - is set, if someone needs the tick
- * @last_tick_jiffies: Value of jiffies seen on last tick
- * @stalled_jiffies:   Number of stalled jiffies detected across ticks
+ * @check_clocks:      Notification mechanism about clocksource changes
  */
 struct tick_sched {
-       struct hrtimer                  sched_timer;
-       unsigned long                   check_clocks;
-       enum tick_nohz_mode             nohz_mode;
-
+       /* Common flags */
        unsigned int                    inidle          : 1;
        unsigned int                    tick_stopped    : 1;
        unsigned int                    idle_active     : 1;
        unsigned int                    do_timer_last   : 1;
        unsigned int                    got_idle_tick   : 1;
 
+       /* Tick handling: jiffies stall check */
+       unsigned int                    stalled_jiffies;
+       unsigned long                   last_tick_jiffies;
+
+       /* Tick handling */
+       struct hrtimer                  sched_timer;
        ktime_t                         last_tick;
        ktime_t                         next_tick;
        unsigned long                   idle_jiffies;
-       unsigned long                   idle_calls;
-       unsigned long                   idle_sleeps;
-       ktime_t                         idle_entrytime;
        ktime_t                         idle_waketime;
-       ktime_t                         idle_exittime;
-       ktime_t                         idle_sleeptime;
-       ktime_t                         iowait_sleeptime;
+
+       /* Idle entry */
+       seqcount_t                      idle_sleeptime_seq;
+       ktime_t                         idle_entrytime;
+
+       /* Tick stop */
+       enum tick_nohz_mode             nohz_mode;
        unsigned long                   last_jiffies;
-       u64                             timer_expires;
        u64                             timer_expires_base;
+       u64                             timer_expires;
        u64                             next_timer;
        ktime_t                         idle_expires;
+       unsigned long                   idle_calls;
+       unsigned long                   idle_sleeps;
+
+       /* Idle exit */
+       ktime_t                         idle_exittime;
+       ktime_t                         idle_sleeptime;
+       ktime_t                         iowait_sleeptime;
+
+       /* Full dynticks handling */
        atomic_t                        tick_dep_mask;
-       unsigned long                   last_tick_jiffies;
-       unsigned int                    stalled_jiffies;
+
+       /* Clocksource changes */
+       unsigned long                   check_clocks;
 };
 
 extern struct tick_sched *tick_get_tick_sched(int cpu);
index 29baa97d0d534284237a4376dda1d88aca6f7c06..c67bcc89a77168cd9d9d7db3e0381db4ebdb86b7 100644 (file)
@@ -1564,7 +1564,8 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
        key.flags = end;        /* overload flags, as it is unsigned long */
 
        for (pg = ftrace_pages_start; pg; pg = pg->next) {
-               if (end < pg->records[0].ip ||
+               if (pg->index == 0 ||
+                   end < pg->records[0].ip ||
                    start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
                        continue;
                rec = bsearch(&key, pg->records, pg->index,
@@ -2591,7 +2592,7 @@ static void call_direct_funcs(unsigned long ip, unsigned long pip,
        arch_ftrace_set_direct_caller(fregs, addr);
 }
 
-struct ftrace_ops direct_ops = {
+static struct ftrace_ops direct_ops = {
        .func           = call_direct_funcs,
        .flags          = FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS
                          | FTRACE_OPS_FL_PERMANENT,
@@ -5666,12 +5667,15 @@ int modify_ftrace_direct(unsigned long ip,
                ret = 0;
        }
 
-       if (unlikely(ret && new_direct)) {
-               direct->count++;
-               list_del_rcu(&new_direct->next);
-               synchronize_rcu_tasks();
-               kfree(new_direct);
-               ftrace_direct_func_count--;
+       if (ret) {
+               direct->addr = old_addr;
+               if (unlikely(new_direct)) {
+                       direct->count++;
+                       list_del_rcu(&new_direct->next);
+                       synchronize_rcu_tasks();
+                       kfree(new_direct);
+                       ftrace_direct_func_count--;
+               }
        }
 
  out_unlock:
index 4850fdfe27f1cb040118eed41c8a3036c4926d2c..5a4b722b50451bfdee42769a6d3be39c055690d1 100644 (file)
@@ -146,7 +146,7 @@ static int __init test_gen_kprobe_cmd(void)
        if (trace_event_file_is_valid(gen_kprobe_test))
                gen_kprobe_test = NULL;
        /* We got an error after creating the event, delete it */
-       ret = kprobe_event_delete("gen_kprobe_test");
+       kprobe_event_delete("gen_kprobe_test");
        goto out;
 }
 
@@ -211,7 +211,7 @@ static int __init test_gen_kretprobe_cmd(void)
        if (trace_event_file_is_valid(gen_kretprobe_test))
                gen_kretprobe_test = NULL;
        /* We got an error after creating the event, delete it */
-       ret = kprobe_event_delete("gen_kretprobe_test");
+       kprobe_event_delete("gen_kretprobe_test");
        goto out;
 }
 
index af50d931b020227991e2e63f4e961c9d0618323f..76a2d91eecad9f302fb30e24c7fc4803ea0eeee5 100644 (file)
@@ -354,10 +354,6 @@ static void rb_init_page(struct buffer_data_page *bpage)
        local_set(&bpage->commit, 0);
 }
 
-/*
- * Also stolen from mm/slob.c. Thanks to Mathieu Desnoyers for pointing
- * this issue out.
- */
 static void free_buffer_page(struct buffer_page *bpage)
 {
        free_page((unsigned long)bpage->page);
@@ -3102,6 +3098,10 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
                if (RB_WARN_ON(cpu_buffer,
                               rb_is_reader_page(cpu_buffer->tail_page)))
                        return;
+               /*
+                * No need for a memory barrier here, as the update
+                * of the tail_page did it for this page.
+                */
                local_set(&cpu_buffer->commit_page->page->commit,
                          rb_page_write(cpu_buffer->commit_page));
                rb_inc_page(&cpu_buffer->commit_page);
@@ -3111,6 +3111,8 @@ rb_set_commit_to_write(struct ring_buffer_per_cpu *cpu_buffer)
        while (rb_commit_index(cpu_buffer) !=
               rb_page_write(cpu_buffer->commit_page)) {
 
+               /* Make sure the readers see the content of what is committed. */
+               smp_wmb();
                local_set(&cpu_buffer->commit_page->page->commit,
                          rb_page_write(cpu_buffer->commit_page));
                RB_WARN_ON(cpu_buffer,
@@ -4688,7 +4690,12 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
 
        /*
         * Make sure we see any padding after the write update
-        * (see rb_reset_tail())
+        * (see rb_reset_tail()).
+        *
+        * In addition, a writer may be writing on the reader page
+        * if the page has not been fully filled, so the read barrier
+        * is also needed to make sure we see the content of what is
+        * committed by the writer (see rb_set_commit_to_write()).
         */
        smp_rmb();
 
index 45551c7b4c36588fac4378f04fe4a4d7ef8e36a9..36a6037823cd9db9ae712258201fc632c437a425 100644 (file)
@@ -1149,22 +1149,22 @@ static void tracing_snapshot_instance_cond(struct trace_array *tr,
        unsigned long flags;
 
        if (in_nmi()) {
-               internal_trace_puts("*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
-               internal_trace_puts("*** snapshot is being ignored        ***\n");
+               trace_array_puts(tr, "*** SNAPSHOT CALLED FROM NMI CONTEXT ***\n");
+               trace_array_puts(tr, "*** snapshot is being ignored        ***\n");
                return;
        }
 
        if (!tr->allocated_snapshot) {
-               internal_trace_puts("*** SNAPSHOT NOT ALLOCATED ***\n");
-               internal_trace_puts("*** stopping trace here!   ***\n");
-               tracing_off();
+               trace_array_puts(tr, "*** SNAPSHOT NOT ALLOCATED ***\n");
+               trace_array_puts(tr, "*** stopping trace here!   ***\n");
+               tracer_tracing_off(tr);
                return;
        }
 
        /* Note, snapshot can not be used when the tracer uses it */
        if (tracer->use_max_tr) {
-               internal_trace_puts("*** LATENCY TRACER ACTIVE ***\n");
-               internal_trace_puts("*** Can not use snapshot (sorry) ***\n");
+               trace_array_puts(tr, "*** LATENCY TRACER ACTIVE ***\n");
+               trace_array_puts(tr, "*** Can not use snapshot (sorry) ***\n");
                return;
        }
 
@@ -5167,6 +5167,8 @@ loff_t tracing_lseek(struct file *file, loff_t offset, int whence)
 static const struct file_operations tracing_fops = {
        .open           = tracing_open,
        .read           = seq_read,
+       .read_iter      = seq_read_iter,
+       .splice_read    = generic_file_splice_read,
        .write          = tracing_write_stub,
        .llseek         = tracing_lseek,
        .release        = tracing_release,
@@ -9514,6 +9516,7 @@ static int __remove_instance(struct trace_array *tr)
        tracefs_remove(tr->dir);
        free_percpu(tr->last_func_repeats);
        free_trace_buffers(tr);
+       clear_tracing_err_log(tr);
 
        for (i = 0; i < tr->nr_topts; i++) {
                kfree(tr->topts[i].topts);
@@ -10391,19 +10394,20 @@ out:
 
 void __init ftrace_boot_snapshot(void)
 {
+#ifdef CONFIG_TRACER_MAX_TRACE
        struct trace_array *tr;
 
-       if (snapshot_at_boot) {
-               tracing_snapshot();
-               internal_trace_puts("** Boot snapshot taken **\n");
-       }
+       if (!snapshot_at_boot)
+               return;
 
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
-               if (tr == &global_trace)
+               if (!tr->allocated_snapshot)
                        continue;
-               trace_array_puts(tr, "** Boot snapshot taken **\n");
+
                tracing_snapshot_instance(tr);
+               trace_array_puts(tr, "** Boot snapshot taken **\n");
        }
+#endif
 }
 
 void __init early_trace_init(void)
index 89877a18f93307fce29789166b68a60d9a7f0c1e..486cca3c2b75450f23f8b680045421cf234d232f 100644 (file)
@@ -1331,6 +1331,9 @@ static const char *hist_field_name(struct hist_field *field,
 {
        const char *field_name = "";
 
+       if (WARN_ON_ONCE(!field))
+               return field_name;
+
        if (level > 1)
                return field_name;
 
@@ -4235,6 +4238,15 @@ static int __create_val_field(struct hist_trigger_data *hist_data,
                goto out;
        }
 
+       /* Some types cannot be a value */
+       if (hist_field->flags & (HIST_FIELD_FL_GRAPH | HIST_FIELD_FL_PERCENT |
+                                HIST_FIELD_FL_BUCKET | HIST_FIELD_FL_LOG2 |
+                                HIST_FIELD_FL_SYM | HIST_FIELD_FL_SYM_OFFSET |
+                                HIST_FIELD_FL_SYSCALL | HIST_FIELD_FL_STACKTRACE)) {
+               hist_err(file->tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(field_str));
+               ret = -EINVAL;
+       }
+
        hist_data->fields[val_idx] = hist_field;
 
        ++hist_data->n_vals;
index 46d0abb32d0fa7c031a0fe33bd9d6e4fb12b9646..d6a70aff24101604016c47f2a8d1d0ae30530a76 100644 (file)
@@ -44,14 +44,21 @@ enum { ERRORS };
 
 static const char *err_text[] = { ERRORS };
 
+static DEFINE_MUTEX(lastcmd_mutex);
 static char *last_cmd;
 
 static int errpos(const char *str)
 {
+       int ret = 0;
+
+       mutex_lock(&lastcmd_mutex);
        if (!str || !last_cmd)
-               return 0;
+               goto out;
 
-       return err_pos(last_cmd, str);
+       ret = err_pos(last_cmd, str);
+ out:
+       mutex_unlock(&lastcmd_mutex);
+       return ret;
 }
 
 static void last_cmd_set(const char *str)
@@ -59,18 +66,22 @@ static void last_cmd_set(const char *str)
        if (!str)
                return;
 
+       mutex_lock(&lastcmd_mutex);
        kfree(last_cmd);
-
        last_cmd = kstrdup(str, GFP_KERNEL);
+       mutex_unlock(&lastcmd_mutex);
 }
 
 static void synth_err(u8 err_type, u16 err_pos)
 {
+       mutex_lock(&lastcmd_mutex);
        if (!last_cmd)
-               return;
+               goto out;
 
        tracing_log_err(NULL, "synthetic_events", last_cmd, err_text,
                        err_type, err_pos);
+ out:
+       mutex_unlock(&lastcmd_mutex);
 }
 
 static int create_synth_event(const char *raw_command);
index d440ddd5fd8b29adf605075004fc5edd9a7ee17c..2f37a6e68aa9f851f19b968eeafdb1034d3efae2 100644 (file)
@@ -339,7 +339,7 @@ static void move_to_next_cpu(void)
        cpumask_clear(current_mask);
        cpumask_set_cpu(next_cpu, current_mask);
 
-       sched_setaffinity(0, current_mask);
+       set_cpus_allowed_ptr(current, current_mask);
        return;
 
  change_mode:
@@ -446,7 +446,7 @@ static int start_single_kthread(struct trace_array *tr)
 
        }
 
-       sched_setaffinity(kthread->pid, current_mask);
+       set_cpus_allowed_ptr(kthread, current_mask);
 
        kdata->kthread = kthread;
        wake_up_process(kthread);
@@ -492,6 +492,10 @@ static int start_cpu_kthread(unsigned int cpu)
 {
        struct task_struct *kthread;
 
+       /* Do not start a new hwlatd thread if it is already running */
+       if (per_cpu(hwlat_per_cpu_data, cpu).kthread)
+               return 0;
+
        kthread = kthread_run_on_cpu(kthread_fn, NULL, cpu, "hwlatd/%u");
        if (IS_ERR(kthread)) {
                pr_err(BANNER "could not start sampling thread\n");
@@ -584,9 +588,6 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
         */
        cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask);
 
-       for_each_online_cpu(cpu)
-               per_cpu(hwlat_per_cpu_data, cpu).kthread = NULL;
-
        for_each_cpu(cpu, current_mask) {
                retval = start_cpu_kthread(cpu);
                if (retval)
index 04f0fdae19a1c0382d6e0ec4f415a36d86d610f7..efbbec2caff832898f45e6f250c5bc43e26f04e9 100644 (file)
@@ -159,7 +159,7 @@ static void osnoise_unregister_instance(struct trace_array *tr)
        if (!found)
                return;
 
-       kvfree_rcu(inst);
+       kvfree_rcu_mightsleep(inst);
 }
 
 /*
@@ -217,7 +217,7 @@ struct osnoise_variables {
 /*
  * Per-cpu runtime information.
  */
-DEFINE_PER_CPU(struct osnoise_variables, per_cpu_osnoise_var);
+static DEFINE_PER_CPU(struct osnoise_variables, per_cpu_osnoise_var);
 
 /*
  * this_cpu_osn_var - Return the per-cpu osnoise_variables on its relative CPU
@@ -240,7 +240,7 @@ struct timerlat_variables {
        u64                     count;
 };
 
-DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var);
+static DEFINE_PER_CPU(struct timerlat_variables, per_cpu_timerlat_var);
 
 /*
  * this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU
@@ -332,7 +332,7 @@ struct timerlat_sample {
 /*
  * Protect the interface.
  */
-struct mutex interface_lock;
+static struct mutex interface_lock;
 
 /*
  * Tracer data.
@@ -1296,7 +1296,7 @@ static void notify_new_max_latency(u64 latency)
        rcu_read_lock();
        list_for_each_entry_rcu(inst, &osnoise_instances, list) {
                tr = inst->tr;
-               if (tr->max_latency < latency) {
+               if (tracer_tracing_is_on(tr) && tr->max_latency < latency) {
                        tr->max_latency = latency;
                        latency_fsnotify(tr);
                }
@@ -1738,6 +1738,8 @@ static int timerlat_main(void *data)
 
                trace_timerlat_sample(&s);
 
+               notify_new_max_latency(diff);
+
                timerlat_dump_stack(time_to_us(diff));
 
                tlat->tracing_thread = false;
@@ -2239,8 +2241,8 @@ static struct trace_min_max_param osnoise_print_stack = {
 /*
  * osnoise/timerlat_period: min 100 us, max 1 s
  */
-u64 timerlat_min_period = 100;
-u64 timerlat_max_period = 1000000;
+static u64 timerlat_min_period = 100;
+static u64 timerlat_max_period = 1000000;
 static struct trace_min_max_param timerlat_period = {
        .lock   = &interface_lock,
        .val    = &osnoise_data.timerlat_period,
index 20d0c4a9763324c1f411f00b552d2b0f0e13f31b..2d261667829504b36c7e515e693a371f71515ef5 100644 (file)
@@ -1172,7 +1172,7 @@ int trace_probe_remove_file(struct trace_probe *tp,
                return -ENOENT;
 
        list_del_rcu(&link->list);
-       kvfree_rcu(link);
+       kvfree_rcu_mightsleep(link);
 
        if (list_empty(&tp->event->files))
                trace_probe_clear_flag(tp, TP_FLAG_TRACE);
diff --git a/kernel/vhost_task.c b/kernel/vhost_task.c
new file mode 100644 (file)
index 0000000..b7cbd66
--- /dev/null
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Oracle Corporation
+ */
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/sched/task.h>
+#include <linux/sched/vhost_task.h>
+#include <linux/sched/signal.h>
+
+enum vhost_task_flags {
+       VHOST_TASK_FLAGS_STOP,
+};
+
+static int vhost_task_fn(void *data)
+{
+       struct vhost_task *vtsk = data;
+       int ret;
+
+       ret = vtsk->fn(vtsk->data);
+       complete(&vtsk->exited);
+       do_exit(ret);
+}
+
+/**
+ * vhost_task_stop - stop a vhost_task
+ * @vtsk: vhost_task to stop
+ *
+ * Callers must call vhost_task_should_stop and return from their worker
+ * function when it returns true;
+ */
+void vhost_task_stop(struct vhost_task *vtsk)
+{
+       pid_t pid = vtsk->task->pid;
+
+       set_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
+       wake_up_process(vtsk->task);
+       /*
+        * Make sure vhost_task_fn is no longer accessing the vhost_task before
+        * freeing it below. If userspace crashed or exited without closing,
+        * then the vhost_task->task could already be marked dead so
+        * kernel_wait will return early.
+        */
+       wait_for_completion(&vtsk->exited);
+       /*
+        * If we are just closing/removing a device and the parent process is
+        * not exiting then reap the task.
+        */
+       kernel_wait4(pid, NULL, __WCLONE, NULL);
+       kfree(vtsk);
+}
+EXPORT_SYMBOL_GPL(vhost_task_stop);
+
+/**
+ * vhost_task_should_stop - should the vhost task return from the work function
+ * @vtsk: vhost_task to stop
+ */
+bool vhost_task_should_stop(struct vhost_task *vtsk)
+{
+       return test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
+}
+EXPORT_SYMBOL_GPL(vhost_task_should_stop);
+
+/**
+ * vhost_task_create - create a copy of a process to be used by the kernel
+ * @fn: thread stack
+ * @arg: data to be passed to fn
+ * @name: the thread's name
+ *
+ * This returns a specialized task for use by the vhost layer or NULL on
+ * failure. The returned task is inactive, and the caller must fire it up
+ * through vhost_task_start().
+ */
+struct vhost_task *vhost_task_create(int (*fn)(void *), void *arg,
+                                    const char *name)
+{
+       struct kernel_clone_args args = {
+               .flags          = CLONE_FS | CLONE_UNTRACED | CLONE_VM,
+               .exit_signal    = 0,
+               .fn             = vhost_task_fn,
+               .name           = name,
+               .user_worker    = 1,
+               .no_files       = 1,
+               .ignore_signals = 1,
+       };
+       struct vhost_task *vtsk;
+       struct task_struct *tsk;
+
+       vtsk = kzalloc(sizeof(*vtsk), GFP_KERNEL);
+       if (!vtsk)
+               return NULL;
+       init_completion(&vtsk->exited);
+       vtsk->data = arg;
+       vtsk->fn = fn;
+
+       args.fn_arg = vtsk;
+
+       tsk = copy_process(NULL, 0, NUMA_NO_NODE, &args);
+       if (IS_ERR(tsk)) {
+               kfree(vtsk);
+               return NULL;
+       }
+
+       vtsk->task = tsk;
+       return vtsk;
+}
+EXPORT_SYMBOL_GPL(vhost_task_create);
+
+/**
+ * vhost_task_start - start a vhost_task created with vhost_task_create
+ * @vtsk: vhost_task to wake up
+ */
+void vhost_task_start(struct vhost_task *vtsk)
+{
+       wake_up_new_task(vtsk->task);
+}
+EXPORT_SYMBOL_GPL(vhost_task_start);
index c8b379e2e9adc14f0a79dbb2b97497a356a2c6e5..39d1d93164bd094e72f88e2db9ce2a0d854abb17 100644 (file)
@@ -1143,7 +1143,7 @@ menu "Scheduler Debugging"
 
 config SCHED_DEBUG
        bool "Collect scheduler debugging info"
-       depends on DEBUG_KERNEL && PROC_FS
+       depends on DEBUG_KERNEL && DEBUG_FS
        default y
        help
          If you say Y here, the /sys/kernel/debug/sched file will be provided
@@ -1392,7 +1392,7 @@ config LOCKDEP_STACK_TRACE_HASH_BITS
        range 10 30
        default 14
        help
-         Try increasing this value if you need large MAX_STACK_TRACE_ENTRIES.
+         Try increasing this value if you need large STACK_TRACE_HASH_SIZE.
 
 config LOCKDEP_CIRCULAR_QUEUE_BITS
        int "Bitsize for elements in circular_queue struct"
index df86e649d8be08125c1469259755ff7fb4b7d3fc..b796799fadb20f89a74db204fcf31b496ad0184d 100644 (file)
@@ -216,10 +216,6 @@ static struct debug_obj *__alloc_object(struct hlist_head *list)
        return obj;
 }
 
-/*
- * Allocate a new object. If the pool is empty, switch off the debugger.
- * Must be called with interrupts disabled.
- */
 static struct debug_obj *
 alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *descr)
 {
@@ -552,11 +548,49 @@ static void debug_object_is_on_stack(void *addr, int onstack)
        WARN_ON(1);
 }
 
+static struct debug_obj *lookup_object_or_alloc(void *addr, struct debug_bucket *b,
+                                               const struct debug_obj_descr *descr,
+                                               bool onstack, bool alloc_ifstatic)
+{
+       struct debug_obj *obj = lookup_object(addr, b);
+       enum debug_obj_state state = ODEBUG_STATE_NONE;
+
+       if (likely(obj))
+               return obj;
+
+       /*
+        * debug_object_init() unconditionally allocates untracked
+        * objects. It does not matter whether it is a static object or
+        * not.
+        *
+        * debug_object_assert_init() and debug_object_activate() allow
+        * allocation only if the descriptor callback confirms that the
+        * object is static and considered initialized. For non-static
+        * objects the allocation needs to be done from the fixup callback.
+        */
+       if (unlikely(alloc_ifstatic)) {
+               if (!descr->is_static_object || !descr->is_static_object(addr))
+                       return ERR_PTR(-ENOENT);
+               /* Statically allocated objects are considered initialized */
+               state = ODEBUG_STATE_INIT;
+       }
+
+       obj = alloc_object(addr, b, descr);
+       if (likely(obj)) {
+               obj->state = state;
+               debug_object_is_on_stack(addr, onstack);
+               return obj;
+       }
+
+       /* Out of memory. Do the cleanup outside of the locked region */
+       debug_objects_enabled = 0;
+       return NULL;
+}
+
 static void
 __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack)
 {
        enum debug_obj_state state;
-       bool check_stack = false;
        struct debug_bucket *db;
        struct debug_obj *obj;
        unsigned long flags;
@@ -572,16 +606,11 @@ __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack
 
        raw_spin_lock_irqsave(&db->lock, flags);
 
-       obj = lookup_object(addr, db);
-       if (!obj) {
-               obj = alloc_object(addr, db, descr);
-               if (!obj) {
-                       debug_objects_enabled = 0;
-                       raw_spin_unlock_irqrestore(&db->lock, flags);
-                       debug_objects_oom();
-                       return;
-               }
-               check_stack = true;
+       obj = lookup_object_or_alloc(addr, db, descr, onstack, false);
+       if (unlikely(!obj)) {
+               raw_spin_unlock_irqrestore(&db->lock, flags);
+               debug_objects_oom();
+               return;
        }
 
        switch (obj->state) {
@@ -607,8 +636,6 @@ __debug_object_init(void *addr, const struct debug_obj_descr *descr, int onstack
        }
 
        raw_spin_unlock_irqrestore(&db->lock, flags);
-       if (check_stack)
-               debug_object_is_on_stack(addr, onstack);
 }
 
 /**
@@ -648,14 +675,12 @@ EXPORT_SYMBOL_GPL(debug_object_init_on_stack);
  */
 int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
 {
+       struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr };
        enum debug_obj_state state;
        struct debug_bucket *db;
        struct debug_obj *obj;
        unsigned long flags;
        int ret;
-       struct debug_obj o = { .object = addr,
-                              .state = ODEBUG_STATE_NOTAVAILABLE,
-                              .descr = descr };
 
        if (!debug_objects_enabled)
                return 0;
@@ -664,8 +689,8 @@ int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
 
        raw_spin_lock_irqsave(&db->lock, flags);
 
-       obj = lookup_object(addr, db);
-       if (obj) {
+       obj = lookup_object_or_alloc(addr, db, descr, false, true);
+       if (likely(!IS_ERR_OR_NULL(obj))) {
                bool print_object = false;
 
                switch (obj->state) {
@@ -698,24 +723,16 @@ int debug_object_activate(void *addr, const struct debug_obj_descr *descr)
 
        raw_spin_unlock_irqrestore(&db->lock, flags);
 
-       /*
-        * We are here when a static object is activated. We
-        * let the type specific code confirm whether this is
-        * true or not. if true, we just make sure that the
-        * static object is tracked in the object tracker. If
-        * not, this must be a bug, so we try to fix it up.
-        */
-       if (descr->is_static_object && descr->is_static_object(addr)) {
-               /* track this static object */
-               debug_object_init(addr, descr);
-               debug_object_activate(addr, descr);
-       } else {
-               debug_print_object(&o, "activate");
-               ret = debug_object_fixup(descr->fixup_activate, addr,
-                                       ODEBUG_STATE_NOTAVAILABLE);
-               return ret ? 0 : -EINVAL;
+       /* If NULL the allocation has hit OOM */
+       if (!obj) {
+               debug_objects_oom();
+               return 0;
        }
-       return 0;
+
+       /* Object is neither static nor tracked. It's not initialized */
+       debug_print_object(&o, "activate");
+       ret = debug_object_fixup(descr->fixup_activate, addr, ODEBUG_STATE_NOTAVAILABLE);
+       return ret ? 0 : -EINVAL;
 }
 EXPORT_SYMBOL_GPL(debug_object_activate);
 
@@ -869,6 +886,7 @@ EXPORT_SYMBOL_GPL(debug_object_free);
  */
 void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr)
 {
+       struct debug_obj o = { .object = addr, .state = ODEBUG_STATE_NOTAVAILABLE, .descr = descr };
        struct debug_bucket *db;
        struct debug_obj *obj;
        unsigned long flags;
@@ -879,31 +897,20 @@ void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr)
        db = get_bucket((unsigned long) addr);
 
        raw_spin_lock_irqsave(&db->lock, flags);
+       obj = lookup_object_or_alloc(addr, db, descr, false, true);
+       raw_spin_unlock_irqrestore(&db->lock, flags);
+       if (likely(!IS_ERR_OR_NULL(obj)))
+               return;
 
-       obj = lookup_object(addr, db);
+       /* If NULL the allocation has hit OOM */
        if (!obj) {
-               struct debug_obj o = { .object = addr,
-                                      .state = ODEBUG_STATE_NOTAVAILABLE,
-                                      .descr = descr };
-
-               raw_spin_unlock_irqrestore(&db->lock, flags);
-               /*
-                * Maybe the object is static, and we let the type specific
-                * code confirm. Track this static object if true, else invoke
-                * fixup.
-                */
-               if (descr->is_static_object && descr->is_static_object(addr)) {
-                       /* Track this static object */
-                       debug_object_init(addr, descr);
-               } else {
-                       debug_print_object(&o, "assert_init");
-                       debug_object_fixup(descr->fixup_assert_init, addr,
-                                          ODEBUG_STATE_NOTAVAILABLE);
-               }
+               debug_objects_oom();
                return;
        }
 
-       raw_spin_unlock_irqrestore(&db->lock, flags);
+       /* Object is neither tracked nor static. It's not initialized. */
+       debug_print_object(&o, "assert_init");
+       debug_object_fixup(descr->fixup_assert_init, addr, ODEBUG_STATE_NOTAVAILABLE);
 }
 EXPORT_SYMBOL_GPL(debug_object_assert_init);
 
index f9d33efa6d09060445dfbf481c01f5594dc37417..f15ac666e9d38bd23bb0cb4ed08beb626540a0c4 100644 (file)
@@ -31,6 +31,7 @@ MODULE_PARM_DESC(iterations,
 
 static void dhry_benchmark(void)
 {
+       unsigned int cpu = get_cpu();
        int i, n;
 
        if (iterations > 0) {
@@ -45,9 +46,10 @@ static void dhry_benchmark(void)
        }
 
 report:
+       put_cpu();
        if (n >= 0)
-               pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n",
-                       smp_processor_id(), n, n / DHRY_VAX);
+               pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n", cpu,
+                       n, n / DHRY_VAX);
        else if (n == -EAGAIN)
                pr_err("Please increase the number of iterations\n");
        else
index c10920e667889c1a2e86f5916b9998b21893ba77..32f99e9a670e64fcdc8e9a7e67d29df199486a69 100644 (file)
@@ -182,6 +182,15 @@ unsigned long _find_next_andnot_bit(const unsigned long *addr1, const unsigned l
 EXPORT_SYMBOL(_find_next_andnot_bit);
 #endif
 
+#ifndef find_next_or_bit
+unsigned long _find_next_or_bit(const unsigned long *addr1, const unsigned long *addr2,
+                                       unsigned long nbits, unsigned long start)
+{
+       return FIND_NEXT_BIT(addr1[idx] | addr2[idx], /* nop */, nbits, start);
+}
+EXPORT_SYMBOL(_find_next_or_bit);
+#endif
+
 #ifndef find_next_zero_bit
 unsigned long _find_next_zero_bit(const unsigned long *addr, unsigned long nbits,
                                         unsigned long start)
index 274014e4eafec2d325470757f32c0dbab65b0b8d..967fba189c5ff068e6da252a6d80e22defb26cc8 100644 (file)
@@ -126,13 +126,13 @@ __out:                                                            \
                        iterate_buf(i, n, base, len, off,       \
                                                i->ubuf, (I))   \
                } else if (likely(iter_is_iovec(i))) {          \
-                       const struct iovec *iov = i->iov;       \
+                       const struct iovec *iov = iter_iov(i);  \
                        void __user *base;                      \
                        size_t len;                             \
                        iterate_iovec(i, n, base, len, off,     \
                                                iov, (I))       \
-                       i->nr_segs -= iov - i->iov;             \
-                       i->iov = iov;                           \
+                       i->nr_segs -= iov - iter_iov(i);        \
+                       i->__iov = iov;                         \
                } else if (iov_iter_is_bvec(i)) {               \
                        const struct bio_vec *bvec = i->bvec;   \
                        void *base;                             \
@@ -355,7 +355,7 @@ size_t fault_in_iov_iter_readable(const struct iov_iter *i, size_t size)
                size_t skip;
 
                size -= count;
-               for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) {
+               for (p = iter_iov(i), skip = i->iov_offset; count; p++, skip = 0) {
                        size_t len = min(count, p->iov_len - skip);
                        size_t ret;
 
@@ -398,7 +398,7 @@ size_t fault_in_iov_iter_writeable(const struct iov_iter *i, size_t size)
                size_t skip;
 
                size -= count;
-               for (p = i->iov, skip = i->iov_offset; count; p++, skip = 0) {
+               for (p = iter_iov(i), skip = i->iov_offset; count; p++, skip = 0) {
                        size_t len = min(count, p->iov_len - skip);
                        size_t ret;
 
@@ -425,7 +425,7 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction,
                .nofault = false,
                .user_backed = true,
                .data_source = direction,
-               .iov = iov,
+               .__iov = iov,
                .nr_segs = nr_segs,
                .iov_offset = 0,
                .count = count
@@ -876,14 +876,14 @@ static void iov_iter_iovec_advance(struct iov_iter *i, size_t size)
        i->count -= size;
 
        size += i->iov_offset; // from beginning of current segment
-       for (iov = i->iov, end = iov + i->nr_segs; iov < end; iov++) {
+       for (iov = iter_iov(i), end = iov + i->nr_segs; iov < end; iov++) {
                if (likely(size < iov->iov_len))
                        break;
                size -= iov->iov_len;
        }
        i->iov_offset = size;
-       i->nr_segs -= iov - i->iov;
-       i->iov = iov;
+       i->nr_segs -= iov - iter_iov(i);
+       i->__iov = iov;
 }
 
 void iov_iter_advance(struct iov_iter *i, size_t size)
@@ -958,12 +958,12 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll)
                        unroll -= n;
                }
        } else { /* same logics for iovec and kvec */
-               const struct iovec *iov = i->iov;
+               const struct iovec *iov = iter_iov(i);
                while (1) {
                        size_t n = (--iov)->iov_len;
                        i->nr_segs++;
                        if (unroll <= n) {
-                               i->iov = iov;
+                               i->__iov = iov;
                                i->iov_offset = n - unroll;
                                return;
                        }
@@ -980,7 +980,7 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i)
 {
        if (i->nr_segs > 1) {
                if (likely(iter_is_iovec(i) || iov_iter_is_kvec(i)))
-                       return min(i->count, i->iov->iov_len - i->iov_offset);
+                       return min(i->count, iter_iov(i)->iov_len - i->iov_offset);
                if (iov_iter_is_bvec(i))
                        return min(i->count, i->bvec->bv_len - i->iov_offset);
        }
@@ -1095,13 +1095,14 @@ static bool iov_iter_aligned_iovec(const struct iov_iter *i, unsigned addr_mask,
        unsigned k;
 
        for (k = 0; k < i->nr_segs; k++, skip = 0) {
-               size_t len = i->iov[k].iov_len - skip;
+               const struct iovec *iov = iter_iov(i) + k;
+               size_t len = iov->iov_len - skip;
 
                if (len > size)
                        len = size;
                if (len & len_mask)
                        return false;
-               if ((unsigned long)(i->iov[k].iov_base + skip) & addr_mask)
+               if ((unsigned long)(iov->iov_base + skip) & addr_mask)
                        return false;
 
                size -= len;
@@ -1194,9 +1195,10 @@ static unsigned long iov_iter_alignment_iovec(const struct iov_iter *i)
        unsigned k;
 
        for (k = 0; k < i->nr_segs; k++, skip = 0) {
-               size_t len = i->iov[k].iov_len - skip;
+               const struct iovec *iov = iter_iov(i) + k;
+               size_t len = iov->iov_len - skip;
                if (len) {
-                       res |= (unsigned long)i->iov[k].iov_base + skip;
+                       res |= (unsigned long)iov->iov_base + skip;
                        if (len > size)
                                len = size;
                        res |= len;
@@ -1273,14 +1275,15 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i)
                return ~0U;
 
        for (k = 0; k < i->nr_segs; k++) {
-               if (i->iov[k].iov_len) {
-                       unsigned long base = (unsigned long)i->iov[k].iov_base;
+               const struct iovec *iov = iter_iov(i) + k;
+               if (iov->iov_len) {
+                       unsigned long base = (unsigned long)iov->iov_base;
                        if (v) // if not the first one
                                res |= base | v; // this start | previous end
-                       v = base + i->iov[k].iov_len;
-                       if (size <= i->iov[k].iov_len)
+                       v = base + iov->iov_len;
+                       if (size <= iov->iov_len)
                                break;
-                       size -= i->iov[k].iov_len;
+                       size -= iov->iov_len;
                }
        }
        return res;
@@ -1396,13 +1399,14 @@ static unsigned long first_iovec_segment(const struct iov_iter *i, size_t *size)
                return (unsigned long)i->ubuf + i->iov_offset;
 
        for (k = 0, skip = i->iov_offset; k < i->nr_segs; k++, skip = 0) {
-               size_t len = i->iov[k].iov_len - skip;
+               const struct iovec *iov = iter_iov(i) + k;
+               size_t len = iov->iov_len - skip;
 
                if (unlikely(!len))
                        continue;
                if (*size > len)
                        *size = len;
-               return (unsigned long)i->iov[k].iov_base + skip;
+               return (unsigned long)iov->iov_base + skip;
        }
        BUG(); // if it had been empty, we wouldn't get called
 }
@@ -1614,7 +1618,7 @@ static int iov_npages(const struct iov_iter *i, int maxpages)
        const struct iovec *p;
        int npages = 0;
 
-       for (p = i->iov; size; skip = 0, p++) {
+       for (p = iter_iov(i); size; skip = 0, p++) {
                unsigned offs = offset_in_page(p->iov_base + skip);
                size_t len = min(p->iov_len - skip, size);
 
@@ -1691,14 +1695,14 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
                                    flags);
        else if (iov_iter_is_kvec(new) || iter_is_iovec(new))
                /* iovec and kvec have identical layout */
-               return new->iov = kmemdup(new->iov,
+               return new->__iov = kmemdup(new->__iov,
                                   new->nr_segs * sizeof(struct iovec),
                                   flags);
        return NULL;
 }
 EXPORT_SYMBOL(dup_iter);
 
-static int copy_compat_iovec_from_user(struct iovec *iov,
+static __noclone int copy_compat_iovec_from_user(struct iovec *iov,
                const struct iovec __user *uvec, unsigned long nr_segs)
 {
        const struct compat_iovec __user *uiov =
@@ -1731,18 +1735,35 @@ uaccess_end:
 }
 
 static int copy_iovec_from_user(struct iovec *iov,
-               const struct iovec __user *uvec, unsigned long nr_segs)
+               const struct iovec __user *uiov, unsigned long nr_segs)
 {
-       unsigned long seg;
+       int ret = -EFAULT;
 
-       if (copy_from_user(iov, uvec, nr_segs * sizeof(*uvec)))
+       if (!user_access_begin(uiov, nr_segs * sizeof(*uiov)))
                return -EFAULT;
-       for (seg = 0; seg < nr_segs; seg++) {
-               if ((ssize_t)iov[seg].iov_len < 0)
-                       return -EINVAL;
-       }
 
-       return 0;
+       do {
+               void __user *buf;
+               ssize_t len;
+
+               unsafe_get_user(len, &uiov->iov_len, uaccess_end);
+               unsafe_get_user(buf, &uiov->iov_base, uaccess_end);
+
+               /* check for size_t not fitting in ssize_t .. */
+               if (unlikely(len < 0)) {
+                       ret = -EINVAL;
+                       goto uaccess_end;
+               }
+               iov->iov_base = buf;
+               iov->iov_len = len;
+
+               uiov++; iov++;
+       } while (--nr_segs);
+
+       ret = 0;
+uaccess_end:
+       user_access_end();
+       return ret;
 }
 
 struct iovec *iovec_from_user(const struct iovec __user *uvec,
@@ -1767,7 +1788,7 @@ struct iovec *iovec_from_user(const struct iovec __user *uvec,
                        return ERR_PTR(-ENOMEM);
        }
 
-       if (compat)
+       if (unlikely(compat))
                ret = copy_compat_iovec_from_user(iov, uvec, nr_segs);
        else
                ret = copy_iovec_from_user(iov, uvec, nr_segs);
@@ -1780,6 +1801,30 @@ struct iovec *iovec_from_user(const struct iovec __user *uvec,
        return iov;
 }
 
+/*
+ * Single segment iovec supplied by the user, import it as ITER_UBUF.
+ */
+static ssize_t __import_iovec_ubuf(int type, const struct iovec __user *uvec,
+                                  struct iovec **iovp, struct iov_iter *i,
+                                  bool compat)
+{
+       struct iovec *iov = *iovp;
+       ssize_t ret;
+
+       if (compat)
+               ret = copy_compat_iovec_from_user(iov, uvec, 1);
+       else
+               ret = copy_iovec_from_user(iov, uvec, 1);
+       if (unlikely(ret))
+               return ret;
+
+       ret = import_ubuf(type, iov->iov_base, iov->iov_len, i);
+       if (unlikely(ret))
+               return ret;
+       *iovp = NULL;
+       return i->count;
+}
+
 ssize_t __import_iovec(int type, const struct iovec __user *uvec,
                 unsigned nr_segs, unsigned fast_segs, struct iovec **iovp,
                 struct iov_iter *i, bool compat)
@@ -1788,6 +1833,9 @@ ssize_t __import_iovec(int type, const struct iovec __user *uvec,
        unsigned long seg;
        struct iovec *iov;
 
+       if (nr_segs == 1)
+               return __import_iovec_ubuf(type, uvec, iovp, i, compat);
+
        iov = iovec_from_user(uvec, nr_segs, fast_segs, *iovp, compat);
        if (IS_ERR(iov)) {
                *iovp = NULL;
@@ -1866,9 +1914,7 @@ int import_single_range(int rw, void __user *buf, size_t len,
        if (unlikely(!access_ok(buf, len)))
                return -EFAULT;
 
-       iov->iov_base = buf;
-       iov->iov_len = len;
-       iov_iter_init(i, rw, iov, 1, len);
+       iov_iter_ubuf(i, rw, buf, len);
        return 0;
 }
 EXPORT_SYMBOL(import_single_range);
@@ -1918,7 +1964,7 @@ void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
        if (iov_iter_is_bvec(i))
                i->bvec -= state->nr_segs - i->nr_segs;
        else
-               i->iov -= state->nr_segs - i->nr_segs;
+               i->__iov -= state->nr_segs - i->nr_segs;
        i->nr_segs = state->nr_segs;
 }
 
index de0ee2e03ed60a44ec6e0c806a407d882144a5ed..b08bb1fba106d8c1c96a53f698a927e304c74439 100644 (file)
@@ -55,14 +55,24 @@ static int debugfs_print_results(struct seq_file *seq, void *v)
        enum kunit_status success = kunit_suite_has_succeeded(suite);
        struct kunit_case *test_case;
 
-       if (!suite || !suite->log)
+       if (!suite)
                return 0;
 
-       seq_printf(seq, "%s", suite->log);
+       /* Print KTAP header so the debugfs log can be parsed as valid KTAP. */
+       seq_puts(seq, "KTAP version 1\n");
+       seq_puts(seq, "1..1\n");
+
+       /* Print suite header because it is not stored in the test logs. */
+       seq_puts(seq, KUNIT_SUBTEST_INDENT "KTAP version 1\n");
+       seq_printf(seq, KUNIT_SUBTEST_INDENT "# Subtest: %s\n", suite->name);
+       seq_printf(seq, KUNIT_SUBTEST_INDENT "1..%zd\n", kunit_suite_num_test_cases(suite));
 
        kunit_suite_for_each_test_case(suite, test_case)
                debugfs_print_result(seq, suite, test_case);
 
+       if (suite->log)
+               seq_printf(seq, "%s", suite->log);
+
        seq_printf(seq, "%s %d %s\n",
                   kunit_status_to_ok_not_ok(success), 1, suite->name);
        return 0;
index 4df0335d0d06edb874820f37128c91013152e2c3..42e44caa1bdd89fe4c0db7fa7140a3db48135dca 100644 (file)
@@ -6,6 +6,7 @@
  * Author: Brendan Higgins <brendanhiggins@google.com>
  */
 #include <kunit/test.h>
+#include <kunit/test-bug.h>
 
 #include "try-catch-impl.h"
 
@@ -443,18 +444,6 @@ static struct kunit_suite kunit_resource_test_suite = {
        .test_cases = kunit_resource_test_cases,
 };
 
-static void kunit_log_test(struct kunit *test);
-
-static struct kunit_case kunit_log_test_cases[] = {
-       KUNIT_CASE(kunit_log_test),
-       {}
-};
-
-static struct kunit_suite kunit_log_test_suite = {
-       .name = "kunit-log-test",
-       .test_cases = kunit_log_test_cases,
-};
-
 static void kunit_log_test(struct kunit *test)
 {
        struct kunit_suite suite;
@@ -481,6 +470,29 @@ static void kunit_log_test(struct kunit *test)
 #endif
 }
 
+static void kunit_log_newline_test(struct kunit *test)
+{
+       kunit_info(test, "Add newline\n");
+       if (test->log) {
+               KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(test->log, "Add newline\n"),
+                       "Missing log line, full log:\n%s", test->log);
+               KUNIT_EXPECT_NULL(test, strstr(test->log, "Add newline\n\n"));
+       } else {
+               kunit_skip(test, "only useful when debugfs is enabled");
+       }
+}
+
+static struct kunit_case kunit_log_test_cases[] = {
+       KUNIT_CASE(kunit_log_test),
+       KUNIT_CASE(kunit_log_newline_test),
+       {}
+};
+
+static struct kunit_suite kunit_log_test_suite = {
+       .name = "kunit-log-test",
+       .test_cases = kunit_log_test_cases,
+};
+
 static void kunit_status_set_failure_test(struct kunit *test)
 {
        struct kunit fake;
@@ -521,7 +533,46 @@ static struct kunit_suite kunit_status_test_suite = {
        .test_cases = kunit_status_test_cases,
 };
 
+static void kunit_current_test(struct kunit *test)
+{
+       /* Check results of both current->kunit_test and
+        * kunit_get_current_test() are equivalent to current test.
+        */
+       KUNIT_EXPECT_PTR_EQ(test, test, current->kunit_test);
+       KUNIT_EXPECT_PTR_EQ(test, test, kunit_get_current_test());
+}
+
+static void kunit_current_fail_test(struct kunit *test)
+{
+       struct kunit fake;
+
+       kunit_init_test(&fake, "fake test", NULL);
+       KUNIT_EXPECT_EQ(test, fake.status, KUNIT_SUCCESS);
+
+       /* Set current->kunit_test to fake test. */
+       current->kunit_test = &fake;
+
+       kunit_fail_current_test("This should make `fake` test fail.");
+       KUNIT_EXPECT_EQ(test, fake.status, (enum kunit_status)KUNIT_FAILURE);
+       kunit_cleanup(&fake);
+
+       /* Reset current->kunit_test to current test. */
+       current->kunit_test = test;
+}
+
+static struct kunit_case kunit_current_test_cases[] = {
+       KUNIT_CASE(kunit_current_test),
+       KUNIT_CASE(kunit_current_fail_test),
+       {}
+};
+
+static struct kunit_suite kunit_current_test_suite = {
+       .name = "kunit_current",
+       .test_cases = kunit_current_test_cases,
+};
+
 kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite,
-                 &kunit_log_test_suite, &kunit_status_test_suite);
+                 &kunit_log_test_suite, &kunit_status_test_suite,
+                 &kunit_current_test_suite);
 
 MODULE_LICENSE("GPL v2");
index c9e15bb60058470adb4106cf892da1a169d657fd..e2910b2611129ddd91d54aa4cffc296b707de39c 100644 (file)
@@ -108,28 +108,51 @@ static void kunit_print_test_stats(struct kunit *test,
                  stats.total);
 }
 
+/**
+ * kunit_log_newline() - Add newline to the end of log if one is not
+ * already present.
+ * @log: The log to add the newline to.
+ */
+static void kunit_log_newline(char *log)
+{
+       int log_len, len_left;
+
+       log_len = strlen(log);
+       len_left = KUNIT_LOG_SIZE - log_len - 1;
+
+       if (log_len > 0 && log[log_len - 1] != '\n')
+               strncat(log, "\n", len_left);
+}
+
 /*
  * Append formatted message to log, size of which is limited to
  * KUNIT_LOG_SIZE bytes (including null terminating byte).
  */
 void kunit_log_append(char *log, const char *fmt, ...)
 {
-       char line[KUNIT_LOG_SIZE];
        va_list args;
-       int len_left;
+       int len, log_len, len_left;
 
        if (!log)
                return;
 
-       len_left = KUNIT_LOG_SIZE - strlen(log) - 1;
+       log_len = strlen(log);
+       len_left = KUNIT_LOG_SIZE - log_len - 1;
        if (len_left <= 0)
                return;
 
+       /* Evaluate length of line to add to log */
+       va_start(args, fmt);
+       len = vsnprintf(NULL, 0, fmt, args) + 1;
+       va_end(args);
+
+       /* Print formatted line to the log */
        va_start(args, fmt);
-       vsnprintf(line, sizeof(line), fmt, args);
+       vsnprintf(log + log_len, min(len, len_left), fmt, args);
        va_end(args);
 
-       strncat(log, line, len_left);
+       /* Add newline to end of log if not already present. */
+       kunit_log_newline(log);
 }
 EXPORT_SYMBOL_GPL(kunit_log_append);
 
@@ -147,10 +170,18 @@ EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
 
 static void kunit_print_suite_start(struct kunit_suite *suite)
 {
-       kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "KTAP version 1\n");
-       kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
+       /*
+        * We do not log the test suite header as doing so would
+        * mean debugfs display would consist of the test suite
+        * header prior to individual test results.
+        * Hence directly printk the suite status, and we will
+        * separately seq_printf() the suite header for the debugfs
+        * representation.
+        */
+       pr_info(KUNIT_SUBTEST_INDENT "KTAP version 1\n");
+       pr_info(KUNIT_SUBTEST_INDENT "# Subtest: %s\n",
                  suite->name);
-       kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
+       pr_info(KUNIT_SUBTEST_INDENT "1..%zd\n",
                  kunit_suite_num_test_cases(suite));
 }
 
@@ -167,10 +198,9 @@ static void kunit_print_ok_not_ok(void *test_or_suite,
 
        /*
         * We do not log the test suite results as doing so would
-        * mean debugfs display would consist of the test suite
-        * description and status prior to individual test results.
-        * Hence directly printk the suite status, and we will
-        * separately seq_printf() the suite status for the debugfs
+        * mean debugfs display would consist of an incorrect test
+        * number. Hence directly printk the suite result, and we will
+        * separately seq_printf() the suite results for the debugfs
         * representation.
         */
        if (suite)
@@ -437,7 +467,6 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
        struct kunit_try_catch_context context;
        struct kunit_try_catch *try_catch;
 
-       kunit_init_test(test, test_case->name, test_case->log);
        try_catch = &test->try_catch;
 
        kunit_try_catch_init(try_catch,
@@ -533,6 +562,8 @@ int kunit_run_tests(struct kunit_suite *suite)
                struct kunit_result_stats param_stats = { 0 };
                test_case->status = KUNIT_SKIPPED;
 
+               kunit_init_test(&test, test_case->name, test_case->log);
+
                if (!test_case->generate_params) {
                        /* Non-parameterised test. */
                        kunit_run_case_catch_errors(suite, test_case, &test);
index d374cf5d1a5790ee7be762630434acbcb1eca31a..0cc27de9cec88899b63a246cb542187b8bbac9b9 100644 (file)
@@ -8,6 +8,7 @@
 #include <kunit/test.h>
 
 #include <linux/list.h>
+#include <linux/klist.h>
 
 struct list_test_struct {
        int data;
@@ -1199,6 +1200,303 @@ static struct kunit_suite hlist_test_module = {
        .test_cases = hlist_test_cases,
 };
 
-kunit_test_suites(&list_test_module, &hlist_test_module);
+
+struct klist_test_struct {
+       int data;
+       struct klist klist;
+       struct klist_node klist_node;
+};
+
+static int node_count;
+static struct klist_node *last_node;
+
+static void check_node(struct klist_node *node_ptr)
+{
+       node_count++;
+       last_node = node_ptr;
+}
+
+static void check_delete_node(struct klist_node *node_ptr)
+{
+       node_count--;
+       last_node = node_ptr;
+}
+
+static void klist_test_add_tail(struct kunit *test)
+{
+       struct klist_node a, b;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, NULL);
+
+       klist_add_tail(&a, &mylist);
+       KUNIT_EXPECT_EQ(test, node_count, 1);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &a);
+
+       klist_add_tail(&b, &mylist);
+       KUNIT_EXPECT_EQ(test, node_count, 2);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &b);
+
+       /* should be [list] -> a -> b */
+       klist_iter_init(&mylist, &i);
+
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       KUNIT_EXPECT_NULL(test, klist_next(&i));
+
+       klist_iter_exit(&i);
+
+}
+
+static void klist_test_add_head(struct kunit *test)
+{
+       struct klist_node a, b;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, NULL);
+
+       klist_add_head(&a, &mylist);
+       KUNIT_EXPECT_EQ(test, node_count, 1);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &a);
+
+       klist_add_head(&b, &mylist);
+       KUNIT_EXPECT_EQ(test, node_count, 2);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &b);
+
+       /* should be [list] -> b -> a */
+       klist_iter_init(&mylist, &i);
+
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_NULL(test, klist_next(&i));
+
+       klist_iter_exit(&i);
+
+}
+
+static void klist_test_add_behind(struct kunit *test)
+{
+       struct klist_node a, b, c, d;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, NULL);
+
+       klist_add_head(&a, &mylist);
+       klist_add_head(&b, &mylist);
+
+       klist_add_behind(&c, &a);
+       KUNIT_EXPECT_EQ(test, node_count, 3);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &c);
+
+       klist_add_behind(&d, &b);
+       KUNIT_EXPECT_EQ(test, node_count, 4);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &d);
+
+       klist_iter_init(&mylist, &i);
+
+       /* should be [list] -> b -> d -> a -> c*/
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &c);
+       KUNIT_EXPECT_NULL(test, klist_next(&i));
+
+       klist_iter_exit(&i);
+
+}
+
+static void klist_test_add_before(struct kunit *test)
+{
+       struct klist_node a, b, c, d;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, NULL);
+
+       klist_add_head(&a, &mylist);
+       klist_add_head(&b, &mylist);
+       klist_add_before(&c, &a);
+       KUNIT_EXPECT_EQ(test, node_count, 3);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &c);
+
+       klist_add_before(&d, &b);
+       KUNIT_EXPECT_EQ(test, node_count, 4);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &d);
+
+       klist_iter_init(&mylist, &i);
+
+       /* should be [list] -> b -> d -> a -> c*/
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &c);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_NULL(test, klist_next(&i));
+
+       klist_iter_exit(&i);
+
+}
+
+/*
+ * Verify that klist_del() delays the deletion of a node until there
+ * are no other references to it
+ */
+static void klist_test_del_refcount_greater_than_zero(struct kunit *test)
+{
+       struct klist_node a, b, c, d;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, &check_delete_node);
+
+       /* Add nodes a,b,c,d to the list*/
+       klist_add_tail(&a, &mylist);
+       klist_add_tail(&b, &mylist);
+       klist_add_tail(&c, &mylist);
+       klist_add_tail(&d, &mylist);
+
+       klist_iter_init(&mylist, &i);
+
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       /* Advance the iterator to point to node c*/
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &c);
+
+       /* Try to delete node c while there is a reference to it*/
+       klist_del(&c);
+
+       /*
+        * Verify that node c is still attached to the list even after being
+        * deleted. Since the iterator still points to c, the reference count is not
+        * decreased to 0
+        */
+       KUNIT_EXPECT_TRUE(test, klist_node_attached(&c));
+
+       /* Check that node c has not been removed yet*/
+       KUNIT_EXPECT_EQ(test, node_count, 4);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &d);
+
+       klist_iter_exit(&i);
+
+       /*
+        * Since the iterator is no longer pointing to node c, node c is removed
+        * from the list
+        */
+       KUNIT_EXPECT_EQ(test, node_count, 3);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &c);
+
+}
+
+/*
+ * Verify that klist_del() deletes a node immediately when there are no
+ * other references to it.
+ */
+static void klist_test_del_refcount_zero(struct kunit *test)
+{
+       struct klist_node a, b, c, d;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, &check_delete_node);
+
+       /* Add nodes a,b,c,d to the list*/
+       klist_add_tail(&a, &mylist);
+       klist_add_tail(&b, &mylist);
+       klist_add_tail(&c, &mylist);
+       klist_add_tail(&d, &mylist);
+       /* Delete node c*/
+       klist_del(&c);
+
+       /* Check that node c is deleted from the list*/
+       KUNIT_EXPECT_EQ(test, node_count, 3);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &c);
+
+       /* Should be [list] -> a -> b -> d*/
+       klist_iter_init(&mylist, &i);
+
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d);
+       KUNIT_EXPECT_NULL(test, klist_next(&i));
+
+       klist_iter_exit(&i);
+
+}
+
+static void klist_test_remove(struct kunit *test)
+{
+       /* This test doesn't check correctness under concurrent access */
+       struct klist_node a, b, c, d;
+       struct klist mylist;
+       struct klist_iter i;
+
+       node_count = 0;
+       klist_init(&mylist, &check_node, &check_delete_node);
+
+       /* Add nodes a,b,c,d to the list*/
+       klist_add_tail(&a, &mylist);
+       klist_add_tail(&b, &mylist);
+       klist_add_tail(&c, &mylist);
+       klist_add_tail(&d, &mylist);
+       /* Delete node c*/
+       klist_remove(&c);
+
+       /* Check the nodes in the list*/
+       KUNIT_EXPECT_EQ(test, node_count, 3);
+       KUNIT_EXPECT_PTR_EQ(test, last_node, &c);
+
+       /* should be [list] -> a -> b -> d*/
+       klist_iter_init(&mylist, &i);
+
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &a);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &b);
+       KUNIT_EXPECT_PTR_EQ(test, klist_next(&i), &d);
+       KUNIT_EXPECT_NULL(test, klist_next(&i));
+
+       klist_iter_exit(&i);
+
+}
+
+static void klist_test_node_attached(struct kunit *test)
+{
+       struct klist_node a = {};
+       struct klist mylist;
+
+       klist_init(&mylist, NULL, NULL);
+
+       KUNIT_EXPECT_FALSE(test, klist_node_attached(&a));
+       klist_add_head(&a, &mylist);
+       KUNIT_EXPECT_TRUE(test, klist_node_attached(&a));
+       klist_del(&a);
+       KUNIT_EXPECT_FALSE(test, klist_node_attached(&a));
+
+}
+
+static struct kunit_case klist_test_cases[] = {
+       KUNIT_CASE(klist_test_add_tail),
+       KUNIT_CASE(klist_test_add_head),
+       KUNIT_CASE(klist_test_add_behind),
+       KUNIT_CASE(klist_test_add_before),
+       KUNIT_CASE(klist_test_del_refcount_greater_than_zero),
+       KUNIT_CASE(klist_test_del_refcount_zero),
+       KUNIT_CASE(klist_test_remove),
+       KUNIT_CASE(klist_test_node_attached),
+       {},
+};
+
+static struct kunit_suite klist_test_module = {
+       .name = "klist",
+       .test_cases = klist_test_cases,
+};
+
+kunit_test_suites(&list_test_module, &hlist_test_module, &klist_test_module);
 
 MODULE_LICENSE("GPL v2");
index 646297cae5d16dea90e9fbc0b22d02f2198c6b93..1281a40d5735c423c47a451c53eec273dd8deda1 100644 (file)
@@ -185,7 +185,7 @@ static void mt_free_rcu(struct rcu_head *head)
  */
 static void ma_free_rcu(struct maple_node *node)
 {
-       node->parent = ma_parent_ptr(node);
+       WARN_ON(node->parent != ma_parent_ptr(node));
        call_rcu(&node->rcu, mt_free_rcu);
 }
 
@@ -539,11 +539,14 @@ static inline struct maple_node *mte_parent(const struct maple_enode *enode)
  */
 static inline bool ma_dead_node(const struct maple_node *node)
 {
-       struct maple_node *parent = (void *)((unsigned long)
-                                            node->parent & ~MAPLE_NODE_MASK);
+       struct maple_node *parent;
 
+       /* Do not reorder reads from the node prior to the parent check */
+       smp_rmb();
+       parent = (void *)((unsigned long) node->parent & ~MAPLE_NODE_MASK);
        return (parent == node);
 }
+
 /*
  * mte_dead_node() - check if the @enode is dead.
  * @enode: The encoded maple node
@@ -555,6 +558,8 @@ static inline bool mte_dead_node(const struct maple_enode *enode)
        struct maple_node *parent, *node;
 
        node = mte_to_node(enode);
+       /* Do not reorder reads from the node prior to the parent check */
+       smp_rmb();
        parent = mte_parent(enode);
        return (parent == node);
 }
@@ -625,6 +630,8 @@ static inline unsigned int mas_alloc_req(const struct ma_state *mas)
  * @node - the maple node
  * @type - the node type
  *
+ * In the event of a dead node, this array may be %NULL
+ *
  * Return: A pointer to the maple node pivots
  */
 static inline unsigned long *ma_pivots(struct maple_node *node,
@@ -817,6 +824,11 @@ static inline void *mt_slot(const struct maple_tree *mt,
        return rcu_dereference_check(slots[offset], mt_locked(mt));
 }
 
+static inline void *mt_slot_locked(struct maple_tree *mt, void __rcu **slots,
+                                  unsigned char offset)
+{
+       return rcu_dereference_protected(slots[offset], mt_locked(mt));
+}
 /*
  * mas_slot_locked() - Get the slot value when holding the maple tree lock.
  * @mas: The maple state
@@ -828,7 +840,7 @@ static inline void *mt_slot(const struct maple_tree *mt,
 static inline void *mas_slot_locked(struct ma_state *mas, void __rcu **slots,
                                       unsigned char offset)
 {
-       return rcu_dereference_protected(slots[offset], mt_locked(mas->tree));
+       return mt_slot_locked(mas->tree, slots, offset);
 }
 
 /*
@@ -899,6 +911,45 @@ static inline void ma_set_meta(struct maple_node *mn, enum maple_type mt,
        meta->end = end;
 }
 
+/*
+ * mt_clear_meta() - clear the metadata information of a node, if it exists
+ * @mt: The maple tree
+ * @mn: The maple node
+ * @type: The maple node type
+ * @offset: The offset of the highest sub-gap in this node.
+ * @end: The end of the data in this node.
+ */
+static inline void mt_clear_meta(struct maple_tree *mt, struct maple_node *mn,
+                                 enum maple_type type)
+{
+       struct maple_metadata *meta;
+       unsigned long *pivots;
+       void __rcu **slots;
+       void *next;
+
+       switch (type) {
+       case maple_range_64:
+               pivots = mn->mr64.pivot;
+               if (unlikely(pivots[MAPLE_RANGE64_SLOTS - 2])) {
+                       slots = mn->mr64.slot;
+                       next = mt_slot_locked(mt, slots,
+                                             MAPLE_RANGE64_SLOTS - 1);
+                       if (unlikely((mte_to_node(next) &&
+                                     mte_node_type(next))))
+                               return; /* no metadata, could be node */
+               }
+               fallthrough;
+       case maple_arange_64:
+               meta = ma_meta(mn, type);
+               break;
+       default:
+               return;
+       }
+
+       meta->gap = 0;
+       meta->end = 0;
+}
+
 /*
  * ma_meta_end() - Get the data end of a node from the metadata
  * @mn: The maple node
@@ -1096,8 +1147,11 @@ static int mas_ascend(struct ma_state *mas)
                a_type = mas_parent_enum(mas, p_enode);
                a_node = mte_parent(p_enode);
                a_slot = mte_parent_slot(p_enode);
-               pivots = ma_pivots(a_node, a_type);
                a_enode = mt_mk_node(a_node, a_type);
+               pivots = ma_pivots(a_node, a_type);
+
+               if (unlikely(ma_dead_node(a_node)))
+                       return 1;
 
                if (!set_min && a_slot) {
                        set_min = true;
@@ -1249,26 +1303,21 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
        node = mas->alloc;
        node->request_count = 0;
        while (requested) {
-               max_req = MAPLE_ALLOC_SLOTS;
-               if (node->node_count) {
-                       unsigned int offset = node->node_count;
-
-                       slots = (void **)&node->slot[offset];
-                       max_req -= offset;
-               } else {
-                       slots = (void **)&node->slot;
-               }
-
+               max_req = MAPLE_ALLOC_SLOTS - node->node_count;
+               slots = (void **)&node->slot[node->node_count];
                max_req = min(requested, max_req);
                count = mt_alloc_bulk(gfp, max_req, slots);
                if (!count)
                        goto nomem_bulk;
 
+               if (node->node_count == 0) {
+                       node->slot[0]->node_count = 0;
+                       node->slot[0]->request_count = 0;
+               }
+
                node->node_count += count;
                allocated += count;
                node = node->slot[0];
-               node->node_count = 0;
-               node->request_count = 0;
                requested -= count;
        }
        mas->alloc->total = allocated;
@@ -1354,12 +1403,16 @@ static inline struct maple_enode *mas_start(struct ma_state *mas)
                mas->max = ULONG_MAX;
                mas->depth = 0;
 
+retry:
                root = mas_root(mas);
                /* Tree with nodes */
                if (likely(xa_is_node(root))) {
                        mas->depth = 1;
                        mas->node = mte_safe_root(root);
                        mas->offset = 0;
+                       if (mte_dead_node(mas->node))
+                               goto retry;
+
                        return NULL;
                }
 
@@ -1401,6 +1454,9 @@ static inline unsigned char ma_data_end(struct maple_node *node,
 {
        unsigned char offset;
 
+       if (!pivots)
+               return 0;
+
        if (type == maple_arange_64)
                return ma_meta_end(node, type);
 
@@ -1436,6 +1492,9 @@ static inline unsigned char mas_data_end(struct ma_state *mas)
                return ma_meta_end(node, type);
 
        pivots = ma_pivots(node, type);
+       if (unlikely(ma_dead_node(node)))
+               return 0;
+
        offset = mt_pivots[type] - 1;
        if (likely(!pivots[offset]))
                return ma_meta_end(node, type);
@@ -1724,8 +1783,10 @@ static inline void mas_replace(struct ma_state *mas, bool advanced)
                rcu_assign_pointer(slots[offset], mas->node);
        }
 
-       if (!advanced)
+       if (!advanced) {
+               mte_set_node_dead(old_enode);
                mas_free(mas, old_enode);
+       }
 }
 
 /*
@@ -3659,10 +3720,9 @@ static inline int mas_root_expand(struct ma_state *mas, void *entry)
                slot++;
        mas->depth = 1;
        mas_set_height(mas);
-
+       ma_set_meta(node, maple_leaf_64, 0, slot);
        /* swap the new root into the tree */
        rcu_assign_pointer(mas->tree->ma_root, mte_mk_root(mas->node));
-       ma_set_meta(node, maple_leaf_64, 0, slot);
        return slot;
 }
 
@@ -3875,18 +3935,13 @@ static inline void *mtree_lookup_walk(struct ma_state *mas)
                end = ma_data_end(node, type, pivots, max);
                if (unlikely(ma_dead_node(node)))
                        goto dead_node;
-
-               if (pivots[offset] >= mas->index)
-                       goto next;
-
                do {
-                       offset++;
-               } while ((offset < end) && (pivots[offset] < mas->index));
-
-               if (likely(offset > end))
-                       max = pivots[offset];
+                       if (pivots[offset] >= mas->index) {
+                               max = pivots[offset];
+                               break;
+                       }
+               } while (++offset < end);
 
-next:
                slots = ma_slots(node, type);
                next = mt_slot(mas->tree, slots, offset);
                if (unlikely(ma_dead_node(node)))
@@ -4164,6 +4219,7 @@ static inline bool mas_wr_node_store(struct ma_wr_state *wr_mas)
 done:
        mas_leaf_set_meta(mas, newnode, dst_pivots, maple_leaf_64, new_end);
        if (in_rcu) {
+               mte_set_node_dead(mas->node);
                mas->node = mt_mk_node(newnode, wr_mas->type);
                mas_replace(mas, false);
        } else {
@@ -4505,6 +4561,9 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
        node = mas_mn(mas);
        slots = ma_slots(node, mt);
        pivots = ma_pivots(node, mt);
+       if (unlikely(ma_dead_node(node)))
+               return 1;
+
        mas->max = pivots[offset];
        if (offset)
                mas->min = pivots[offset - 1] + 1;
@@ -4526,6 +4585,9 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
                slots = ma_slots(node, mt);
                pivots = ma_pivots(node, mt);
                offset = ma_data_end(node, mt, pivots, mas->max);
+               if (unlikely(ma_dead_node(node)))
+                       return 1;
+
                if (offset)
                        mas->min = pivots[offset - 1] + 1;
 
@@ -4574,6 +4636,7 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
        struct maple_enode *enode;
        int level = 0;
        unsigned char offset;
+       unsigned char node_end;
        enum maple_type mt;
        void __rcu **slots;
 
@@ -4597,7 +4660,11 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
                node = mas_mn(mas);
                mt = mte_node_type(mas->node);
                pivots = ma_pivots(node, mt);
-       } while (unlikely(offset == ma_data_end(node, mt, pivots, mas->max)));
+               node_end = ma_data_end(node, mt, pivots, mas->max);
+               if (unlikely(ma_dead_node(node)))
+                       return 1;
+
+       } while (unlikely(offset == node_end));
 
        slots = ma_slots(node, mt);
        pivot = mas_safe_pivot(mas, pivots, ++offset, mt);
@@ -4613,6 +4680,9 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
                mt = mte_node_type(mas->node);
                slots = ma_slots(node, mt);
                pivots = ma_pivots(node, mt);
+               if (unlikely(ma_dead_node(node)))
+                       return 1;
+
                offset = 0;
                pivot = pivots[0];
        }
@@ -4659,11 +4729,14 @@ static inline void *mas_next_nentry(struct ma_state *mas,
                return NULL;
        }
 
-       pivots = ma_pivots(node, type);
        slots = ma_slots(node, type);
-       mas->index = mas_safe_min(mas, pivots, mas->offset);
+       pivots = ma_pivots(node, type);
        count = ma_data_end(node, type, pivots, mas->max);
-       if (ma_dead_node(node))
+       if (unlikely(ma_dead_node(node)))
+               return NULL;
+
+       mas->index = mas_safe_min(mas, pivots, mas->offset);
+       if (unlikely(ma_dead_node(node)))
                return NULL;
 
        if (mas->index > max)
@@ -4817,6 +4890,11 @@ retry:
 
        slots = ma_slots(mn, mt);
        pivots = ma_pivots(mn, mt);
+       if (unlikely(ma_dead_node(mn))) {
+               mas_rewalk(mas, index);
+               goto retry;
+       }
+
        if (offset == mt_pivots[mt])
                pivot = mas->max;
        else
@@ -4887,7 +4965,8 @@ not_found:
  * Return: True if found in a leaf, false otherwise.
  *
  */
-static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
+static bool mas_rev_awalk(struct ma_state *mas, unsigned long size,
+               unsigned long *gap_min, unsigned long *gap_max)
 {
        enum maple_type type = mte_node_type(mas->node);
        struct maple_node *node = mas_mn(mas);
@@ -4952,8 +5031,8 @@ static bool mas_rev_awalk(struct ma_state *mas, unsigned long size)
 
        if (unlikely(ma_is_leaf(type))) {
                mas->offset = offset;
-               mas->min = min;
-               mas->max = min + gap - 1;
+               *gap_min = min;
+               *gap_max = min + gap - 1;
                return true;
        }
 
@@ -4977,10 +5056,10 @@ static inline bool mas_anode_descend(struct ma_state *mas, unsigned long size)
 {
        enum maple_type type = mte_node_type(mas->node);
        unsigned long pivot, min, gap = 0;
-       unsigned char offset;
-       unsigned long *gaps;
-       unsigned long *pivots = ma_pivots(mas_mn(mas), type);
-       void __rcu **slots = ma_slots(mas_mn(mas), type);
+       unsigned char offset, data_end;
+       unsigned long *gaps, *pivots;
+       void __rcu **slots;
+       struct maple_node *node;
        bool found = false;
 
        if (ma_is_dense(type)) {
@@ -4988,13 +5067,15 @@ static inline bool mas_anode_descend(struct ma_state *mas, unsigned long size)
                return true;
        }
 
-       gaps = ma_gaps(mte_to_node(mas->node), type);
+       node = mas_mn(mas);
+       pivots = ma_pivots(node, type);
+       slots = ma_slots(node, type);
+       gaps = ma_gaps(node, type);
        offset = mas->offset;
        min = mas_safe_min(mas, pivots, offset);
-       for (; offset < mt_slots[type]; offset++) {
-               pivot = mas_safe_pivot(mas, pivots, offset, type);
-               if (offset && !pivot)
-                       break;
+       data_end = ma_data_end(node, type, pivots, mas->max);
+       for (; offset <= data_end; offset++) {
+               pivot = mas_logical_pivot(mas, pivots, offset, type);
 
                /* Not within lower bounds */
                if (mas->index > pivot)
@@ -5099,35 +5180,21 @@ static inline bool mas_rewind_node(struct ma_state *mas)
  */
 static inline bool mas_skip_node(struct ma_state *mas)
 {
-       unsigned char slot, slot_count;
-       unsigned long *pivots;
-       enum maple_type mt;
+       if (mas_is_err(mas))
+               return false;
 
-       mt = mte_node_type(mas->node);
-       slot_count = mt_slots[mt] - 1;
        do {
                if (mte_is_root(mas->node)) {
-                       slot = mas->offset;
-                       if (slot > slot_count) {
+                       if (mas->offset >= mas_data_end(mas)) {
                                mas_set_err(mas, -EBUSY);
                                return false;
                        }
                } else {
                        mas_ascend(mas);
-                       slot = mas->offset;
-                       mt = mte_node_type(mas->node);
-                       slot_count = mt_slots[mt] - 1;
                }
-       } while (slot > slot_count);
-
-       mas->offset = ++slot;
-       pivots = ma_pivots(mas_mn(mas), mt);
-       if (slot > 0)
-               mas->min = pivots[slot - 1] + 1;
-
-       if (slot <= slot_count)
-               mas->max = pivots[slot];
+       } while (mas->offset >= mas_data_end(mas));
 
+       mas->offset++;
        return true;
 }
 
@@ -5243,6 +5310,9 @@ int mas_empty_area(struct ma_state *mas, unsigned long min,
        unsigned long *pivots;
        enum maple_type mt;
 
+       if (min >= max)
+               return -EINVAL;
+
        if (mas_is_start(mas))
                mas_start(mas);
        else if (mas->offset >= 2)
@@ -5297,6 +5367,9 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
 {
        struct maple_enode *last = mas->node;
 
+       if (min >= max)
+               return -EINVAL;
+
        if (mas_is_start(mas)) {
                mas_start(mas);
                mas->offset = mas_data_end(mas);
@@ -5316,7 +5389,7 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
        mas->index = min;
        mas->last = max;
 
-       while (!mas_rev_awalk(mas, size)) {
+       while (!mas_rev_awalk(mas, size, &min, &max)) {
                if (last == mas->node) {
                        if (!mas_rewind_node(mas))
                                return -EBUSY;
@@ -5331,17 +5404,9 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
        if (unlikely(mas->offset == MAPLE_NODE_SLOTS))
                return -EBUSY;
 
-       /*
-        * mas_rev_awalk() has set mas->min and mas->max to the gap values.  If
-        * the maximum is outside the window we are searching, then use the last
-        * location in the search.
-        * mas->max and mas->min is the range of the gap.
-        * mas->index and mas->last are currently set to the search range.
-        */
-
        /* Trim the upper limit to the max. */
-       if (mas->max <= mas->last)
-               mas->last = mas->max;
+       if (max <= mas->last)
+               mas->last = max;
 
        mas->index = mas->last - size + 1;
        return 0;
@@ -5414,24 +5479,26 @@ no_gap:
 }
 
 /*
- * mas_dead_leaves() - Mark all leaves of a node as dead.
+ * mte_dead_leaves() - Mark all leaves of a node as dead.
  * @mas: The maple state
  * @slots: Pointer to the slot array
+ * @type: The maple node type
  *
  * Must hold the write lock.
  *
  * Return: The number of leaves marked as dead.
  */
 static inline
-unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
+unsigned char mte_dead_leaves(struct maple_enode *enode, struct maple_tree *mt,
+                             void __rcu **slots)
 {
        struct maple_node *node;
        enum maple_type type;
        void *entry;
        int offset;
 
-       for (offset = 0; offset < mt_slot_count(mas->node); offset++) {
-               entry = mas_slot_locked(mas, slots, offset);
+       for (offset = 0; offset < mt_slot_count(enode); offset++) {
+               entry = mt_slot(mt, slots, offset);
                type = mte_node_type(entry);
                node = mte_to_node(entry);
                /* Use both node and type to catch LE & BE metadata */
@@ -5439,7 +5506,6 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
                        break;
 
                mte_set_node_dead(entry);
-               smp_wmb(); /* Needed for RCU */
                node->type = type;
                rcu_assign_pointer(slots[offset], node);
        }
@@ -5447,151 +5513,160 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots)
        return offset;
 }
 
-static void __rcu **mas_dead_walk(struct ma_state *mas, unsigned char offset)
+/**
+ * mte_dead_walk() - Walk down a dead tree to just before the leaves
+ * @enode: The maple encoded node
+ * @offset: The starting offset
+ *
+ * Note: This can only be used from the RCU callback context.
+ */
+static void __rcu **mte_dead_walk(struct maple_enode **enode, unsigned char offset)
 {
        struct maple_node *node, *next;
        void __rcu **slots = NULL;
 
-       next = mas_mn(mas);
+       next = mte_to_node(*enode);
        do {
-               mas->node = ma_enode_ptr(next);
-               node = mas_mn(mas);
+               *enode = ma_enode_ptr(next);
+               node = mte_to_node(*enode);
                slots = ma_slots(node, node->type);
-               next = mas_slot_locked(mas, slots, offset);
+               next = rcu_dereference_protected(slots[offset],
+                                       lock_is_held(&rcu_callback_map));
                offset = 0;
        } while (!ma_is_leaf(next->type));
 
        return slots;
 }
 
+/**
+ * mt_free_walk() - Walk & free a tree in the RCU callback context
+ * @head: The RCU head that's within the node.
+ *
+ * Note: This can only be used from the RCU callback context.
+ */
 static void mt_free_walk(struct rcu_head *head)
 {
        void __rcu **slots;
        struct maple_node *node, *start;
-       struct maple_tree mt;
+       struct maple_enode *enode;
        unsigned char offset;
        enum maple_type type;
-       MA_STATE(mas, &mt, 0, 0);
 
        node = container_of(head, struct maple_node, rcu);
 
        if (ma_is_leaf(node->type))
                goto free_leaf;
 
-       mt_init_flags(&mt, node->ma_flags);
-       mas_lock(&mas);
        start = node;
-       mas.node = mt_mk_node(node, node->type);
-       slots = mas_dead_walk(&mas, 0);
-       node = mas_mn(&mas);
+       enode = mt_mk_node(node, node->type);
+       slots = mte_dead_walk(&enode, 0);
+       node = mte_to_node(enode);
        do {
                mt_free_bulk(node->slot_len, slots);
                offset = node->parent_slot + 1;
-               mas.node = node->piv_parent;
-               if (mas_mn(&mas) == node)
-                       goto start_slots_free;
-
-               type = mte_node_type(mas.node);
-               slots = ma_slots(mte_to_node(mas.node), type);
-               if ((offset < mt_slots[type]) && (slots[offset]))
-                       slots = mas_dead_walk(&mas, offset);
-
-               node = mas_mn(&mas);
+               enode = node->piv_parent;
+               if (mte_to_node(enode) == node)
+                       goto free_leaf;
+
+               type = mte_node_type(enode);
+               slots = ma_slots(mte_to_node(enode), type);
+               if ((offset < mt_slots[type]) &&
+                   rcu_dereference_protected(slots[offset],
+                                             lock_is_held(&rcu_callback_map)))
+                       slots = mte_dead_walk(&enode, offset);
+               node = mte_to_node(enode);
        } while ((node != start) || (node->slot_len < offset));
 
        slots = ma_slots(node, node->type);
        mt_free_bulk(node->slot_len, slots);
 
-start_slots_free:
-       mas_unlock(&mas);
 free_leaf:
        mt_free_rcu(&node->rcu);
 }
 
-static inline void __rcu **mas_destroy_descend(struct ma_state *mas,
-                       struct maple_enode *prev, unsigned char offset)
+static inline void __rcu **mte_destroy_descend(struct maple_enode **enode,
+       struct maple_tree *mt, struct maple_enode *prev, unsigned char offset)
 {
        struct maple_node *node;
-       struct maple_enode *next = mas->node;
+       struct maple_enode *next = *enode;
        void __rcu **slots = NULL;
+       enum maple_type type;
+       unsigned char next_offset = 0;
 
        do {
-               mas->node = next;
-               node = mas_mn(mas);
-               slots = ma_slots(node, mte_node_type(mas->node));
-               next = mas_slot_locked(mas, slots, 0);
+               *enode = next;
+               node = mte_to_node(*enode);
+               type = mte_node_type(*enode);
+               slots = ma_slots(node, type);
+               next = mt_slot_locked(mt, slots, next_offset);
                if ((mte_dead_node(next)))
-                       next = mas_slot_locked(mas, slots, 1);
+                       next = mt_slot_locked(mt, slots, ++next_offset);
 
-               mte_set_node_dead(mas->node);
-               node->type = mte_node_type(mas->node);
+               mte_set_node_dead(*enode);
+               node->type = type;
                node->piv_parent = prev;
                node->parent_slot = offset;
-               offset = 0;
-               prev = mas->node;
+               offset = next_offset;
+               next_offset = 0;
+               prev = *enode;
        } while (!mte_is_leaf(next));
 
        return slots;
 }
 
-static void mt_destroy_walk(struct maple_enode *enode, unsigned char ma_flags,
+static void mt_destroy_walk(struct maple_enode *enode, struct maple_tree *mt,
                            bool free)
 {
        void __rcu **slots;
        struct maple_node *node = mte_to_node(enode);
        struct maple_enode *start;
-       struct maple_tree mt;
-
-       MA_STATE(mas, &mt, 0, 0);
 
-       if (mte_is_leaf(enode))
+       if (mte_is_leaf(enode)) {
+               node->type = mte_node_type(enode);
                goto free_leaf;
+       }
 
-       mt_init_flags(&mt, ma_flags);
-       mas_lock(&mas);
-
-       mas.node = start = enode;
-       slots = mas_destroy_descend(&mas, start, 0);
-       node = mas_mn(&mas);
+       start = enode;
+       slots = mte_destroy_descend(&enode, mt, start, 0);
+       node = mte_to_node(enode); // Updated in the above call.
        do {
                enum maple_type type;
                unsigned char offset;
                struct maple_enode *parent, *tmp;
 
-               node->slot_len = mas_dead_leaves(&mas, slots);
+               node->slot_len = mte_dead_leaves(enode, mt, slots);
                if (free)
                        mt_free_bulk(node->slot_len, slots);
                offset = node->parent_slot + 1;
-               mas.node = node->piv_parent;
-               if (mas_mn(&mas) == node)
-                       goto start_slots_free;
+               enode = node->piv_parent;
+               if (mte_to_node(enode) == node)
+                       goto free_leaf;
 
-               type = mte_node_type(mas.node);
-               slots = ma_slots(mte_to_node(mas.node), type);
+               type = mte_node_type(enode);
+               slots = ma_slots(mte_to_node(enode), type);
                if (offset >= mt_slots[type])
                        goto next;
 
-               tmp = mas_slot_locked(&mas, slots, offset);
+               tmp = mt_slot_locked(mt, slots, offset);
                if (mte_node_type(tmp) && mte_to_node(tmp)) {
-                       parent = mas.node;
-                       mas.node = tmp;
-                       slots = mas_destroy_descend(&mas, parent, offset);
+                       parent = enode;
+                       enode = tmp;
+                       slots = mte_destroy_descend(&enode, mt, parent, offset);
                }
 next:
-               node = mas_mn(&mas);
-       } while (start != mas.node);
+               node = mte_to_node(enode);
+       } while (start != enode);
 
-       node = mas_mn(&mas);
-       node->slot_len = mas_dead_leaves(&mas, slots);
+       node = mte_to_node(enode);
+       node->slot_len = mte_dead_leaves(enode, mt, slots);
        if (free)
                mt_free_bulk(node->slot_len, slots);
 
-start_slots_free:
-       mas_unlock(&mas);
-
 free_leaf:
        if (free)
                mt_free_rcu(&node->rcu);
+       else
+               mt_clear_meta(mt, node, node->type);
 }
 
 /*
@@ -5607,10 +5682,10 @@ static inline void mte_destroy_walk(struct maple_enode *enode,
        struct maple_node *node = mte_to_node(enode);
 
        if (mt_in_rcu(mt)) {
-               mt_destroy_walk(enode, mt->ma_flags, false);
+               mt_destroy_walk(enode, mt, false);
                call_rcu(&node->rcu, mt_free_walk);
        } else {
-               mt_destroy_walk(enode, mt->ma_flags, true);
+               mt_destroy_walk(enode, mt, true);
        }
 }
 
@@ -6631,11 +6706,11 @@ static inline void *mas_first_entry(struct ma_state *mas, struct maple_node *mn,
        while (likely(!ma_is_leaf(mt))) {
                MT_BUG_ON(mas->tree, mte_dead_node(mas->node));
                slots = ma_slots(mn, mt);
-               pivots = ma_pivots(mn, mt);
-               max = pivots[0];
                entry = mas_slot(mas, slots, 0);
+               pivots = ma_pivots(mn, mt);
                if (unlikely(ma_dead_node(mn)))
                        return NULL;
+               max = pivots[0];
                mas->node = entry;
                mn = mas_mn(mas);
                mt = mte_node_type(mas->node);
@@ -6655,13 +6730,13 @@ static inline void *mas_first_entry(struct ma_state *mas, struct maple_node *mn,
        if (likely(entry))
                return entry;
 
-       pivots = ma_pivots(mn, mt);
-       mas->index = pivots[0] + 1;
        mas->offset = 1;
        entry = mas_slot(mas, slots, 1);
+       pivots = ma_pivots(mn, mt);
        if (unlikely(ma_dead_node(mn)))
                return NULL;
 
+       mas->index = pivots[0] + 1;
        if (mas->index > limit)
                goto none;
 
index dba56c5c1837912132b5e01bd66eba8a8e3a01fa..5004463c4f9f1243674ca77c2aea8e7050edfbda 100644 (file)
@@ -122,8 +122,19 @@ void percpu_counter_sync(struct percpu_counter *fbc)
 }
 EXPORT_SYMBOL(percpu_counter_sync);
 
-static s64 __percpu_counter_sum_mask(struct percpu_counter *fbc,
-                             const struct cpumask *cpu_mask)
+/*
+ * Add up all the per-cpu counts, return the result.  This is a more accurate
+ * but much slower version of percpu_counter_read_positive().
+ *
+ * We use the cpu mask of (cpu_online_mask | cpu_dying_mask) to capture sums
+ * from CPUs that are in the process of being taken offline. Dying cpus have
+ * been removed from the online mask, but may not have had the hotplug dead
+ * notifier called to fold the percpu count back into the global counter sum.
+ * By including dying CPUs in the iteration mask, we avoid this race condition
+ * so __percpu_counter_sum() just does the right thing when CPUs are being taken
+ * offline.
+ */
+s64 __percpu_counter_sum(struct percpu_counter *fbc)
 {
        s64 ret;
        int cpu;
@@ -131,35 +142,15 @@ static s64 __percpu_counter_sum_mask(struct percpu_counter *fbc,
 
        raw_spin_lock_irqsave(&fbc->lock, flags);
        ret = fbc->count;
-       for_each_cpu(cpu, cpu_mask) {
+       for_each_cpu_or(cpu, cpu_online_mask, cpu_dying_mask) {
                s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
                ret += *pcount;
        }
        raw_spin_unlock_irqrestore(&fbc->lock, flags);
        return ret;
 }
-
-/*
- * Add up all the per-cpu counts, return the result.  This is a more accurate
- * but much slower version of percpu_counter_read_positive()
- */
-s64 __percpu_counter_sum(struct percpu_counter *fbc)
-{
-       return __percpu_counter_sum_mask(fbc, cpu_online_mask);
-}
 EXPORT_SYMBOL(__percpu_counter_sum);
 
-/*
- * This is slower version of percpu_counter_sum as it traverses all possible
- * cpus. Use this only in the cases where accurate data is needed in the
- * presense of CPUs getting offlined.
- */
-s64 percpu_counter_sum_all(struct percpu_counter *fbc)
-{
-       return __percpu_counter_sum_mask(fbc, cpu_possible_mask);
-}
-EXPORT_SYMBOL(percpu_counter_sum_all);
-
 int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, gfp_t gfp,
                          struct lock_class_key *key)
 {
index 3d19b1f78d7189a8a0a63241f765bbec12729d93..f1db333270e9fa4f2743a1e4c72420358eea5831 100644 (file)
@@ -2670,6 +2670,49 @@ static noinline void check_empty_area_window(struct maple_tree *mt)
        rcu_read_unlock();
 }
 
+static noinline void check_empty_area_fill(struct maple_tree *mt)
+{
+       const unsigned long max = 0x25D78000;
+       unsigned long size;
+       int loop, shift;
+       MA_STATE(mas, mt, 0, 0);
+
+       mt_set_non_kernel(99999);
+       for (shift = 12; shift <= 16; shift++) {
+               loop = 5000;
+               size = 1 << shift;
+               while (loop--) {
+                       mas_set(&mas, 0);
+                       mas_lock(&mas);
+                       MT_BUG_ON(mt, mas_empty_area(&mas, 0, max, size) != 0);
+                       MT_BUG_ON(mt, mas.last != mas.index + size - 1);
+                       mas_store_gfp(&mas, (void *)size, GFP_KERNEL);
+                       mas_unlock(&mas);
+                       mas_reset(&mas);
+               }
+       }
+
+       /* No space left. */
+       size = 0x1000;
+       rcu_read_lock();
+       MT_BUG_ON(mt, mas_empty_area(&mas, 0, max, size) != -EBUSY);
+       rcu_read_unlock();
+
+       /* Fill a depth 3 node to the maximum */
+       for (unsigned long i = 629440511; i <= 629440800; i += 6)
+               mtree_store_range(mt, i, i + 5, (void *)i, GFP_KERNEL);
+       /* Make space in the second-last depth 4 node */
+       mtree_erase(mt, 631668735);
+       /* Make space in the last depth 4 node */
+       mtree_erase(mt, 629506047);
+       mas_reset(&mas);
+       /* Search from just after the gap in the second-last depth 4 */
+       rcu_read_lock();
+       MT_BUG_ON(mt, mas_empty_area(&mas, 629506048, 690000000, 0x5000) != 0);
+       rcu_read_unlock();
+       mt_set_non_kernel(0);
+}
+
 static DEFINE_MTREE(tree);
 static int maple_tree_seed(void)
 {
@@ -2926,6 +2969,11 @@ static int maple_tree_seed(void)
        check_empty_area_window(&tree);
        mtree_destroy(&tree);
 
+       mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
+       check_empty_area_fill(&tree);
+       mtree_destroy(&tree);
+
+
 #if defined(BENCH)
 skip:
 #endif
index de4ee0d50906215e9469b29229594251a9995dcf..cd2bdba6d3edbcd44aeaa1995a96afd1e0646a8a 100644 (file)
@@ -334,7 +334,7 @@ kvfree_rcu_1_arg_vmalloc_test(void)
                        return -1;
 
                p->array[0] = 'a';
-               kvfree_rcu(p);
+               kvfree_rcu_mightsleep(p);
        }
 
        return 0;
index e814061d6aa010e90ab11a75e8a8171dc4cf8755..9f031eafc4651dd9f3dd414d3454addb370a1148 100644 (file)
@@ -5,18 +5,13 @@ GENERIC_VDSO_DIR := $(dir $(GENERIC_VDSO_MK_PATH))
 
 c-gettimeofday-$(CONFIG_GENERIC_GETTIMEOFDAY) := $(addprefix $(GENERIC_VDSO_DIR), gettimeofday.c)
 
-# This cmd checks that the vdso library does not contain absolute relocation
+# This cmd checks that the vdso library does not contain dynamic relocations.
 # It has to be called after the linking of the vdso library and requires it
 # as a parameter.
 #
-# $(ARCH_REL_TYPE_ABS) is defined in the arch specific makefile and corresponds
-# to the absolute relocation types printed by "objdump -R" and accepted by the
-# dynamic linker.
-ifndef ARCH_REL_TYPE_ABS
-$(error ARCH_REL_TYPE_ABS is not set)
-endif
-
+# As a workaround for some GNU ld ports which produce unneeded R_*_NONE
+# dynamic relocations, ignore R_*_NONE.
 quiet_cmd_vdso_check = VDSOCHK $@
-      cmd_vdso_check = if $(OBJDUMP) -R $@ | grep -E -h "$(ARCH_REL_TYPE_ABS)"; \
+      cmd_vdso_check = if $(READELF) -rW $@ | grep -v _NONE | grep -q " R_\w*_"; \
                       then (echo >&2 "$@: dynamic relocations are not supported"; \
                             rm -f $@; /bin/false); fi
index 7a5bf44839c9ce0d633362451dc875c7679f5ba9..f06df065dec01126c07a225e009981b809caf2b2 100644 (file)
@@ -84,7 +84,7 @@ static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {
 
 #include <linux/kernel.h>
 
-#define assert(x) WARN_ON((x))
+#define assert(x) WARN_ON(!(x))
 
 #endif /* ZSTD_DEPS_ASSERT */
 #endif /* ZSTD_DEPS_NEED_ASSERT */
index 89b269a641c7e03aeb8f54892e6c401f04ed91a0..60958afebc41506928bcc75199af86226c786443 100644 (file)
@@ -985,7 +985,7 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32
 
 static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
                            const sortedSymbol_t* sortedList,
-                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
+                           const U32* rankStart, rankValCol_t *rankValOrigin, const U32 maxWeight,
                            const U32 nbBitsBaseline)
 {
     U32* const rankVal = rankValOrigin[0];
index b9b935a9f5c0da9c6c3c5d3fc8d38fccd4fcc6ce..6b3177c947114a74723d2cd905e959fc3299237e 100644 (file)
@@ -798,7 +798,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
         if (srcSize == 0) return 0;
         RETURN_ERROR(dstBuffer_null, "");
     }
-    ZSTD_memcpy(dst, src, srcSize);
+    ZSTD_memmove(dst, src, srcSize);
     return srcSize;
 }
 
@@ -858,6 +858,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
 
     /* Loop on each block */
     while (1) {
+        BYTE* oBlockEnd = oend;
         size_t decodedSize;
         blockProperties_t blockProperties;
         size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
@@ -867,16 +868,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
         remainingSrcSize -= ZSTD_blockHeaderSize;
         RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
 
+        if (ip >= op && ip < oBlockEnd) {
+            /* We are decompressing in-place. Limit the output pointer so that we
+             * don't overwrite the block that we are currently reading. This will
+             * fail decompression if the input & output pointers aren't spaced
+             * far enough apart.
+             *
+             * This is important to set, even when the pointers are far enough
+             * apart, because ZSTD_decompressBlock_internal() can decide to store
+             * literals in the output buffer, after the block it is decompressing.
+             * Since we don't want anything to overwrite our input, we have to tell
+             * ZSTD_decompressBlock_internal to never write past ip.
+             *
+             * See ZSTD_allocateLiteralsBuffer() for reference.
+             */
+            oBlockEnd = op + (ip - op);
+        }
+
         switch(blockProperties.blockType)
         {
         case bt_compressed:
-            decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
+            decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
             break;
         case bt_raw :
+            /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
             decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
             break;
         case bt_rle :
-            decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
+            decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
             break;
         case bt_reserved :
         default:
index 4751031f3f052238f44b0eb9a4fc8eb610ae7878..ebfe5796adf83fac91c09b1920adcaa796304d8b 100644 (file)
@@ -686,7 +686,6 @@ config BOUNCE
 
 config MMU_NOTIFIER
        bool
-       select SRCU
        select INTERVAL_TREE
 
 config KSM
index a53b9360b72ec8cf3bfd8af86486a56de1b6be5a..30d2d0386fdb914a5f5a42ba302ad7157eb7a9ca 100644 (file)
@@ -507,6 +507,15 @@ static LIST_HEAD(offline_cgwbs);
 static void cleanup_offline_cgwbs_workfn(struct work_struct *work);
 static DECLARE_WORK(cleanup_offline_cgwbs_work, cleanup_offline_cgwbs_workfn);
 
+static void cgwb_free_rcu(struct rcu_head *rcu_head)
+{
+       struct bdi_writeback *wb = container_of(rcu_head,
+                       struct bdi_writeback, rcu);
+
+       percpu_ref_exit(&wb->refcnt);
+       kfree(wb);
+}
+
 static void cgwb_release_workfn(struct work_struct *work)
 {
        struct bdi_writeback *wb = container_of(work, struct bdi_writeback,
@@ -529,11 +538,10 @@ static void cgwb_release_workfn(struct work_struct *work)
        list_del(&wb->offline_node);
        spin_unlock_irq(&cgwb_lock);
 
-       percpu_ref_exit(&wb->refcnt);
        wb_exit(wb);
        bdi_put(bdi);
        WARN_ON_ONCE(!list_empty(&wb->b_attached));
-       kfree_rcu(wb, rcu);
+       call_rcu(&wb->rcu, cgwb_free_rcu);
 }
 
 static void cgwb_release(struct percpu_ref *refcnt)
index 6c655d9b5639106722baed45b3f27fae1ca20664..dd9c33fbe805273f32fbc518356d722bacf4e09b 100644 (file)
@@ -130,7 +130,6 @@ static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz)
                        accessed = false;
                else
                        accessed = true;
-               folio_put(folio);
                goto out;
        }
 
@@ -144,10 +143,10 @@ static bool damon_pa_young(unsigned long paddr, unsigned long *folio_sz)
 
        if (need_lock)
                folio_unlock(folio);
-       folio_put(folio);
 
 out:
        *folio_sz = folio_size(folio);
+       folio_put(folio);
        return accessed;
 }
 
@@ -281,8 +280,8 @@ static inline unsigned long damon_pa_mark_accessed_or_deactivate(
                        folio_mark_accessed(folio);
                else
                        folio_deactivate(folio);
-               folio_put(folio);
                applied += folio_nr_pages(folio);
+               folio_put(folio);
        }
        return applied * PAGE_SIZE;
 }
index 4fc43859e59a31932a657cd2fac2b511c00e812b..3fae2d2496ab5d9929ed5d6a862fcd7737e45f8f 100644 (file)
@@ -1838,10 +1838,10 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
        if (is_swap_pmd(*pmd)) {
                swp_entry_t entry = pmd_to_swp_entry(*pmd);
                struct page *page = pfn_swap_entry_to_page(entry);
+               pmd_t newpmd;
 
                VM_BUG_ON(!is_pmd_migration_entry(*pmd));
                if (is_writable_migration_entry(entry)) {
-                       pmd_t newpmd;
                        /*
                         * A protection check is difficult so
                         * just be safe and disable write
@@ -1855,8 +1855,16 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
                                newpmd = pmd_swp_mksoft_dirty(newpmd);
                        if (pmd_swp_uffd_wp(*pmd))
                                newpmd = pmd_swp_mkuffd_wp(newpmd);
-                       set_pmd_at(mm, addr, pmd, newpmd);
+               } else {
+                       newpmd = *pmd;
                }
+
+               if (uffd_wp)
+                       newpmd = pmd_swp_mkuffd_wp(newpmd);
+               else if (uffd_wp_resolve)
+                       newpmd = pmd_swp_clear_uffd_wp(newpmd);
+               if (!pmd_same(*pmd, newpmd))
+                       set_pmd_at(mm, addr, pmd, newpmd);
                goto unlock;
        }
 #endif
@@ -2037,7 +2045,7 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
 {
        struct mm_struct *mm = vma->vm_mm;
        pgtable_t pgtable;
-       pmd_t _pmd;
+       pmd_t _pmd, old_pmd;
        int i;
 
        /*
@@ -2048,7 +2056,7 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
         *
         * See Documentation/mm/mmu_notifier.rst
         */
-       pmdp_huge_clear_flush(vma, haddr, pmd);
+       old_pmd = pmdp_huge_clear_flush(vma, haddr, pmd);
 
        pgtable = pgtable_trans_huge_withdraw(mm, pmd);
        pmd_populate(mm, &_pmd, pgtable);
@@ -2057,6 +2065,8 @@ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma,
                pte_t *pte, entry;
                entry = pfn_pte(my_zero_pfn(haddr), vma->vm_page_prot);
                entry = pte_mkspecial(entry);
+               if (pmd_uffd_wp(old_pmd))
+                       entry = pte_mkuffd_wp(entry);
                pte = pte_offset_map(&_pmd, haddr);
                VM_BUG_ON(!pte_none(*pte));
                set_pte_at(mm, haddr, pte, entry);
@@ -2655,9 +2665,10 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
        VM_BUG_ON_FOLIO(!folio_test_large(folio), folio);
 
        is_hzp = is_huge_zero_page(&folio->page);
-       VM_WARN_ON_ONCE_FOLIO(is_hzp, folio);
-       if (is_hzp)
+       if (is_hzp) {
+               pr_warn_ratelimited("Called split_huge_page for huge zero page\n");
                return -EBUSY;
+       }
 
        if (folio_test_writeback(folio))
                return -EBUSY;
@@ -3249,6 +3260,8 @@ int set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
        pmdswp = swp_entry_to_pmd(entry);
        if (pmd_soft_dirty(pmdval))
                pmdswp = pmd_swp_mksoft_dirty(pmdswp);
+       if (pmd_uffd_wp(pmdval))
+               pmdswp = pmd_swp_mkuffd_wp(pmdswp);
        set_pmd_at(mm, address, pvmw->pmd, pmdswp);
        page_remove_rmap(page, vma, true);
        put_page(page);
index 07abcb6eb203044e39ed9cb839023774c53f3a8a..245038a9fe4eaa27e51ad83ba0abf4cb2c403deb 100644 (file)
@@ -5478,7 +5478,7 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
                       struct folio *pagecache_folio, spinlock_t *ptl)
 {
        const bool unshare = flags & FAULT_FLAG_UNSHARE;
-       pte_t pte;
+       pte_t pte = huge_ptep_get(ptep);
        struct hstate *h = hstate_vma(vma);
        struct page *old_page;
        struct folio *new_folio;
@@ -5487,6 +5487,17 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
        unsigned long haddr = address & huge_page_mask(h);
        struct mmu_notifier_range range;
 
+       /*
+        * Never handle CoW for uffd-wp protected pages.  It should be only
+        * handled when the uffd-wp protection is removed.
+        *
+        * Note that only the CoW optimization path (in hugetlb_no_page())
+        * can trigger this, because hugetlb_fault() will always resolve
+        * uffd-wp bit first.
+        */
+       if (!unshare && huge_pte_uffd_wp(pte))
+               return 0;
+
        /*
         * hugetlb does not support FOLL_FORCE-style write faults that keep the
         * PTE mapped R/O such as maybe_mkwrite() would do.
@@ -5500,7 +5511,6 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
                return 0;
        }
 
-       pte = huge_ptep_get(ptep);
        old_page = pte_page(pte);
 
        delayacct_wpcopy_start();
index 0bb95728a7845ff2210ede9c712743cee8dc6347..2de2a58d11a101d328fbb73862bd5bcaf27a1463 100644 (file)
@@ -2,5 +2,5 @@
 
 obj-y := core.o report.o
 
-CFLAGS_kfence_test.o := -g -fno-omit-frame-pointer -fno-optimize-sibling-calls
+CFLAGS_kfence_test.o := -fno-omit-frame-pointer -fno-optimize-sibling-calls
 obj-$(CONFIG_KFENCE_KUNIT_TEST) += kfence_test.o
index 5349c37a5dac9fc83f9a1eec0f12a9f6c6ab4b48..1065e0568d05a350641b4cbb6fce7ef7c808203b 100644 (file)
@@ -556,15 +556,11 @@ static unsigned long kfence_init_pool(void)
         * enters __slab_free() slow-path.
         */
        for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
-               struct slab *slab = page_slab(&pages[i]);
+               struct slab *slab = page_slab(nth_page(pages, i));
 
                if (!i || (i % 2))
                        continue;
 
-               /* Verify we do not have a compound head page. */
-               if (WARN_ON(compound_head(&pages[i]) != &pages[i]))
-                       return addr;
-
                __folio_set_slab(slab_folio(slab));
 #ifdef CONFIG_MEMCG
                slab->memcg_data = (unsigned long)&kfence_metadata[i / 2 - 1].objcg |
@@ -597,12 +593,26 @@ static unsigned long kfence_init_pool(void)
 
                /* Protect the right redzone. */
                if (unlikely(!kfence_protect(addr + PAGE_SIZE)))
-                       return addr;
+                       goto reset_slab;
 
                addr += 2 * PAGE_SIZE;
        }
 
        return 0;
+
+reset_slab:
+       for (i = 0; i < KFENCE_POOL_SIZE / PAGE_SIZE; i++) {
+               struct slab *slab = page_slab(nth_page(pages, i));
+
+               if (!i || (i % 2))
+                       continue;
+#ifdef CONFIG_MEMCG
+               slab->memcg_data = 0;
+#endif
+               __folio_clear_slab(slab_folio(slab));
+       }
+
+       return addr;
 }
 
 static bool __init kfence_init_pool_early(void)
@@ -632,16 +642,6 @@ static bool __init kfence_init_pool_early(void)
         * fails for the first page, and therefore expect addr==__kfence_pool in
         * most failure cases.
         */
-       for (char *p = (char *)addr; p < __kfence_pool + KFENCE_POOL_SIZE; p += PAGE_SIZE) {
-               struct slab *slab = virt_to_slab(p);
-
-               if (!slab)
-                       continue;
-#ifdef CONFIG_MEMCG
-               slab->memcg_data = 0;
-#endif
-               __folio_clear_slab(slab_folio(slab));
-       }
        memblock_free_late(__pa(addr), KFENCE_POOL_SIZE - (addr - (unsigned long)__kfence_pool));
        __kfence_pool = NULL;
        return false;
@@ -726,10 +726,14 @@ static const struct seq_operations objects_sops = {
 };
 DEFINE_SEQ_ATTRIBUTE(objects);
 
-static int __init kfence_debugfs_init(void)
+static int kfence_debugfs_init(void)
 {
-       struct dentry *kfence_dir = debugfs_create_dir("kfence", NULL);
+       struct dentry *kfence_dir;
+
+       if (!READ_ONCE(kfence_enabled))
+               return 0;
 
+       kfence_dir = debugfs_create_dir("kfence", NULL);
        debugfs_create_file("stats", 0444, kfence_dir, NULL, &stats_fops);
        debugfs_create_file("objects", 0400, kfence_dir, NULL, &objects_fops);
        return 0;
@@ -883,6 +887,8 @@ static int kfence_init_late(void)
        }
 
        kfence_init_enable();
+       kfence_debugfs_init();
+
        return 0;
 }
 
index 92e6f56a932da3b5ca401f62a5e956f1a7d230db..0ec69b96b497bb11db2563d70adf1604a0cfa7a9 100644 (file)
@@ -572,6 +572,10 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
                        result = SCAN_PTE_NON_PRESENT;
                        goto out;
                }
+               if (pte_uffd_wp(pteval)) {
+                       result = SCAN_PTE_UFFD_WP;
+                       goto out;
+               }
                page = vm_normal_page(vma, address, pteval);
                if (unlikely(!page) || unlikely(is_zone_device_page(page))) {
                        result = SCAN_PAGE_NULL;
index 3807502766a3e3baa639400db8e4f69224f3941e..ec0da72e65aa09a2ddd525c6cbf2f39597352699 100644 (file)
@@ -148,35 +148,74 @@ void kmsan_vunmap_range_noflush(unsigned long start, unsigned long end)
  * into the virtual memory. If those physical pages already had shadow/origin,
  * those are ignored.
  */
-void kmsan_ioremap_page_range(unsigned long start, unsigned long end,
-                             phys_addr_t phys_addr, pgprot_t prot,
-                             unsigned int page_shift)
+int kmsan_ioremap_page_range(unsigned long start, unsigned long end,
+                            phys_addr_t phys_addr, pgprot_t prot,
+                            unsigned int page_shift)
 {
        gfp_t gfp_mask = GFP_KERNEL | __GFP_ZERO;
        struct page *shadow, *origin;
        unsigned long off = 0;
-       int nr;
+       int nr, err = 0, clean = 0, mapped;
 
        if (!kmsan_enabled || kmsan_in_runtime())
-               return;
+               return 0;
 
        nr = (end - start) / PAGE_SIZE;
        kmsan_enter_runtime();
-       for (int i = 0; i < nr; i++, off += PAGE_SIZE) {
+       for (int i = 0; i < nr; i++, off += PAGE_SIZE, clean = i) {
                shadow = alloc_pages(gfp_mask, 1);
                origin = alloc_pages(gfp_mask, 1);
-               __vmap_pages_range_noflush(
+               if (!shadow || !origin) {
+                       err = -ENOMEM;
+                       goto ret;
+               }
+               mapped = __vmap_pages_range_noflush(
                        vmalloc_shadow(start + off),
                        vmalloc_shadow(start + off + PAGE_SIZE), prot, &shadow,
                        PAGE_SHIFT);
-               __vmap_pages_range_noflush(
+               if (mapped) {
+                       err = mapped;
+                       goto ret;
+               }
+               shadow = NULL;
+               mapped = __vmap_pages_range_noflush(
                        vmalloc_origin(start + off),
                        vmalloc_origin(start + off + PAGE_SIZE), prot, &origin,
                        PAGE_SHIFT);
+               if (mapped) {
+                       __vunmap_range_noflush(
+                               vmalloc_shadow(start + off),
+                               vmalloc_shadow(start + off + PAGE_SIZE));
+                       err = mapped;
+                       goto ret;
+               }
+               origin = NULL;
+       }
+       /* Page mapping loop finished normally, nothing to clean up. */
+       clean = 0;
+
+ret:
+       if (clean > 0) {
+               /*
+                * Something went wrong. Clean up shadow/origin pages allocated
+                * on the last loop iteration, then delete mappings created
+                * during the previous iterations.
+                */
+               if (shadow)
+                       __free_pages(shadow, 1);
+               if (origin)
+                       __free_pages(origin, 1);
+               __vunmap_range_noflush(
+                       vmalloc_shadow(start),
+                       vmalloc_shadow(start + clean * PAGE_SIZE));
+               __vunmap_range_noflush(
+                       vmalloc_origin(start),
+                       vmalloc_origin(start + clean * PAGE_SIZE));
        }
        flush_cache_vmap(vmalloc_shadow(start), vmalloc_shadow(end));
        flush_cache_vmap(vmalloc_origin(start), vmalloc_origin(end));
        kmsan_leave_runtime();
+       return err;
 }
 
 void kmsan_iounmap_page_range(unsigned long start, unsigned long end)
index a787c04e9583cfad45814d92d9ea8a644f6b5e25..b8bb95eea5e3de243423f122a486648b4e1a225a 100644 (file)
@@ -216,27 +216,29 @@ void kmsan_free_page(struct page *page, unsigned int order)
        kmsan_leave_runtime();
 }
 
-void kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
-                                   pgprot_t prot, struct page **pages,
-                                   unsigned int page_shift)
+int kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
+                                  pgprot_t prot, struct page **pages,
+                                  unsigned int page_shift)
 {
        unsigned long shadow_start, origin_start, shadow_end, origin_end;
        struct page **s_pages, **o_pages;
-       int nr, mapped;
+       int nr, mapped, err = 0;
 
        if (!kmsan_enabled)
-               return;
+               return 0;
 
        shadow_start = vmalloc_meta((void *)start, KMSAN_META_SHADOW);
        shadow_end = vmalloc_meta((void *)end, KMSAN_META_SHADOW);
        if (!shadow_start)
-               return;
+               return 0;
 
        nr = (end - start) / PAGE_SIZE;
        s_pages = kcalloc(nr, sizeof(*s_pages), GFP_KERNEL);
        o_pages = kcalloc(nr, sizeof(*o_pages), GFP_KERNEL);
-       if (!s_pages || !o_pages)
+       if (!s_pages || !o_pages) {
+               err = -ENOMEM;
                goto ret;
+       }
        for (int i = 0; i < nr; i++) {
                s_pages[i] = shadow_page_for(pages[i]);
                o_pages[i] = origin_page_for(pages[i]);
@@ -249,10 +251,16 @@ void kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
        kmsan_enter_runtime();
        mapped = __vmap_pages_range_noflush(shadow_start, shadow_end, prot,
                                            s_pages, page_shift);
-       KMSAN_WARN_ON(mapped);
+       if (mapped) {
+               err = mapped;
+               goto ret;
+       }
        mapped = __vmap_pages_range_noflush(origin_start, origin_end, prot,
                                            o_pages, page_shift);
-       KMSAN_WARN_ON(mapped);
+       if (mapped) {
+               err = mapped;
+               goto ret;
+       }
        kmsan_leave_runtime();
        flush_tlb_kernel_range(shadow_start, shadow_end);
        flush_tlb_kernel_range(origin_start, origin_end);
@@ -262,6 +270,7 @@ void kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
 ret:
        kfree(s_pages);
        kfree(o_pages);
+       return err;
 }
 
 /* Allocate metadata for pages allocated at boot time. */
index ad591b779d534127a0ccde6781db77ee32cee0dc..2b8d30068cbbd702862a91bd3ce9cfcecfce01e2 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -988,9 +988,15 @@ static int unmerge_and_remove_all_rmap_items(void)
 
                mm = mm_slot->slot.mm;
                mmap_read_lock(mm);
+
+               /*
+                * Exit right away if mm is exiting to avoid lockdep issue in
+                * the maple tree
+                */
+               if (ksm_test_exit(mm))
+                       goto mm_exiting;
+
                for_each_vma(vmi, vma) {
-                       if (ksm_test_exit(mm))
-                               break;
                        if (!(vma->vm_flags & VM_MERGEABLE) || !vma->anon_vma)
                                continue;
                        err = unmerge_ksm_pages(vma,
@@ -999,6 +1005,7 @@ static int unmerge_and_remove_all_rmap_items(void)
                                goto error;
                }
 
+mm_exiting:
                remove_trailing_rmap_items(&mm_slot->rmap_list);
                mmap_read_unlock(mm);
 
index 340125d08c03d9638cc5a47a19f6179039ef2b6c..9f389c5304d24f6cb27483d19853028b5f46e1e3 100644 (file)
@@ -1456,7 +1456,7 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
                size_t, vlen, int, behavior, unsigned int, flags)
 {
        ssize_t ret;
-       struct iovec iovstack[UIO_FASTIOV], iovec;
+       struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
        struct iov_iter iter;
        struct task_struct *task;
@@ -1503,12 +1503,11 @@ SYSCALL_DEFINE5(process_madvise, int, pidfd, const struct iovec __user *, vec,
        total_len = iov_iter_count(&iter);
 
        while (iov_iter_count(&iter)) {
-               iovec = iov_iter_iovec(&iter);
-               ret = do_madvise(mm, (unsigned long)iovec.iov_base,
-                                       iovec.iov_len, behavior);
+               ret = do_madvise(mm, (unsigned long)iter_iov_addr(&iter),
+                                       iter_iov_len(&iter), behavior);
                if (ret < 0)
                        break;
-               iov_iter_advance(&iter, iovec.iov_len);
+               iov_iter_advance(&iter, iter_iov_len(&iter));
        }
 
        ret = (total_len - iov_iter_count(&iter)) ? : ret;
index f456f3b5049cf1545e875436cd9138b3c2b6ead4..01a23ad48a042ddf69d0cec5cb3fb8c83b6cd2f3 100644 (file)
@@ -3563,8 +3563,21 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf)
        struct vm_area_struct *vma = vmf->vma;
        struct mmu_notifier_range range;
 
-       if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags))
+       /*
+        * We need a reference to lock the folio because we don't hold
+        * the PTL so a racing thread can remove the device-exclusive
+        * entry and unmap it. If the folio is free the entry must
+        * have been removed already. If it happens to have already
+        * been re-allocated after being freed all we do is lock and
+        * unlock it.
+        */
+       if (!folio_try_get(folio))
+               return 0;
+
+       if (!folio_lock_or_retry(folio, vma->vm_mm, vmf->flags)) {
+               folio_put(folio);
                return VM_FAULT_RETRY;
+       }
        mmu_notifier_range_init_owner(&range, MMU_NOTIFY_EXCLUSIVE, 0,
                                vma->vm_mm, vmf->address & PAGE_MASK,
                                (vmf->address & PAGE_MASK) + PAGE_SIZE, NULL);
@@ -3577,6 +3590,7 @@ static vm_fault_t remove_device_exclusive_entry(struct vm_fault *vmf)
 
        pte_unmap_unlock(vmf->pte, vmf->ptl);
        folio_unlock(folio);
+       folio_put(folio);
 
        mmu_notifier_invalidate_range_end(&range);
        return 0;
index a256a241fd1dae8d54abb08d866fa1000773c796..2068b594dc882fa0f0da9a4c781302e36423f980 100644 (file)
@@ -790,61 +790,50 @@ static int vma_replace_policy(struct vm_area_struct *vma,
        return err;
 }
 
-/* Step 2: apply policy to a range and do splits. */
-static int mbind_range(struct mm_struct *mm, unsigned long start,
-                      unsigned long end, struct mempolicy *new_pol)
+/* Split or merge the VMA (if required) and apply the new policy */
+static int mbind_range(struct vma_iterator *vmi, struct vm_area_struct *vma,
+               struct vm_area_struct **prev, unsigned long start,
+               unsigned long end, struct mempolicy *new_pol)
 {
-       VMA_ITERATOR(vmi, mm, start);
-       struct vm_area_struct *prev;
-       struct vm_area_struct *vma;
-       int err = 0;
+       struct vm_area_struct *merged;
+       unsigned long vmstart, vmend;
        pgoff_t pgoff;
+       int err;
 
-       prev = vma_prev(&vmi);
-       vma = vma_find(&vmi, end);
-       if (WARN_ON(!vma))
+       vmend = min(end, vma->vm_end);
+       if (start > vma->vm_start) {
+               *prev = vma;
+               vmstart = start;
+       } else {
+               vmstart = vma->vm_start;
+       }
+
+       if (mpol_equal(vma_policy(vma), new_pol))
                return 0;
 
-       if (start > vma->vm_start)
-               prev = vma;
-
-       do {
-               unsigned long vmstart = max(start, vma->vm_start);
-               unsigned long vmend = min(end, vma->vm_end);
-
-               if (mpol_equal(vma_policy(vma), new_pol))
-                       goto next;
-
-               pgoff = vma->vm_pgoff +
-                       ((vmstart - vma->vm_start) >> PAGE_SHIFT);
-               prev = vma_merge(&vmi, mm, prev, vmstart, vmend, vma->vm_flags,
-                                vma->anon_vma, vma->vm_file, pgoff,
-                                new_pol, vma->vm_userfaultfd_ctx,
-                                anon_vma_name(vma));
-               if (prev) {
-                       vma = prev;
-                       goto replace;
-               }
-               if (vma->vm_start != vmstart) {
-                       err = split_vma(&vmi, vma, vmstart, 1);
-                       if (err)
-                               goto out;
-               }
-               if (vma->vm_end != vmend) {
-                       err = split_vma(&vmi, vma, vmend, 0);
-                       if (err)
-                               goto out;
-               }
-replace:
-               err = vma_replace_policy(vma, new_pol);
+       pgoff = vma->vm_pgoff + ((vmstart - vma->vm_start) >> PAGE_SHIFT);
+       merged = vma_merge(vmi, vma->vm_mm, *prev, vmstart, vmend, vma->vm_flags,
+                        vma->anon_vma, vma->vm_file, pgoff, new_pol,
+                        vma->vm_userfaultfd_ctx, anon_vma_name(vma));
+       if (merged) {
+               *prev = merged;
+               return vma_replace_policy(merged, new_pol);
+       }
+
+       if (vma->vm_start != vmstart) {
+               err = split_vma(vmi, vma, vmstart, 1);
                if (err)
-                       goto out;
-next:
-               prev = vma;
-       } for_each_vma_range(vmi, vma, end);
+                       return err;
+       }
 
-out:
-       return err;
+       if (vma->vm_end != vmend) {
+               err = split_vma(vmi, vma, vmend, 0);
+               if (err)
+                       return err;
+       }
+
+       *prev = vma;
+       return vma_replace_policy(vma, new_pol);
 }
 
 /* Set the process memory policy */
@@ -1259,6 +1248,8 @@ static long do_mbind(unsigned long start, unsigned long len,
                     nodemask_t *nmask, unsigned long flags)
 {
        struct mm_struct *mm = current->mm;
+       struct vm_area_struct *vma, *prev;
+       struct vma_iterator vmi;
        struct mempolicy *new;
        unsigned long end;
        int err;
@@ -1328,7 +1319,13 @@ static long do_mbind(unsigned long start, unsigned long len,
                goto up_out;
        }
 
-       err = mbind_range(mm, start, end, new);
+       vma_iter_init(&vmi, mm, start);
+       prev = vma_prev(&vmi);
+       for_each_vma_range(vmi, vma, end) {
+               err = mbind_range(&vmi, vma, &prev, start, end, new);
+               if (err)
+                       break;
+       }
 
        if (!err) {
                int nr_failed = 0;
@@ -1489,10 +1486,8 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le
                unsigned long, home_node, unsigned long, flags)
 {
        struct mm_struct *mm = current->mm;
-       struct vm_area_struct *vma;
+       struct vm_area_struct *vma, *prev;
        struct mempolicy *new, *old;
-       unsigned long vmstart;
-       unsigned long vmend;
        unsigned long end;
        int err = -ENOENT;
        VMA_ITERATOR(vmi, mm, start);
@@ -1521,6 +1516,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le
        if (end == start)
                return 0;
        mmap_write_lock(mm);
+       prev = vma_prev(&vmi);
        for_each_vma_range(vmi, vma, end) {
                /*
                 * If any vma in the range got policy other than MPOL_BIND
@@ -1541,9 +1537,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le
                }
 
                new->home_node = home_node;
-               vmstart = max(start, vma->vm_start);
-               vmend   = min(end, vma->vm_end);
-               err = mbind_range(mm, vmstart, vmend, new);
+               err = mbind_range(&vmi, vma, &prev, start, end, new);
                mpol_put(new);
                if (err)
                        break;
index 98f1c11197a8c5f057ed23f5aea9cdc62536bed4..db3f154446af4e1210d7557bcb65eaa57cae03e8 100644 (file)
@@ -1112,9 +1112,8 @@ static void migrate_folio_done(struct folio *src,
 /* Obtain the lock on page, remove all ptes. */
 static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page,
                               unsigned long private, struct folio *src,
-                              struct folio **dstp, int force, bool avoid_force_lock,
-                              enum migrate_mode mode, enum migrate_reason reason,
-                              struct list_head *ret)
+                              struct folio **dstp, enum migrate_mode mode,
+                              enum migrate_reason reason, struct list_head *ret)
 {
        struct folio *dst;
        int rc = -EAGAIN;
@@ -1144,7 +1143,7 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page
        dst->private = NULL;
 
        if (!folio_trylock(src)) {
-               if (!force || mode == MIGRATE_ASYNC)
+               if (mode == MIGRATE_ASYNC)
                        goto out;
 
                /*
@@ -1163,17 +1162,6 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page
                if (current->flags & PF_MEMALLOC)
                        goto out;
 
-               /*
-                * We have locked some folios and are going to wait to lock
-                * this folio.  To avoid a potential deadlock, let's bail
-                * out and not do that. The locked folios will be moved and
-                * unlocked, then we can wait to lock this folio.
-                */
-               if (avoid_force_lock) {
-                       rc = -EDEADLOCK;
-                       goto out;
-               }
-
                folio_lock(src);
        }
        locked = true;
@@ -1193,8 +1181,6 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page
                        rc = -EBUSY;
                        goto out;
                }
-               if (!force)
-                       goto out;
                folio_wait_writeback(src);
        }
 
@@ -1253,7 +1239,7 @@ static int migrate_folio_unmap(new_page_t get_new_page, free_page_t put_new_page
                /* Establish migration ptes */
                VM_BUG_ON_FOLIO(folio_test_anon(src) &&
                               !folio_test_ksm(src) && !anon_vma, src);
-               try_to_migrate(src, TTU_BATCH_FLUSH);
+               try_to_migrate(src, mode == MIGRATE_ASYNC ? TTU_BATCH_FLUSH : 0);
                page_was_mapped = 1;
        }
 
@@ -1267,7 +1253,7 @@ out:
         * A folio that has not been unmapped will be restored to
         * right list unless we want to retry.
         */
-       if (rc == -EAGAIN || rc == -EDEADLOCK)
+       if (rc == -EAGAIN)
                ret = NULL;
 
        migrate_folio_undo_src(src, page_was_mapped, anon_vma, locked, ret);
@@ -1508,6 +1494,9 @@ static inline int try_split_folio(struct folio *folio, struct list_head *split_f
 #define NR_MAX_BATCHED_MIGRATION       512
 #endif
 #define NR_MAX_MIGRATE_PAGES_RETRY     10
+#define NR_MAX_MIGRATE_ASYNC_RETRY     3
+#define NR_MAX_MIGRATE_SYNC_RETRY                                      \
+       (NR_MAX_MIGRATE_PAGES_RETRY - NR_MAX_MIGRATE_ASYNC_RETRY)
 
 struct migrate_pages_stats {
        int nr_succeeded;       /* Normal and large folios migrated successfully, in
@@ -1618,13 +1607,19 @@ static int migrate_hugetlbs(struct list_head *from, new_page_t get_new_page,
 /*
  * migrate_pages_batch() first unmaps folios in the from list as many as
  * possible, then move the unmapped folios.
+ *
+ * We only batch migration if mode == MIGRATE_ASYNC to avoid to wait a
+ * lock or bit when we have locked more than one folio.  Which may cause
+ * deadlock (e.g., for loop device).  So, if mode != MIGRATE_ASYNC, the
+ * length of the from list must be <= 1.
  */
 static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page,
                free_page_t put_new_page, unsigned long private,
                enum migrate_mode mode, int reason, struct list_head *ret_folios,
-               struct migrate_pages_stats *stats)
+               struct list_head *split_folios, struct migrate_pages_stats *stats,
+               int nr_pass)
 {
-       int retry;
+       int retry = 1;
        int large_retry = 1;
        int thp_retry = 1;
        int nr_failed = 0;
@@ -1634,21 +1629,15 @@ static int migrate_pages_batch(struct list_head *from, new_page_t get_new_page,
        bool is_large = false;
        bool is_thp = false;
        struct folio *folio, *folio2, *dst = NULL, *dst2;
-       int rc, rc_saved, nr_pages;
-       LIST_HEAD(split_folios);
+       int rc, rc_saved = 0, nr_pages;
        LIST_HEAD(unmap_folios);
        LIST_HEAD(dst_folios);
        bool nosplit = (reason == MR_NUMA_MISPLACED);
-       bool no_split_folio_counting = false;
-       bool avoid_force_lock;
 
-retry:
-       rc_saved = 0;
-       avoid_force_lock = false;
-       retry = 1;
-       for (pass = 0;
-            pass < NR_MAX_MIGRATE_PAGES_RETRY && (retry || large_retry);
-            pass++) {
+       VM_WARN_ON_ONCE(mode != MIGRATE_ASYNC &&
+                       !list_empty(from) && !list_is_singular(from));
+
+       for (pass = 0; pass < nr_pass && (retry || large_retry); pass++) {
                retry = 0;
                large_retry = 0;
                thp_retry = 0;
@@ -1679,7 +1668,7 @@ retry:
                        if (!thp_migration_supported() && is_thp) {
                                nr_large_failed++;
                                stats->nr_thp_failed++;
-                               if (!try_split_folio(folio, &split_folios)) {
+                               if (!try_split_folio(folio, split_folios)) {
                                        stats->nr_thp_split++;
                                        continue;
                                }
@@ -1689,15 +1678,13 @@ retry:
                        }
 
                        rc = migrate_folio_unmap(get_new_page, put_new_page, private,
-                                                folio, &dst, pass > 2, avoid_force_lock,
-                                                mode, reason, ret_folios);
+                                                folio, &dst, mode, reason, ret_folios);
                        /*
                         * The rules are:
                         *      Success: folio will be freed
                         *      Unmap: folio will be put on unmap_folios list,
                         *             dst folio put on dst_folios list
                         *      -EAGAIN: stay on the from list
-                        *      -EDEADLOCK: stay on the from list
                         *      -ENOMEM: stay on the from list
                         *      Other errno: put on ret_folios list
                         */
@@ -1712,7 +1699,7 @@ retry:
                                        stats->nr_thp_failed += is_thp;
                                        /* Large folio NUMA faulting doesn't split to retry. */
                                        if (!nosplit) {
-                                               int ret = try_split_folio(folio, &split_folios);
+                                               int ret = try_split_folio(folio, split_folios);
 
                                                if (!ret) {
                                                        stats->nr_thp_split += is_thp;
@@ -1729,18 +1716,11 @@ retry:
                                                        break;
                                                }
                                        }
-                               } else if (!no_split_folio_counting) {
+                               } else {
                                        nr_failed++;
                                }
 
                                stats->nr_failed_pages += nr_pages + nr_retry_pages;
-                               /*
-                                * There might be some split folios of fail-to-migrate large
-                                * folios left in split_folios list. Move them to ret_folios
-                                * list so that they could be put back to the right list by
-                                * the caller otherwise the folio refcnt will be leaked.
-                                */
-                               list_splice_init(&split_folios, ret_folios);
                                /* nr_failed isn't updated for not used */
                                nr_large_failed += large_retry;
                                stats->nr_thp_failed += thp_retry;
@@ -1749,19 +1729,11 @@ retry:
                                        goto out;
                                else
                                        goto move;
-                       case -EDEADLOCK:
-                               /*
-                                * The folio cannot be locked for potential deadlock.
-                                * Go move (and unlock) all locked folios.  Then we can
-                                * try again.
-                                */
-                               rc_saved = rc;
-                               goto move;
                        case -EAGAIN:
                                if (is_large) {
                                        large_retry++;
                                        thp_retry += is_thp;
-                               } else if (!no_split_folio_counting) {
+                               } else {
                                        retry++;
                                }
                                nr_retry_pages += nr_pages;
@@ -1771,11 +1743,6 @@ retry:
                                stats->nr_thp_succeeded += is_thp;
                                break;
                        case MIGRATEPAGE_UNMAP:
-                               /*
-                                * We have locked some folios, don't force lock
-                                * to avoid deadlock.
-                                */
-                               avoid_force_lock = true;
                                list_move_tail(&folio->lru, &unmap_folios);
                                list_add_tail(&dst->lru, &dst_folios);
                                break;
@@ -1789,7 +1756,7 @@ retry:
                                if (is_large) {
                                        nr_large_failed++;
                                        stats->nr_thp_failed += is_thp;
-                               } else if (!no_split_folio_counting) {
+                               } else {
                                        nr_failed++;
                                }
 
@@ -1807,9 +1774,7 @@ move:
        try_to_unmap_flush();
 
        retry = 1;
-       for (pass = 0;
-            pass < NR_MAX_MIGRATE_PAGES_RETRY && (retry || large_retry);
-            pass++) {
+       for (pass = 0; pass < nr_pass && (retry || large_retry); pass++) {
                retry = 0;
                large_retry = 0;
                thp_retry = 0;
@@ -1838,7 +1803,7 @@ move:
                                if (is_large) {
                                        large_retry++;
                                        thp_retry += is_thp;
-                               } else if (!no_split_folio_counting) {
+                               } else {
                                        retry++;
                                }
                                nr_retry_pages += nr_pages;
@@ -1851,7 +1816,7 @@ move:
                                if (is_large) {
                                        nr_large_failed++;
                                        stats->nr_thp_failed += is_thp;
-                               } else if (!no_split_folio_counting) {
+                               } else {
                                        nr_failed++;
                                }
 
@@ -1888,30 +1853,52 @@ out:
                dst2 = list_next_entry(dst, lru);
        }
 
-       /*
-        * Try to migrate split folios of fail-to-migrate large folios, no
-        * nr_failed counting in this round, since all split folios of a
-        * large folio is counted as 1 failure in the first round.
-        */
-       if (rc >= 0 && !list_empty(&split_folios)) {
-               /*
-                * Move non-migrated folios (after NR_MAX_MIGRATE_PAGES_RETRY
-                * retries) to ret_folios to avoid migrating them again.
-                */
-               list_splice_init(from, ret_folios);
-               list_splice_init(&split_folios, from);
-               no_split_folio_counting = true;
-               goto retry;
-       }
+       return rc;
+}
 
+static int migrate_pages_sync(struct list_head *from, new_page_t get_new_page,
+               free_page_t put_new_page, unsigned long private,
+               enum migrate_mode mode, int reason, struct list_head *ret_folios,
+               struct list_head *split_folios, struct migrate_pages_stats *stats)
+{
+       int rc, nr_failed = 0;
+       LIST_HEAD(folios);
+       struct migrate_pages_stats astats;
+
+       memset(&astats, 0, sizeof(astats));
+       /* Try to migrate in batch with MIGRATE_ASYNC mode firstly */
+       rc = migrate_pages_batch(from, get_new_page, put_new_page, private, MIGRATE_ASYNC,
+                                reason, &folios, split_folios, &astats,
+                                NR_MAX_MIGRATE_ASYNC_RETRY);
+       stats->nr_succeeded += astats.nr_succeeded;
+       stats->nr_thp_succeeded += astats.nr_thp_succeeded;
+       stats->nr_thp_split += astats.nr_thp_split;
+       if (rc < 0) {
+               stats->nr_failed_pages += astats.nr_failed_pages;
+               stats->nr_thp_failed += astats.nr_thp_failed;
+               list_splice_tail(&folios, ret_folios);
+               return rc;
+       }
+       stats->nr_thp_failed += astats.nr_thp_split;
+       nr_failed += astats.nr_thp_split;
        /*
-        * We have unlocked all locked folios, so we can force lock now, let's
-        * try again.
+        * Fall back to migrate all failed folios one by one synchronously. All
+        * failed folios except split THPs will be retried, so their failure
+        * isn't counted
         */
-       if (rc == -EDEADLOCK)
-               goto retry;
+       list_splice_tail_init(&folios, from);
+       while (!list_empty(from)) {
+               list_move(from->next, &folios);
+               rc = migrate_pages_batch(&folios, get_new_page, put_new_page,
+                                        private, mode, reason, ret_folios,
+                                        split_folios, stats, NR_MAX_MIGRATE_SYNC_RETRY);
+               list_splice_tail_init(&folios, ret_folios);
+               if (rc < 0)
+                       return rc;
+               nr_failed += rc;
+       }
 
-       return rc;
+       return nr_failed;
 }
 
 /*
@@ -1949,6 +1936,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
        struct folio *folio, *folio2;
        LIST_HEAD(folios);
        LIST_HEAD(ret_folios);
+       LIST_HEAD(split_folios);
        struct migrate_pages_stats stats;
 
        trace_mm_migrate_pages_start(mode, reason);
@@ -1959,6 +1947,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
                                     mode, reason, &stats, &ret_folios);
        if (rc_gather < 0)
                goto out;
+
 again:
        nr_pages = 0;
        list_for_each_entry_safe(folio, folio2, from, lru) {
@@ -1969,20 +1958,36 @@ again:
                }
 
                nr_pages += folio_nr_pages(folio);
-               if (nr_pages > NR_MAX_BATCHED_MIGRATION)
+               if (nr_pages >= NR_MAX_BATCHED_MIGRATION)
                        break;
        }
-       if (nr_pages > NR_MAX_BATCHED_MIGRATION)
-               list_cut_before(&folios, from, &folio->lru);
+       if (nr_pages >= NR_MAX_BATCHED_MIGRATION)
+               list_cut_before(&folios, from, &folio2->lru);
        else
                list_splice_init(from, &folios);
-       rc = migrate_pages_batch(&folios, get_new_page, put_new_page, private,
-                                mode, reason, &ret_folios, &stats);
+       if (mode == MIGRATE_ASYNC)
+               rc = migrate_pages_batch(&folios, get_new_page, put_new_page, private,
+                                        mode, reason, &ret_folios, &split_folios, &stats,
+                                        NR_MAX_MIGRATE_PAGES_RETRY);
+       else
+               rc = migrate_pages_sync(&folios, get_new_page, put_new_page, private,
+                                       mode, reason, &ret_folios, &split_folios, &stats);
        list_splice_tail_init(&folios, &ret_folios);
        if (rc < 0) {
                rc_gather = rc;
+               list_splice_tail(&split_folios, &ret_folios);
                goto out;
        }
+       if (!list_empty(&split_folios)) {
+               /*
+                * Failure isn't counted since all split folios of a large folio
+                * is counted as 1 failure already.  And, we only try to migrate
+                * with minimal effort, force MIGRATE_ASYNC mode and retry once.
+                */
+               migrate_pages_batch(&split_folios, get_new_page, put_new_page, private,
+                                   MIGRATE_ASYNC, reason, &ret_folios, NULL, &stats, 1);
+               list_splice_tail_init(&split_folios, &ret_folios);
+       }
        rc_gather += rc;
        if (!list_empty(from))
                goto again;
index cd69b9db00812655c42fdc91957d6826bd97d9d6..d359650b0f75b9c099e75ecd994a0b82ac38a9fa 100644 (file)
@@ -33,7 +33,7 @@ static int mincore_hugetlb(pte_t *pte, unsigned long hmask, unsigned long addr,
         * Hugepages under user process are always in RAM and never
         * swapped out, but theoretically it needs to be checked.
         */
-       present = pte && !huge_pte_none(huge_ptep_get(pte));
+       present = pte && !huge_pte_none_mostly(huge_ptep_get(pte));
        for (; addr != end; vec++, addr += PAGE_SIZE)
                *vec = present;
        walk->private = vec;
index 740b54be3ed4140f16a6731a275ab49f3a8b256f..d5475fbf572969dd14361e8781620b027dec6b0e 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1518,7 +1518,8 @@ static inline int accountable_mapping(struct file *file, vm_flags_t vm_flags)
  */
 static unsigned long unmapped_area(struct vm_unmapped_area_info *info)
 {
-       unsigned long length, gap;
+       unsigned long length, gap, low_limit;
+       struct vm_area_struct *tmp;
 
        MA_STATE(mas, &current->mm->mm_mt, 0, 0);
 
@@ -1527,12 +1528,29 @@ static unsigned long unmapped_area(struct vm_unmapped_area_info *info)
        if (length < info->length)
                return -ENOMEM;
 
-       if (mas_empty_area(&mas, info->low_limit, info->high_limit - 1,
-                                 length))
+       low_limit = info->low_limit;
+retry:
+       if (mas_empty_area(&mas, low_limit, info->high_limit - 1, length))
                return -ENOMEM;
 
        gap = mas.index;
        gap += (info->align_offset - gap) & info->align_mask;
+       tmp = mas_next(&mas, ULONG_MAX);
+       if (tmp && (tmp->vm_flags & VM_GROWSDOWN)) { /* Avoid prev check if possible */
+               if (vm_start_gap(tmp) < gap + length - 1) {
+                       low_limit = tmp->vm_end;
+                       mas_reset(&mas);
+                       goto retry;
+               }
+       } else {
+               tmp = mas_prev(&mas, 0);
+               if (tmp && vm_end_gap(tmp) > gap) {
+                       low_limit = vm_end_gap(tmp);
+                       mas_reset(&mas);
+                       goto retry;
+               }
+       }
+
        return gap;
 }
 
@@ -1548,7 +1566,8 @@ static unsigned long unmapped_area(struct vm_unmapped_area_info *info)
  */
 static unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
 {
-       unsigned long length, gap;
+       unsigned long length, gap, high_limit, gap_end;
+       struct vm_area_struct *tmp;
 
        MA_STATE(mas, &current->mm->mm_mt, 0, 0);
        /* Adjust search length to account for worst case alignment overhead */
@@ -1556,12 +1575,31 @@ static unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
        if (length < info->length)
                return -ENOMEM;
 
-       if (mas_empty_area_rev(&mas, info->low_limit, info->high_limit - 1,
+       high_limit = info->high_limit;
+retry:
+       if (mas_empty_area_rev(&mas, info->low_limit, high_limit - 1,
                                length))
                return -ENOMEM;
 
        gap = mas.last + 1 - info->length;
        gap -= (gap - info->align_offset) & info->align_mask;
+       gap_end = mas.last;
+       tmp = mas_next(&mas, ULONG_MAX);
+       if (tmp && (tmp->vm_flags & VM_GROWSDOWN)) { /* Avoid prev check if possible */
+               if (vm_start_gap(tmp) <= gap_end) {
+                       high_limit = vm_start_gap(tmp);
+                       mas_reset(&mas);
+                       goto retry;
+               }
+       } else {
+               tmp = mas_prev(&mas, 0);
+               if (tmp && vm_end_gap(tmp) > gap) {
+                       high_limit = tmp->vm_start;
+                       mas_reset(&mas);
+                       goto retry;
+               }
+       }
+
        return gap;
 }
 
@@ -2277,7 +2315,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
        int count = 0;
        int error = -ENOMEM;
        MA_STATE(mas_detach, &mt_detach, 0, 0);
-       mt_init_flags(&mt_detach, MT_FLAGS_LOCK_EXTERN);
+       mt_init_flags(&mt_detach, vmi->mas.tree->ma_flags & MT_FLAGS_LOCK_MASK);
        mt_set_external_lock(&mt_detach, &mm->mmap_lock);
 
        /*
@@ -2621,12 +2659,7 @@ cannot_expand:
 
        if (map_deny_write_exec(vma, vma->vm_flags)) {
                error = -EACCES;
-               if (file)
-                       goto close_and_free_vma;
-               else if (vma->vm_file)
-                       goto unmap_and_free_vma;
-               else
-                       goto free_vma;
+               goto close_and_free_vma;
        }
 
        /* Allow architectures to sanity-check the vm_flags */
@@ -3042,6 +3075,7 @@ void exit_mmap(struct mm_struct *mm)
         */
        set_bit(MMF_OOM_SKIP, &mm->flags);
        mmap_write_lock(mm);
+       mt_clear_in_rcu(&mm->mm_mt);
        free_pgtables(&tlb, &mm->mm_mt, vma, FIRST_USER_ADDRESS,
                      USER_PGTABLES_CEILING);
        tlb_finish_mmu(&tlb);
index 231929f119d958f73aba0680b6ed8bae8493b35d..36351a00c0e82de1508575f152b816c4d40cf66c 100644 (file)
@@ -805,7 +805,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
 
                if (map_deny_write_exec(vma, newflags)) {
                        error = -EACCES;
-                       goto out;
+                       break;
                }
 
                /* Allow architectures to sanity-check the new flags */
@@ -838,7 +838,7 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
        }
        tlb_finish_mmu(&tlb);
 
-       if (vma_iter_end(&vmi) < end)
+       if (!error && vma_iter_end(&vmi) < end)
                error = -ENOMEM;
 
 out:
index 516b1aa247e83fd4564dfcea0f8892c8481a1dab..db7943999007346c279bb79185efba4b4384a6bb 100644 (file)
@@ -2583,46 +2583,6 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc)
        return ret;
 }
 
-/**
- * folio_write_one - write out a single folio and wait on I/O.
- * @folio: The folio to write.
- *
- * The folio must be locked by the caller and will be unlocked upon return.
- *
- * Note that the mapping's AS_EIO/AS_ENOSPC flags will be cleared when this
- * function returns.
- *
- * Return: %0 on success, negative error code otherwise
- */
-int folio_write_one(struct folio *folio)
-{
-       struct address_space *mapping = folio->mapping;
-       int ret = 0;
-       struct writeback_control wbc = {
-               .sync_mode = WB_SYNC_ALL,
-               .nr_to_write = folio_nr_pages(folio),
-       };
-
-       BUG_ON(!folio_test_locked(folio));
-
-       folio_wait_writeback(folio);
-
-       if (folio_clear_dirty_for_io(folio)) {
-               folio_get(folio);
-               ret = mapping->a_ops->writepage(&folio->page, &wbc);
-               if (ret == 0)
-                       folio_wait_writeback(folio);
-               folio_put(folio);
-       } else {
-               folio_unlock(folio);
-       }
-
-       if (!ret)
-               ret = filemap_check_errors(mapping);
-       return ret;
-}
-EXPORT_SYMBOL(folio_write_one);
-
 /*
  * For address_spaces which do not use buffers nor write back.
  */
index ac1fc986af44c46736d4891dea771473c3bee7f1..8e39705c7bdc29f7669fae143af05100b0d93a61 100644 (file)
@@ -1398,6 +1398,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
                        unsigned int order, bool check_free, fpi_t fpi_flags)
 {
        int bad = 0;
+       bool skip_kasan_poison = should_skip_kasan_poison(page, fpi_flags);
        bool init = want_init_on_free();
 
        VM_BUG_ON_PAGE(PageTail(page), page);
@@ -1470,7 +1471,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
         * With hardware tag-based KASAN, memory tags must be set before the
         * page becomes unavailable via debug_pagealloc or arch_free_page.
         */
-       if (!should_skip_kasan_poison(page, fpi_flags)) {
+       if (!skip_kasan_poison) {
                kasan_poison_pages(page, order, init);
 
                /* Memory is already initialized if KASAN did it internally. */
@@ -6631,7 +6632,21 @@ static void __build_all_zonelists(void *data)
        int nid;
        int __maybe_unused cpu;
        pg_data_t *self = data;
+       unsigned long flags;
 
+       /*
+        * Explicitly disable this CPU's interrupts before taking seqlock
+        * to prevent any IRQ handler from calling into the page allocator
+        * (e.g. GFP_ATOMIC) that could hit zonelist_iter_begin and livelock.
+        */
+       local_irq_save(flags);
+       /*
+        * Explicitly disable this CPU's synchronous printk() before taking
+        * seqlock to prevent any printk() from trying to hold port->lock, for
+        * tty_insert_flip_string_and_push_buffer() on other CPU might be
+        * calling kmalloc(GFP_ATOMIC | __GFP_NOWARN) with port->lock held.
+        */
+       printk_deferred_enter();
        write_seqlock(&zonelist_update_seq);
 
 #ifdef CONFIG_NUMA
@@ -6670,6 +6685,8 @@ static void __build_all_zonelists(void *data)
        }
 
        write_sequnlock(&zonelist_update_seq);
+       printk_deferred_exit();
+       local_irq_restore(flags);
 }
 
 static noinline void __init
@@ -9449,6 +9466,9 @@ static bool pfn_range_valid_contig(struct zone *z, unsigned long start_pfn,
 
                if (PageReserved(page))
                        return false;
+
+               if (PageHuge(page))
+                       return false;
        }
        return true;
 }
index 448f393d8ab2b1bd5f22eec603195977716a8727..b76521ed372dfdfc03117b2773b39f104b9901a6 100644 (file)
@@ -3339,10 +3339,6 @@ static const struct xattr_handler shmem_trusted_xattr_handler = {
 };
 
 static const struct xattr_handler *shmem_xattr_handlers[] = {
-#ifdef CONFIG_TMPFS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &shmem_security_xattr_handler,
        &shmem_trusted_xattr_handler,
        NULL
index dabc2a671fc6f7ffc5da481a3b7a9574500cdb0a..edbe722fb906481fc151f7038652894b85b5b5cc 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -839,7 +839,7 @@ static int init_cache_node(struct kmem_cache *cachep, int node, gfp_t gfp)
        return 0;
 }
 
-#if (defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG)) || defined(CONFIG_SMP)
+#if defined(CONFIG_NUMA) || defined(CONFIG_SMP)
 /*
  * Allocates and initializes node for a node on each slab cache, used for
  * either memory or cpu hotplug.  If memory is being hot-added, the kmem_cache_node
index 57cb01b042f6231b87378529fe02c84116afb968..423199ee8478c19542126c029c7dbd2f7a4db6bc 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -222,7 +222,7 @@ static void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn)
        if (lruvec)
                unlock_page_lruvec_irqrestore(lruvec, flags);
        folios_put(fbatch->folios, folio_batch_count(fbatch));
-       folio_batch_init(fbatch);
+       folio_batch_reinit(fbatch);
 }
 
 static void folio_batch_add_and_move(struct folio_batch *fbatch,
index 62ba2bf577d7e7210398181b47f11fca9e5f5099..2c718f45745f8c87fdac889fa3d255ffa58b774a 100644 (file)
@@ -679,6 +679,7 @@ static void __del_from_avail_list(struct swap_info_struct *p)
 {
        int nid;
 
+       assert_spin_locked(&p->lock);
        for_each_node(nid)
                plist_del(&p->avail_lists[nid], &swap_avail_heads[nid]);
 }
@@ -2434,8 +2435,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
                spin_unlock(&swap_lock);
                goto out_dput;
        }
-       del_from_avail_list(p);
        spin_lock(&p->lock);
+       del_from_avail_list(p);
        if (p->prio < 0) {
                struct swap_info_struct *si = p;
                int nid;
index ef910bf349e1361e64edc0ed0166605160a0fe52..31ff782d368b02138b4cc2606290aba862c7ebd7 100644 (file)
@@ -313,8 +313,8 @@ int ioremap_page_range(unsigned long addr, unsigned long end,
                                 ioremap_max_page_shift);
        flush_cache_vmap(addr, end);
        if (!err)
-               kmsan_ioremap_page_range(addr, end, phys_addr, prot,
-                                        ioremap_max_page_shift);
+               err = kmsan_ioremap_page_range(addr, end, phys_addr, prot,
+                                              ioremap_max_page_shift);
        return err;
 }
 
@@ -605,7 +605,11 @@ int __vmap_pages_range_noflush(unsigned long addr, unsigned long end,
 int vmap_pages_range_noflush(unsigned long addr, unsigned long end,
                pgprot_t prot, struct page **pages, unsigned int page_shift)
 {
-       kmsan_vmap_pages_range_noflush(addr, end, prot, pages, page_shift);
+       int ret = kmsan_vmap_pages_range_noflush(addr, end, prot, pages,
+                                                page_shift);
+
+       if (ret)
+               return ret;
        return __vmap_pages_range_noflush(addr, end, prot, pages, page_shift);
 }
 
@@ -2883,6 +2887,8 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
                unsigned int order, unsigned int nr_pages, struct page **pages)
 {
        unsigned int nr_allocated = 0;
+       gfp_t alloc_gfp = gfp;
+       bool nofail = false;
        struct page *page;
        int i;
 
@@ -2893,6 +2899,7 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
         * more permissive.
         */
        if (!order) {
+               /* bulk allocator doesn't support nofail req. officially */
                gfp_t bulk_gfp = gfp & ~__GFP_NOFAIL;
 
                while (nr_allocated < nr_pages) {
@@ -2931,20 +2938,35 @@ vm_area_alloc_pages(gfp_t gfp, int nid,
                        if (nr != nr_pages_request)
                                break;
                }
+       } else if (gfp & __GFP_NOFAIL) {
+               /*
+                * Higher order nofail allocations are really expensive and
+                * potentially dangerous (pre-mature OOM, disruptive reclaim
+                * and compaction etc.
+                */
+               alloc_gfp &= ~__GFP_NOFAIL;
+               nofail = true;
        }
 
        /* High-order pages or fallback path if "bulk" fails. */
-
        while (nr_allocated < nr_pages) {
                if (fatal_signal_pending(current))
                        break;
 
                if (nid == NUMA_NO_NODE)
-                       page = alloc_pages(gfp, order);
+                       page = alloc_pages(alloc_gfp, order);
                else
-                       page = alloc_pages_node(nid, gfp, order);
-               if (unlikely(!page))
-                       break;
+                       page = alloc_pages_node(nid, alloc_gfp, order);
+               if (unlikely(!page)) {
+                       if (!nofail)
+                               break;
+
+                       /* fall back to the zero order allocations */
+                       alloc_gfp |= __GFP_NOFAIL;
+                       order = 0;
+                       continue;
+               }
+
                /*
                 * Higher order allocations must be able to be treated as
                 * indepdenent small pages by callers (as they can with
@@ -3024,9 +3046,11 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
         * allocation request, free them via vfree() if any.
         */
        if (area->nr_pages != nr_small_pages) {
-               warn_alloc(gfp_mask, NULL,
-                       "vmalloc error: size %lu, page order %u, failed to allocate pages",
-                       area->nr_pages * PAGE_SIZE, page_order);
+               /* vm_area_alloc_pages() can also fail due to a fatal signal */
+               if (!fatal_signal_pending(current))
+                       warn_alloc(gfp_mask, NULL,
+                               "vmalloc error: size %lu, page order %u, failed to allocate pages",
+                               area->nr_pages * PAGE_SIZE, page_order);
                goto fail;
        }
 
index 9c1c5e8b24b8f56fe05d8d3883ce17ffaa2eb7f3..7ba6bfdd9a5f7bf3ef357947bb98c25b87da2c07 100644 (file)
@@ -1151,12 +1151,12 @@ void reclaim_throttle(pg_data_t *pgdat, enum vmscan_throttle_state reason)
        DEFINE_WAIT(wait);
 
        /*
-        * Do not throttle IO workers, kthreads other than kswapd or
+        * Do not throttle user workers, kthreads other than kswapd or
         * workqueues. They may be required for reclaim to make
         * forward progress (e.g. journalling workqueues or kthreads).
         */
        if (!current_is_kswapd() &&
-           current->flags & (PF_IO_WORKER|PF_KTHREAD)) {
+           current->flags & (PF_USER_WORKER|PF_KTHREAD)) {
                cond_resched();
                return;
        }
index c64050e839ac6faccd7f9741654cfa74bf661836..1fffe2bed5b02f3480b9f074d8b472016708729f 100644 (file)
@@ -280,6 +280,10 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
        write_unlock(&xen_9pfs_lock);
 
        for (i = 0; i < priv->num_rings; i++) {
+               struct xen_9pfs_dataring *ring = &priv->rings[i];
+
+               cancel_work_sync(&ring->work);
+
                if (!priv->rings[i].intf)
                        break;
                if (priv->rings[i].irq > 0)
index 17b946f9ba317c7c04222379f95b12e104f88a87..8455ba141ee6192cb039020e58de6c662e4d34f9 100644 (file)
@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
 };
 
 /* This function requires the caller holds hdev->lock */
-static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
+static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
 {
        struct hci_conn_params *params;
        struct hci_dev *hdev = conn->hdev;
@@ -88,9 +88,28 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
 
        params = hci_pend_le_action_lookup(&hdev->pend_le_conns, bdaddr,
                                           bdaddr_type);
-       if (!params || !params->explicit_connect)
+       if (!params)
                return;
 
+       if (params->conn) {
+               hci_conn_drop(params->conn);
+               hci_conn_put(params->conn);
+               params->conn = NULL;
+       }
+
+       if (!params->explicit_connect)
+               return;
+
+       /* If the status indicates successful cancellation of
+        * the attempt (i.e. Unknown Connection Id) there's no point of
+        * notifying failure since we'll go back to keep trying to
+        * connect. The only exception is explicit connect requests
+        * where a timeout + cancel does indicate an actual failure.
+        */
+       if (status && status != HCI_ERROR_UNKNOWN_CONN_ID)
+               mgmt_connect_failed(hdev, &conn->dst, conn->type,
+                                   conn->dst_type, status);
+
        /* The connection attempt was doing scan for new RPA, and is
         * in scan phase. If params are not associated with any other
         * autoconnect action, remove them completely. If they are, just unmark
@@ -178,7 +197,7 @@ static void le_scan_cleanup(struct work_struct *work)
        rcu_read_unlock();
 
        if (c == conn) {
-               hci_connect_le_scan_cleanup(conn);
+               hci_connect_le_scan_cleanup(conn, 0x00);
                hci_conn_cleanup(conn);
        }
 
@@ -1049,6 +1068,17 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
        return conn;
 }
 
+static bool hci_conn_unlink(struct hci_conn *conn)
+{
+       if (!conn->link)
+               return false;
+
+       conn->link->link = NULL;
+       conn->link = NULL;
+
+       return true;
+}
+
 int hci_conn_del(struct hci_conn *conn)
 {
        struct hci_dev *hdev = conn->hdev;
@@ -1060,15 +1090,16 @@ int hci_conn_del(struct hci_conn *conn)
        cancel_delayed_work_sync(&conn->idle_work);
 
        if (conn->type == ACL_LINK) {
-               struct hci_conn *sco = conn->link;
-               if (sco) {
-                       sco->link = NULL;
+               struct hci_conn *link = conn->link;
+
+               if (link) {
+                       hci_conn_unlink(conn);
                        /* Due to race, SCO connection might be not established
                         * yet at this point. Delete it now, otherwise it is
                         * possible for it to be stuck and can't be deleted.
                         */
-                       if (sco->handle == HCI_CONN_HANDLE_UNSET)
-                               hci_conn_del(sco);
+                       if (link->handle == HCI_CONN_HANDLE_UNSET)
+                               hci_conn_del(link);
                }
 
                /* Unacked frames */
@@ -1084,7 +1115,7 @@ int hci_conn_del(struct hci_conn *conn)
                struct hci_conn *acl = conn->link;
 
                if (acl) {
-                       acl->link = NULL;
+                       hci_conn_unlink(conn);
                        hci_conn_drop(acl);
                }
 
@@ -1179,31 +1210,8 @@ EXPORT_SYMBOL(hci_get_route);
 static void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 {
        struct hci_dev *hdev = conn->hdev;
-       struct hci_conn_params *params;
 
-       params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
-                                          conn->dst_type);
-       if (params && params->conn) {
-               hci_conn_drop(params->conn);
-               hci_conn_put(params->conn);
-               params->conn = NULL;
-       }
-
-       /* If the status indicates successful cancellation of
-        * the attempt (i.e. Unknown Connection Id) there's no point of
-        * notifying failure since we'll go back to keep trying to
-        * connect. The only exception is explicit connect requests
-        * where a timeout + cancel does indicate an actual failure.
-        */
-       if (status != HCI_ERROR_UNKNOWN_CONN_ID ||
-           (params && params->explicit_connect))
-               mgmt_connect_failed(hdev, &conn->dst, conn->type,
-                                   conn->dst_type, status);
-
-       /* Since we may have temporarily stopped the background scanning in
-        * favor of connection establishment, we should restart it.
-        */
-       hci_update_passive_scan(hdev);
+       hci_connect_le_scan_cleanup(conn, status);
 
        /* Enable advertising in case this was a failed connection
         * attempt as a peripheral.
@@ -1237,15 +1245,15 @@ static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
 {
        struct hci_conn *conn = data;
 
+       bt_dev_dbg(hdev, "err %d", err);
+
        hci_dev_lock(hdev);
 
        if (!err) {
-               hci_connect_le_scan_cleanup(conn);
+               hci_connect_le_scan_cleanup(conn, 0x00);
                goto done;
        }
 
-       bt_dev_err(hdev, "request failed to create LE connection: err %d", err);
-
        /* Check if connection is still pending */
        if (conn != hci_lookup_le_connect(hdev))
                goto done;
@@ -2438,6 +2446,12 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
                c->state = BT_CLOSED;
 
                hci_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM);
+
+               /* Unlink before deleting otherwise it is possible that
+                * hci_conn_del removes the link which may cause the list to
+                * contain items already freed.
+                */
+               hci_conn_unlink(c);
                hci_conn_del(c);
        }
 }
@@ -2775,6 +2789,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
 {
        int r = 0;
 
+       if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
+               return 0;
+
        switch (conn->state) {
        case BT_CONNECTED:
        case BT_CONFIG:
index b65c3aabcd53665fa32bcaee888b3ecdaeb76b07..334e308451f5397fb4cda8b8b6f8ef724aade2c1 100644 (file)
@@ -2871,10 +2871,25 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
                return -ENXIO;
        }
 
-       if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
-           hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
-           hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
-           hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
+       switch (hci_skb_pkt_type(skb)) {
+       case HCI_EVENT_PKT:
+               break;
+       case HCI_ACLDATA_PKT:
+               /* Detect if ISO packet has been sent as ACL */
+               if (hci_conn_num(hdev, ISO_LINK)) {
+                       __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
+                       __u8 type;
+
+                       type = hci_conn_lookup_type(hdev, hci_handle(handle));
+                       if (type == ISO_LINK)
+                               hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
+               }
+               break;
+       case HCI_SCODATA_PKT:
+               break;
+       case HCI_ISODATA_PKT:
+               break;
+       default:
                kfree_skb(skb);
                return -EINVAL;
        }
index ad92a4be5851739cba345c629690b9274e154db5..e87c928c9e17ae5608bd4614ed6f59edf680bcf4 100644 (file)
@@ -2881,16 +2881,6 @@ static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
 
        conn->resp_addr_type = peer_addr_type;
        bacpy(&conn->resp_addr, peer_addr);
-
-       /* We don't want the connection attempt to stick around
-        * indefinitely since LE doesn't have a page timeout concept
-        * like BR/EDR. Set a timer for any connection that doesn't use
-        * the accept list for connecting.
-        */
-       if (filter_policy == HCI_LE_USE_PEER_ADDR)
-               queue_delayed_work(conn->hdev->workqueue,
-                                  &conn->le_conn_timeout,
-                                  conn->conn_timeout);
 }
 
 static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
@@ -5902,6 +5892,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
        if (status)
                goto unlock;
 
+       /* Drop the connection if it has been aborted */
+       if (test_bit(HCI_CONN_CANCEL, &conn->flags)) {
+               hci_conn_drop(conn);
+               goto unlock;
+       }
+
        if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
                addr_type = BDADDR_LE_PUBLIC;
        else
@@ -6995,7 +6991,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
                bis->iso_qos.in.latency = le16_to_cpu(ev->interval) * 125 / 100;
                bis->iso_qos.in.sdu = le16_to_cpu(ev->max_pdu);
 
-               hci_connect_cfm(bis, ev->status);
+               hci_iso_setup_path(bis);
        }
 
        hci_dev_unlock(hdev);
index 117eedb6f70993a5b58987a7a7bf794aaf8e000e..632be12672887ae0fdb8d4df67de4f63aa855f4e 100644 (file)
@@ -246,8 +246,9 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
 
        skb = __hci_cmd_sync_sk(hdev, opcode, plen, param, event, timeout, sk);
        if (IS_ERR(skb)) {
-               bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
-                               PTR_ERR(skb));
+               if (!event)
+                       bt_dev_err(hdev, "Opcode 0x%4x failed: %ld", opcode,
+                                  PTR_ERR(skb));
                return PTR_ERR(skb);
        }
 
@@ -643,6 +644,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
        cancel_work_sync(&hdev->cmd_sync_work);
        cancel_work_sync(&hdev->reenable_adv_work);
 
+       mutex_lock(&hdev->cmd_sync_work_lock);
        list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
                if (entry->destroy)
                        entry->destroy(hdev, entry->data, -ECANCELED);
@@ -650,6 +652,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
                list_del(&entry->list);
                kfree(entry);
        }
+       mutex_unlock(&hdev->cmd_sync_work_lock);
 }
 
 void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
@@ -2367,6 +2370,45 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
        return err;
 }
 
+static int hci_pause_addr_resolution(struct hci_dev *hdev)
+{
+       int err;
+
+       if (!use_ll_privacy(hdev))
+               return 0;
+
+       if (!hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION))
+               return 0;
+
+       /* Cannot disable addr resolution if scanning is enabled or
+        * when initiating an LE connection.
+        */
+       if (hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
+           hci_lookup_le_connect(hdev)) {
+               bt_dev_err(hdev, "Command not allowed when scan/LE connect");
+               return -EPERM;
+       }
+
+       /* Cannot disable addr resolution if advertising is enabled. */
+       err = hci_pause_advertising_sync(hdev);
+       if (err) {
+               bt_dev_err(hdev, "Pause advertising failed: %d", err);
+               return err;
+       }
+
+       err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
+       if (err)
+               bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
+                          err);
+
+       /* Return if address resolution is disabled and RPA is not used. */
+       if (!err && scan_use_rpa(hdev))
+               return err;
+
+       hci_resume_advertising_sync(hdev);
+       return err;
+}
+
 struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
                                             bool extended, struct sock *sk)
 {
@@ -2402,7 +2444,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
        u8 filter_policy;
        int err;
 
-       /* Pause advertising if resolving list can be used as controllers are
+       /* Pause advertising if resolving list can be used as controllers
         * cannot accept resolving list modifications while advertising.
         */
        if (use_ll_privacy(hdev)) {
@@ -3319,6 +3361,7 @@ static const struct hci_init_stage amp_init1[] = {
        HCI_INIT(hci_read_flow_control_mode_sync),
        /* HCI_OP_READ_LOCATION_DATA */
        HCI_INIT(hci_read_location_data_sync),
+       {}
 };
 
 static int hci_init1_sync(struct hci_dev *hdev)
@@ -3353,6 +3396,7 @@ static int hci_init1_sync(struct hci_dev *hdev)
 static const struct hci_init_stage amp_init2[] = {
        /* HCI_OP_READ_LOCAL_FEATURES */
        HCI_INIT(hci_read_local_features_sync),
+       {}
 };
 
 /* Read Buffer Size (ACL mtu, max pkt, etc.) */
@@ -5083,8 +5127,11 @@ static int hci_le_connect_cancel_sync(struct hci_dev *hdev,
        if (test_bit(HCI_CONN_SCANNING, &conn->flags))
                return 0;
 
+       if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
+               return 0;
+
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_CREATE_CONN_CANCEL,
-                                    6, &conn->dst, HCI_CMD_TIMEOUT);
+                                    0, NULL, HCI_CMD_TIMEOUT);
 }
 
 static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn)
@@ -5394,27 +5441,12 @@ static int hci_active_scan_sync(struct hci_dev *hdev, uint16_t interval)
 
        cancel_interleave_scan(hdev);
 
-       /* Pause advertising since active scanning disables address resolution
-        * which advertising depend on in order to generate its RPAs.
+       /* Pause address resolution for active scan and stop advertising if
+        * privacy is enabled.
         */
-       if (use_ll_privacy(hdev) && hci_dev_test_flag(hdev, HCI_PRIVACY)) {
-               err = hci_pause_advertising_sync(hdev);
-               if (err) {
-                       bt_dev_err(hdev, "pause advertising failed: %d", err);
-                       goto failed;
-               }
-       }
-
-       /* Disable address resolution while doing active scanning since the
-        * accept list shall not be used and all reports shall reach the host
-        * anyway.
-        */
-       err = hci_le_set_addr_resolution_enable_sync(hdev, 0x00);
-       if (err) {
-               bt_dev_err(hdev, "Unable to disable Address Resolution: %d",
-                          err);
+       err = hci_pause_addr_resolution(hdev);
+       if (err)
                goto failed;
-       }
 
        /* All active scans will be done with either a resolvable private
         * address (when privacy feature has been enabled) or non-resolvable
@@ -6074,6 +6106,9 @@ int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
                                       conn->conn_timeout, NULL);
 
 done:
+       if (err == -ETIMEDOUT)
+               hci_le_connect_cancel_sync(hdev, conn);
+
        /* Re-enable advertising after the connection attempt is finished. */
        hci_resume_advertising_sync(hdev);
        return err;
index bed1a7b9205c20cceacd45a529b50f9b378dff9c..707f229f896a1fb01195b3001fd1629cbf16d0d9 100644 (file)
@@ -433,7 +433,7 @@ static void hidp_set_timer(struct hidp_session *session)
 static void hidp_del_timer(struct hidp_session *session)
 {
        if (session->idle_to > 0)
-               del_timer(&session->timer);
+               del_timer_sync(&session->timer);
 }
 
 static void hidp_process_report(struct hidp_session *session, int type,
index 24444b502e5865400d4eecbdcf68ace4b9e687b6..8d136a7301630d3172178e063b0a8c36b5540f4f 100644 (file)
@@ -1620,7 +1620,6 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
 void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
        struct iso_conn *conn = hcon->iso_data;
-       struct hci_iso_data_hdr *hdr;
        __u16 pb, ts, len;
 
        if (!conn)
@@ -1642,6 +1641,8 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                }
 
                if (ts) {
+                       struct hci_iso_ts_data_hdr *hdr;
+
                        /* TODO: add timestamp to the packet? */
                        hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE);
                        if (!hdr) {
@@ -1649,15 +1650,19 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
                                goto drop;
                        }
 
+                       len = __le16_to_cpu(hdr->slen);
                } else {
+                       struct hci_iso_data_hdr *hdr;
+
                        hdr = skb_pull_data(skb, HCI_ISO_DATA_HDR_SIZE);
                        if (!hdr) {
                                BT_ERR("Frame is too short (len %d)", skb->len);
                                goto drop;
                        }
+
+                       len = __le16_to_cpu(hdr->slen);
                }
 
-               len    = __le16_to_cpu(hdr->slen);
                flags  = hci_iso_data_flags(len);
                len    = hci_iso_data_len(len);
 
index adfc3ea06d088ef6b68dc28422092351bafa7133..55a7226233f96df0836e5945be61e9ec3fed8880 100644 (file)
@@ -708,6 +708,17 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
 }
 EXPORT_SYMBOL_GPL(l2cap_chan_del);
 
+static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id,
+                                l2cap_chan_func_t func, void *data)
+{
+       struct l2cap_chan *chan, *l;
+
+       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+               if (chan->ident == id)
+                       func(chan, data);
+       }
+}
+
 static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
                              void *data)
 {
@@ -775,23 +786,9 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan)
 
 static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan)
 {
-       struct l2cap_conn *conn = chan->conn;
-       struct l2cap_ecred_conn_rsp rsp;
-       u16 result;
-
-       if (test_bit(FLAG_DEFER_SETUP, &chan->flags))
-               result = L2CAP_CR_LE_AUTHORIZATION;
-       else
-               result = L2CAP_CR_LE_BAD_PSM;
-
        l2cap_state_change(chan, BT_DISCONN);
 
-       memset(&rsp, 0, sizeof(rsp));
-
-       rsp.result  = cpu_to_le16(result);
-
-       l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp),
-                      &rsp);
+       __l2cap_ecred_conn_rsp_defer(chan);
 }
 
 static void l2cap_chan_connect_reject(struct l2cap_chan *chan)
@@ -846,7 +843,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
                                        break;
                                case L2CAP_MODE_EXT_FLOWCTL:
                                        l2cap_chan_ecred_connect_reject(chan);
-                                       break;
+                                       return;
                                }
                        }
                }
@@ -3938,43 +3935,86 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan)
                       &rsp);
 }
 
-void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
+static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data)
 {
+       int *result = data;
+
+       if (*result || test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
+               return;
+
+       switch (chan->state) {
+       case BT_CONNECT2:
+               /* If channel still pending accept add to result */
+               (*result)++;
+               return;
+       case BT_CONNECTED:
+               return;
+       default:
+               /* If not connected or pending accept it has been refused */
+               *result = -ECONNREFUSED;
+               return;
+       }
+}
+
+struct l2cap_ecred_rsp_data {
        struct {
                struct l2cap_ecred_conn_rsp rsp;
-               __le16 dcid[5];
+               __le16 scid[L2CAP_ECRED_MAX_CID];
        } __packed pdu;
+       int count;
+};
+
+static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
+{
+       struct l2cap_ecred_rsp_data *rsp = data;
+
+       if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
+               return;
+
+       /* Reset ident so only one response is sent */
+       chan->ident = 0;
+
+       /* Include all channels pending with the same ident */
+       if (!rsp->pdu.rsp.result)
+               rsp->pdu.rsp.dcid[rsp->count++] = cpu_to_le16(chan->scid);
+       else
+               l2cap_chan_del(chan, ECONNRESET);
+}
+
+void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan)
+{
        struct l2cap_conn *conn = chan->conn;
-       u16 ident = chan->ident;
-       int i = 0;
+       struct l2cap_ecred_rsp_data data;
+       u16 id = chan->ident;
+       int result = 0;
 
-       if (!ident)
+       if (!id)
                return;
 
-       BT_DBG("chan %p ident %d", chan, ident);
+       BT_DBG("chan %p id %d", chan, id);
 
-       pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
-       pdu.rsp.mps     = cpu_to_le16(chan->mps);
-       pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
-       pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
+       memset(&data, 0, sizeof(data));
 
-       mutex_lock(&conn->chan_lock);
+       data.pdu.rsp.mtu     = cpu_to_le16(chan->imtu);
+       data.pdu.rsp.mps     = cpu_to_le16(chan->mps);
+       data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits);
+       data.pdu.rsp.result  = cpu_to_le16(L2CAP_CR_LE_SUCCESS);
 
-       list_for_each_entry(chan, &conn->chan_l, list) {
-               if (chan->ident != ident)
-                       continue;
+       /* Verify that all channels are ready */
+       __l2cap_chan_list_id(conn, id, l2cap_ecred_list_defer, &result);
 
-               /* Reset ident so only one response is sent */
-               chan->ident = 0;
+       if (result > 0)
+               return;
 
-               /* Include all channels pending with the same ident */
-               pdu.dcid[i++] = cpu_to_le16(chan->scid);
-       }
+       if (result < 0)
+               data.pdu.rsp.result = cpu_to_le16(L2CAP_CR_LE_AUTHORIZATION);
 
-       mutex_unlock(&conn->chan_lock);
+       /* Build response */
+       __l2cap_chan_list_id(conn, id, l2cap_ecred_rsp_defer, &data);
 
-       l2cap_send_cmd(conn, ident, L2CAP_ECRED_CONN_RSP,
-                       sizeof(pdu.rsp) + i * sizeof(__le16), &pdu);
+       l2cap_send_cmd(conn, id, L2CAP_ECRED_CONN_RSP,
+                      sizeof(data.pdu.rsp) + (data.count * sizeof(__le16)),
+                      &data.pdu);
 }
 
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
@@ -4612,33 +4652,27 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
 
        BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
 
-       mutex_lock(&conn->chan_lock);
-
-       chan = __l2cap_get_chan_by_scid(conn, dcid);
+       chan = l2cap_get_chan_by_scid(conn, dcid);
        if (!chan) {
-               mutex_unlock(&conn->chan_lock);
                cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
                return 0;
        }
 
-       l2cap_chan_hold(chan);
-       l2cap_chan_lock(chan);
-
        rsp.dcid = cpu_to_le16(chan->scid);
        rsp.scid = cpu_to_le16(chan->dcid);
        l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
 
        chan->ops->set_shutdown(chan);
 
+       mutex_lock(&conn->chan_lock);
        l2cap_chan_del(chan, ECONNRESET);
+       mutex_unlock(&conn->chan_lock);
 
        chan->ops->close(chan);
 
        l2cap_chan_unlock(chan);
        l2cap_chan_put(chan);
 
-       mutex_unlock(&conn->chan_lock);
-
        return 0;
 }
 
@@ -4658,33 +4692,27 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
 
        BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
 
-       mutex_lock(&conn->chan_lock);
-
-       chan = __l2cap_get_chan_by_scid(conn, scid);
+       chan = l2cap_get_chan_by_scid(conn, scid);
        if (!chan) {
                mutex_unlock(&conn->chan_lock);
                return 0;
        }
 
-       l2cap_chan_hold(chan);
-       l2cap_chan_lock(chan);
-
        if (chan->state != BT_DISCONN) {
                l2cap_chan_unlock(chan);
                l2cap_chan_put(chan);
-               mutex_unlock(&conn->chan_lock);
                return 0;
        }
 
+       mutex_lock(&conn->chan_lock);
        l2cap_chan_del(chan, 0);
+       mutex_unlock(&conn->chan_lock);
 
        chan->ops->close(chan);
 
        l2cap_chan_unlock(chan);
        l2cap_chan_put(chan);
 
-       mutex_unlock(&conn->chan_lock);
-
        return 0;
 }
 
@@ -6078,6 +6106,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
                __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
 
                chan->ident = cmd->ident;
+               chan->mode = L2CAP_MODE_EXT_FLOWCTL;
 
                if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
                        l2cap_state_change(chan, BT_CONNECT2);
index 7add66f30e4d1a858a75dfba41260c922eacb444..249dc6777fb4e92963d150a1ec135299fb7faa29 100644 (file)
@@ -4639,12 +4639,6 @@ static int set_mgmt_mesh_func(struct sock *sk, struct hci_dev *hdev,
                                       MGMT_OP_SET_EXP_FEATURE,
                                       MGMT_STATUS_INVALID_INDEX);
 
-       /* Changes can only be made when controller is powered down */
-       if (hdev_is_powered(hdev))
-               return mgmt_cmd_status(sk, hdev->id,
-                                      MGMT_OP_SET_EXP_FEATURE,
-                                      MGMT_STATUS_REJECTED);
-
        /* Parameters are limited to a single octet */
        if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
                return mgmt_cmd_status(sk, hdev->id,
@@ -9363,7 +9357,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
        { add_ext_adv_data,        MGMT_ADD_EXT_ADV_DATA_SIZE,
                                                HCI_MGMT_VAR_LEN },
        { add_adv_patterns_monitor_rssi,
-                                  MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE },
+                                  MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE,
+                                               HCI_MGMT_VAR_LEN },
        { set_mesh,                MGMT_SET_MESH_RECEIVER_SIZE,
                                                HCI_MGMT_VAR_LEN },
        { mesh_features,           MGMT_MESH_READ_FEATURES_SIZE },
index 1111da4e2f2bd533572ee82a1b42ffd725a2d593..cd1a27ac555d009a65dbebb5a5ea125b9261f147 100644 (file)
@@ -235,27 +235,41 @@ static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
        return err;
 }
 
-static int sco_connect(struct hci_dev *hdev, struct sock *sk)
+static int sco_connect(struct sock *sk)
 {
        struct sco_conn *conn;
        struct hci_conn *hcon;
+       struct hci_dev  *hdev;
        int err, type;
 
        BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
 
+       hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
+       if (!hdev)
+               return -EHOSTUNREACH;
+
+       hci_dev_lock(hdev);
+
        if (lmp_esco_capable(hdev) && !disable_esco)
                type = ESCO_LINK;
        else
                type = SCO_LINK;
 
        if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
-           (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)))
-               return -EOPNOTSUPP;
+           (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
+               err = -EOPNOTSUPP;
+               goto unlock;
+       }
 
        hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
                               sco_pi(sk)->setting, &sco_pi(sk)->codec);
-       if (IS_ERR(hcon))
-               return PTR_ERR(hcon);
+       if (IS_ERR(hcon)) {
+               err = PTR_ERR(hcon);
+               goto unlock;
+       }
+
+       hci_dev_unlock(hdev);
+       hci_dev_put(hdev);
 
        conn = sco_conn_add(hcon);
        if (!conn) {
@@ -263,13 +277,15 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk)
                return -ENOMEM;
        }
 
-       /* Update source addr of the socket */
-       bacpy(&sco_pi(sk)->src, &hcon->src);
-
        err = sco_chan_add(conn, sk, NULL);
        if (err)
                return err;
 
+       lock_sock(sk);
+
+       /* Update source addr of the socket */
+       bacpy(&sco_pi(sk)->src, &hcon->src);
+
        if (hcon->state == BT_CONNECTED) {
                sco_sock_clear_timer(sk);
                sk->sk_state = BT_CONNECTED;
@@ -278,6 +294,13 @@ static int sco_connect(struct hci_dev *hdev, struct sock *sk)
                sco_sock_set_timer(sk, sk->sk_sndtimeo);
        }
 
+       release_sock(sk);
+
+       return err;
+
+unlock:
+       hci_dev_unlock(hdev);
+       hci_dev_put(hdev);
        return err;
 }
 
@@ -565,7 +588,6 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
 {
        struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
        struct sock *sk = sock->sk;
-       struct hci_dev  *hdev;
        int err;
 
        BT_DBG("sk %p", sk);
@@ -574,37 +596,26 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
            addr->sa_family != AF_BLUETOOTH)
                return -EINVAL;
 
-       lock_sock(sk);
-       if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
-               err = -EBADFD;
-               goto done;
-       }
+       if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND)
+               return -EBADFD;
 
-       if (sk->sk_type != SOCK_SEQPACKET) {
+       if (sk->sk_type != SOCK_SEQPACKET)
                err = -EINVAL;
-               goto done;
-       }
-
-       hdev = hci_get_route(&sa->sco_bdaddr, &sco_pi(sk)->src, BDADDR_BREDR);
-       if (!hdev) {
-               err = -EHOSTUNREACH;
-               goto done;
-       }
-       hci_dev_lock(hdev);
 
+       lock_sock(sk);
        /* Set destination address and psm */
        bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr);
+       release_sock(sk);
 
-       err = sco_connect(hdev, sk);
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
+       err = sco_connect(sk);
        if (err)
-               goto done;
+               return err;
+
+       lock_sock(sk);
 
        err = bt_sock_wait_state(sk, BT_CONNECTED,
                                 sock_sndtimeo(sk, flags & O_NONBLOCK));
 
-done:
        release_sock(sk);
        return err;
 }
@@ -1129,6 +1140,8 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
                        break;
                }
 
+               release_sock(sk);
+
                /* find total buffer size required to copy codec + caps */
                hci_dev_lock(hdev);
                list_for_each_entry(c, &hdev->local_codecs, list) {
@@ -1146,15 +1159,13 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
                buf_len += sizeof(struct bt_codecs);
                if (buf_len > len) {
                        hci_dev_put(hdev);
-                       err = -ENOBUFS;
-                       break;
+                       return -ENOBUFS;
                }
                ptr = optval;
 
                if (put_user(num_codecs, ptr)) {
                        hci_dev_put(hdev);
-                       err = -EFAULT;
-                       break;
+                       return -EFAULT;
                }
                ptr += sizeof(num_codecs);
 
@@ -1194,12 +1205,14 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
                        ptr += len;
                }
 
-               if (!err && put_user(buf_len, optlen))
-                       err = -EFAULT;
-
                hci_dev_unlock(hdev);
                hci_dev_put(hdev);
 
+               lock_sock(sk);
+
+               if (!err && put_user(buf_len, optlen))
+                       err = -EFAULT;
+
                break;
 
        default:
index 638a4d5359db08f72a1191548a8874190c5983f2..4bc6761517bbc4c8da3622deea6f81e56508f30c 100644 (file)
@@ -868,12 +868,17 @@ static unsigned int ip_sabotage_in(void *priv,
 {
        struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
 
-       if (nf_bridge && !nf_bridge->in_prerouting &&
-           !netif_is_l3_master(skb->dev) &&
-           !netif_is_l3_slave(skb->dev)) {
-               nf_bridge_info_free(skb);
-               state->okfn(state->net, state->sk, skb);
-               return NF_STOLEN;
+       if (nf_bridge) {
+               if (nf_bridge->sabotage_in_done)
+                       return NF_ACCEPT;
+
+               if (!nf_bridge->in_prerouting &&
+                   !netif_is_l3_master(skb->dev) &&
+                   !netif_is_l3_slave(skb->dev)) {
+                       nf_bridge->sabotage_in_done = 1;
+                       state->okfn(state->net, state->sk, skb);
+                       return NF_STOLEN;
+               }
        }
 
        return NF_ACCEPT;
index de18e9c1d7a784dcc89a514f91ad7ed8a0aa6b71..ba95c4d74a60141ca488d488cfded3e56ef4d602 100644 (file)
@@ -148,6 +148,17 @@ br_switchdev_fdb_notify(struct net_bridge *br,
        if (test_bit(BR_FDB_LOCKED, &fdb->flags))
                return;
 
+       /* Entries with these flags were created using ndm_state == NUD_REACHABLE,
+        * ndm_flags == NTF_MASTER( | NTF_STICKY), ext_flags == 0 by something
+        * equivalent to 'bridge fdb add ... master dynamic (sticky)'.
+        * Drivers don't know how to deal with these, so don't notify them to
+        * avoid confusing them.
+        */
+       if (test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags) &&
+           !test_bit(BR_FDB_STATIC, &fdb->flags) &&
+           !test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags))
+               return;
+
        br_switchdev_fdb_populate(br, &item, fdb, NULL);
 
        switch (type) {
index 27706f6ace34a0296392ae66ca5b0ab1fad26e04..a962ec2b8ba5b393a7e5fafa6e88450dd7359008 100644 (file)
@@ -941,6 +941,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 
                        cf = op->frames + op->cfsiz * i;
                        err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
+                       if (err < 0)
+                               goto free_op;
 
                        if (op->flags & CAN_FD_FRAME) {
                                if (cf->len > 64)
@@ -950,12 +952,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                                        err = -EINVAL;
                        }
 
-                       if (err < 0) {
-                               if (op->frames != &op->sframe)
-                                       kfree(op->frames);
-                               kfree(op);
-                               return err;
-                       }
+                       if (err < 0)
+                               goto free_op;
 
                        if (msg_head->flags & TX_CP_CAN_ID) {
                                /* copy can_id into frame */
@@ -1026,6 +1024,12 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                bcm_tx_start_timer(op);
 
        return msg_head->nframes * op->cfsiz + MHSIZ;
+
+free_op:
+       if (op->frames != &op->sframe)
+               kfree(op->frames);
+       kfree(op);
+       return err;
 }
 
 /*
index 9bc344851704e3683c4be04cd841b7db0eade8e8..5761d4ab839dd9776f072ba9ce78ac969defc97d 100644 (file)
@@ -119,7 +119,8 @@ enum {
        ISOTP_WAIT_FIRST_FC,
        ISOTP_WAIT_FC,
        ISOTP_WAIT_DATA,
-       ISOTP_SENDING
+       ISOTP_SENDING,
+       ISOTP_SHUTDOWN,
 };
 
 struct tpcon {
@@ -880,8 +881,8 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
                                             txtimer);
        struct sock *sk = &so->sk;
 
-       /* don't handle timeouts in IDLE state */
-       if (so->tx.state == ISOTP_IDLE)
+       /* don't handle timeouts in IDLE or SHUTDOWN state */
+       if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN)
                return HRTIMER_NORESTART;
 
        /* we did not get any flow control or echo frame in time */
@@ -918,7 +919,6 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 {
        struct sock *sk = sock->sk;
        struct isotp_sock *so = isotp_sk(sk);
-       u32 old_state = so->tx.state;
        struct sk_buff *skb;
        struct net_device *dev;
        struct canfd_frame *cf;
@@ -928,23 +928,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
        int off;
        int err;
 
-       if (!so->bound)
+       if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
                return -EADDRNOTAVAIL;
 
+wait_free_buffer:
        /* we do not support multiple buffers - for now */
-       if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE ||
-           wq_has_sleeper(&so->wait)) {
-               if (msg->msg_flags & MSG_DONTWAIT) {
-                       err = -EAGAIN;
-                       goto err_out;
-               }
+       if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT))
+               return -EAGAIN;
 
-               /* wait for complete transmission of current pdu */
-               err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
-               if (err)
-                       goto err_out;
+       /* wait for complete transmission of current pdu */
+       err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+       if (err)
+               goto err_event_drop;
 
-               so->tx.state = ISOTP_SENDING;
+       if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) {
+               if (so->tx.state == ISOTP_SHUTDOWN)
+                       return -EADDRNOTAVAIL;
+
+               goto wait_free_buffer;
        }
 
        if (!size || size > MAX_MSG_LENGTH) {
@@ -1074,7 +1075,9 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
        if (wait_tx_done) {
                /* wait for complete transmission of current pdu */
-               wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+               err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+               if (err)
+                       goto err_event_drop;
 
                if (sk->sk_err)
                        return -sk->sk_err;
@@ -1082,13 +1085,15 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
        return size;
 
+err_event_drop:
+       /* got signal: force tx state machine to be idle */
+       so->tx.state = ISOTP_IDLE;
+       hrtimer_cancel(&so->txfrtimer);
+       hrtimer_cancel(&so->txtimer);
 err_out_drop:
        /* drop this PDU and unlock a potential wait queue */
-       old_state = ISOTP_IDLE;
-err_out:
-       so->tx.state = old_state;
-       if (so->tx.state == ISOTP_IDLE)
-               wake_up_interruptible(&so->wait);
+       so->tx.state = ISOTP_IDLE;
+       wake_up_interruptible(&so->wait);
 
        return err;
 }
@@ -1120,7 +1125,7 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
        if (ret < 0)
                goto out_err;
 
-       sock_recv_timestamp(msg, sk, skb);
+       sock_recv_cmsgs(msg, sk, skb);
 
        if (msg->msg_name) {
                __sockaddr_check_size(ISOTP_MIN_NAMELEN);
@@ -1150,10 +1155,12 @@ static int isotp_release(struct socket *sock)
        net = sock_net(sk);
 
        /* wait for complete transmission of current pdu */
-       wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+       while (wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0 &&
+              cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SHUTDOWN) != ISOTP_IDLE)
+               ;
 
        /* force state machines to be idle also when a signal occurred */
-       so->tx.state = ISOTP_IDLE;
+       so->tx.state = ISOTP_SHUTDOWN;
        so->rx.state = ISOTP_IDLE;
 
        spin_lock(&isotp_notifier_lock);
@@ -1608,6 +1615,21 @@ static int isotp_init(struct sock *sk)
        return 0;
 }
 
+static __poll_t isotp_poll(struct file *file, struct socket *sock, poll_table *wait)
+{
+       struct sock *sk = sock->sk;
+       struct isotp_sock *so = isotp_sk(sk);
+
+       __poll_t mask = datagram_poll(file, sock, wait);
+       poll_wait(file, &so->wait, wait);
+
+       /* Check for false positives due to TX state */
+       if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE))
+               mask &= ~(EPOLLOUT | EPOLLWRNORM);
+
+       return mask;
+}
+
 static int isotp_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd,
                                  unsigned long arg)
 {
@@ -1623,7 +1645,7 @@ static const struct proto_ops isotp_ops = {
        .socketpair = sock_no_socketpair,
        .accept = sock_no_accept,
        .getname = isotp_getname,
-       .poll = datagram_poll,
+       .poll = isotp_poll,
        .ioctl = isotp_sock_no_ioctlcmd,
        .gettstamp = sock_gettstamp,
        .listen = sock_no_listen,
index fce9b9ebf13f668584c26bda3be121bf227baa12..fe3df23a259578e13bb4ca449e0cc722f2eca95f 100644 (file)
@@ -604,7 +604,10 @@ sk_buff *j1939_tp_tx_dat_new(struct j1939_priv *priv,
        /* reserve CAN header */
        skb_reserve(skb, offsetof(struct can_frame, data));
 
-       memcpy(skb->cb, re_skcb, sizeof(skb->cb));
+       /* skb->cb must be large enough to hold a j1939_sk_buff_cb structure */
+       BUILD_BUG_ON(sizeof(skb->cb) < sizeof(*re_skcb));
+
+       memcpy(skb->cb, re_skcb, sizeof(*re_skcb));
        skcb = j1939_skb_to_cb(skb);
        if (swap_src_dst)
                j1939_skbcb_swap(skcb);
@@ -1124,8 +1127,6 @@ static void __j1939_session_cancel(struct j1939_session *session,
 
        if (session->sk)
                j1939_sk_send_loop_abort(session->sk, session->err);
-       else
-               j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_ABORT);
 }
 
 static void j1939_session_cancel(struct j1939_session *session,
@@ -1140,6 +1141,9 @@ static void j1939_session_cancel(struct j1939_session *session,
        }
 
        j1939_session_list_unlock(session->priv);
+
+       if (!session->sk)
+               j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_ABORT);
 }
 
 static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer)
@@ -1253,6 +1257,9 @@ static enum hrtimer_restart j1939_tp_rxtimer(struct hrtimer *hrtimer)
                        __j1939_session_cancel(session, J1939_XTP_ABORT_TIMEOUT);
                }
                j1939_session_list_unlock(session->priv);
+
+               if (!session->sk)
+                       j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_ABORT);
        }
 
        j1939_session_put(session);
index 253584777101f2e6af3fc30107516f1e1197f8d3..1488f700bf819a9ee0b8cb59cdfa501075b2e74a 100644 (file)
@@ -3199,6 +3199,7 @@ static u16 skb_tx_hash(const struct net_device *dev,
        }
 
        if (skb_rx_queue_recorded(skb)) {
+               DEBUG_NET_WARN_ON_ONCE(qcount == 0);
                hash = skb_get_rx_queue(skb);
                if (hash >= qoffset)
                        hash -= qoffset;
@@ -10846,7 +10847,7 @@ void unregister_netdevice_many_notify(struct list_head *head,
                    dev->rtnl_link_state == RTNL_LINK_INITIALIZED)
                        skb = rtmsg_ifinfo_build_skb(RTM_DELLINK, dev, ~0U, 0,
                                                     GFP_KERNEL, NULL, 0,
-                                                    portid, nlmsg_seq(nlh));
+                                                    portid, nlh);
 
                /*
                 *      Flush the unicast and multicast chains
index 7b69cf882b8efd901be57217013ebb155b616787..3e3598cd49f23e8202c4dd9b8c04edb77d296af7 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sched/task.h>
 #include <linux/uidgid.h>
 #include <linux/cookie.h>
+#include <linux/proc_fs.h>
 
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -676,21 +677,19 @@ EXPORT_SYMBOL_GPL(get_net_ns);
 
 struct net *get_net_ns_by_fd(int fd)
 {
-       struct file *file;
-       struct ns_common *ns;
-       struct net *net;
+       struct fd f = fdget(fd);
+       struct net *net = ERR_PTR(-EINVAL);
 
-       file = proc_ns_fget(fd);
-       if (IS_ERR(file))
-               return ERR_CAST(file);
+       if (!f.file)
+               return ERR_PTR(-EBADF);
 
-       ns = get_proc_ns(file_inode(file));
-       if (ns->ops == &netns_operations)
-               net = get_net(container_of(ns, struct net, ns));
-       else
-               net = ERR_PTR(-EINVAL);
+       if (proc_ns_file(f.file)) {
+               struct ns_common *ns = get_proc_ns(file_inode(f.file));
+               if (ns->ops == &netns_operations)
+                       net = get_net(container_of(ns, struct net, ns));
+       }
+       fdput(f);
 
-       fput(file);
        return net;
 }
 EXPORT_SYMBOL_GPL(get_net_ns_by_fd);
index 9e10802587fc3c3057eda5c1786ac3f6fef7b9bb..3abab70d66ddc8a3342dfe6c3f94f2eff9bb3a79 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/netdev.yaml */
 /* YNL-GEN kernel source */
index 2c5fc7d1e8a741e3ba2e7c3332ec4f436225c6d4..74d74fc23167988996d56107771e90e9a3cc7e0e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/netdev.yaml */
 /* YNL-GEN kernel header */
index a089b704b986d78692b3c2a202a6c4f542716bf6..e6a739b1afa9e480ce3ca6b2adae43b667ae8cf7 100644 (file)
@@ -137,6 +137,20 @@ static void queue_process(struct work_struct *work)
        }
 }
 
+static int netif_local_xmit_active(struct net_device *dev)
+{
+       int i;
+
+       for (i = 0; i < dev->num_tx_queues; i++) {
+               struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+
+               if (READ_ONCE(txq->xmit_lock_owner) == smp_processor_id())
+                       return 1;
+       }
+
+       return 0;
+}
+
 static void poll_one_napi(struct napi_struct *napi)
 {
        int work;
@@ -183,7 +197,10 @@ void netpoll_poll_dev(struct net_device *dev)
        if (!ni || down_trylock(&ni->dev_lock))
                return;
 
-       if (!netif_running(dev)) {
+       /* Some drivers will take the same locks in poll and xmit,
+        * we can't poll if local CPU is already in xmit.
+        */
+       if (!netif_running(dev) || netif_local_xmit_active(dev)) {
                up(&ni->dev_lock);
                return;
        }
index 5d8eb57867a96fa1730fcafd95f0801fbfc76188..6e44e92ebdf5dc6aaa91b32c3c439b15044024ef 100644 (file)
@@ -3972,16 +3972,23 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
                                       unsigned int change,
                                       u32 event, gfp_t flags, int *new_nsid,
-                                      int new_ifindex, u32 portid, u32 seq)
+                                      int new_ifindex, u32 portid,
+                                      const struct nlmsghdr *nlh)
 {
        struct net *net = dev_net(dev);
        struct sk_buff *skb;
        int err = -ENOBUFS;
+       u32 seq = 0;
 
        skb = nlmsg_new(if_nlmsg_size(dev, 0), flags);
        if (skb == NULL)
                goto errout;
 
+       if (nlmsg_report(nlh))
+               seq = nlmsg_seq(nlh);
+       else
+               portid = 0;
+
        err = rtnl_fill_ifinfo(skb, dev, dev_net(dev),
                               type, portid, seq, change, 0, 0, event,
                               new_nsid, new_ifindex, -1, flags);
@@ -4017,7 +4024,7 @@ static void rtmsg_ifinfo_event(int type, struct net_device *dev,
                return;
 
        skb = rtmsg_ifinfo_build_skb(type, dev, change, event, flags, new_nsid,
-                                    new_ifindex, portid, nlmsg_seq(nlh));
+                                    new_ifindex, portid, nlh);
        if (skb)
                rtmsg_ifinfo_send(skb, dev, flags, portid, nlh);
 }
index 1a31815104d617a66fee5e981131ceeffaa67128..4c0879798eb8a830abf748bdada7790d06154f7a 100644 (file)
@@ -5599,18 +5599,18 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
        if (skb_cloned(to))
                return false;
 
-       /* In general, avoid mixing slab allocated and page_pool allocated
-        * pages within the same SKB. However when @to is not pp_recycle and
-        * @from is cloned, we can transition frag pages from page_pool to
-        * reference counted.
-        *
-        * On the other hand, don't allow coalescing two pp_recycle SKBs if
-        * @from is cloned, in case the SKB is using page_pool fragment
+       /* In general, avoid mixing page_pool and non-page_pool allocated
+        * pages within the same SKB. Additionally avoid dealing with clones
+        * with page_pool pages, in case the SKB is using page_pool fragment
         * references (PP_FLAG_PAGE_FRAG). Since we only take full page
         * references for cloned SKBs at the moment that would result in
         * inconsistent reference counts.
+        * In theory we could take full references if @from is cloned and
+        * !@to->pp_recycle but its tricky (due to potential race with
+        * the clone disappearing) and rare, so not worth dealing with.
         */
-       if (to->pp_recycle != (from->pp_recycle && !skb_cloned(from)))
+       if (to->pp_recycle != from->pp_recycle ||
+           (from->pp_recycle && skb_cloned(from)))
                return false;
 
        if (len <= skb_tailroom(to)) {
index 74842b453407015a735118f4a06a77be47bcfafb..782273bb93c23c10b733dd6a1100f309acdb67f9 100644 (file)
@@ -177,7 +177,7 @@ static int rps_sock_flow_sysctl(struct ctl_table *table, int write,
                        if (orig_sock_table) {
                                static_branch_dec(&rps_needed);
                                static_branch_dec(&rfs_needed);
-                               kvfree_rcu(orig_sock_table);
+                               kvfree_rcu_mightsleep(orig_sock_table);
                        }
                }
        }
@@ -215,7 +215,7 @@ static int flow_limit_cpu_sysctl(struct ctl_table *table, int write,
                                     lockdep_is_held(&flow_limit_update_mutex));
                        if (cur && !cpumask_test_cpu(i, mask)) {
                                RCU_INIT_POINTER(sd->flow_limit, NULL);
-                               kfree_rcu(cur);
+                               kfree_rcu_mightsleep(cur);
                        } else if (!cur && cpumask_test_cpu(i, mask)) {
                                cur = kzalloc_node(len, GFP_KERNEL,
                                                   cpu_to_node(i));
index 8c92fc55331771495b7c11fe5b4e660d8c11a11c..fb85aca819619b344bdbb74f72e1e0a0d4c3e5b2 100644 (file)
@@ -720,7 +720,10 @@ __diag_ignore_all("-Wmissing-prototypes",
  * @ctx: XDP context pointer.
  * @timestamp: Return value pointer.
  *
- * Returns 0 on success or ``-errno`` on error.
+ * Return:
+ * * Returns 0 on success or ``-errno`` on error.
+ * * ``-EOPNOTSUPP`` : means device driver does not implement kfunc
+ * * ``-ENODATA``    : means no RX-timestamp available for this frame
  */
 __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
 {
@@ -731,10 +734,21 @@ __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *tim
  * bpf_xdp_metadata_rx_hash - Read XDP frame RX hash.
  * @ctx: XDP context pointer.
  * @hash: Return value pointer.
+ * @rss_type: Return value pointer for RSS type.
  *
- * Returns 0 on success or ``-errno`` on error.
+ * The RSS hash type (@rss_type) specifies what portion of packet headers NIC
+ * hardware used when calculating RSS hash value.  The RSS type can be decoded
+ * via &enum xdp_rss_hash_type either matching on individual L3/L4 bits
+ * ``XDP_RSS_L*`` or by combined traditional *RSS Hashing Types*
+ * ``XDP_RSS_TYPE_L*``.
+ *
+ * Return:
+ * * Returns 0 on success or ``-errno`` on error.
+ * * ``-EOPNOTSUPP`` : means device driver doesn't implement kfunc
+ * * ``-ENODATA``    : means no RX-hash available for this frame
  */
-__bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash)
+__bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                                        enum xdp_rss_hash_type *rss_type)
 {
        return -EOPNOTSUPP;
 }
@@ -774,20 +788,34 @@ static int __init xdp_metadata_init(void)
 }
 late_initcall(xdp_metadata_init);
 
+void xdp_set_features_flag(struct net_device *dev, xdp_features_t val)
+{
+       val &= NETDEV_XDP_ACT_MASK;
+       if (dev->xdp_features == val)
+               return;
+
+       dev->xdp_features = val;
+
+       if (dev->reg_state == NETREG_REGISTERED)
+               call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev);
+}
+EXPORT_SYMBOL_GPL(xdp_set_features_flag);
+
 void xdp_features_set_redirect_target(struct net_device *dev, bool support_sg)
 {
-       dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT;
-       if (support_sg)
-               dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT_SG;
+       xdp_features_t val = (dev->xdp_features | NETDEV_XDP_ACT_NDO_XMIT);
 
-       call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev);
+       if (support_sg)
+               val |= NETDEV_XDP_ACT_NDO_XMIT_SG;
+       xdp_set_features_flag(dev, val);
 }
 EXPORT_SYMBOL_GPL(xdp_features_set_redirect_target);
 
 void xdp_features_clear_redirect_target(struct net_device *dev)
 {
-       dev->xdp_features &= ~(NETDEV_XDP_ACT_NDO_XMIT |
-                              NETDEV_XDP_ACT_NDO_XMIT_SG);
-       call_netdevice_notifiers(NETDEV_XDP_FEAT_CHANGE, dev);
+       xdp_features_t val = dev->xdp_features;
+
+       val &= ~(NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_NDO_XMIT_SG);
+       xdp_set_features_flag(dev, val);
 }
 EXPORT_SYMBOL_GPL(xdp_features_clear_redirect_target);
index 6957971c2db23a0cd68cdf74830615d0bc7760a4..165bb2cb84316092261f67dcdd1efdebd78ca199 100644 (file)
@@ -57,6 +57,12 @@ struct dsa_standalone_event_work {
        u16 vid;
 };
 
+struct dsa_host_vlan_rx_filtering_ctx {
+       struct net_device *dev;
+       const unsigned char *addr;
+       enum dsa_standalone_event event;
+};
+
 static bool dsa_switch_supports_uc_filtering(struct dsa_switch *ds)
 {
        return ds->ops->port_fdb_add && ds->ops->port_fdb_del &&
@@ -155,18 +161,37 @@ static int dsa_slave_schedule_standalone_work(struct net_device *dev,
        return 0;
 }
 
+static int dsa_slave_host_vlan_rx_filtering(struct net_device *vdev, int vid,
+                                           void *arg)
+{
+       struct dsa_host_vlan_rx_filtering_ctx *ctx = arg;
+
+       return dsa_slave_schedule_standalone_work(ctx->dev, ctx->event,
+                                                 ctx->addr, vid);
+}
+
 static int dsa_slave_sync_uc(struct net_device *dev,
                             const unsigned char *addr)
 {
        struct net_device *master = dsa_slave_to_master(dev);
        struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_host_vlan_rx_filtering_ctx ctx = {
+               .dev = dev,
+               .addr = addr,
+               .event = DSA_UC_ADD,
+       };
+       int err;
 
        dev_uc_add(master, addr);
 
        if (!dsa_switch_supports_uc_filtering(dp->ds))
                return 0;
 
-       return dsa_slave_schedule_standalone_work(dev, DSA_UC_ADD, addr, 0);
+       err = dsa_slave_schedule_standalone_work(dev, DSA_UC_ADD, addr, 0);
+       if (err)
+               return err;
+
+       return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx);
 }
 
 static int dsa_slave_unsync_uc(struct net_device *dev,
@@ -174,13 +199,23 @@ static int dsa_slave_unsync_uc(struct net_device *dev,
 {
        struct net_device *master = dsa_slave_to_master(dev);
        struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_host_vlan_rx_filtering_ctx ctx = {
+               .dev = dev,
+               .addr = addr,
+               .event = DSA_UC_DEL,
+       };
+       int err;
 
        dev_uc_del(master, addr);
 
        if (!dsa_switch_supports_uc_filtering(dp->ds))
                return 0;
 
-       return dsa_slave_schedule_standalone_work(dev, DSA_UC_DEL, addr, 0);
+       err = dsa_slave_schedule_standalone_work(dev, DSA_UC_DEL, addr, 0);
+       if (err)
+               return err;
+
+       return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx);
 }
 
 static int dsa_slave_sync_mc(struct net_device *dev,
@@ -188,13 +223,23 @@ static int dsa_slave_sync_mc(struct net_device *dev,
 {
        struct net_device *master = dsa_slave_to_master(dev);
        struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_host_vlan_rx_filtering_ctx ctx = {
+               .dev = dev,
+               .addr = addr,
+               .event = DSA_MC_ADD,
+       };
+       int err;
 
        dev_mc_add(master, addr);
 
        if (!dsa_switch_supports_mc_filtering(dp->ds))
                return 0;
 
-       return dsa_slave_schedule_standalone_work(dev, DSA_MC_ADD, addr, 0);
+       err = dsa_slave_schedule_standalone_work(dev, DSA_MC_ADD, addr, 0);
+       if (err)
+               return err;
+
+       return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx);
 }
 
 static int dsa_slave_unsync_mc(struct net_device *dev,
@@ -202,13 +247,23 @@ static int dsa_slave_unsync_mc(struct net_device *dev,
 {
        struct net_device *master = dsa_slave_to_master(dev);
        struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_host_vlan_rx_filtering_ctx ctx = {
+               .dev = dev,
+               .addr = addr,
+               .event = DSA_MC_DEL,
+       };
+       int err;
 
        dev_mc_del(master, addr);
 
        if (!dsa_switch_supports_mc_filtering(dp->ds))
                return 0;
 
-       return dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL, addr, 0);
+       err = dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL, addr, 0);
+       if (err)
+               return err;
+
+       return vlan_for_each(dev, dsa_slave_host_vlan_rx_filtering, &ctx);
 }
 
 void dsa_slave_sync_ha(struct net_device *dev)
@@ -1702,6 +1757,8 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
                .flags = 0,
        };
        struct netlink_ext_ack extack = {0};
+       struct dsa_switch *ds = dp->ds;
+       struct netdev_hw_addr *ha;
        int ret;
 
        /* User port... */
@@ -1721,6 +1778,30 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
                return ret;
        }
 
+       if (!dsa_switch_supports_uc_filtering(ds) &&
+           !dsa_switch_supports_mc_filtering(ds))
+               return 0;
+
+       netif_addr_lock_bh(dev);
+
+       if (dsa_switch_supports_mc_filtering(ds)) {
+               netdev_for_each_synced_mc_addr(ha, dev) {
+                       dsa_slave_schedule_standalone_work(dev, DSA_MC_ADD,
+                                                          ha->addr, vid);
+               }
+       }
+
+       if (dsa_switch_supports_uc_filtering(ds)) {
+               netdev_for_each_synced_uc_addr(ha, dev) {
+                       dsa_slave_schedule_standalone_work(dev, DSA_UC_ADD,
+                                                          ha->addr, vid);
+               }
+       }
+
+       netif_addr_unlock_bh(dev);
+
+       dsa_flush_workqueue();
+
        return 0;
 }
 
@@ -1733,13 +1814,43 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
                /* This API only allows programming tagged, non-PVID VIDs */
                .flags = 0,
        };
+       struct dsa_switch *ds = dp->ds;
+       struct netdev_hw_addr *ha;
        int err;
 
        err = dsa_port_vlan_del(dp, &vlan);
        if (err)
                return err;
 
-       return dsa_port_host_vlan_del(dp, &vlan);
+       err = dsa_port_host_vlan_del(dp, &vlan);
+       if (err)
+               return err;
+
+       if (!dsa_switch_supports_uc_filtering(ds) &&
+           !dsa_switch_supports_mc_filtering(ds))
+               return 0;
+
+       netif_addr_lock_bh(dev);
+
+       if (dsa_switch_supports_mc_filtering(ds)) {
+               netdev_for_each_synced_mc_addr(ha, dev) {
+                       dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL,
+                                                          ha->addr, vid);
+               }
+       }
+
+       if (dsa_switch_supports_uc_filtering(ds)) {
+               netdev_for_each_synced_uc_addr(ha, dev) {
+                       dsa_slave_schedule_standalone_work(dev, DSA_UC_DEL,
+                                                          ha->addr, vid);
+               }
+       }
+
+       netif_addr_unlock_bh(dev);
+
+       dsa_flush_workqueue();
+
+       return 0;
 }
 
 static int dsa_slave_restore_vlan(struct net_device *vdev, int vid, void *arg)
@@ -1933,6 +2044,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
        int new_master_mtu;
        int old_master_mtu;
        int mtu_limit;
+       int overhead;
        int cpu_mtu;
        int err;
 
@@ -1961,9 +2073,10 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
                        largest_mtu = slave_mtu;
        }
 
-       mtu_limit = min_t(int, master->max_mtu, dev->max_mtu);
+       overhead = dsa_tag_protocol_overhead(cpu_dp->tag_ops);
+       mtu_limit = min_t(int, master->max_mtu, dev->max_mtu + overhead);
        old_master_mtu = master->mtu;
-       new_master_mtu = largest_mtu + dsa_tag_protocol_overhead(cpu_dp->tag_ops);
+       new_master_mtu = largest_mtu + overhead;
        if (new_master_mtu > mtu_limit)
                return -ERANGE;
 
@@ -1998,8 +2111,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
 
 out_port_failed:
        if (new_master_mtu != old_master_mtu)
-               dsa_port_mtu_change(cpu_dp, old_master_mtu -
-                                   dsa_tag_protocol_overhead(cpu_dp->tag_ops));
+               dsa_port_mtu_change(cpu_dp, old_master_mtu - overhead);
 out_cpu_failed:
        if (new_master_mtu != old_master_mtu)
                dev_set_mtu(master, old_master_mtu);
index b2fba1a003ce369a275b7fdbb08952d7165804a5..5105a5ff58fa20156099977a64f81edc98f9c710 100644 (file)
@@ -114,7 +114,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
                skb = nskb;
        }
 
-       dev_sw_netstats_rx_add(skb->dev, skb->len);
+       dev_sw_netstats_rx_add(skb->dev, skb->len + ETH_HLEN);
 
        if (dsa_skb_defer_rx_timestamp(p, skb))
                return 0;
index 10239daa57454360b7f867a3bc9771f204f1bbe6..cacdafb41200e5f941dff2e259a57720fb916f43 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/dsa/brcm.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 
@@ -252,6 +253,7 @@ static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
 static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
                                        struct net_device *dev)
 {
+       int len = BRCM_LEG_TAG_LEN;
        int source_port;
        u8 *brcm_tag;
 
@@ -266,12 +268,16 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
        if (!skb->dev)
                return NULL;
 
+       /* VLAN tag is added by BCM63xx internal switch */
+       if (netdev_uses_dsa(skb->dev))
+               len += VLAN_HLEN;
+
        /* Remove Broadcom tag and update checksum */
-       skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
+       skb_pull_rcsum(skb, len);
 
        dsa_default_offload_fwd_mark(skb);
 
-       dsa_strip_etype_header(skb, BRCM_LEG_TAG_LEN);
+       dsa_strip_etype_header(skb, len);
 
        return skb;
 }
index fab66c169b9fa92f2f23b6d3654076f0d0457377..20165e07ef901b20e274487b61d5684d23c60ee7 100644 (file)
@@ -270,11 +270,12 @@ static int ethnl_update_linkmodes(struct genl_info *info, struct nlattr **tb,
                                            "lanes configuration not supported by device");
                        return -EOPNOTSUPP;
                }
-       } else if (!lsettings->autoneg) {
-               /* If autoneg is off and lanes parameter is not passed from user,
-                * set the lanes parameter to 0.
+       } else if (!lsettings->autoneg && ksettings->lanes) {
+               /* If autoneg is off and lanes parameter is not passed from user but
+                * it was defined previously then set the lanes parameter to 0.
                 */
                ksettings->lanes = 0;
+               *mod = true;
        }
 
        ret = ethnl_update_bitset(ksettings->link_modes.advertising,
index 00db74d96583d0f7b33b29697037b979f052c1d5..b77f1189d19d1ff5dc76f4a7345efc7a65918399 100644 (file)
@@ -415,7 +415,7 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb,
        node_dst = find_node_by_addr_A(&port->hsr->node_db,
                                       eth_hdr(skb)->h_dest);
        if (!node_dst) {
-               if (net_ratelimit())
+               if (port->hsr->prot_version != PRP_V1 && net_ratelimit())
                        netdev_err(skb->dev, "%s: Unknown node\n", __func__);
                return;
        }
index d8f4379d4fa68b5b07bb2c45cd74d4b73213c107..832e3c50816c47a23d16b59107e5e9be9a5163d5 100644 (file)
@@ -2488,8 +2488,7 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
        if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
                return -EOPNOTSUPP;
 
-       if (!info->attrs[NL802154_ATTR_SEC_LEVEL] ||
-           llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
+       if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
                                 &sl) < 0)
                return -EINVAL;
 
index b5736ef16ed2d54d1b15be79de35766d36bd12b3..390f4be7f7bec20f33aa80e9bf12d5e2f3760562 100644 (file)
@@ -576,6 +576,9 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
                        cfg->fc_scope = RT_SCOPE_UNIVERSE;
        }
 
+       if (!cfg->fc_table)
+               cfg->fc_table = RT_TABLE_MAIN;
+
        if (cmd == SIOCDELRT)
                return 0;
 
index 5c14fe030eda555ebfc25e2e073b550ad40495ef..6c37c4f98ccab403e29740f41003b3696df7250f 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/fou.yaml */
 /* YNL-GEN kernel source */
index 58b1e1ed4b3bb3cb6855c74b4c87f8d5876b7b07..dbd0780a5d34c3963681c1d7f0aaf579fc186e5e 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/fou.yaml */
 /* YNL-GEN kernel header */
index 8cebb476b3ab1833b4efe073efc57dbdfeffd21d..b8607763d113a5878181ffd17a36a3ea4261ca55 100644 (file)
@@ -749,6 +749,11 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
                room = 576;
        room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen;
        room -= sizeof(struct icmphdr);
+       /* Guard against tiny mtu. We need to include at least one
+        * IP network header for this message to make any sense.
+        */
+       if (room <= (int)sizeof(struct iphdr))
+               goto ende;
 
        icmp_param.data_len = skb_in->len - icmp_param.offset;
        if (icmp_param.data_len > room)
index e41fdc38ce196fa3ba7c8ed5e6a0aa20c7e30362..6edae3886885565985f9f45bae65ef2f4498f22f 100644 (file)
@@ -828,8 +828,14 @@ bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const
 #if IS_ENABLED(CONFIG_IPV6)
        struct in6_addr addr_any = {};
 
-       if (sk->sk_family != tb->family)
+       if (sk->sk_family != tb->family) {
+               if (sk->sk_family == AF_INET)
+                       return net_eq(ib2_net(tb), net) && tb->port == port &&
+                               tb->l3mdev == l3mdev &&
+                               ipv6_addr_equal(&tb->v6_rcv_saddr, &addr_any);
+
                return false;
+       }
 
        if (sk->sk_family == AF_INET6)
                return net_eq(ib2_net(tb), net) && tb->port == port &&
index ffff46cdcb58f9b5b4c210a548d685d8f0c7716a..e55a202649608f6f3c814e143581d631ce0467e6 100644 (file)
@@ -552,7 +552,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                truncate = true;
        }
 
-       nhoff = skb_network_header(skb) - skb_mac_header(skb);
+       nhoff = skb_network_offset(skb);
        if (skb->protocol == htons(ETH_P_IP) &&
            (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
                truncate = true;
@@ -561,7 +561,7 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                int thoff;
 
                if (skb_transport_header_was_set(skb))
-                       thoff = skb_transport_header(skb) - skb_mac_header(skb);
+                       thoff = skb_transport_offset(skb);
                else
                        thoff = nhoff + sizeof(struct ipv6hdr);
                if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
index de90b09dfe78fc4510985dd436c017d3c46f054c..2541083d49ad66fcc6c4485abb4bd96c50dc0989 100644 (file)
@@ -614,10 +614,10 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        }
 
        headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
-       if (headroom > dev->needed_headroom)
-               dev->needed_headroom = headroom;
+       if (headroom > READ_ONCE(dev->needed_headroom))
+               WRITE_ONCE(dev->needed_headroom, headroom);
 
-       if (skb_cow_head(skb, dev->needed_headroom)) {
+       if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom))) {
                ip_rt_put(rt);
                goto tx_dropped;
        }
@@ -800,10 +800,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 
        max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
                        + rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
-       if (max_headroom > dev->needed_headroom)
-               dev->needed_headroom = max_headroom;
+       if (max_headroom > READ_ONCE(dev->needed_headroom))
+               WRITE_ONCE(dev->needed_headroom, max_headroom);
 
-       if (skb_cow_head(skb, dev->needed_headroom)) {
+       if (skb_cow_head(skb, READ_ONCE(dev->needed_headroom))) {
                ip_rt_put(rt);
                DEV_STATS_INC(dev, tx_dropped);
                kfree_skb(skb);
index 409ec2a1f95b0657dc12734f715d28d441894370..5178a3f3cb5378befbfef34442e6934a1b6ffc22 100644 (file)
@@ -1089,13 +1089,13 @@ static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos)
 }
 
 void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family)
-       __acquires(RCU)
+       __acquires(ping_table.lock)
 {
        struct ping_iter_state *state = seq->private;
        state->bucket = 0;
        state->family = family;
 
-       rcu_read_lock();
+       spin_lock(&ping_table.lock);
 
        return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN;
 }
@@ -1121,9 +1121,9 @@ void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 EXPORT_SYMBOL_GPL(ping_seq_next);
 
 void ping_seq_stop(struct seq_file *seq, void *v)
-       __releases(RCU)
+       __releases(ping_table.lock)
 {
-       rcu_read_unlock();
+       spin_unlock(&ping_table.lock);
 }
 EXPORT_SYMBOL_GPL(ping_seq_stop);
 
index 94df935ee0c5a83a4b1393653b79ac6060b4f12a..8088a5011e7df0b49b785390b50ed3ce3cd3504e 100644 (file)
@@ -91,12 +91,12 @@ EXPORT_SYMBOL_GPL(raw_v4_hashinfo);
 int raw_hash_sk(struct sock *sk)
 {
        struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
-       struct hlist_nulls_head *hlist;
+       struct hlist_head *hlist;
 
        hlist = &h->ht[raw_hashfunc(sock_net(sk), inet_sk(sk)->inet_num)];
 
        spin_lock(&h->lock);
-       __sk_nulls_add_node_rcu(sk, hlist);
+       sk_add_node_rcu(sk, hlist);
        sock_set_flag(sk, SOCK_RCU_FREE);
        spin_unlock(&h->lock);
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
@@ -110,7 +110,7 @@ void raw_unhash_sk(struct sock *sk)
        struct raw_hashinfo *h = sk->sk_prot->h.raw_hash;
 
        spin_lock(&h->lock);
-       if (__sk_nulls_del_node_init_rcu(sk))
+       if (sk_del_node_init_rcu(sk))
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
        spin_unlock(&h->lock);
 }
@@ -163,16 +163,15 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
 static int raw_v4_input(struct net *net, struct sk_buff *skb,
                        const struct iphdr *iph, int hash)
 {
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
        int sdif = inet_sdif(skb);
+       struct hlist_head *hlist;
        int dif = inet_iif(skb);
        int delivered = 0;
        struct sock *sk;
 
        hlist = &raw_v4_hashinfo.ht[hash];
        rcu_read_lock();
-       sk_nulls_for_each(sk, hnode, hlist) {
+       sk_for_each_rcu(sk, hlist) {
                if (!raw_v4_match(net, sk, iph->protocol,
                                  iph->saddr, iph->daddr, dif, sdif))
                        continue;
@@ -264,10 +263,9 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
 void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
 {
        struct net *net = dev_net(skb->dev);
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
        int dif = skb->dev->ifindex;
        int sdif = inet_sdif(skb);
+       struct hlist_head *hlist;
        const struct iphdr *iph;
        struct sock *sk;
        int hash;
@@ -276,7 +274,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
        hlist = &raw_v4_hashinfo.ht[hash];
 
        rcu_read_lock();
-       sk_nulls_for_each(sk, hnode, hlist) {
+       sk_for_each_rcu(sk, hlist) {
                iph = (const struct iphdr *)skb->data;
                if (!raw_v4_match(net, sk, iph->protocol,
                                  iph->daddr, iph->saddr, dif, sdif))
@@ -950,14 +948,13 @@ static struct sock *raw_get_first(struct seq_file *seq, int bucket)
 {
        struct raw_hashinfo *h = pde_data(file_inode(seq->file));
        struct raw_iter_state *state = raw_seq_private(seq);
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
+       struct hlist_head *hlist;
        struct sock *sk;
 
        for (state->bucket = bucket; state->bucket < RAW_HTABLE_SIZE;
                        ++state->bucket) {
                hlist = &h->ht[state->bucket];
-               sk_nulls_for_each(sk, hnode, hlist) {
+               sk_for_each(sk, hlist) {
                        if (sock_net(sk) == seq_file_net(seq))
                                return sk;
                }
@@ -970,7 +967,7 @@ static struct sock *raw_get_next(struct seq_file *seq, struct sock *sk)
        struct raw_iter_state *state = raw_seq_private(seq);
 
        do {
-               sk = sk_nulls_next(sk);
+               sk = sk_next(sk);
        } while (sk && sock_net(sk) != seq_file_net(seq));
 
        if (!sk)
@@ -989,9 +986,12 @@ static struct sock *raw_get_idx(struct seq_file *seq, loff_t pos)
 }
 
 void *raw_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(RCU)
+       __acquires(&h->lock)
 {
-       rcu_read_lock();
+       struct raw_hashinfo *h = pde_data(file_inode(seq->file));
+
+       spin_lock(&h->lock);
+
        return *pos ? raw_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
 }
 EXPORT_SYMBOL_GPL(raw_seq_start);
@@ -1010,9 +1010,11 @@ void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 EXPORT_SYMBOL_GPL(raw_seq_next);
 
 void raw_seq_stop(struct seq_file *seq, void *v)
-       __releases(RCU)
+       __releases(&h->lock)
 {
-       rcu_read_unlock();
+       struct raw_hashinfo *h = pde_data(file_inode(seq->file));
+
+       spin_unlock(&h->lock);
 }
 EXPORT_SYMBOL_GPL(raw_seq_stop);
 
index 999321834b94a8f7f2a4996575b7cfaafb6fa2b7..da3591a66a169f5a790676c01111b430d93d72ab 100644 (file)
@@ -57,8 +57,7 @@ static bool raw_lookup(struct net *net, struct sock *sk,
 static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r)
 {
        struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
+       struct hlist_head *hlist;
        struct sock *sk;
        int slot;
 
@@ -68,7 +67,7 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2
        rcu_read_lock();
        for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) {
                hlist = &hashinfo->ht[slot];
-               sk_nulls_for_each(sk, hnode, hlist) {
+               sk_for_each_rcu(sk, hlist) {
                        if (raw_lookup(net, sk, r)) {
                                /*
                                 * Grab it and keep until we fill
@@ -142,9 +141,8 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
        struct raw_hashinfo *hashinfo = raw_get_hashinfo(r);
        struct net *net = sock_net(skb->sk);
        struct inet_diag_dump_data *cb_data;
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
        int num, s_num, slot, s_slot;
+       struct hlist_head *hlist;
        struct sock *sk = NULL;
        struct nlattr *bc;
 
@@ -161,7 +159,7 @@ static void raw_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
                num = 0;
 
                hlist = &hashinfo->ht[slot];
-               sk_nulls_for_each(sk, hnode, hlist) {
+               sk_for_each_rcu(sk, hlist) {
                        struct inet_sock *inet = inet_sk(sk);
 
                        if (!net_eq(sock_net(sk), net))
index 0d0cc4ef2b85a453582d3301f62d7d25d439e592..40fe70fc2015d5ce0a8d2791a714f1324ecb231e 100644 (file)
@@ -25,6 +25,7 @@ static int ip_local_port_range_min[] = { 1, 1 };
 static int ip_local_port_range_max[] = { 65535, 65535 };
 static int tcp_adv_win_scale_min = -31;
 static int tcp_adv_win_scale_max = 31;
+static int tcp_app_win_max = 31;
 static int tcp_min_snd_mss_min = TCP_MIN_SND_MSS;
 static int tcp_min_snd_mss_max = 65535;
 static int ip_privileged_port_min;
@@ -1198,6 +1199,8 @@ static struct ctl_table ipv4_net_table[] = {
                .maxlen         = sizeof(u8),
                .mode           = 0644,
                .proc_handler   = proc_dou8vec_minmax,
+               .extra1         = SYSCTL_ZERO,
+               .extra2         = &tcp_app_win_max,
        },
        {
                .procname       = "tcp_adv_win_scale",
index ea370afa70ed979266dbeea474b034e833b15db4..b9d55277cb858a3a288e1ae800c9f507444f0be1 100644 (file)
@@ -2780,7 +2780,7 @@ static int tcp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
 static void bpf_iter_tcp_put_batch(struct bpf_tcp_iter_state *iter)
 {
        while (iter->cur_sk < iter->end_sk)
-               sock_put(iter->batch[iter->cur_sk++]);
+               sock_gen_put(iter->batch[iter->cur_sk++]);
 }
 
 static int bpf_iter_tcp_realloc_batch(struct bpf_tcp_iter_state *iter,
@@ -2941,7 +2941,7 @@ static void *bpf_iter_tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
                 * st->bucket.  See tcp_seek_last_pos().
                 */
                st->offset++;
-               sock_put(iter->batch[iter->cur_sk++]);
+               sock_gen_put(iter->batch[iter->cur_sk++]);
        }
 
        if (iter->cur_sk < iter->end_sk)
index 71d01cf3c13eb4bd3d314ef140568d2ffd6a499e..ba839e441450f195012a8d77cb9e5ed956962d2f 100644 (file)
@@ -3605,7 +3605,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
        th->window = htons(min(req->rsk_rcv_wnd, 65535U));
        tcp_options_write(th, NULL, &opts);
        th->doff = (tcp_header_size >> 2);
-       __TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS);
+       TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS);
 
 #ifdef CONFIG_TCP_MD5SIG
        /* Okay, we have all we need - do the md5 hash if needed */
index 89f5f0f3f5d65b6aac0dae2302d8a5607a492155..a4ecfc9d25930967a6af7bd9de9aa52bfd08730d 100644 (file)
@@ -959,7 +959,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                truncate = true;
        }
 
-       nhoff = skb_network_header(skb) - skb_mac_header(skb);
+       nhoff = skb_network_offset(skb);
        if (skb->protocol == htons(ETH_P_IP) &&
            (ntohs(ip_hdr(skb)->tot_len) > skb->len - nhoff))
                truncate = true;
@@ -968,7 +968,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                int thoff;
 
                if (skb_transport_header_was_set(skb))
-                       thoff = skb_transport_header(skb) - skb_mac_header(skb);
+                       thoff = skb_transport_offset(skb);
                else
                        thoff = nhoff + sizeof(struct ipv6hdr);
                if (ntohs(ipv6_hdr(skb)->payload_len) > skb->len - thoff)
index c314fdde0097c8c8dc30ab1dc43cbc2905c0f5d1..95a55c6630add2c060d8923a3f7311dd7bdcb4ea 100644 (file)
@@ -1965,8 +1965,13 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
        IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
        if (proto == IPPROTO_ICMPV6) {
                struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+               u8 icmp6_type;
 
-               ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type);
+               if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl)
+                       icmp6_type = fl6->fl6_icmp_type;
+               else
+                       icmp6_type = icmp6_hdr(skb)->icmp6_type;
+               ICMP6MSGOUT_INC_STATS(net, idev, icmp6_type);
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
        }
 
index 47b6607a13706ef415e0b19f38014700e673da84..5e80e517f071013410349d1fd93afc00a394e284 100644 (file)
@@ -1240,8 +1240,8 @@ route_lookup:
         */
        max_headroom = LL_RESERVED_SPACE(dst->dev) + sizeof(struct ipv6hdr)
                        + dst->header_len + t->hlen;
-       if (max_headroom > dev->needed_headroom)
-               dev->needed_headroom = max_headroom;
+       if (max_headroom > READ_ONCE(dev->needed_headroom))
+               WRITE_ONCE(dev->needed_headroom, max_headroom);
 
        err = ip6_tnl_encap(skb, t, &proto, fl6);
        if (err)
index bac9ba747bdecf8df24acb6c980a822d8f237403..a327aa481df48b8baed42ae11db53f05ce4f6841 100644 (file)
@@ -141,10 +141,9 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
 static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
 {
        struct net *net = dev_net(skb->dev);
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
        const struct in6_addr *saddr;
        const struct in6_addr *daddr;
+       struct hlist_head *hlist;
        struct sock *sk;
        bool delivered = false;
        __u8 hash;
@@ -155,7 +154,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
        hash = raw_hashfunc(net, nexthdr);
        hlist = &raw_v6_hashinfo.ht[hash];
        rcu_read_lock();
-       sk_nulls_for_each(sk, hnode, hlist) {
+       sk_for_each_rcu(sk, hlist) {
                int filtered;
 
                if (!raw_v6_match(net, sk, nexthdr, daddr, saddr,
@@ -333,15 +332,14 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
                u8 type, u8 code, int inner_offset, __be32 info)
 {
        struct net *net = dev_net(skb->dev);
-       struct hlist_nulls_head *hlist;
-       struct hlist_nulls_node *hnode;
+       struct hlist_head *hlist;
        struct sock *sk;
        int hash;
 
        hash = raw_hashfunc(net, nexthdr);
        hlist = &raw_v6_hashinfo.ht[hash];
        rcu_read_lock();
-       sk_nulls_for_each(sk, hnode, hlist) {
+       sk_for_each_rcu(sk, hlist) {
                /* Note: ipv6_hdr(skb) != skb->data */
                const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;
 
index 488aec9e1a74f338a777e3c6b0e2d53f2b48777c..d1876f19222552ca374b19e37502df0e570946ba 100644 (file)
@@ -32,7 +32,8 @@ static void *ipv6_rpl_segdata_pos(const struct ipv6_rpl_sr_hdr *hdr, int i)
 size_t ipv6_rpl_srh_size(unsigned char n, unsigned char cmpri,
                         unsigned char cmpre)
 {
-       return (n * IPV6_PFXTAIL_LEN(cmpri)) + IPV6_PFXTAIL_LEN(cmpre);
+       return sizeof(struct ipv6_rpl_sr_hdr) + (n * IPV6_PFXTAIL_LEN(cmpri)) +
+               IPV6_PFXTAIL_LEN(cmpre);
 }
 
 void ipv6_rpl_srh_decompress(struct ipv6_rpl_sr_hdr *outhdr,
index 9fb2f33ee3a76a09bbe15a9aaf1371a804f91ee2..a675acfb901d102ce56563b1d50ae827d9e04859 100644 (file)
@@ -1395,9 +1395,11 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                        msg->msg_name = &sin;
                        msg->msg_namelen = sizeof(sin);
 do_udp_sendmsg:
-                       if (ipv6_only_sock(sk))
-                               return -ENETUNREACH;
-                       return udp_sendmsg(sk, msg, len);
+                       err = ipv6_only_sock(sk) ?
+                               -ENETUNREACH : udp_sendmsg(sk, msg, len);
+                       msg->msg_name = sin6;
+                       msg->msg_namelen = addr_len;
+                       return err;
                }
        }
 
index eb0295d90039577acc88da033d45ac13692c9cfd..fc3fddeb6f36d4066c91d4eae889deccb07799fc 100644 (file)
@@ -83,7 +83,7 @@ struct iucv_irq_data {
        u16 ippathid;
        u8  ipflags1;
        u8  iptype;
-       u32 res2[8];
+       u32 res2[9];
 };
 
 struct iucv_irq_list {
index 4db5a554bdbd9e80eb697a88cb7208e15d7931bc..41a74fc84ca13a4d86d1b16b942667cfc1b3c9a8 100644 (file)
@@ -677,8 +677,8 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("L2TP over IP");
 MODULE_VERSION("1.0");
 
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
- * enums
+/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol,
+ * because __stringify doesn't like enums
  */
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
-MODULE_ALIAS_NET_PF_PROTO(PF_INET, IPPROTO_L2TP);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 115, 2);
+MODULE_ALIAS_NET_PF_PROTO(PF_INET, 115);
index 2478aa60145fbd6c91155fad595e6b37252ed198..5137ea1861ce26a2e6efc1f5c29e4de0fdce2c06 100644 (file)
@@ -806,8 +806,8 @@ MODULE_AUTHOR("Chris Elston <celston@katalix.com>");
 MODULE_DESCRIPTION("L2TP IP encapsulation for IPv6");
 MODULE_VERSION("1.0");
 
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
- * enums
+/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol,
+ * because __stringify doesn't like enums
  */
-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 2, IPPROTO_L2TP);
-MODULE_ALIAS_NET_PF_PROTO(PF_INET6, IPPROTO_L2TP);
+MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 115, 2);
+MODULE_ALIAS_NET_PF_PROTO(PF_INET6, 115);
index 8eb3423008687a3f09c3512d8adbb00b19579695..d3d861911ed65084bd617736c5c32c3ed899de50 100644 (file)
@@ -2611,6 +2611,17 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
        if (!sband)
                return -EINVAL;
 
+       if (params->basic_rates) {
+               if (!ieee80211_parse_bitrates(link->conf->chandef.width,
+                                             wiphy->bands[sband->band],
+                                             params->basic_rates,
+                                             params->basic_rates_len,
+                                             &link->conf->basic_rates))
+                       return -EINVAL;
+               changed |= BSS_CHANGED_BASIC_RATES;
+               ieee80211_check_rate_mask(link);
+       }
+
        if (params->use_cts_prot >= 0) {
                link->conf->use_cts_prot = params->use_cts_prot;
                changed |= BSS_CHANGED_ERP_CTS_PROT;
@@ -2632,16 +2643,6 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
                changed |= BSS_CHANGED_ERP_SLOT;
        }
 
-       if (params->basic_rates) {
-               ieee80211_parse_bitrates(link->conf->chandef.width,
-                                        wiphy->bands[sband->band],
-                                        params->basic_rates,
-                                        params->basic_rates_len,
-                                        &link->conf->basic_rates);
-               changed |= BSS_CHANGED_BASIC_RATES;
-               ieee80211_check_rate_mask(link);
-       }
-
        if (params->ap_isolate >= 0) {
                if (params->ap_isolate)
                        sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
index ecc232eb1ee82f9f3a143a65b5b258a2dbd32773..e082582e0aa284b4af3792c4c6dc7c176f61df68 100644 (file)
@@ -1284,6 +1284,9 @@ struct ieee80211_local {
        struct list_head active_txqs[IEEE80211_NUM_ACS];
        u16 schedule_round[IEEE80211_NUM_ACS];
 
+       /* serializes ieee80211_handle_wake_tx_queue */
+       spinlock_t handle_wake_tx_queue_lock;
+
        u16 airtime_flags;
        u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
        u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
index 846528850612a7d9886be8d5ca5147b24fea61e1..ddf2b7811c557973846a5926ef5b521295740e31 100644 (file)
@@ -802,6 +802,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
        local->aql_threshold = IEEE80211_AQL_THRESHOLD;
        atomic_set(&local->aql_total_pending_airtime, 0);
 
+       spin_lock_init(&local->handle_wake_tx_queue_lock);
+
        INIT_LIST_HEAD(&local->chanctx_list);
        mutex_init(&local->chanctx_mtx);
 
index f7fdfe710951faa1c9402cfd8d71ced290864f3e..af57616d2f1d9368906dfcb68d6cc8f60938e725 100644 (file)
@@ -2765,29 +2765,10 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
            mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
                return RX_DROP_MONITOR;
 
-       /* Frame has reached destination.  Don't forward */
-       if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
-               goto rx_accept;
-
-       if (!ifmsh->mshcfg.dot11MeshForwarding) {
-               if (is_multicast_ether_addr(eth->h_dest))
-                       goto rx_accept;
-
-               return RX_DROP_MONITOR;
-       }
-
        /* forward packet */
        if (sdata->crypto_tx_tailroom_needed_cnt)
                tailroom = IEEE80211_ENCRYPT_TAILROOM;
 
-       if (!--mesh_hdr->ttl) {
-               if (multicast)
-                       goto rx_accept;
-
-               IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-               return RX_DROP_MONITOR;
-       }
-
        if (mesh_hdr->flags & MESH_FLAGS_AE) {
                struct mesh_path *mppath;
                char *proxied_addr;
@@ -2814,6 +2795,25 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
                rcu_read_unlock();
        }
 
+       /* Frame has reached destination.  Don't forward */
+       if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
+               goto rx_accept;
+
+       if (!--mesh_hdr->ttl) {
+               if (multicast)
+                       goto rx_accept;
+
+               IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
+               return RX_DROP_MONITOR;
+       }
+
+       if (!ifmsh->mshcfg.dot11MeshForwarding) {
+               if (is_multicast_ether_addr(eth->h_dest))
+                       goto rx_accept;
+
+               return RX_DROP_MONITOR;
+       }
+
        skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
 
        ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
@@ -2833,6 +2833,9 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
 
                if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
                        return RX_DROP_UNUSABLE;
+
+               if (skb_linearize(fwd_skb))
+                       return RX_DROP_UNUSABLE;
        }
 
        fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
@@ -2847,7 +2850,7 @@ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta
                hdrlen += ETH_ALEN;
        else
                fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
-       skb_set_network_header(fwd_skb, hdrlen);
+       skb_set_network_header(fwd_skb, hdrlen + 2);
 
        info = IEEE80211_SKB_CB(fwd_skb);
        memset(info, 0, sizeof(*info));
@@ -2896,7 +2899,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        __le16 fc = hdr->frame_control;
        struct sk_buff_head frame_list;
-       static ieee80211_rx_result res;
+       ieee80211_rx_result res;
        struct ethhdr ethhdr;
        const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
 
@@ -2930,7 +2933,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
                                          data_offset, true))
                return RX_DROP_UNUSABLE;
 
-       if (rx->sta && rx->sta->amsdu_mesh_control < 0) {
+       if (rx->sta->amsdu_mesh_control < 0) {
                bool valid_std = ieee80211_is_valid_amsdu(skb, true);
                bool valid_nonstd = ieee80211_is_valid_amsdu(skb, false);
 
@@ -3006,7 +3009,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
                }
        }
 
-       if (is_multicast_ether_addr(hdr->addr1))
+       if (is_multicast_ether_addr(hdr->addr1) || !rx->sta)
                return RX_DROP_UNUSABLE;
 
        if (rx->key) {
@@ -3037,7 +3040,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        struct net_device *dev = sdata->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        __le16 fc = hdr->frame_control;
-       static ieee80211_rx_result res;
+       ieee80211_rx_result res;
        bool port_control;
        int err;
 
index 7d68dbc872d7736f5d72eeb1b6f64ddbdf67ca6f..941bda9141faab6883a0e7a715eee47d1e34d806 100644 (file)
@@ -1264,7 +1264,8 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
        list_del_rcu(&sta->list);
        sta->removed = true;
 
-       drv_sta_pre_rcu_remove(local, sta->sdata, sta);
+       if (sta->uploaded)
+               drv_sta_pre_rcu_remove(local, sta->sdata, sta);
 
        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
            rcu_access_pointer(sdata->u.vlan.sta) == sta)
index 1a28fe5cb614f2a5fe6f9007d1769fa7d6446a18..8c397650b96f605f3b2e75c599337cdac47f5555 100644 (file)
@@ -314,6 +314,8 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
        struct ieee80211_txq *queue;
 
+       spin_lock(&local->handle_wake_tx_queue_lock);
+
        /* Use ieee80211_next_txq() for airtime fairness accounting */
        ieee80211_txq_schedule_start(hw, txq->ac);
        while ((queue = ieee80211_next_txq(hw, txq->ac))) {
@@ -321,6 +323,7 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
                ieee80211_return_txq(hw, queue, false);
        }
        ieee80211_txq_schedule_end(hw, txq->ac);
+       spin_unlock(&local->handle_wake_tx_queue_lock);
 }
 EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
 
@@ -4903,7 +4906,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
                                       &eht_cap->eht_cap_elem,
                                       is_ap);
        return 2 + 1 +
-              sizeof(he_cap->he_cap_elem) + n +
+              sizeof(eht_cap->eht_cap_elem) + n +
               ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
                                      eht_cap->eht_cap_elem.phy_cap_info);
        return 0;
index a12c63638680122f7f449fba4060066c78a07c14..1601be5764145d3c736c59699ccc3873a726750f 100644 (file)
@@ -147,6 +147,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
                           struct sta_info *sta, struct sk_buff *skb)
 {
+       const struct ethhdr *eth = (void *)skb->data;
        struct mac80211_qos_map *qos_map;
        bool qos;
 
@@ -154,8 +155,9 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
        skb_get_hash(skb);
 
        /* all mesh/ocb stations are required to support WME */
-       if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
-                   sdata->vif.type == NL80211_IFTYPE_OCB))
+       if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT &&
+           !is_multicast_ether_addr(eth->h_dest)) ||
+           (sdata->vif.type == NL80211_IFTYPE_OCB && sta))
                qos = true;
        else if (sta)
                qos = sta->sta.wme;
index 9b0933a185ebc9981ff8c64478742f7f6e9d8e9e..5c191bedd72c4440b4ddffdef8848c2011451e8b 100644 (file)
@@ -52,7 +52,7 @@ static int mac802154_scan_cleanup_locked(struct ieee802154_local *local,
        request = rcu_replace_pointer(local->scan_req, NULL, 1);
        if (!request)
                return 0;
-       kfree_rcu(request);
+       kvfree_rcu_mightsleep(request);
 
        /* Advertize first, while we know the devices cannot be removed */
        if (aborted)
@@ -403,7 +403,7 @@ int mac802154_stop_beacons_locked(struct ieee802154_local *local,
        request = rcu_replace_pointer(local->beacon_req, NULL, 1);
        if (!request)
                return 0;
-       kfree_rcu(request);
+       kvfree_rcu_mightsleep(request);
 
        nl802154_beaconing_done(wpan_dev);
 
index d237d142171c5a96b13ef459832fc988fa2f5401..bceaab8dd8e460e7a3459e12af6089ab6bb6b2b7 100644 (file)
@@ -9,11 +9,18 @@
 void mptcp_fastopen_subflow_synack_set_params(struct mptcp_subflow_context *subflow,
                                              struct request_sock *req)
 {
-       struct sock *ssk = subflow->tcp_sock;
-       struct sock *sk = subflow->conn;
+       struct sock *sk, *ssk;
        struct sk_buff *skb;
        struct tcp_sock *tp;
 
+       /* on early fallback the subflow context is deleted by
+        * subflow_syn_recv_sock()
+        */
+       if (!subflow)
+               return;
+
+       ssk = subflow->tcp_sock;
+       sk = subflow->conn;
        tp = tcp_sk(ssk);
 
        subflow->is_mptfo = 1;
index b30cea2fbf3fd0d4706573c4c41624ca3d9cfe26..355f798d575a40542195fcc724819e1de9f2e4e7 100644 (file)
@@ -1192,9 +1192,8 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
         */
        if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
                if (mp_opt.data_fin && mp_opt.data_len == 1 &&
-                   mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64) &&
-                   schedule_work(&msk->work))
-                       sock_hold(subflow->conn);
+                   mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64))
+                       mptcp_schedule_work((struct sock *)msk);
 
                return true;
        }
index 56628b52d1001a967eb2e504bdbeac0c4cd17acc..5c8dea49626c31a008f9243498564fbcd3cebb1c 100644 (file)
@@ -997,9 +997,13 @@ out:
        return ret;
 }
 
+static struct lock_class_key mptcp_slock_keys[2];
+static struct lock_class_key mptcp_keys[2];
+
 static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
                                            struct mptcp_pm_addr_entry *entry)
 {
+       bool is_ipv6 = sk->sk_family == AF_INET6;
        int addrlen = sizeof(struct sockaddr_in);
        struct sockaddr_storage addr;
        struct socket *ssock;
@@ -1016,6 +1020,18 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
        if (!newsk)
                return -EINVAL;
 
+       /* The subflow socket lock is acquired in a nested to the msk one
+        * in several places, even by the TCP stack, and this msk is a kernel
+        * socket: lockdep complains. Instead of propagating the _nested
+        * modifiers in several places, re-init the lock class for the msk
+        * socket to an mptcp specific one.
+        */
+       sock_lock_init_class_and_name(newsk,
+                                     is_ipv6 ? "mlock-AF_INET6" : "mlock-AF_INET",
+                                     &mptcp_slock_keys[is_ipv6],
+                                     is_ipv6 ? "msk_lock-AF_INET6" : "msk_lock-AF_INET",
+                                     &mptcp_keys[is_ipv6]);
+
        lock_sock(newsk);
        ssock = __mptcp_nmpc_socket(mptcp_sk(newsk));
        release_sock(newsk);
index 3ad9c46202fc63a5b3a870bf2ba994a8d9148264..b998e9df53cef4c3e5fcffab0fee9ca0080ef7bf 100644 (file)
@@ -825,7 +825,6 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
        if (sk->sk_socket && !ssk->sk_socket)
                mptcp_sock_graft(ssk, sk->sk_socket);
 
-       mptcp_propagate_sndbuf((struct sock *)msk, ssk);
        mptcp_sockopt_sync_locked(msk, ssk);
        return true;
 }
@@ -2316,7 +2315,26 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
                              unsigned int flags)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
-       bool need_push, dispose_it;
+       bool dispose_it, need_push = false;
+
+       /* If the first subflow moved to a close state before accept, e.g. due
+        * to an incoming reset, mptcp either:
+        * - if either the subflow or the msk are dead, destroy the context
+        *   (the subflow socket is deleted by inet_child_forget) and the msk
+        * - otherwise do nothing at the moment and take action at accept and/or
+        *   listener shutdown - user-space must be able to accept() the closed
+        *   socket.
+        */
+       if (msk->in_accept_queue && msk->first == ssk) {
+               if (!sock_flag(sk, SOCK_DEAD) && !sock_flag(ssk, SOCK_DEAD))
+                       return;
+
+               /* ensure later check in mptcp_worker() will dispose the msk */
+               sock_set_flag(sk, SOCK_DEAD);
+               lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+               mptcp_subflow_drop_ctx(ssk);
+               goto out_release;
+       }
 
        dispose_it = !msk->subflow || ssk != msk->subflow->sk;
        if (dispose_it)
@@ -2343,7 +2361,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
                goto out;
        }
 
-       sock_orphan(ssk);
        subflow->disposable = 1;
 
        /* if ssk hit tcp_done(), tcp_cleanup_ulp() cleared the related ops
@@ -2351,6 +2368,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
         * reference owned by msk;
         */
        if (!inet_csk(ssk)->icsk_ulp_ops) {
+               WARN_ON_ONCE(!sock_flag(ssk, SOCK_DEAD));
                kfree_rcu(subflow, rcu);
        } else {
                /* otherwise tcp will dispose of the ssk and subflow ctx */
@@ -2360,11 +2378,14 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
                        inet_csk_listen_stop(ssk);
                        mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CLOSED);
                }
+
                __tcp_close(ssk, 0);
 
                /* close acquired an extra ref */
                __sock_put(ssk);
        }
+
+out_release:
        release_sock(ssk);
 
        sock_put(ssk);
@@ -2399,9 +2420,10 @@ static unsigned int mptcp_sync_mss(struct sock *sk, u32 pmtu)
        return 0;
 }
 
-static void __mptcp_close_subflow(struct mptcp_sock *msk)
+static void __mptcp_close_subflow(struct sock *sk)
 {
        struct mptcp_subflow_context *subflow, *tmp;
+       struct mptcp_sock *msk = mptcp_sk(sk);
 
        might_sleep();
 
@@ -2415,16 +2437,17 @@ static void __mptcp_close_subflow(struct mptcp_sock *msk)
                if (!skb_queue_empty_lockless(&ssk->sk_receive_queue))
                        continue;
 
-               mptcp_close_ssk((struct sock *)msk, ssk, subflow);
+               mptcp_close_ssk(sk, ssk, subflow);
        }
+
 }
 
-static bool mptcp_check_close_timeout(const struct sock *sk)
+static bool mptcp_should_close(const struct sock *sk)
 {
        s32 delta = tcp_jiffies32 - inet_csk(sk)->icsk_mtup.probe_timestamp;
        struct mptcp_subflow_context *subflow;
 
-       if (delta >= TCP_TIMEWAIT_LEN)
+       if (delta >= TCP_TIMEWAIT_LEN || mptcp_sk(sk)->in_accept_queue)
                return true;
 
        /* if all subflows are in closed status don't bother with additional
@@ -2609,7 +2632,7 @@ static void mptcp_worker(struct work_struct *work)
 
        lock_sock(sk);
        state = sk->sk_state;
-       if (unlikely(state == TCP_CLOSE))
+       if (unlikely((1 << state) & (TCPF_CLOSE | TCPF_LISTEN)))
                goto unlock;
 
        mptcp_check_data_fin_ack(sk);
@@ -2624,12 +2647,15 @@ static void mptcp_worker(struct work_struct *work)
        __mptcp_check_send_data_fin(sk);
        mptcp_check_data_fin(sk);
 
+       if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
+               __mptcp_close_subflow(sk);
+
        /* There is no point in keeping around an orphaned sk timedout or
         * closed, but we need the msk around to reply to incoming DATA_FIN,
         * even if it is orphaned and in FIN_WAIT2 state
         */
        if (sock_flag(sk, SOCK_DEAD)) {
-               if (mptcp_check_close_timeout(sk)) {
+               if (mptcp_should_close(sk)) {
                        inet_sk_state_store(sk, TCP_CLOSE);
                        mptcp_do_fastclose(sk);
                }
@@ -2639,9 +2665,6 @@ static void mptcp_worker(struct work_struct *work)
                }
        }
 
-       if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
-               __mptcp_close_subflow(msk);
-
        if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
                __mptcp_retrans(sk);
 
@@ -2878,6 +2901,14 @@ static void __mptcp_destroy_sock(struct sock *sk)
        sock_put(sk);
 }
 
+void __mptcp_unaccepted_force_close(struct sock *sk)
+{
+       sock_set_flag(sk, SOCK_DEAD);
+       inet_sk_state_store(sk, TCP_CLOSE);
+       mptcp_do_fastclose(sk);
+       __mptcp_destroy_sock(sk);
+}
+
 static __poll_t mptcp_check_readable(struct mptcp_sock *msk)
 {
        /* Concurrent splices from sk_receive_queue into receive_queue will
@@ -3079,6 +3110,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
        msk->local_key = subflow_req->local_key;
        msk->token = subflow_req->token;
        msk->subflow = NULL;
+       msk->in_accept_queue = 1;
        WRITE_ONCE(msk->fully_established, false);
        if (mp_opt->suboptions & OPTION_MPTCP_CSUMREQD)
                WRITE_ONCE(msk->csum_enabled, true);
@@ -3096,8 +3128,7 @@ struct sock *mptcp_sk_clone(const struct sock *sk,
        security_inet_csk_clone(nsk, req);
        bh_unlock_sock(nsk);
 
-       /* keep a single reference */
-       __sock_put(nsk);
+       /* note: the newly allocated socket refcount is 2 now */
        return nsk;
 }
 
@@ -3153,8 +3184,6 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
                        goto out;
                }
 
-               /* acquire the 2nd reference for the owning socket */
-               sock_hold(new_mptcp_sock);
                newsk = new_mptcp_sock;
                MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEPASSIVEACK);
        } else {
@@ -3705,25 +3734,10 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
                struct sock *newsk = newsock->sk;
 
                set_bit(SOCK_CUSTOM_SOCKOPT, &newsock->flags);
+               msk->in_accept_queue = 0;
 
                lock_sock(newsk);
 
-               /* PM/worker can now acquire the first subflow socket
-                * lock without racing with listener queue cleanup,
-                * we can notify it, if needed.
-                *
-                * Even if remote has reset the initial subflow by now
-                * the refcnt is still at least one.
-                */
-               subflow = mptcp_subflow_ctx(msk->first);
-               list_add(&subflow->node, &msk->conn_list);
-               sock_hold(msk->first);
-               if (mptcp_is_fully_established(newsk))
-                       mptcp_pm_fully_established(msk, msk->first, GFP_KERNEL);
-
-               mptcp_rcv_space_init(msk, msk->first);
-               mptcp_propagate_sndbuf(newsk, msk->first);
-
                /* set ssk->sk_socket of accept()ed flows to mptcp socket.
                 * This is needed so NOSPACE flag can be set from tcp stack.
                 */
@@ -3733,6 +3747,18 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
                        if (!ssk->sk_socket)
                                mptcp_sock_graft(ssk, newsock);
                }
+
+               /* Do late cleanup for the first subflow as necessary. Also
+                * deal with bad peers not doing a complete shutdown.
+                */
+               if (msk->first &&
+                   unlikely(inet_sk_state_load(msk->first) == TCP_CLOSE)) {
+                       __mptcp_close_ssk(newsk, msk->first,
+                                         mptcp_subflow_ctx(msk->first), 0);
+                       if (unlikely(list_empty(&msk->conn_list)))
+                               inet_sk_state_store(newsk, TCP_CLOSE);
+               }
+
                release_sock(newsk);
        }
 
index 61fd8eabfca2028680e04558b4baca9f48bbaaaa..d6469b6ab38e3c6b91fba0ac7465c2a29c7b54cd 100644 (file)
@@ -295,7 +295,8 @@ struct mptcp_sock {
        u8              recvmsg_inq:1,
                        cork:1,
                        nodelay:1,
-                       fastopening:1;
+                       fastopening:1,
+                       in_accept_queue:1;
        int             connect_flags;
        struct work_struct work;
        struct sk_buff  *ooo_last_skb;
@@ -633,6 +634,7 @@ void mptcp_sock_graft(struct sock *sk, struct socket *parent);
 struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk);
 bool __mptcp_close(struct sock *sk, long timeout);
 void mptcp_cancel_work(struct sock *sk);
+void __mptcp_unaccepted_force_close(struct sock *sk);
 void mptcp_set_owner_r(struct sk_buff *skb, struct sock *sk);
 
 bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
@@ -666,6 +668,8 @@ void mptcp_subflow_set_active(struct mptcp_subflow_context *subflow);
 
 bool mptcp_subflow_active(struct mptcp_subflow_context *subflow);
 
+void mptcp_subflow_drop_ctx(struct sock *ssk);
+
 static inline void mptcp_subflow_tcp_fallback(struct sock *sk,
                                              struct mptcp_subflow_context *ctx)
 {
index 4ae1a7304cf0da1840a1d236969549d18cf8ff97..281c1cc8dc8dc072c936d578a03259a7cab75b07 100644 (file)
@@ -397,15 +397,19 @@ void mptcp_subflow_reset(struct sock *ssk)
        struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
        struct sock *sk = subflow->conn;
 
+       /* mptcp_mp_fail_no_response() can reach here on an already closed
+        * socket
+        */
+       if (ssk->sk_state == TCP_CLOSE)
+               return;
+
        /* must hold: tcp_done() could drop last reference on parent */
        sock_hold(sk);
 
-       tcp_set_state(ssk, TCP_CLOSE);
        tcp_send_active_reset(ssk, GFP_ATOMIC);
        tcp_done(ssk);
-       if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags) &&
-           schedule_work(&mptcp_sk(sk)->work))
-               return; /* worker will put sk for us */
+       if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags))
+               mptcp_schedule_work(sk);
 
        sock_put(sk);
 }
@@ -622,7 +626,7 @@ static struct request_sock_ops mptcp_subflow_v6_request_sock_ops __ro_after_init
 static struct tcp_request_sock_ops subflow_request_sock_ipv6_ops __ro_after_init;
 static struct inet_connection_sock_af_ops subflow_v6_specific __ro_after_init;
 static struct inet_connection_sock_af_ops subflow_v6m_specific __ro_after_init;
-static struct proto tcpv6_prot_override;
+static struct proto tcpv6_prot_override __ro_after_init;
 
 static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 {
@@ -693,9 +697,10 @@ static bool subflow_hmac_valid(const struct request_sock *req,
 
 static void mptcp_force_close(struct sock *sk)
 {
-       /* the msk is not yet exposed to user-space */
+       /* the msk is not yet exposed to user-space, and refcount is 2 */
        inet_sk_state_store(sk, TCP_CLOSE);
        sk_common_release(sk);
+       sock_put(sk);
 }
 
 static void subflow_ulp_fallback(struct sock *sk,
@@ -711,16 +716,19 @@ static void subflow_ulp_fallback(struct sock *sk,
        mptcp_subflow_ops_undo_override(sk);
 }
 
-static void subflow_drop_ctx(struct sock *ssk)
+void mptcp_subflow_drop_ctx(struct sock *ssk)
 {
        struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(ssk);
 
        if (!ctx)
                return;
 
-       subflow_ulp_fallback(ssk, ctx);
-       if (ctx->conn)
-               sock_put(ctx->conn);
+       list_del(&mptcp_subflow_ctx(ssk)->node);
+       if (inet_csk(ssk)->icsk_ulp_ops) {
+               subflow_ulp_fallback(ssk, ctx);
+               if (ctx->conn)
+                       sock_put(ctx->conn);
+       }
 
        kfree_rcu(ctx, rcu);
 }
@@ -750,6 +758,7 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
        struct mptcp_options_received mp_opt;
        bool fallback, fallback_is_fatal;
        struct sock *new_msk = NULL;
+       struct mptcp_sock *owner;
        struct sock *child;
 
        pr_debug("listener=%p, req=%p, conn=%p", listener, req, listener->conn);
@@ -816,7 +825,7 @@ create_child:
 
                        if (new_msk)
                                mptcp_copy_inaddrs(new_msk, child);
-                       subflow_drop_ctx(child);
+                       mptcp_subflow_drop_ctx(child);
                        goto out;
                }
 
@@ -824,6 +833,8 @@ create_child:
                ctx->setsockopt_seq = listener->setsockopt_seq;
 
                if (ctx->mp_capable) {
+                       owner = mptcp_sk(new_msk);
+
                        /* this can't race with mptcp_close(), as the msk is
                         * not yet exposted to user-space
                         */
@@ -832,14 +843,14 @@ create_child:
                        /* record the newly created socket as the first msk
                         * subflow, but don't link it yet into conn_list
                         */
-                       WRITE_ONCE(mptcp_sk(new_msk)->first, child);
+                       WRITE_ONCE(owner->first, child);
 
                        /* new mpc subflow takes ownership of the newly
                         * created mptcp socket
                         */
                        mptcp_sk(new_msk)->setsockopt_seq = ctx->setsockopt_seq;
-                       mptcp_pm_new_connection(mptcp_sk(new_msk), child, 1);
-                       mptcp_token_accept(subflow_req, mptcp_sk(new_msk));
+                       mptcp_pm_new_connection(owner, child, 1);
+                       mptcp_token_accept(subflow_req, owner);
                        ctx->conn = new_msk;
                        new_msk = NULL;
 
@@ -847,15 +858,21 @@ create_child:
                         * uses the correct data
                         */
                        mptcp_copy_inaddrs(ctx->conn, child);
+                       mptcp_propagate_sndbuf(ctx->conn, child);
+
+                       mptcp_rcv_space_init(owner, child);
+                       list_add(&ctx->node, &owner->conn_list);
+                       sock_hold(child);
 
                        /* with OoO packets we can reach here without ingress
                         * mpc option
                         */
-                       if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK)
+                       if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK) {
                                mptcp_subflow_fully_established(ctx, &mp_opt);
+                               mptcp_pm_fully_established(owner, child, GFP_ATOMIC);
+                               ctx->pm_notified = 1;
+                       }
                } else if (ctx->mp_join) {
-                       struct mptcp_sock *owner;
-
                        owner = subflow_req->msk;
                        if (!owner) {
                                subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
@@ -899,7 +916,7 @@ out:
        return child;
 
 dispose_child:
-       subflow_drop_ctx(child);
+       mptcp_subflow_drop_ctx(child);
        tcp_rsk(req)->drop_req = true;
        inet_csk_prepare_for_destroy_sock(child);
        tcp_done(child);
@@ -910,7 +927,7 @@ dispose_child:
 }
 
 static struct inet_connection_sock_af_ops subflow_specific __ro_after_init;
-static struct proto tcp_prot_override;
+static struct proto tcp_prot_override __ro_after_init;
 
 enum mapping_status {
        MAPPING_OK,
@@ -1103,8 +1120,8 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
                                skb_ext_del(skb, SKB_EXT_MPTCP);
                                return MAPPING_OK;
                        } else {
-                               if (updated && schedule_work(&msk->work))
-                                       sock_hold((struct sock *)msk);
+                               if (updated)
+                                       mptcp_schedule_work((struct sock *)msk);
 
                                return MAPPING_DATA_FIN;
                        }
@@ -1207,17 +1224,12 @@ static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,
 /* sched mptcp worker to remove the subflow if no more data is pending */
 static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)
 {
-       struct sock *sk = (struct sock *)msk;
-
        if (likely(ssk->sk_state != TCP_CLOSE))
                return;
 
        if (skb_queue_empty(&ssk->sk_receive_queue) &&
-           !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags)) {
-               sock_hold(sk);
-               if (!schedule_work(&msk->work))
-                       sock_put(sk);
-       }
+           !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
+               mptcp_schedule_work((struct sock *)msk);
 }
 
 static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
@@ -1432,6 +1444,13 @@ static void subflow_error_report(struct sock *ssk)
 {
        struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
 
+       /* bail early if this is a no-op, so that we avoid introducing a
+        * problematic lockdep dependency between TCP accept queue lock
+        * and msk socket spinlock
+        */
+       if (!sk->sk_socket)
+               return;
+
        mptcp_data_lock(sk);
        if (!sock_owned_by_user(sk))
                __mptcp_error_report(sk);
@@ -1808,13 +1827,13 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
        struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
        struct mptcp_sock *msk, *next, *head = NULL;
        struct request_sock *req;
+       struct sock *sk;
 
        /* build a list of all unaccepted mptcp sockets */
        spin_lock_bh(&queue->rskq_lock);
        for (req = queue->rskq_accept_head; req; req = req->dl_next) {
                struct mptcp_subflow_context *subflow;
                struct sock *ssk = req->sk;
-               struct mptcp_sock *msk;
 
                if (!sk_is_mptcp(ssk))
                        continue;
@@ -1824,10 +1843,12 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
                        continue;
 
                /* skip if already in list */
-               msk = mptcp_sk(subflow->conn);
+               sk = subflow->conn;
+               msk = mptcp_sk(sk);
                if (msk->dl_next || msk == head)
                        continue;
 
+               sock_hold(sk);
                msk->dl_next = head;
                head = msk;
        }
@@ -1841,34 +1862,30 @@ void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_s
        release_sock(listener_ssk);
 
        for (msk = head; msk; msk = next) {
-               struct sock *sk = (struct sock *)msk;
-               bool do_cancel_work;
+               sk = (struct sock *)msk;
 
-               sock_hold(sk);
                lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
                next = msk->dl_next;
-               msk->first = NULL;
                msk->dl_next = NULL;
 
-               do_cancel_work = __mptcp_close(sk, 0);
+               __mptcp_unaccepted_force_close(sk);
                release_sock(sk);
-               if (do_cancel_work) {
-                       /* lockdep will report a false positive ABBA deadlock
-                        * between cancel_work_sync and the listener socket.
-                        * The involved locks belong to different sockets WRT
-                        * the existing AB chain.
-                        * Using a per socket key is problematic as key
-                        * deregistration requires process context and must be
-                        * performed at socket disposal time, in atomic
-                        * context.
-                        * Just tell lockdep to consider the listener socket
-                        * released here.
-                        */
-                       mutex_release(&listener_sk->sk_lock.dep_map, _RET_IP_);
-                       mptcp_cancel_work(sk);
-                       mutex_acquire(&listener_sk->sk_lock.dep_map,
-                                     SINGLE_DEPTH_NESTING, 0, _RET_IP_);
-               }
+
+               /* lockdep will report a false positive ABBA deadlock
+                * between cancel_work_sync and the listener socket.
+                * The involved locks belong to different sockets WRT
+                * the existing AB chain.
+                * Using a per socket key is problematic as key
+                * deregistration requires process context and must be
+                * performed at socket disposal time, in atomic
+                * context.
+                * Just tell lockdep to consider the listener socket
+                * released here.
+                */
+               mutex_release(&listener_sk->sk_lock.dep_map, _RET_IP_);
+               mptcp_cancel_work(sk);
+               mutex_acquire(&listener_sk->sk_lock.dep_map, 0, 0, _RET_IP_);
+
                sock_put(sk);
        }
 
@@ -1932,6 +1949,13 @@ static void subflow_ulp_release(struct sock *ssk)
                 * when the subflow is still unaccepted
                 */
                release = ctx->disposable || list_empty(&ctx->node);
+
+               /* inet_child_forget() does not call sk_state_change(),
+                * explicitly trigger the socket close machinery
+                */
+               if (!release && !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW,
+                                                 &mptcp_sk(sk)->flags))
+                       mptcp_schedule_work(sk);
                sock_put(sk);
        }
 
index 80713febfac6dd1911f83d05eb649888dcb93514..d9da942ad53dd98da908d2b80d98a4827eee4954 100644 (file)
@@ -1803,8 +1803,8 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
        pdev = to_platform_device(dev->dev.parent);
        if (pdev) {
                np = pdev->dev.of_node;
-               if (np && (of_get_property(np, "mellanox,multi-host", NULL) ||
-                          of_get_property(np, "mlx,multi-host", NULL)))
+               if (np && (of_property_read_bool(np, "mellanox,multi-host") ||
+                          of_property_read_bool(np, "mlx,multi-host")))
                        ndp->mlx_multi_host = true;
        }
 
index 6004d4b244518b540302ca48264068a507c2306b..e48ab8dfb54101e02342217acd1d8c08a391fd88 100644 (file)
@@ -3447,6 +3447,64 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
        return 0;
 }
 
+int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
+                        const struct nft_set_iter *iter,
+                        struct nft_set_elem *elem)
+{
+       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
+       struct nft_ctx *pctx = (struct nft_ctx *)ctx;
+       const struct nft_data *data;
+       int err;
+
+       if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
+           *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
+               return 0;
+
+       data = nft_set_ext_data(ext);
+       switch (data->verdict.code) {
+       case NFT_JUMP:
+       case NFT_GOTO:
+               pctx->level++;
+               err = nft_chain_validate(ctx, data->verdict.chain);
+               if (err < 0)
+                       return err;
+               pctx->level--;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+struct nft_set_elem_catchall {
+       struct list_head        list;
+       struct rcu_head         rcu;
+       void                    *elem;
+};
+
+int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
+{
+       u8 genmask = nft_genmask_next(ctx->net);
+       struct nft_set_elem_catchall *catchall;
+       struct nft_set_elem elem;
+       struct nft_set_ext *ext;
+       int ret = 0;
+
+       list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+               ext = nft_set_elem_ext(set, catchall->elem);
+               if (!nft_set_elem_active(ext, genmask))
+                       continue;
+
+               elem.priv = catchall->elem;
+               ret = nft_setelem_validate(ctx, set, NULL, &elem);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return ret;
+}
+
 static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
                                             const struct nft_chain *chain,
                                             const struct nlattr *nla);
@@ -4759,12 +4817,6 @@ err_set_name:
        return err;
 }
 
-struct nft_set_elem_catchall {
-       struct list_head        list;
-       struct rcu_head         rcu;
-       void                    *elem;
-};
-
 static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
                                     struct nft_set *set)
 {
@@ -6056,7 +6108,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
        if (err < 0)
                return err;
 
-       if (!nla[NFTA_SET_ELEM_KEY] && !(flags & NFT_SET_ELEM_CATCHALL))
+       if (((flags & NFT_SET_ELEM_CATCHALL) && nla[NFTA_SET_ELEM_KEY]) ||
+           (!(flags & NFT_SET_ELEM_CATCHALL) && !nla[NFTA_SET_ELEM_KEY]))
                return -EINVAL;
 
        if (flags != 0) {
@@ -7052,7 +7105,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
        }
 
        if (nla[NFTA_OBJ_USERDATA]) {
-               obj->udata = nla_memdup(nla[NFTA_OBJ_USERDATA], GFP_KERNEL);
+               obj->udata = nla_memdup(nla[NFTA_OBJ_USERDATA], GFP_KERNEL_ACCOUNT);
                if (obj->udata == NULL)
                        goto err_userdata;
 
index cae5a67241634edacda0ddc8f90aa72932dca507..cecf8ab90e58f7e84dd73168f69c87a50811837c 100644 (file)
@@ -199,37 +199,6 @@ nla_put_failure:
        return -1;
 }
 
-static int nft_lookup_validate_setelem(const struct nft_ctx *ctx,
-                                      struct nft_set *set,
-                                      const struct nft_set_iter *iter,
-                                      struct nft_set_elem *elem)
-{
-       const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
-       struct nft_ctx *pctx = (struct nft_ctx *)ctx;
-       const struct nft_data *data;
-       int err;
-
-       if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
-           *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
-               return 0;
-
-       data = nft_set_ext_data(ext);
-       switch (data->verdict.code) {
-       case NFT_JUMP:
-       case NFT_GOTO:
-               pctx->level++;
-               err = nft_chain_validate(ctx, data->verdict.chain);
-               if (err < 0)
-                       return err;
-               pctx->level--;
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
 static int nft_lookup_validate(const struct nft_ctx *ctx,
                               const struct nft_expr *expr,
                               const struct nft_data **d)
@@ -245,9 +214,12 @@ static int nft_lookup_validate(const struct nft_ctx *ctx,
        iter.skip       = 0;
        iter.count      = 0;
        iter.err        = 0;
-       iter.fn         = nft_lookup_validate_setelem;
+       iter.fn         = nft_setelem_validate;
 
        priv->set->ops->walk(ctx, priv->set, &iter);
+       if (!iter.err)
+               iter.err = nft_set_catchall_validate(ctx, priv->set);
+
        if (iter.err < 0)
                return iter.err;
 
index e55e455275c48ea8875d09e45c474527464c366c..9544c2f16998bf75420576d9a1fad8313297f4d0 100644 (file)
@@ -43,7 +43,7 @@ static int nft_masq_init(const struct nft_ctx *ctx,
                         const struct nft_expr *expr,
                         const struct nlattr * const tb[])
 {
-       u32 plen = sizeof_field(struct nf_nat_range, min_addr.all);
+       u32 plen = sizeof_field(struct nf_nat_range, min_proto.all);
        struct nft_masq *priv = nft_expr_priv(expr);
        int err;
 
index 0479991503900ec24b8ce7391481b46713c1de9b..5c29915ab0289ee615a47a0d336cead0b377cef2 100644 (file)
@@ -226,7 +226,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                priv->flags |= NF_NAT_RANGE_MAP_IPS;
        }
 
-       plen = sizeof_field(struct nf_nat_range, min_addr.all);
+       plen = sizeof_field(struct nf_nat_range, min_proto.all);
        if (tb[NFTA_NAT_REG_PROTO_MIN]) {
                err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
                                              &priv->sreg_proto_min, plen);
index 5f77399875593ba6dd88d6ea54fdae904eb6cd69..67cec56bc84a35ca111853b58f799953b56eef6c 100644 (file)
@@ -48,7 +48,7 @@ static int nft_redir_init(const struct nft_ctx *ctx,
        unsigned int plen;
        int err;
 
-       plen = sizeof_field(struct nf_nat_range, min_addr.all);
+       plen = sizeof_field(struct nf_nat_range, min_proto.all);
        if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
                err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
                                              &priv->sreg_proto_min, plen);
@@ -236,7 +236,7 @@ static struct nft_expr_type nft_redir_inet_type __read_mostly = {
        .name           = "redir",
        .ops            = &nft_redir_inet_ops,
        .policy         = nft_redir_policy,
-       .maxattr        = NFTA_MASQ_MAX,
+       .maxattr        = NFTA_REDIR_MAX,
        .owner          = THIS_MODULE,
 };
 
index c6427765975318b4c7fe3d5291dc4d69988f5249..f365dfdd672d7576b02bd5ae2871cf317e879248 100644 (file)
@@ -1952,7 +1952,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
        struct scm_cookie scm;
        struct sock *sk = sock->sk;
        struct netlink_sock *nlk = nlk_sk(sk);
-       size_t copied;
+       size_t copied, max_recvmsg_len;
        struct sk_buff *skb, *data_skb;
        int err, ret;
 
@@ -1985,9 +1985,10 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 #endif
 
        /* Record the max length of recvmsg() calls for future allocations */
-       nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len);
-       nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len,
-                                    SKB_WITH_OVERHEAD(32768));
+       max_recvmsg_len = max(READ_ONCE(nlk->max_recvmsg_len), len);
+       max_recvmsg_len = min_t(size_t, max_recvmsg_len,
+                               SKB_WITH_OVERHEAD(32768));
+       WRITE_ONCE(nlk->max_recvmsg_len, max_recvmsg_len);
 
        copied = data_skb->len;
        if (len < copied) {
@@ -2236,6 +2237,7 @@ static int netlink_dump(struct sock *sk)
        struct netlink_ext_ack extack = {};
        struct netlink_callback *cb;
        struct sk_buff *skb = NULL;
+       size_t max_recvmsg_len;
        struct module *module;
        int err = -ENOBUFS;
        int alloc_min_size;
@@ -2258,8 +2260,9 @@ static int netlink_dump(struct sock *sk)
        cb = &nlk->cb;
        alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
 
-       if (alloc_min_size < nlk->max_recvmsg_len) {
-               alloc_size = nlk->max_recvmsg_len;
+       max_recvmsg_len = READ_ONCE(nlk->max_recvmsg_len);
+       if (alloc_min_size < max_recvmsg_len) {
+               alloc_size = max_recvmsg_len;
                skb = alloc_skb(alloc_size,
                                (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM) |
                                __GFP_NOWARN | __GFP_NORETRY);
index ca3ebfdb30231dd48b22cc36d8890c5e4b39223d..a8cf9a88758ef555743e3873648a1ea14b07c0a2 100644 (file)
@@ -913,7 +913,7 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
 {
        struct vport *vport = ovs_vport_rcu(dp, out_port);
 
-       if (likely(vport)) {
+       if (likely(vport && netif_carrier_ok(vport->dev))) {
                u16 mru = OVS_CB(skb)->mru;
                u32 cutlen = OVS_CB(skb)->cutlen;
 
index 5c2fb992803b7acbeed3d712104d45d7e0b3c68f..76f0434d3d06a48b80d80c54241440ff4ce8ea9c 100644 (file)
@@ -393,10 +393,12 @@ static struct qrtr_node *qrtr_node_lookup(unsigned int nid)
        struct qrtr_node *node;
        unsigned long flags;
 
+       mutex_lock(&qrtr_node_lock);
        spin_lock_irqsave(&qrtr_nodes_lock, flags);
        node = radix_tree_lookup(&qrtr_nodes, nid);
        node = qrtr_node_acquire(node);
        spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
+       mutex_unlock(&qrtr_node_lock);
 
        return node;
 }
@@ -496,6 +498,11 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
        if (!size || len != ALIGN(size, 4) + hdrlen)
                goto err;
 
+       if ((cb->type == QRTR_TYPE_NEW_SERVER ||
+            cb->type == QRTR_TYPE_RESUME_TX) &&
+           size < sizeof(struct qrtr_ctrl_pkt))
+               goto err;
+
        if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA &&
            cb->type != QRTR_TYPE_RESUME_TX)
                goto err;
@@ -508,9 +515,6 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
                /* Remote node endpoint can bridge other distant nodes */
                const struct qrtr_ctrl_pkt *pkt;
 
-               if (size < sizeof(*pkt))
-                       goto err;
-
                pkt = data + hdrlen;
                qrtr_node_assign(node, le32_to_cpu(pkt->server.node));
        }
index 722936f7dd988984d0351839c22a3a7319208c3e..0f25a386138c91af11f87d086fda5bc19a85aaf9 100644 (file)
@@ -274,7 +274,7 @@ err:
        return NULL;
 }
 
-static int server_del(struct qrtr_node *node, unsigned int port)
+static int server_del(struct qrtr_node *node, unsigned int port, bool bcast)
 {
        struct qrtr_lookup *lookup;
        struct qrtr_server *srv;
@@ -287,7 +287,7 @@ static int server_del(struct qrtr_node *node, unsigned int port)
        radix_tree_delete(&node->servers, port);
 
        /* Broadcast the removal of local servers */
-       if (srv->node == qrtr_ns.local_node)
+       if (srv->node == qrtr_ns.local_node && bcast)
                service_announce_del(&qrtr_ns.bcast_sq, srv);
 
        /* Announce the service's disappearance to observers */
@@ -373,7 +373,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
                }
                slot = radix_tree_iter_resume(slot, &iter);
                rcu_read_unlock();
-               server_del(node, srv->port);
+               server_del(node, srv->port, true);
                rcu_read_lock();
        }
        rcu_read_unlock();
@@ -459,10 +459,13 @@ static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
                kfree(lookup);
        }
 
-       /* Remove the server belonging to this port */
+       /* Remove the server belonging to this port but don't broadcast
+        * DEL_SERVER. Neighbours would've already removed the server belonging
+        * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove().
+        */
        node = node_get(node_id);
        if (node)
-               server_del(node, port);
+               server_del(node, port, false);
 
        /* Advertise the removal of this client to all local servers */
        local_node = node_get(qrtr_ns.local_node);
@@ -567,7 +570,7 @@ static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
        if (!node)
                return -ENOENT;
 
-       return server_del(node, port);
+       return server_del(node, port, true);
 }
 
 static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
index 34c50867504160d02d413ea211c075525ad6bf26..296fc1afedd82bdaed2e08aa12a03180a1ff7184 100644 (file)
@@ -1589,6 +1589,10 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
        t->tca__pad1 = 0;
        t->tca__pad2 = 0;
 
+       if (extack && extack->_msg &&
+           nla_put_string(skb, TCA_ROOT_EXT_WARN_MSG, extack->_msg))
+               goto out_nlmsg_trim;
+
        nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
        if (!nest)
                goto out_nlmsg_trim;
@@ -1596,10 +1600,6 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
        if (tcf_action_dump(skb, actions, bind, ref, false) < 0)
                goto out_nlmsg_trim;
 
-       if (extack && extack->_msg &&
-           nla_put_string(skb, TCA_EXT_WARN_MSG, extack->_msg))
-               goto out_nlmsg_trim;
-
        nla_nest_end(skb, nest);
 
        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
index 2a6b6be0811b84129306409bc55ca553bda3c70a..35785a36c80298f086d6b27f63dfaeb80dfec65f 100644 (file)
@@ -3235,6 +3235,9 @@ int tcf_exts_init_ex(struct tcf_exts *exts, struct net *net, int action,
 
 err_miss_alloc:
        tcf_exts_destroy(exts);
+#ifdef CONFIG_NET_CLS_ACT
+       exts->actions = NULL;
+#endif
        return err;
 }
 EXPORT_SYMBOL(tcf_exts_init_ex);
index cf5ebe43b3b4eb7f163da31cc565bc7faaab69e5..02098a02943eb90a67cce829b26a4cf9b79e545c 100644 (file)
@@ -421,15 +421,16 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        } else
                weight = 1;
 
-       if (tb[TCA_QFQ_LMAX]) {
+       if (tb[TCA_QFQ_LMAX])
                lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
-               if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
-                       pr_notice("qfq: invalid max length %u\n", lmax);
-                       return -EINVAL;
-               }
-       } else
+       else
                lmax = psched_mtu(qdisc_dev(sch));
 
+       if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
+               pr_notice("qfq: invalid max length %u\n", lmax);
+               return -EINVAL;
+       }
+
        inv_w = ONE_FP / weight;
        weight = ONE_FP / inv_w;
 
index b91616f819def9e7e067c3e82d26d36a2d34c17e..218e0982c370726b7ea1a7e5c32ce0de3ad9ab2d 100644 (file)
@@ -1830,6 +1830,10 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
                err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
                if (err)
                        goto err;
+               if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) {
+                       err = -EINVAL;
+                       goto err;
+               }
        }
 
        if (sctp_state(asoc, CLOSED)) {
index 94727feb07b3e0ebd80e88acf5d08ed19f24da0f..b046b11200c93e53f1df4a91d061449772a643d1 100644 (file)
@@ -1154,7 +1154,8 @@ static void sctp_generate_iftsn(struct sctp_outq *q, __u32 ctsn)
 
 #define _sctp_walk_ifwdtsn(pos, chunk, end) \
        for (pos = chunk->subh.ifwdtsn_hdr->skip; \
-            (void *)pos < (void *)chunk->subh.ifwdtsn_hdr->skip + (end); pos++)
+            (void *)pos <= (void *)chunk->subh.ifwdtsn_hdr->skip + (end) - \
+                           sizeof(struct sctp_ifwdtsn_skip); pos++)
 
 #define sctp_walk_ifwdtsn(pos, ch) \
        _sctp_walk_ifwdtsn((pos), (ch), ntohs((ch)->chunk_hdr->length) - \
index ff6dd86bdc9f3f504426f0d3f91424f14d77b689..50c38b624f772c05d8ecd2745da8fa719d6dc4b1 100644 (file)
@@ -3270,6 +3270,17 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,
                        sk_common_release(sk);
                        goto out;
                }
+
+               /* smc_clcsock_release() does not wait smc->clcsock->sk's
+                * destruction;  its sk_state might not be TCP_CLOSE after
+                * smc->sk is close()d, and TCP timers can be fired later,
+                * which need net ref.
+                */
+               sk = smc->clcsock->sk;
+               __netns_tracker_free(net, &sk->ns_tracker, false);
+               sk->sk_net_refcnt = 1;
+               get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
+               sock_inuse_add(net, 1);
        } else {
                smc->clcsock = clcsock;
        }
@@ -3501,6 +3512,7 @@ out_pnet:
 out_nl:
        smc_nl_exit();
 out_ism:
+       smc_clc_exit();
        smc_ism_exit();
 out_pernet_subsys_stat:
        unregister_pernet_subsys(&smc_net_stat_ops);
index 53f63bfbaf5f92915bb7af4e02fe8fe2e96b89f2..89105e95b4523f0a0d197e7167f27914430f482e 100644 (file)
@@ -114,6 +114,9 @@ int smc_cdc_msg_send(struct smc_connection *conn,
        union smc_host_cursor cfed;
        int rc;
 
+       if (unlikely(!READ_ONCE(conn->sndbuf_desc)))
+               return -ENOBUFS;
+
        smc_cdc_add_pending_send(conn, pend);
 
        conn->tx_cdc_seq++;
index d52060b2680cf0090cb91f454a27f22b10ff2e02..454356771cda55b10c496cbebc470c273d4c56ea 100644 (file)
@@ -1464,7 +1464,7 @@ static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft)
        if (lgr->terminating)
                return; /* lgr already terminating */
        /* cancel free_work sync, will terminate when lgr->freeing is set */
-       cancel_delayed_work_sync(&lgr->free_work);
+       cancel_delayed_work(&lgr->free_work);
        lgr->terminating = 1;
 
        /* kill remaining link group connections */
index 6c7c52eeed4f85773c71fea22879d04b14a9f665..212c5d57465a1bf56afc96af1e91d135ca6e1325 100644 (file)
@@ -353,7 +353,9 @@ gss_krb5_checksum(struct crypto_ahash *tfm, char *header, int hdrlen,
        err = crypto_ahash_final(req);
        if (err)
                goto out_free_ahash;
-       memcpy(cksumout->data, checksumdata, cksumout->len);
+
+       memcpy(cksumout->data, checksumdata,
+              min_t(int, cksumout->len, crypto_ahash_digestsize(tfm)));
 
 out_free_ahash:
        ahash_request_free(req);
@@ -809,8 +811,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
        buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN;
        buf->len += GSS_KRB5_TOK_HDR_LEN;
 
-       /* Do the HMAC */
-       hmac.len = GSS_KRB5_MAX_CKSUM_LEN;
+       hmac.len = kctx->gk5e->cksumlength;
        hmac.data = buf->tail[0].iov_base + buf->tail[0].iov_len;
 
        /*
@@ -873,8 +874,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
        if (ret)
                goto out_err;
 
-       /* Calculate our hmac over the plaintext data */
-       our_hmac_obj.len = sizeof(our_hmac);
+       our_hmac_obj.len = kctx->gk5e->cksumlength;
        our_hmac_obj.data = our_hmac;
        ret = gss_krb5_checksum(ahash, NULL, 0, &subbuf, 0, &our_hmac_obj);
        if (ret)
index ce0541e32fc9827bbc2eb355c5b71b82734da48e..95ca783795c5e241fc36ec9c58b6c0d12afef9d3 100644 (file)
@@ -73,7 +73,6 @@ static void checksum_case(struct kunit *test)
 {
        const struct gss_krb5_test_param *param = test->param_value;
        struct xdr_buf buf = {
-               .head[0].iov_base       = param->plaintext->data,
                .head[0].iov_len        = param->plaintext->len,
                .len                    = param->plaintext->len,
        };
@@ -99,6 +98,10 @@ static void checksum_case(struct kunit *test)
        err = crypto_ahash_setkey(tfm, Kc.data, Kc.len);
        KUNIT_ASSERT_EQ(test, err, 0);
 
+       buf.head[0].iov_base = kunit_kzalloc(test, buf.head[0].iov_len, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf.head[0].iov_base);
+       memcpy(buf.head[0].iov_base, param->plaintext->data, buf.head[0].iov_len);
+
        checksum.len = gk5e->cksumlength;
        checksum.data = kunit_kzalloc(test, checksum.len, GFP_KERNEL);
        KUNIT_ASSERT_NOT_ERR_OR_NULL(test, checksum.data);
@@ -1327,6 +1330,7 @@ static void rfc6803_encrypt_case(struct kunit *test)
        if (!gk5e)
                kunit_skip(test, "Encryption type is not available");
 
+       memset(usage_data, 0, sizeof(usage_data));
        usage.data[3] = param->constant;
 
        Ke.len = gk5e->Ke_length;
index 983c5891cb5655fe7ddedf1e5053229ea349b429..4246363cb0951c0fba470844ee63ed22d2bc7de9 100644 (file)
@@ -416,14 +416,23 @@ static int unix_gid_hash(kuid_t uid)
        return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
 }
 
-static void unix_gid_put(struct kref *kref)
+static void unix_gid_free(struct rcu_head *rcu)
 {
-       struct cache_head *item = container_of(kref, struct cache_head, ref);
-       struct unix_gid *ug = container_of(item, struct unix_gid, h);
+       struct unix_gid *ug = container_of(rcu, struct unix_gid, rcu);
+       struct cache_head *item = &ug->h;
+
        if (test_bit(CACHE_VALID, &item->flags) &&
            !test_bit(CACHE_NEGATIVE, &item->flags))
                put_group_info(ug->gi);
-       kfree_rcu(ug, rcu);
+       kfree(ug);
+}
+
+static void unix_gid_put(struct kref *kref)
+{
+       struct cache_head *item = container_of(kref, struct cache_head, ref);
+       struct unix_gid *ug = container_of(item, struct unix_gid, h);
+
+       call_rcu(&ug->rcu, unix_gid_free);
 }
 
 static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
index adcbedc244d63f70804ad73f290bfaa2e7c4be3b..6cacd70a15ffa15ed7f70d073cd9d23410d41784 100644 (file)
@@ -2158,6 +2158,7 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt)
        switch (skst) {
        case TCP_FIN_WAIT1:
        case TCP_FIN_WAIT2:
+       case TCP_LAST_ACK:
                break;
        case TCP_ESTABLISHED:
        case TCP_CLOSE_WAIT:
index a1581c77cf84a81bb5503d57039e49b5b970ce85..ee78b4082ef95fe6277bef1fa2960fc9684b1fb3 100644 (file)
@@ -94,6 +94,11 @@ virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
                                         info->op,
                                         info->flags);
 
+       if (info->vsk && !skb_set_owner_sk_safe(skb, sk_vsock(info->vsk))) {
+               WARN_ONCE(1, "failed to allocate skb on vsock socket with sk_refcnt == 0\n");
+               goto out;
+       }
+
        return skb;
 
 out:
@@ -241,21 +246,18 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
 }
 
 static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
-                                       struct sk_buff *skb)
+                                       u32 len)
 {
-       if (vvs->rx_bytes + skb->len > vvs->buf_alloc)
+       if (vvs->rx_bytes + len > vvs->buf_alloc)
                return false;
 
-       vvs->rx_bytes += skb->len;
+       vvs->rx_bytes += len;
        return true;
 }
 
 static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs,
-                                       struct sk_buff *skb)
+                                       u32 len)
 {
-       int len;
-
-       len = skb_headroom(skb) - sizeof(struct virtio_vsock_hdr) - skb->len;
        vvs->rx_bytes -= len;
        vvs->fwd_cnt += len;
 }
@@ -366,8 +368,15 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
        u32 free_space;
 
        spin_lock_bh(&vvs->rx_lock);
+
+       if (WARN_ONCE(skb_queue_empty(&vvs->rx_queue) && vvs->rx_bytes,
+                     "rx_queue is empty, but rx_bytes is non-zero\n")) {
+               spin_unlock_bh(&vvs->rx_lock);
+               return err;
+       }
+
        while (total < len && !skb_queue_empty(&vvs->rx_queue)) {
-               skb = __skb_dequeue(&vvs->rx_queue);
+               skb = skb_peek(&vvs->rx_queue);
 
                bytes = len - total;
                if (bytes > skb->len)
@@ -388,10 +397,11 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
                skb_pull(skb, bytes);
 
                if (skb->len == 0) {
-                       virtio_transport_dec_rx_pkt(vvs, skb);
+                       u32 pkt_len = le32_to_cpu(virtio_vsock_hdr(skb)->len);
+
+                       virtio_transport_dec_rx_pkt(vvs, pkt_len);
+                       __skb_unlink(skb, &vvs->rx_queue);
                        consume_skb(skb);
-               } else {
-                       __skb_queue_head(&vvs->rx_queue, skb);
                }
        }
 
@@ -437,17 +447,17 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
 
        while (!msg_ready) {
                struct virtio_vsock_hdr *hdr;
+               size_t pkt_len;
 
                skb = __skb_dequeue(&vvs->rx_queue);
                if (!skb)
                        break;
                hdr = virtio_vsock_hdr(skb);
+               pkt_len = (size_t)le32_to_cpu(hdr->len);
 
                if (dequeued_len >= 0) {
-                       size_t pkt_len;
                        size_t bytes_to_copy;
 
-                       pkt_len = (size_t)le32_to_cpu(hdr->len);
                        bytes_to_copy = min(user_buf_len, pkt_len);
 
                        if (bytes_to_copy) {
@@ -466,7 +476,6 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
                                        dequeued_len = err;
                                } else {
                                        user_buf_len -= bytes_to_copy;
-                                       skb_pull(skb, bytes_to_copy);
                                }
 
                                spin_lock_bh(&vvs->rx_lock);
@@ -484,7 +493,7 @@ static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
                                msg->msg_flags |= MSG_EOR;
                }
 
-               virtio_transport_dec_rx_pkt(vvs, skb);
+               virtio_transport_dec_rx_pkt(vvs, pkt_len);
                kfree_skb(skb);
        }
 
@@ -1040,7 +1049,7 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
 
        spin_lock_bh(&vvs->rx_lock);
 
-       can_enqueue = virtio_transport_inc_rx_pkt(vvs, skb);
+       can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
        if (!can_enqueue) {
                free_pkt = true;
                goto out;
@@ -1071,7 +1080,7 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
                        memcpy(skb_put(last_skb, skb->len), skb->data, skb->len);
                        free_pkt = true;
                        last_hdr->flags |= hdr->flags;
-                       last_hdr->len = cpu_to_le32(last_skb->len);
+                       le32_add_cpu(&last_hdr->len, len);
                        goto out;
                }
        }
@@ -1299,6 +1308,11 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
                goto free_pkt;
        }
 
+       if (!skb_set_owner_sk_safe(skb, sk)) {
+               WARN_ONCE(1, "receiving vsock socket has sk_refcnt == 0\n");
+               goto free_pkt;
+       }
+
        vsk = vsock_sk(sk);
 
        lock_sock(sk);
index 36eb16a40745d2fc07f3a8dd5c81396c20320843..95cc4d79ba2961019799ba25a74185c51d8493fc 100644 (file)
@@ -1842,7 +1842,13 @@ static ssize_t vmci_transport_stream_enqueue(
        struct msghdr *msg,
        size_t len)
 {
-       return vmci_qpair_enquev(vmci_trans(vsk)->qpair, msg, len, 0);
+       ssize_t err;
+
+       err = vmci_qpair_enquev(vmci_trans(vsk)->qpair, msg, len, 0);
+       if (err < 0)
+               err = -ENOMEM;
+
+       return err;
 }
 
 static s64 vmci_transport_stream_has_data(struct vsock_sock *vsk)
index 671e03240fc522a5a51b4c47d387b76bfa345eee..89905c092645a5187970883cea0d8a5610cb09d4 100644 (file)
@@ -15,7 +15,6 @@
 struct vsock_loopback {
        struct workqueue_struct *workqueue;
 
-       spinlock_t pkt_list_lock; /* protects pkt_list */
        struct sk_buff_head pkt_queue;
        struct work_struct pkt_work;
 };
@@ -32,9 +31,7 @@ static int vsock_loopback_send_pkt(struct sk_buff *skb)
        struct vsock_loopback *vsock = &the_vsock_loopback;
        int len = skb->len;
 
-       spin_lock_bh(&vsock->pkt_list_lock);
        skb_queue_tail(&vsock->pkt_queue, skb);
-       spin_unlock_bh(&vsock->pkt_list_lock);
 
        queue_work(vsock->workqueue, &vsock->pkt_work);
 
@@ -113,9 +110,9 @@ static void vsock_loopback_work(struct work_struct *work)
 
        skb_queue_head_init(&pkts);
 
-       spin_lock_bh(&vsock->pkt_list_lock);
+       spin_lock_bh(&vsock->pkt_queue.lock);
        skb_queue_splice_init(&vsock->pkt_queue, &pkts);
-       spin_unlock_bh(&vsock->pkt_list_lock);
+       spin_unlock_bh(&vsock->pkt_queue.lock);
 
        while ((skb = __skb_dequeue(&pkts))) {
                virtio_transport_deliver_tap_pkt(skb);
@@ -132,7 +129,6 @@ static int __init vsock_loopback_init(void)
        if (!vsock->workqueue)
                return -ENOMEM;
 
-       spin_lock_init(&vsock->pkt_list_lock);
        skb_queue_head_init(&vsock->pkt_queue);
        INIT_WORK(&vsock->pkt_work, vsock_loopback_work);
 
@@ -156,9 +152,7 @@ static void __exit vsock_loopback_exit(void)
 
        flush_work(&vsock->pkt_work);
 
-       spin_lock_bh(&vsock->pkt_list_lock);
        virtio_vsock_skb_queue_purge(&vsock->pkt_queue);
-       spin_unlock_bh(&vsock->pkt_list_lock);
 
        destroy_workqueue(vsock->workqueue);
 }
index 112b4bb009c80f648748256b322d9a5e7a7e8514..4f63059efd813ba6dd257a7c7ebebacb2f102cd1 100644 (file)
@@ -462,6 +462,11 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = {
        [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
 };
 
+static struct netlink_range_validation nl80211_punct_bitmap_range = {
+       .min = 0,
+       .max = 0xffff,
+};
+
 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
        [NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
@@ -805,7 +810,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
        [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
        [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
-       [NL80211_ATTR_PUNCT_BITMAP] = NLA_POLICY_RANGE(NLA_U8, 0, 0xffff),
+       [NL80211_ATTR_PUNCT_BITMAP] =
+               NLA_POLICY_FULL_RANGE(NLA_U32, &nl80211_punct_bitmap_range),
 };
 
 /* policy for the key attributes */
@@ -8901,7 +8907,7 @@ static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev,
                struct cfg80211_chan_def *chandef;
 
                chandef = wdev_chandef(wdev, link_id);
-               if (!chandef)
+               if (!chandef || !chandef->chan)
                        continue;
 
                /*
@@ -10793,8 +10799,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
 
 static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
                                              const u8 *ssid, int ssid_len,
-                                             struct nlattr **attrs,
-                                             const u8 **bssid_out)
+                                             struct nlattr **attrs)
 {
        struct ieee80211_channel *chan;
        struct cfg80211_bss *bss;
@@ -10821,7 +10826,6 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
        if (!bss)
                return ERR_PTR(-ENOENT);
 
-       *bssid_out = bssid;
        return bss;
 }
 
@@ -10831,7 +10835,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
        struct net_device *dev = info->user_ptr[1];
        struct cfg80211_assoc_request req = {};
        struct nlattr **attrs = NULL;
-       const u8 *bssid, *ssid;
+       const u8 *ap_addr, *ssid;
        unsigned int link_id;
        int err, ssid_len;
 
@@ -10968,6 +10972,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                        return -EINVAL;
 
                req.ap_mld_addr = nla_data(info->attrs[NL80211_ATTR_MLD_ADDR]);
+               ap_addr = req.ap_mld_addr;
 
                attrs = kzalloc(attrsize, GFP_KERNEL);
                if (!attrs)
@@ -10993,8 +10998,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                                goto free;
                        }
                        req.links[link_id].bss =
-                               nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
-                                                 &bssid);
+                               nl80211_assoc_bss(rdev, ssid, ssid_len, attrs);
                        if (IS_ERR(req.links[link_id].bss)) {
                                err = PTR_ERR(req.links[link_id].bss);
                                req.links[link_id].bss = NULL;
@@ -11045,10 +11049,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                if (req.link_id >= 0)
                        return -EINVAL;
 
-               req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs,
-                                           &bssid);
+               req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs);
                if (IS_ERR(req.bss))
                        return PTR_ERR(req.bss);
+               ap_addr = req.bss->bssid;
        }
 
        err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
@@ -11061,7 +11065,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                        dev->ieee80211_ptr->conn_owner_nlportid =
                                info->snd_portid;
                        memcpy(dev->ieee80211_ptr->disconnect_bssid,
-                              bssid, ETH_ALEN);
+                              ap_addr, ETH_ALEN);
                }
 
                wdev_unlock(dev->ieee80211_ptr);
index 4681e8e8ad943605b61aa6be685e6c76a70b4c0f..02207e852d796d31a04e3a1a83f500c27b21203d 100644 (file)
@@ -150,10 +150,11 @@ static int xdp_umem_account_pages(struct xdp_umem *umem)
 
 static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 {
-       u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom;
        bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG;
-       u64 npgs, addr = mr->addr, size = mr->len;
-       unsigned int chunks, chunks_rem;
+       u32 chunk_size = mr->chunk_size, headroom = mr->headroom;
+       u64 addr = mr->addr, size = mr->len;
+       u32 chunks_rem, npgs_rem;
+       u64 chunks, npgs;
        int err;
 
        if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) {
@@ -188,8 +189,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        if (npgs > U32_MAX)
                return -EINVAL;
 
-       chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem);
-       if (chunks == 0)
+       chunks = div_u64_rem(size, chunk_size, &chunks_rem);
+       if (!chunks || chunks > U32_MAX)
                return -EINVAL;
 
        if (!unaligned_chunks && chunks_rem)
@@ -202,7 +203,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
        umem->headroom = headroom;
        umem->chunk_size = chunk_size;
        umem->chunks = chunks;
-       umem->npgs = (u32)npgs;
+       umem->npgs = npgs;
        umem->pgs = NULL;
        umem->user = NULL;
        umem->flags = mr->flags;
index 2ab3e09e2227126f5e5eba7d4f1ea172de090c58..50baf50dc513ac36f540c172b9a8389d7c78d5f2 100644 (file)
@@ -2815,11 +2815,6 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload,
                        goto error;
                }
 
-               if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) {
-                       NL_SET_ERR_MSG(extack, "Only tunnel modes can accommodate an AF_UNSPEC selector");
-                       goto error;
-               }
-
                x->inner_mode = *inner_mode;
 
                if (x->props.family == AF_INET)
index cf5172d4ce68cfed78c88b782335ca4d8b66f09d..103af2b3e986f322882810c132096d65429e3d07 100644 (file)
@@ -1012,7 +1012,9 @@ static int copy_to_user_aead(struct xfrm_algo_aead *aead, struct sk_buff *skb)
                return -EMSGSIZE;
 
        ap = nla_data(nla);
-       memcpy(ap, aead, sizeof(*aead));
+       strscpy_pad(ap->alg_name, aead->alg_name, sizeof(ap->alg_name));
+       ap->alg_key_len = aead->alg_key_len;
+       ap->alg_icv_len = aead->alg_icv_len;
 
        if (redact_secret && aead->alg_key_len)
                memset(ap->alg_key, 0, (aead->alg_key_len + 7) / 8);
@@ -1032,7 +1034,8 @@ static int copy_to_user_ealg(struct xfrm_algo *ealg, struct sk_buff *skb)
                return -EMSGSIZE;
 
        ap = nla_data(nla);
-       memcpy(ap, ealg, sizeof(*ealg));
+       strscpy_pad(ap->alg_name, ealg->alg_name, sizeof(ap->alg_name));
+       ap->alg_key_len = ealg->alg_key_len;
 
        if (redact_secret && ealg->alg_key_len)
                memset(ap->alg_key, 0, (ealg->alg_key_len + 7) / 8);
@@ -1043,6 +1046,40 @@ static int copy_to_user_ealg(struct xfrm_algo *ealg, struct sk_buff *skb)
        return 0;
 }
 
+static int copy_to_user_calg(struct xfrm_algo *calg, struct sk_buff *skb)
+{
+       struct nlattr *nla = nla_reserve(skb, XFRMA_ALG_COMP, sizeof(*calg));
+       struct xfrm_algo *ap;
+
+       if (!nla)
+               return -EMSGSIZE;
+
+       ap = nla_data(nla);
+       strscpy_pad(ap->alg_name, calg->alg_name, sizeof(ap->alg_name));
+       ap->alg_key_len = 0;
+
+       return 0;
+}
+
+static int copy_to_user_encap(struct xfrm_encap_tmpl *ep, struct sk_buff *skb)
+{
+       struct nlattr *nla = nla_reserve(skb, XFRMA_ENCAP, sizeof(*ep));
+       struct xfrm_encap_tmpl *uep;
+
+       if (!nla)
+               return -EMSGSIZE;
+
+       uep = nla_data(nla);
+       memset(uep, 0, sizeof(*uep));
+
+       uep->encap_type = ep->encap_type;
+       uep->encap_sport = ep->encap_sport;
+       uep->encap_dport = ep->encap_dport;
+       uep->encap_oa = ep->encap_oa;
+
+       return 0;
+}
+
 static int xfrm_smark_put(struct sk_buff *skb, struct xfrm_mark *m)
 {
        int ret = 0;
@@ -1098,12 +1135,12 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
                        goto out;
        }
        if (x->calg) {
-               ret = nla_put(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
+               ret = copy_to_user_calg(x->calg, skb);
                if (ret)
                        goto out;
        }
        if (x->encap) {
-               ret = nla_put(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+               ret = copy_to_user_encap(x->encap, skb);
                if (ret)
                        goto out;
        }
index f88d108fbef07adc1e039123e7855617cec6c426..aef85e9e8eeb8d930e41b0dd82b7fd4c8c0fac4e 100644 (file)
@@ -262,6 +262,20 @@ BINDGEN_TARGET             := $(BINDGEN_TARGET_$(SRCARCH))
 # some configurations, with new GCC versions, etc.
 bindgen_extra_c_flags = -w --target=$(BINDGEN_TARGET)
 
+# Auto variable zero-initialization requires an additional special option with
+# clang that is going to be removed sometime in the future (likely in
+# clang-18), so make sure to pass this option only if clang supports it
+# (libclang major version < 16).
+#
+# https://github.com/llvm/llvm-project/issues/44842
+# https://github.com/llvm/llvm-project/blob/llvmorg-16.0.0-rc2/clang/docs/ReleaseNotes.rst#deprecated-compiler-flags
+ifdef CONFIG_INIT_STACK_ALL_ZERO
+libclang_maj_ver=$(shell $(BINDGEN) $(srctree)/scripts/rust_is_available_bindgen_libclang.h 2>&1 | sed -ne 's/.*clang version \([0-9]*\).*/\1/p')
+ifeq ($(shell expr $(libclang_maj_ver) \< 16), 1)
+bindgen_extra_c_flags += -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
+endif
+endif
+
 bindgen_c_flags = $(filter-out $(bindgen_skip_c_flags), $(c_flags)) \
        $(bindgen_extra_c_flags)
 endif
@@ -283,7 +297,7 @@ quiet_cmd_bindgen = BINDGEN $@
                $(bindgen_target_cflags) $(bindgen_target_extra)
 
 $(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
-    $(shell grep -v '^\#\|^$$' $(srctree)/$(src)/bindgen_parameters)
+    $(shell grep -v '^#\|^$$' $(srctree)/$(src)/bindgen_parameters)
 $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
     $(src)/bindgen_parameters FORCE
        $(call if_changed_dep,bindgen)
index 30103325696d801df5458f7f398a997835fbe8fe..8009184bf6d768539507c6a0fc543655d2f671fa 100644 (file)
@@ -18,7 +18,11 @@ use crate::bindings;
 
 // Called from `vsprintf` with format specifier `%pA`.
 #[no_mangle]
-unsafe fn rust_fmt_argument(buf: *mut c_char, end: *mut c_char, ptr: *const c_void) -> *mut c_char {
+unsafe extern "C" fn rust_fmt_argument(
+    buf: *mut c_char,
+    end: *mut c_char,
+    ptr: *const c_void,
+) -> *mut c_char {
     use fmt::Write;
     // SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`.
     let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) };
index b771310fa4a49e0a1f2389f438784ec899725212..cd3d2a6cf1fc1205c5f3fc62bf5aad5c3a261ab7 100644 (file)
@@ -408,7 +408,7 @@ impl RawFormatter {
     /// If `pos` is less than `end`, then the region between `pos` (inclusive) and `end`
     /// (exclusive) must be valid for writes for the lifetime of the returned [`RawFormatter`].
     pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {
-        // INVARIANT: The safety requierments guarantee the type invariants.
+        // INVARIANT: The safety requirements guarantee the type invariants.
         Self {
             beg: pos as _,
             pos: pos as _,
index feb43045d1b1ed84bab049b98cd50af88d3643cc..6e9ce6720a05aacbaa2f7e0dc96c2e67819e7269 100644 (file)
@@ -3,7 +3,6 @@
 /generate_rust_target
 /insert-sys-cert
 /kallsyms
-/list-gitignored
 /module.lds
 /recordmcount
 /sign-file
index e8917975905ca65973bc2e1e005a53006c08e5a3..32b6ba7227284c0482c980d6f9a02a15d8ab4f7a 100644 (file)
@@ -38,7 +38,7 @@ HOSTCFLAGS_sorttable.o += -DMCOUNT_SORT_ENABLED
 endif
 
 # The following programs are only built on demand
-hostprogs += list-gitignored unifdef
+hostprogs += unifdef
 
 # The module linker script is preprocessed on demand
 targets += module.lds
index b941e6341b364f26cba7555a56a9390745656e71..4000ad04c1220d48366b78b568fc1d34d6ed0691 100644 (file)
@@ -2,6 +2,7 @@
 # Makefile for the different targets used to generate full packages of a kernel
 
 include $(srctree)/scripts/Kbuild.include
+include $(srctree)/scripts/Makefile.lib
 
 KERNELPATH := kernel-$(subst -,_,$(KERNELRELEASE))
 KBUILD_PKG_ROOTCMD ?="fakeroot -u"
@@ -26,54 +27,39 @@ fi ; \
 tar -I $(KGZIP) -c $(RCS_TAR_IGNORE) -f $(2).tar.gz \
        --transform 's:^:$(2)/:S' $(TAR_CONTENT) $(3)
 
-# .tmp_filelist .tmp_filelist_exclude
+# Git
 # ---------------------------------------------------------------------------
 
-scripts/list-gitignored: FORCE
-       $(Q)$(MAKE) -f $(srctree)/Makefile scripts_package
+filechk_HEAD = git -C $(srctree) rev-parse --verify HEAD 2>/dev/null
 
-# 1f5d3a6b6532e25a5cdf1f311956b2b03d343a48 removed '*.rej' from .gitignore,
-# but it is definitely a generated file.
-filechk_filelist = \
-       $< --exclude='*.rej' --output=$@_exclude --prefix=./ --rootdir=$(srctree) --stat=-
+.tmp_HEAD: check-git FORCE
+       $(call filechk,HEAD)
 
-.tmp_filelist: scripts/list-gitignored FORCE
-       $(call filechk,filelist)
-
-# tarball
-# ---------------------------------------------------------------------------
-
-quiet_cmd_tar = TAR     $@
-      cmd_tar = tar -c -f $@ $(tar-compress-opt) $(tar-exclude-opt) \
-                --owner=0 --group=0 --sort=name \
-                --transform 's:^\.:$*:S' -C $(tar-rootdir) .
-
-tar-rootdir := $(srctree)
-
-%.tar:
-       $(call cmd,tar)
-
-%.tar.gz: private tar-compress-opt := -I $(KGZIP)
-%.tar.gz:
-       $(call cmd,tar)
-
-%.tar.bz2: private tar-compress-opt := -I $(KBZIP2)
-%.tar.bz2:
-       $(call cmd,tar)
+PHONY += check-git
+check-git:
+       @if ! $(srctree)/scripts/check-git; then \
+               echo >&2 "error: creating source package requires git repository"; \
+               false; \
+       fi
 
-%.tar.xz: private tar-compress-opt := -I $(XZ)
-%.tar.xz:
-       $(call cmd,tar)
+git-config-tar.gz  = -c tar.tar.gz.command="$(KGZIP)"
+git-config-tar.bz2 = -c tar.tar.bz2.command="$(KBZIP2)"
+git-config-tar.xz  = -c tar.tar.xz.command="$(XZ)"
+git-config-tar.zst = -c tar.tar.zst.command="$(ZSTD)"
 
-%.tar.zst: private tar-compress-opt := -I $(ZSTD)
-%.tar.zst:
-       $(call cmd,tar)
+quiet_cmd_archive = ARCHIVE $@
+      cmd_archive = git -C $(srctree) $(git-config-tar$(suffix $@)) archive \
+                    --output=$$(realpath $@) $(archive-args)
 
 # Linux source tarball
 # ---------------------------------------------------------------------------
 
-linux.tar.gz: tar-exclude-opt = --exclude=./$@ --exclude-from=$<_exclude
-linux.tar.gz: .tmp_filelist
+linux-tarballs := $(addprefix linux, .tar.gz)
+
+targets += $(linux-tarballs)
+$(linux-tarballs): archive-args = --prefix=linux/ $$(cat $<)
+$(linux-tarballs): .tmp_HEAD FORCE
+       $(call if_changed,archive)
 
 # rpm-pkg
 # ---------------------------------------------------------------------------
@@ -89,7 +75,7 @@ PHONY += srcrpm-pkg
 srcrpm-pkg: linux.tar.gz
        $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec
        +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE)-linux -bs kernel.spec \
-       --define='_smp_mflags %{nil}' --define='_sourcedir .' --define='_srcrpmdir .'
+       --define='_smp_mflags %{nil}' --define='_sourcedir rpmbuild/SOURCES' --define='_srcrpmdir .'
 
 # binrpm-pkg
 # ---------------------------------------------------------------------------
@@ -101,7 +87,7 @@ binrpm-pkg:
                $(UTS_MACHINE)-linux -bb $(objtree)/binkernel.spec
 
 quiet_cmd_debianize = GEN     $@
-      cmd_debianize = $(srctree)/scripts/package/mkdebian
+      cmd_debianize = $(srctree)/scripts/package/mkdebian $(mkdebian-opts)
 
 debian: FORCE
        $(call cmd,debianize)
@@ -110,6 +96,7 @@ PHONY += debian-orig
 debian-orig: private source = $(shell dpkg-parsechangelog -S Source)
 debian-orig: private version = $(shell dpkg-parsechangelog -S Version | sed 's/-[^-]*$$//')
 debian-orig: private orig-name = $(source)_$(version).orig.tar.gz
+debian-orig: mkdebian-opts = --need-source
 debian-orig: linux.tar.gz debian
        $(Q)if [ "$(df  --output=target .. 2>/dev/null)" = "$(df --output=target $< 2>/dev/null)" ]; then \
                ln -f $< ../$(orig-name); \
@@ -148,74 +135,70 @@ snap-pkg:
 # dir-pkg tar*-pkg - tarball targets
 # ---------------------------------------------------------------------------
 
-tar-pkg-tarball = linux-$(KERNELRELEASE)-$(ARCH).$(1)
-tar-pkg-phony = $(subst .,,$(1))-pkg
-
 tar-install: FORCE
        $(Q)$(MAKE) -f $(srctree)/Makefile
        +$(Q)$(srctree)/scripts/package/buildtar $@
 
+compress-tar.gz  = -I "$(KGZIP)"
+compress-tar.bz2 = -I "$(KBZIP2)"
+compress-tar.xz  = -I "$(XZ)"
+compress-tar.zst = -I "$(ZSTD)"
+
+quiet_cmd_tar = TAR     $@
+      cmd_tar = cd $<; tar cf ../$@ $(compress-tar$(suffix $@)) --owner=root --group=root --sort=name *
+
+dir-tarballs := $(addprefix linux-$(KERNELRELEASE)-$(ARCH), .tar .tar.gz .tar.bz2 .tar.xz .tar.zst)
+
+$(dir-tarballs): tar-install
+       $(call cmd,tar)
+
 PHONY += dir-pkg
 dir-pkg: tar-install
        @echo "Kernel tree successfully created in $<"
 
-define tar-pkg-rule
-PHONY += $(tar-pkg-phony)
-$(tar-pkg-phony): $(tar-pkg-tarball)
+PHONY += tar-pkg
+tar-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar
        @:
 
-$(tar-pkg-tarball): private tar-rootdir := tar-install
-$(tar-pkg-tarball): tar-install
-endef
-
-$(foreach x, tar tar.gz tar.bz2 tar.xz tar.zst, $(eval $(call tar-pkg-rule,$(x))))
+tar%-pkg: linux-$(KERNELRELEASE)-$(ARCH).tar.% FORCE
+       @:
 
 # perf-tar*-src-pkg - generate a source tarball with perf source
 # ---------------------------------------------------------------------------
 
-perf-tar-src-pkg-tarball = perf-$(KERNELVERSION).$(1)
-perf-tar-src-pkg-phony   = perf-$(subst .,,$(1))-src-pkg
-
-quiet_cmd_stage_perf_src = STAGE   $@
-      cmd_stage_perf_src = \
-       rm -rf $@; \
-       mkdir -p $@; \
-       tar -c -f - --exclude-from=$<_exclude -C $(srctree) --files-from=$(srctree)/tools/perf/MANIFEST | \
-       tar -x -f - -C $@
-
-.tmp_perf: .tmp_filelist
-       $(call cmd,stage_perf_src)
-
-filechk_perf_head = \
-       if test -z "$(git -C $(srctree) rev-parse --show-cdup 2>/dev/null)" && \
-              head=$$(git -C $(srctree) rev-parse --verify HEAD 2>/dev/null); then \
-               echo $$head; \
-       else \
-               echo "not a git tree"; \
-       fi
+.tmp_perf:
+       $(Q)mkdir .tmp_perf
 
-.tmp_perf/HEAD: .tmp_perf FORCE
-       $(call filechk,perf_head)
+.tmp_perf/HEAD: .tmp_HEAD | .tmp_perf
+       $(call cmd,copy)
 
 quiet_cmd_perf_version_file = GEN     $@
       cmd_perf_version_file = cd $(srctree)/tools/perf; util/PERF-VERSION-GEN $(dir $(abspath $@))
 
-# PERF-VERSION-FILE and HEAD are independent, but this avoids updating the
+# PERF-VERSION-FILE and .tmp_HEAD are independent, but this avoids updating the
 # timestamp of PERF-VERSION-FILE.
 # The best is to fix tools/perf/util/PERF-VERSION-GEN.
-.tmp_perf/PERF-VERSION-FILE: .tmp_perf/HEAD $(srctree)/tools/perf/util/PERF-VERSION-GEN
+.tmp_perf/PERF-VERSION-FILE: .tmp_HEAD $(srctree)/tools/perf/util/PERF-VERSION-GEN | .tmp_perf
        $(call cmd,perf_version_file)
 
-define perf-tar-src-pkg-rule
-PHONY += $(perf-tar-src-pkg-phony)
-$(perf-tar-src-pkg-phony): $(perf-tar-src-pkg-tarball)
-       @:
+perf-archive-args = --add-file=$$(realpath $(word 2, $^)) \
+       --add-file=$$(realpath $(word 3, $^)) \
+       $$(cat $(word 2, $^))^{tree} $$(cat $<)
+
 
-$(perf-tar-src-pkg-tarball): private tar-rootdir := .tmp_perf
-$(perf-tar-src-pkg-tarball): .tmp_filelist .tmp_perf/HEAD .tmp_perf/PERF-VERSION-FILE
-endef
+perf-tarballs := $(addprefix perf-$(KERNELVERSION), .tar .tar.gz .tar.bz2 .tar.xz .tar.zst)
 
-$(foreach x, tar tar.gz tar.bz2 tar.xz tar.zst, $(eval $(call perf-tar-src-pkg-rule,$(x))))
+targets += $(perf-tarballs)
+$(perf-tarballs): archive-args = --prefix=perf-$(KERNELVERSION)/ $(perf-archive-args)
+$(perf-tarballs): tools/perf/MANIFEST .tmp_perf/HEAD .tmp_perf/PERF-VERSION-FILE FORCE
+       $(call if_changed,archive)
+
+PHONY += perf-tar-src-pkg
+perf-tar-src-pkg: perf-$(KERNELVERSION).tar
+       @:
+
+perf-tar%-src-pkg: perf-$(KERNELVERSION).tar.% FORCE
+       @:
 
 # Help text displayed when executing 'make help'
 # ---------------------------------------------------------------------------
@@ -243,4 +226,13 @@ help:
 PHONY += FORCE
 FORCE:
 
+# Read all saved command lines and dependencies for the $(targets) we
+# may be building above, using $(if_changed{,_dep}). As an
+# optimization, we don't need to read them if the target does not
+# exist, we will rebuild anyway in that case.
+
+existing-targets := $(wildcard $(sort $(targets)))
+
+-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
+
 .PHONY: $(PHONY)
index 7b6756a8c15d99440078dbfbb2b323abf376ed45..4c3f645065a45bf8105d31c3cc1c335fdb9defd2 100644 (file)
@@ -625,7 +625,7 @@ int main(int argc, char **argv)
        p = strrchr(argv[1], '/');
        p = p ? p + 1 : argv[1];
        grammar_name = strdup(p);
-       if (!p) {
+       if (!grammar_name) {
                perror(NULL);
                exit(1);
        }
index 0573c92e841d3209b9034a0673e46a2e750510d5..a7e28b6a514e5e6adc6070e20f46c8c4b160d7cd 100755 (executable)
@@ -45,10 +45,6 @@ Clang)
        version=$2.$3.$4
        min_version=$($min_tool_version llvm)
        ;;
-ICC)
-       version=$(($2 / 100)).$(($2 % 100)).$3
-       min_version=$($min_tool_version icc)
-       ;;
 *)
        echo "$orig_args: unknown C compiler" >&2
        exit 1
diff --git a/scripts/check-git b/scripts/check-git
new file mode 100755 (executable)
index 0000000..2ca6c5d
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# succeed if we are in a git repository
+
+srctree="$(dirname $0)/.."
+
+if ! git -C "${srctree}" rev-parse --verify HEAD >/dev/null 2>/dev/null; then
+       exit 1
+fi
+
+if ! test -z $(git -C "${srctree}" rev-parse --show-cdup 2>/dev/null); then
+       exit 1
+fi
index bd44d12965c98e99042938880a17730c6dfac5c9..4bfbe3c9fa15fa0828ca33b282d9c169d37aab80 100755 (executable)
@@ -6388,6 +6388,15 @@ sub process {
                        }
                }
 
+# 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*\)/ &&
index f33e61aca93d34ee4cc05b1266f7449ff71fc213..1e5d2eeb726df00e5be8b7aef040b97b011546c8 100755 (executable)
@@ -114,7 +114,6 @@ cat << EOF
 #define __IGNORE_truncate
 #define __IGNORE_stat
 #define __IGNORE_lstat
-#define __IGNORE_fstat
 #define __IGNORE_fcntl
 #define __IGNORE_fadvise64
 #define __IGNORE_newfstatat
@@ -255,6 +254,9 @@ cat << EOF
 /* 64-bit ports never needed these, and new 32-bit ports can use statx */
 #define __IGNORE_fstat64
 #define __IGNORE_fstatat64
+
+/* Newer ports are not required to provide fstat in favor of statx */
+#define __IGNORE_fstat
 EOF
 }
 
index ecc7ea9a4dcfc6f1c89f289f8866bad9ed1e430b..946e250c1b2a6f9b243d8836ea47ad067970530b 100755 (executable)
@@ -104,7 +104,10 @@ def generate_crates(srctree, objtree, sysroot_src):
             name = path.name.replace(".rs", "")
 
             # Skip those that are not crate roots.
-            if f"{name}.o" not in open(path.parent / "Makefile").read():
+            try:
+                if f"{name}.o" not in open(path.parent / "Makefile").read():
+                    continue
+            except FileNotFoundError:
                 continue
 
             logging.info("Adding %s", name)
index 28b3831a7593f42b12b4b3e8a67733d9a1c0fe44..464761a7cf7f25c0b194b1cd72481e2cb2bc5d48 100755 (executable)
@@ -13,4 +13,4 @@ set -e
 #
 # In the future, checking for the `.comment` section may be another
 # option, see https://github.com/rust-lang/rust/pull/97550.
-${NM} "$*" | grep -qE '^[0-9a-fA-F]+ r _R[^[:space:]]+16___IS_RUST_MODULE[^[:space:]]*$'
+${NM} "$*" | grep -qE '^[0-9a-fA-F]+ [Rr] _R[^[:space:]]+16___IS_RUST_MODULE[^[:space:]]*$'
index 8a68179a98a3986ed12a25bcbb0e535c5c54a5f4..a239a87e7bec1c75ffba780d291fb7493c868780 100644 (file)
@@ -119,6 +119,7 @@ static bool is_ignored_symbol(const char *name, char type)
                "kallsyms_markers",
                "kallsyms_token_table",
                "kallsyms_token_index",
+               "kallsyms_seqs_of_names",
                /* Exclude linker generated symbols which vary between passes */
                "_SDA_BASE_",           /* ppc */
                "_SDA2_BASE_",          /* ppc */
index b7c9f1dd5e4229df71e99ae9585424155ac101f0..992575f1e97693af4f715bb66d6dfd7f3a93f58b 100644 (file)
@@ -1226,10 +1226,12 @@ static void (*conf_changed_callback)(void);
 
 void conf_set_changed(bool val)
 {
-       if (conf_changed_callback && conf_changed != val)
-               conf_changed_callback();
+       bool changed = conf_changed != val;
 
        conf_changed = val;
+
+       if (conf_changed_callback && changed)
+               conf_changed_callback();
 }
 
 bool conf_get_changed(void)
index 32620de473ad2dc42e261c3a6fcf49587198b6fd..902eb429b9dbd92e060925fdefd06bf2fdd45b4b 100755 (executable)
@@ -145,7 +145,7 @@ for ORIG_MERGE_FILE in $MERGE_LIST ; do
                NEW_VAL=$(grep -w $CFG $MERGE_FILE)
                BUILTIN_FLAG=false
                if [ "$BUILTIN" = "true" ] && [ "${NEW_VAL#CONFIG_*=}" = "m" ] && [ "${PREV_VAL#CONFIG_*=}" = "y" ]; then
-                       ${WARNOVVERIDE} Previous  value: $PREV_VAL
+                       ${WARNOVERRIDE} Previous  value: $PREV_VAL
                        ${WARNOVERRIDE} New value:       $NEW_VAL
                        ${WARNOVERRIDE} -y passed, will not demote y to m
                        ${WARNOVERRIDE}
diff --git a/scripts/list-gitignored.c b/scripts/list-gitignored.c
deleted file mode 100644 (file)
index f9941f8..0000000
+++ /dev/null
@@ -1,1057 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-//
-// Traverse the source tree, parsing all .gitignore files, and print file paths
-// that are ignored by git.
-// The output is suitable to the --exclude-from option of tar.
-// This is useful until the --exclude-vcs-ignores option gets working correctly.
-//
-// Copyright (C) 2023 Masahiro Yamada <masahiroy@kernel.org>
-//                      (a lot of code imported from GIT)
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-// Imported from commit 23c56f7bd5f1667f8b793d796bf30e39545920f6 in GIT
-//
-//---------------------------(IMPORT FROM GIT BEGIN)---------------------------
-
-// Copied from environment.c
-
-static bool ignore_case;
-
-// Copied from git-compat-util.h
-
-/* Sane ctype - no locale, and works with signed chars */
-#undef isascii
-#undef isspace
-#undef isdigit
-#undef isalpha
-#undef isalnum
-#undef isprint
-#undef islower
-#undef isupper
-#undef tolower
-#undef toupper
-#undef iscntrl
-#undef ispunct
-#undef isxdigit
-
-static const unsigned char sane_ctype[256];
-#define GIT_SPACE 0x01
-#define GIT_DIGIT 0x02
-#define GIT_ALPHA 0x04
-#define GIT_GLOB_SPECIAL 0x08
-#define GIT_REGEX_SPECIAL 0x10
-#define GIT_PATHSPEC_MAGIC 0x20
-#define GIT_CNTRL 0x40
-#define GIT_PUNCT 0x80
-#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
-#define isascii(x) (((x) & ~0x7f) == 0)
-#define isspace(x) sane_istest(x,GIT_SPACE)
-#define isdigit(x) sane_istest(x,GIT_DIGIT)
-#define isalpha(x) sane_istest(x,GIT_ALPHA)
-#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
-#define isprint(x) ((x) >= 0x20 && (x) <= 0x7e)
-#define islower(x) sane_iscase(x, 1)
-#define isupper(x) sane_iscase(x, 0)
-#define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL)
-#define iscntrl(x) (sane_istest(x,GIT_CNTRL))
-#define ispunct(x) sane_istest(x, GIT_PUNCT | GIT_REGEX_SPECIAL | \
-               GIT_GLOB_SPECIAL | GIT_PATHSPEC_MAGIC)
-#define isxdigit(x) (hexval_table[(unsigned char)(x)] != -1)
-#define tolower(x) sane_case((unsigned char)(x), 0x20)
-#define toupper(x) sane_case((unsigned char)(x), 0)
-
-static inline int sane_case(int x, int high)
-{
-       if (sane_istest(x, GIT_ALPHA))
-               x = (x & ~0x20) | high;
-       return x;
-}
-
-static inline int sane_iscase(int x, int is_lower)
-{
-       if (!sane_istest(x, GIT_ALPHA))
-               return 0;
-
-       if (is_lower)
-               return (x & 0x20) != 0;
-       else
-               return (x & 0x20) == 0;
-}
-
-// Copied from ctype.c
-
-enum {
-       S = GIT_SPACE,
-       A = GIT_ALPHA,
-       D = GIT_DIGIT,
-       G = GIT_GLOB_SPECIAL,   /* *, ?, [, \\ */
-       R = GIT_REGEX_SPECIAL,  /* $, (, ), +, ., ^, {, | */
-       P = GIT_PATHSPEC_MAGIC, /* other non-alnum, except for ] and } */
-       X = GIT_CNTRL,
-       U = GIT_PUNCT,
-       Z = GIT_CNTRL | GIT_SPACE
-};
-
-static const unsigned char sane_ctype[256] = {
-       X, X, X, X, X, X, X, X, X, Z, Z, X, X, Z, X, X,         /*   0.. 15 */
-       X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,         /*  16.. 31 */
-       S, P, P, P, R, P, P, P, R, R, G, R, P, P, R, P,         /*  32.. 47 */
-       D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G,         /*  48.. 63 */
-       P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,         /*  64.. 79 */
-       A, A, A, A, A, A, A, A, A, A, A, G, G, U, R, P,         /*  80.. 95 */
-       P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,         /*  96..111 */
-       A, A, A, A, A, A, A, A, A, A, A, R, R, U, P, X,         /* 112..127 */
-       /* Nothing in the 128.. range */
-};
-
-// Copied from hex.c
-
-static const signed char hexval_table[256] = {
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 00-07 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 08-0f */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 10-17 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 18-1f */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 20-27 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 28-2f */
-         0,  1,  2,  3,  4,  5,  6,  7,                /* 30-37 */
-         8,  9, -1, -1, -1, -1, -1, -1,                /* 38-3f */
-        -1, 10, 11, 12, 13, 14, 15, -1,                /* 40-47 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 48-4f */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 50-57 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 58-5f */
-        -1, 10, 11, 12, 13, 14, 15, -1,                /* 60-67 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 68-67 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 70-77 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 78-7f */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 80-87 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 88-8f */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 90-97 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* 98-9f */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* a0-a7 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* a8-af */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* b0-b7 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* b8-bf */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* c0-c7 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* c8-cf */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* d0-d7 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* d8-df */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* e0-e7 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* e8-ef */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* f0-f7 */
-        -1, -1, -1, -1, -1, -1, -1, -1,                /* f8-ff */
-};
-
-// Copied from wildmatch.h
-
-#define WM_CASEFOLD 1
-#define WM_PATHNAME 2
-
-#define WM_NOMATCH 1
-#define WM_MATCH 0
-#define WM_ABORT_ALL -1
-#define WM_ABORT_TO_STARSTAR -2
-
-// Copied from wildmatch.c
-
-typedef unsigned char uchar;
-
-// local modification: remove NEGATE_CLASS(2)
-
-#define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \
-                                   && *(class) == *(litmatch) \
-                                   && strncmp((char*)class, litmatch, len) == 0)
-
-// local modification: simpilify macros
-#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-#define ISGRAPH(c) (isprint(c) && !isspace(c))
-#define ISPRINT(c) isprint(c)
-#define ISDIGIT(c) isdigit(c)
-#define ISALNUM(c) isalnum(c)
-#define ISALPHA(c) isalpha(c)
-#define ISCNTRL(c) iscntrl(c)
-#define ISLOWER(c) islower(c)
-#define ISPUNCT(c) ispunct(c)
-#define ISSPACE(c) isspace(c)
-#define ISUPPER(c) isupper(c)
-#define ISXDIGIT(c) isxdigit(c)
-
-/* Match pattern "p" against "text" */
-static int dowild(const uchar *p, const uchar *text, unsigned int flags)
-{
-       uchar p_ch;
-       const uchar *pattern = p;
-
-       for ( ; (p_ch = *p) != '\0'; text++, p++) {
-               int matched, match_slash, negated;
-               uchar t_ch, prev_ch;
-               if ((t_ch = *text) == '\0' && p_ch != '*')
-                       return WM_ABORT_ALL;
-               if ((flags & WM_CASEFOLD) && ISUPPER(t_ch))
-                       t_ch = tolower(t_ch);
-               if ((flags & WM_CASEFOLD) && ISUPPER(p_ch))
-                       p_ch = tolower(p_ch);
-               switch (p_ch) {
-               case '\\':
-                       /* Literal match with following character.  Note that the test
-                        * in "default" handles the p[1] == '\0' failure case. */
-                       p_ch = *++p;
-                       /* FALLTHROUGH */
-               default:
-                       if (t_ch != p_ch)
-                               return WM_NOMATCH;
-                       continue;
-               case '?':
-                       /* Match anything but '/'. */
-                       if ((flags & WM_PATHNAME) && t_ch == '/')
-                               return WM_NOMATCH;
-                       continue;
-               case '*':
-                       if (*++p == '*') {
-                               const uchar *prev_p = p - 2;
-                               while (*++p == '*') {}
-                               if (!(flags & WM_PATHNAME))
-                                       /* without WM_PATHNAME, '*' == '**' */
-                                       match_slash = 1;
-                               else if ((prev_p < pattern || *prev_p == '/') &&
-                                   (*p == '\0' || *p == '/' ||
-                                    (p[0] == '\\' && p[1] == '/'))) {
-                                       /*
-                                        * Assuming we already match 'foo/' and are at
-                                        * <star star slash>, just assume it matches
-                                        * nothing and go ahead match the rest of the
-                                        * pattern with the remaining string. This
-                                        * helps make foo/<*><*>/bar (<> because
-                                        * otherwise it breaks C comment syntax) match
-                                        * both foo/bar and foo/a/bar.
-                                        */
-                                       if (p[0] == '/' &&
-                                           dowild(p + 1, text, flags) == WM_MATCH)
-                                               return WM_MATCH;
-                                       match_slash = 1;
-                               } else /* WM_PATHNAME is set */
-                                       match_slash = 0;
-                       } else
-                               /* without WM_PATHNAME, '*' == '**' */
-                               match_slash = flags & WM_PATHNAME ? 0 : 1;
-                       if (*p == '\0') {
-                               /* Trailing "**" matches everything.  Trailing "*" matches
-                                * only if there are no more slash characters. */
-                               if (!match_slash) {
-                                       if (strchr((char *)text, '/'))
-                                               return WM_NOMATCH;
-                               }
-                               return WM_MATCH;
-                       } else if (!match_slash && *p == '/') {
-                               /*
-                                * _one_ asterisk followed by a slash
-                                * with WM_PATHNAME matches the next
-                                * directory
-                                */
-                               const char *slash = strchr((char*)text, '/');
-                               if (!slash)
-                                       return WM_NOMATCH;
-                               text = (const uchar*)slash;
-                               /* the slash is consumed by the top-level for loop */
-                               break;
-                       }
-                       while (1) {
-                               if (t_ch == '\0')
-                                       break;
-                               /*
-                                * Try to advance faster when an asterisk is
-                                * followed by a literal. We know in this case
-                                * that the string before the literal
-                                * must belong to "*".
-                                * If match_slash is false, do not look past
-                                * the first slash as it cannot belong to '*'.
-                                */
-                               if (!is_glob_special(*p)) {
-                                       p_ch = *p;
-                                       if ((flags & WM_CASEFOLD) && ISUPPER(p_ch))
-                                               p_ch = tolower(p_ch);
-                                       while ((t_ch = *text) != '\0' &&
-                                              (match_slash || t_ch != '/')) {
-                                               if ((flags & WM_CASEFOLD) && ISUPPER(t_ch))
-                                                       t_ch = tolower(t_ch);
-                                               if (t_ch == p_ch)
-                                                       break;
-                                               text++;
-                                       }
-                                       if (t_ch != p_ch)
-                                               return WM_NOMATCH;
-                               }
-                               if ((matched = dowild(p, text, flags)) != WM_NOMATCH) {
-                                       if (!match_slash || matched != WM_ABORT_TO_STARSTAR)
-                                               return matched;
-                               } else if (!match_slash && t_ch == '/')
-                                       return WM_ABORT_TO_STARSTAR;
-                               t_ch = *++text;
-                       }
-                       return WM_ABORT_ALL;
-               case '[':
-                       p_ch = *++p;
-                       if (p_ch == '^')
-                               p_ch = '!';
-                       /* Assign literal 1/0 because of "matched" comparison. */
-                       negated = p_ch == '!' ? 1 : 0;
-                       if (negated) {
-                               /* Inverted character class. */
-                               p_ch = *++p;
-                       }
-                       prev_ch = 0;
-                       matched = 0;
-                       do {
-                               if (!p_ch)
-                                       return WM_ABORT_ALL;
-                               if (p_ch == '\\') {
-                                       p_ch = *++p;
-                                       if (!p_ch)
-                                               return WM_ABORT_ALL;
-                                       if (t_ch == p_ch)
-                                               matched = 1;
-                               } else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
-                                       p_ch = *++p;
-                                       if (p_ch == '\\') {
-                                               p_ch = *++p;
-                                               if (!p_ch)
-                                                       return WM_ABORT_ALL;
-                                       }
-                                       if (t_ch <= p_ch && t_ch >= prev_ch)
-                                               matched = 1;
-                                       else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) {
-                                               uchar t_ch_upper = toupper(t_ch);
-                                               if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch)
-                                                       matched = 1;
-                                       }
-                                       p_ch = 0; /* This makes "prev_ch" get set to 0. */
-                               } else if (p_ch == '[' && p[1] == ':') {
-                                       const uchar *s;
-                                       int i;
-                                       for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {} /*SHARED ITERATOR*/
-                                       if (!p_ch)
-                                               return WM_ABORT_ALL;
-                                       i = p - s - 1;
-                                       if (i < 0 || p[-1] != ':') {
-                                               /* Didn't find ":]", so treat like a normal set. */
-                                               p = s - 2;
-                                               p_ch = '[';
-                                               if (t_ch == p_ch)
-                                                       matched = 1;
-                                               continue;
-                                       }
-                                       if (CC_EQ(s,i, "alnum")) {
-                                               if (ISALNUM(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "alpha")) {
-                                               if (ISALPHA(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "blank")) {
-                                               if (ISBLANK(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "cntrl")) {
-                                               if (ISCNTRL(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "digit")) {
-                                               if (ISDIGIT(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "graph")) {
-                                               if (ISGRAPH(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "lower")) {
-                                               if (ISLOWER(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "print")) {
-                                               if (ISPRINT(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "punct")) {
-                                               if (ISPUNCT(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "space")) {
-                                               if (ISSPACE(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "upper")) {
-                                               if (ISUPPER(t_ch))
-                                                       matched = 1;
-                                               else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch))
-                                                       matched = 1;
-                                       } else if (CC_EQ(s,i, "xdigit")) {
-                                               if (ISXDIGIT(t_ch))
-                                                       matched = 1;
-                                       } else /* malformed [:class:] string */
-                                               return WM_ABORT_ALL;
-                                       p_ch = 0; /* This makes "prev_ch" get set to 0. */
-                               } else if (t_ch == p_ch)
-                                       matched = 1;
-                       } while (prev_ch = p_ch, (p_ch = *++p) != ']');
-                       if (matched == negated ||
-                           ((flags & WM_PATHNAME) && t_ch == '/'))
-                               return WM_NOMATCH;
-                       continue;
-               }
-       }
-
-       return *text ? WM_NOMATCH : WM_MATCH;
-}
-
-/* Match the "pattern" against the "text" string. */
-static int wildmatch(const char *pattern, const char *text, unsigned int flags)
-{
-       // local modification: move WM_CASEFOLD here
-       if (ignore_case)
-               flags |= WM_CASEFOLD;
-
-       return dowild((const uchar*)pattern, (const uchar*)text, flags);
-}
-
-// Copied from dir.h
-
-#define PATTERN_FLAG_NODIR 1
-#define PATTERN_FLAG_ENDSWITH 4
-#define PATTERN_FLAG_MUSTBEDIR 8
-#define PATTERN_FLAG_NEGATIVE 16
-
-// Copied from dir.c
-
-static int fspathncmp(const char *a, const char *b, size_t count)
-{
-       return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
-}
-
-static int simple_length(const char *match)
-{
-       int len = -1;
-
-       for (;;) {
-               unsigned char c = *match++;
-               len++;
-               if (c == '\0' || is_glob_special(c))
-                       return len;
-       }
-}
-
-static int no_wildcard(const char *string)
-{
-       return string[simple_length(string)] == '\0';
-}
-
-static void parse_path_pattern(const char **pattern,
-                              int *patternlen,
-                              unsigned *flags,
-                              int *nowildcardlen)
-{
-       const char *p = *pattern;
-       size_t i, len;
-
-       *flags = 0;
-       if (*p == '!') {
-               *flags |= PATTERN_FLAG_NEGATIVE;
-               p++;
-       }
-       len = strlen(p);
-       if (len && p[len - 1] == '/') {
-               len--;
-               *flags |= PATTERN_FLAG_MUSTBEDIR;
-       }
-       for (i = 0; i < len; i++) {
-               if (p[i] == '/')
-                       break;
-       }
-       if (i == len)
-               *flags |= PATTERN_FLAG_NODIR;
-       *nowildcardlen = simple_length(p);
-       /*
-        * we should have excluded the trailing slash from 'p' too,
-        * but that's one more allocation. Instead just make sure
-        * nowildcardlen does not exceed real patternlen
-        */
-       if (*nowildcardlen > len)
-               *nowildcardlen = len;
-       if (*p == '*' && no_wildcard(p + 1))
-               *flags |= PATTERN_FLAG_ENDSWITH;
-       *pattern = p;
-       *patternlen = len;
-}
-
-static void trim_trailing_spaces(char *buf)
-{
-       char *p, *last_space = NULL;
-
-       for (p = buf; *p; p++)
-               switch (*p) {
-               case ' ':
-                       if (!last_space)
-                               last_space = p;
-                       break;
-               case '\\':
-                       p++;
-                       if (!*p)
-                               return;
-                       /* fallthrough */
-               default:
-                       last_space = NULL;
-               }
-
-       if (last_space)
-               *last_space = '\0';
-}
-
-static int match_basename(const char *basename, int basenamelen,
-                         const char *pattern, int prefix, int patternlen,
-                         unsigned flags)
-{
-       if (prefix == patternlen) {
-               if (patternlen == basenamelen &&
-                   !fspathncmp(pattern, basename, basenamelen))
-                       return 1;
-       } else if (flags & PATTERN_FLAG_ENDSWITH) {
-               /* "*literal" matching against "fooliteral" */
-               if (patternlen - 1 <= basenamelen &&
-                   !fspathncmp(pattern + 1,
-                                  basename + basenamelen - (patternlen - 1),
-                                  patternlen - 1))
-                       return 1;
-       } else {
-               // local modification: call wildmatch() directly
-               if (!wildmatch(pattern, basename, flags))
-                       return 1;
-       }
-       return 0;
-}
-
-static int match_pathname(const char *pathname, int pathlen,
-                         const char *base, int baselen,
-                         const char *pattern, int prefix, int patternlen)
-{
-       // local modification: remove local variables
-
-       /*
-        * match with FNM_PATHNAME; the pattern has base implicitly
-        * in front of it.
-        */
-       if (*pattern == '/') {
-               pattern++;
-               patternlen--;
-               prefix--;
-       }
-
-       /*
-        * baselen does not count the trailing slash. base[] may or
-        * may not end with a trailing slash though.
-        */
-       if (pathlen < baselen + 1 ||
-           (baselen && pathname[baselen] != '/') ||
-           fspathncmp(pathname, base, baselen))
-               return 0;
-
-       // local modification: simplified because always baselen > 0
-       pathname += baselen + 1;
-       pathlen -= baselen + 1;
-
-       if (prefix) {
-               /*
-                * if the non-wildcard part is longer than the
-                * remaining pathname, surely it cannot match.
-                */
-               if (prefix > pathlen)
-                       return 0;
-
-               if (fspathncmp(pattern, pathname, prefix))
-                       return 0;
-               pattern += prefix;
-               patternlen -= prefix;
-               pathname += prefix;
-               pathlen -= prefix;
-
-               /*
-                * If the whole pattern did not have a wildcard,
-                * then our prefix match is all we need; we
-                * do not need to call fnmatch at all.
-                */
-               if (!patternlen && !pathlen)
-                       return 1;
-       }
-
-       // local modification: call wildmatch() directly
-       return !wildmatch(pattern, pathname, WM_PATHNAME);
-}
-
-// Copied from git/utf8.c
-
-static const char utf8_bom[] = "\357\273\277";
-
-//----------------------------(IMPORT FROM GIT END)----------------------------
-
-struct pattern {
-       unsigned int flags;
-       int nowildcardlen;
-       int patternlen;
-       int dirlen;
-       char pattern[];
-};
-
-static struct pattern **pattern_list;
-static int nr_patterns, alloced_patterns;
-
-// Remember the number of patterns at each directory level
-static int *nr_patterns_at;
-// Track the current/max directory level;
-static int depth, max_depth;
-static bool debug_on;
-static FILE *out_fp, *stat_fp;
-static char *prefix = "";
-static char *progname;
-
-static void __attribute__((noreturn)) perror_exit(const char *s)
-{
-       perror(s);
-
-       exit(EXIT_FAILURE);
-}
-
-static void __attribute__((noreturn)) error_exit(const char *fmt, ...)
-{
-       va_list args;
-
-       fprintf(stderr, "%s: error: ", progname);
-
-       va_start(args, fmt);
-       vfprintf(stderr, fmt, args);
-       va_end(args);
-
-       exit(EXIT_FAILURE);
-}
-
-static void debug(const char *fmt, ...)
-{
-       va_list args;
-       int i;
-
-       if (!debug_on)
-               return;
-
-       fprintf(stderr, "[DEBUG] ");
-
-       for (i = 0; i < depth * 2; i++)
-               fputc(' ', stderr);
-
-       va_start(args, fmt);
-       vfprintf(stderr, fmt, args);
-       va_end(args);
-}
-
-static void *xrealloc(void *ptr, size_t size)
-{
-       ptr = realloc(ptr, size);
-       if (!ptr)
-               perror_exit(progname);
-
-       return ptr;
-}
-
-static void *xmalloc(size_t size)
-{
-       return xrealloc(NULL, size);
-}
-
-// similar to last_matching_pattern_from_list() in GIT
-static bool is_ignored(const char *path, int pathlen, int dirlen, bool is_dir)
-{
-       int i;
-
-       // Search in the reverse order because the last matching pattern wins.
-       for (i = nr_patterns - 1; i >= 0; i--) {
-               struct pattern *p = pattern_list[i];
-               unsigned int flags = p->flags;
-               const char *gitignore_dir = p->pattern + p->patternlen + 1;
-               bool ignored;
-
-               if ((flags & PATTERN_FLAG_MUSTBEDIR) && !is_dir)
-                       continue;
-
-               if (flags & PATTERN_FLAG_NODIR) {
-                       if (!match_basename(path + dirlen + 1,
-                                           pathlen - dirlen - 1,
-                                           p->pattern,
-                                           p->nowildcardlen,
-                                           p->patternlen,
-                                           p->flags))
-                               continue;
-               } else {
-                       if (!match_pathname(path, pathlen,
-                                           gitignore_dir, p->dirlen,
-                                           p->pattern,
-                                           p->nowildcardlen,
-                                           p->patternlen))
-                               continue;
-               }
-
-               debug("%s: matches %s%s%s (%s/.gitignore)\n", path,
-                     flags & PATTERN_FLAG_NEGATIVE ? "!" : "", p->pattern,
-                     flags & PATTERN_FLAG_MUSTBEDIR ? "/" : "",
-                     gitignore_dir);
-
-               ignored = (flags & PATTERN_FLAG_NEGATIVE) == 0;
-               if (ignored)
-                       debug("Ignore: %s\n", path);
-
-               return ignored;
-       }
-
-       debug("%s: no match\n", path);
-
-       return false;
-}
-
-static void add_pattern(const char *string, const char *dir, int dirlen)
-{
-       struct pattern *p;
-       int patternlen, nowildcardlen;
-       unsigned int flags;
-
-       parse_path_pattern(&string, &patternlen, &flags, &nowildcardlen);
-
-       if (patternlen == 0)
-               return;
-
-       p = xmalloc(sizeof(*p) + patternlen + dirlen + 2);
-
-       memcpy(p->pattern, string, patternlen);
-       p->pattern[patternlen] = 0;
-       memcpy(p->pattern + patternlen + 1, dir, dirlen);
-       p->pattern[patternlen + 1 + dirlen] = 0;
-
-       p->patternlen = patternlen;
-       p->nowildcardlen = nowildcardlen;
-       p->dirlen = dirlen;
-       p->flags = flags;
-
-       debug("Add pattern: %s%s%s\n",
-             flags & PATTERN_FLAG_NEGATIVE ? "!" : "", p->pattern,
-             flags & PATTERN_FLAG_MUSTBEDIR ? "/" : "");
-
-       if (nr_patterns >= alloced_patterns) {
-               alloced_patterns += 128;
-               pattern_list = xrealloc(pattern_list,
-                                       sizeof(*pattern_list) * alloced_patterns);
-       }
-
-       pattern_list[nr_patterns++] = p;
-}
-
-// similar to add_patterns_from_buffer() in GIT
-static void add_patterns_from_gitignore(const char *dir, int dirlen)
-{
-       struct stat st;
-       char path[PATH_MAX], *buf, *entry;
-       size_t size;
-       int fd, pathlen, i;
-
-       pathlen = snprintf(path, sizeof(path), "%s/.gitignore", dir);
-       if (pathlen >= sizeof(path))
-               error_exit("%s: too long path was truncated\n", path);
-
-       fd = open(path, O_RDONLY | O_NOFOLLOW);
-       if (fd < 0) {
-               if (errno != ENOENT)
-                       return perror_exit(path);
-               return;
-       }
-
-       if (fstat(fd, &st) < 0)
-               perror_exit(path);
-
-       size = st.st_size;
-
-       buf = xmalloc(size + 1);
-       if (read(fd, buf, st.st_size) != st.st_size)
-               perror_exit(path);
-
-       buf[st.st_size] = '\n';
-       if (close(fd))
-               perror_exit(path);
-
-       debug("Parse %s\n", path);
-
-       entry = buf;
-
-       // skip utf8 bom
-       if (!strncmp(entry, utf8_bom, strlen(utf8_bom)))
-               entry += strlen(utf8_bom);
-
-       for (i = entry - buf; i < size; i++) {
-               if (buf[i] == '\n') {
-                       if (entry != buf + i && entry[0] != '#') {
-                               buf[i - (i && buf[i-1] == '\r')] = 0;
-                               trim_trailing_spaces(entry);
-                               add_pattern(entry, dir, dirlen);
-                       }
-                       entry = buf + i + 1;
-               }
-       }
-
-       free(buf);
-}
-
-// Save the current number of patterns and increment the depth
-static void increment_depth(void)
-{
-       if (depth >= max_depth) {
-               max_depth += 1;
-               nr_patterns_at = xrealloc(nr_patterns_at,
-                                         sizeof(*nr_patterns_at) * max_depth);
-       }
-
-       nr_patterns_at[depth] = nr_patterns;
-       depth++;
-}
-
-// Decrement the depth, and free up the patterns of this directory level.
-static void decrement_depth(void)
-{
-       depth--;
-       assert(depth >= 0);
-
-       while (nr_patterns > nr_patterns_at[depth])
-               free(pattern_list[--nr_patterns]);
-}
-
-static void print_path(const char *path)
-{
-       // The path always starts with "./"
-       assert(strlen(path) >= 2);
-
-       // Replace the root directory with a preferred prefix.
-       // This is useful for the tar command.
-       fprintf(out_fp, "%s%s\n", prefix, path + 2);
-}
-
-static void print_stat(const char *path, struct stat *st)
-{
-       if (!stat_fp)
-               return;
-
-       if (!S_ISREG(st->st_mode) && !S_ISLNK(st->st_mode))
-               return;
-
-       assert(strlen(path) >= 2);
-
-       fprintf(stat_fp, "%c %9ld %10ld %s\n",
-               S_ISLNK(st->st_mode) ? 'l' : '-',
-               st->st_size, st->st_mtim.tv_sec, path + 2);
-}
-
-// Traverse the entire directory tree, parsing .gitignore files.
-// Print file paths that are not tracked by git.
-//
-// Return true if all files under the directory are ignored, false otherwise.
-static bool traverse_directory(const char *dir, int dirlen)
-{
-       bool all_ignored = true;
-       DIR *dirp;
-
-       debug("Enter[%d]: %s\n", depth, dir);
-       increment_depth();
-
-       add_patterns_from_gitignore(dir, dirlen);
-
-       dirp = opendir(dir);
-       if (!dirp)
-               perror_exit(dir);
-
-       while (1) {
-               struct dirent *d;
-               struct stat st;
-               char path[PATH_MAX];
-               int pathlen;
-               bool ignored;
-
-               errno = 0;
-               d = readdir(dirp);
-               if (!d) {
-                       if (errno)
-                               perror_exit(dir);
-                       break;
-               }
-
-               if (!strcmp(d->d_name, "..") || !strcmp(d->d_name, "."))
-                       continue;
-
-               pathlen = snprintf(path, sizeof(path), "%s/%s", dir, d->d_name);
-               if (pathlen >= sizeof(path))
-                       error_exit("%s: too long path was truncated\n", path);
-
-               if (lstat(path, &st) < 0)
-                       perror_exit(path);
-
-               if ((!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) ||
-                   is_ignored(path, pathlen, dirlen, S_ISDIR(st.st_mode))) {
-                       ignored = true;
-               } else {
-                       if (S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
-                               // If all the files in a directory are ignored,
-                               // let's ignore that directory as well. This
-                               // will avoid empty directories in the tarball.
-                               ignored = traverse_directory(path, pathlen);
-                       else
-                               ignored = false;
-               }
-
-               if (ignored) {
-                       print_path(path);
-               } else {
-                       print_stat(path, &st);
-                       all_ignored = false;
-               }
-       }
-
-       if (closedir(dirp))
-               perror_exit(dir);
-
-       decrement_depth();
-       debug("Leave[%d]: %s\n", depth, dir);
-
-       return all_ignored;
-}
-
-static void usage(void)
-{
-       fprintf(stderr,
-               "usage: %s [options]\n"
-               "\n"
-               "Show files that are ignored by git\n"
-               "\n"
-               "options:\n"
-               "  -d, --debug                  print debug messages to stderr\n"
-               "  -e, --exclude PATTERN        add the given exclude pattern\n"
-               "  -h, --help                   show this help message and exit\n"
-               "  -i, --ignore-case            Ignore case differences between the patterns and the files\n"
-               "  -o, --output FILE            output the ignored files to a file (default: '-', i.e. stdout)\n"
-               "  -p, --prefix PREFIX          prefix added to each path (default: empty string)\n"
-               "  -r, --rootdir DIR            root of the source tree (default: current working directory)\n"
-               "  -s, --stat FILE              output the file stat of non-ignored files to a file\n",
-               progname);
-}
-
-static void open_output(const char *pathname, FILE **fp)
-{
-       if (strcmp(pathname, "-")) {
-               *fp = fopen(pathname, "w");
-               if (!*fp)
-                       perror_exit(pathname);
-       } else {
-               *fp = stdout;
-       }
-}
-
-static void close_output(const char *pathname, FILE *fp)
-{
-       fflush(fp);
-
-       if (ferror(fp))
-               error_exit("not all data was written to the output\n");
-
-       if (fclose(fp))
-               perror_exit(pathname);
-}
-
-int main(int argc, char *argv[])
-{
-       const char *output = "-";
-       const char *rootdir = ".";
-       const char *stat = NULL;
-
-       progname = strrchr(argv[0], '/');
-       if (progname)
-               progname++;
-       else
-               progname = argv[0];
-
-       while (1) {
-               static struct option long_options[] = {
-                       {"debug",       no_argument,       NULL, 'd'},
-                       {"help",        no_argument,       NULL, 'h'},
-                       {"ignore-case", no_argument,       NULL, 'i'},
-                       {"output",      required_argument, NULL, 'o'},
-                       {"prefix",      required_argument, NULL, 'p'},
-                       {"rootdir",     required_argument, NULL, 'r'},
-                       {"stat",        required_argument, NULL, 's'},
-                       {"exclude",     required_argument, NULL, 'x'},
-                       {},
-               };
-
-               int c = getopt_long(argc, argv, "dhino:p:r:s:x:", long_options, NULL);
-
-               if (c == -1)
-                       break;
-
-               switch (c) {
-               case 'd':
-                       debug_on = true;
-                       break;
-               case 'h':
-                       usage();
-                       exit(0);
-               case 'i':
-                       ignore_case = true;
-                       break;
-               case 'o':
-                       output = optarg;
-                       break;
-               case 'p':
-                       prefix = optarg;
-                       break;
-               case 'r':
-                       rootdir = optarg;
-                       break;
-               case 's':
-                       stat = optarg;
-                       break;
-               case 'x':
-                       add_pattern(optarg, ".", strlen("."));
-                       break;
-               case '?':
-                       usage();
-                       /* fallthrough */
-               default:
-                       exit(EXIT_FAILURE);
-               }
-       }
-
-       open_output(output, &out_fp);
-       if (stat && stat[0])
-               open_output(stat, &stat_fp);
-
-       if (chdir(rootdir))
-               perror_exit(rootdir);
-
-       add_pattern(".git/", ".", strlen("."));
-
-       if (traverse_directory(".", strlen(".")))
-               print_path("./");
-
-       assert(depth == 0);
-
-       while (nr_patterns > 0)
-               free(pattern_list[--nr_patterns]);
-       free(pattern_list);
-       free(nr_patterns_at);
-
-       close_output(output, out_fp);
-       if (stat_fp)
-               close_output(stat, stat_fp);
-
-       return 0;
-}
index efff8078e39581349f72fd8fbe6e2c062e36d372..9466b6a2abae46c41ec1d4d4e06eb9001dc79608 100644 (file)
@@ -1733,7 +1733,7 @@ static void extract_crcs_for_object(const char *object, struct module *mod)
                if (!isdigit(*p))
                        continue;       /* skip this line */
 
-               crc = strtol(p, &p, 0);
+               crc = strtoul(p, &p, 0);
                if (*p != '\n')
                        continue;       /* skip this line */
 
index ff5e7d8e380bba654657bf43dc544a571fd90e28..7b23f52c70c5fe33145bc4838dd52e95973b3a14 100755 (executable)
@@ -51,8 +51,118 @@ create_package() {
        dpkg-deb $dpkg_deb_opts ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" ..
 }
 
-deploy_kernel_headers () {
+install_linux_image () {
        pdir=$1
+       pname=$2
+
+       rm -rf ${pdir}
+
+       # Only some architectures with OF support have this target
+       if is_enabled CONFIG_OF_EARLY_FLATTREE && [ -d "${srctree}/arch/${SRCARCH}/boot/dts" ]; then
+               ${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install
+       fi
+
+       if is_enabled CONFIG_MODULES; then
+               ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install
+               rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build"
+               rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source"
+               if [ "${SRCARCH}" = um ] ; then
+                       mkdir -p "${pdir}/usr/lib/uml/modules"
+                       mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}"
+               fi
+       fi
+
+       # Install the kernel
+       if [ "${ARCH}" = um ] ; then
+               mkdir -p "${pdir}/usr/bin" "${pdir}/usr/share/doc/${pname}"
+               cp System.map "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}/System.map"
+               cp ${KCONFIG_CONFIG} "${pdir}/usr/share/doc/${pname}/config"
+               gzip "${pdir}/usr/share/doc/${pname}/config"
+       else
+               mkdir -p "${pdir}/boot"
+               cp System.map "${pdir}/boot/System.map-${KERNELRELEASE}"
+               cp ${KCONFIG_CONFIG} "${pdir}/boot/config-${KERNELRELEASE}"
+       fi
+
+       # Not all arches have the same installed path in debian
+       # XXX: have each arch Makefile export a variable of the canonical image install
+       # path instead
+       case "${SRCARCH}" in
+       um)
+               installed_image_path="usr/bin/linux-${KERNELRELEASE}";;
+       parisc|mips|powerpc)
+               installed_image_path="boot/vmlinux-${KERNELRELEASE}";;
+       *)
+               installed_image_path="boot/vmlinuz-${KERNELRELEASE}";;
+       esac
+       cp "$(${MAKE} -s -f ${srctree}/Makefile image_name)" "${pdir}/${installed_image_path}"
+
+       # Install the maintainer scripts
+       # Note: hook scripts under /etc/kernel are also executed by official Debian
+       # kernel packages, as well as kernel packages built using make-kpkg.
+       # make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and
+       # so do we; recent versions of dracut and initramfs-tools will obey this.
+       debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
+       for script in postinst postrm preinst prerm; do
+               mkdir -p "${pdir}${debhookdir}/${script}.d"
+
+               mkdir -p "${pdir}/DEBIAN"
+               cat <<-EOF > "${pdir}/DEBIAN/${script}"
+
+               #!/bin/sh
+
+               set -e
+
+               # Pass maintainer script parameters to hook scripts
+               export DEB_MAINT_PARAMS="\$*"
+
+               # Tell initramfs builder whether it's wanted
+               export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No)
+
+               test -d ${debhookdir}/${script}.d && run-parts --arg="${KERNELRELEASE}" --arg="/${installed_image_path}" ${debhookdir}/${script}.d
+               exit 0
+               EOF
+               chmod 755 "${pdir}/DEBIAN/${script}"
+       done
+}
+
+install_linux_image_dbg () {
+       pdir=$1
+       image_pdir=$2
+
+       rm -rf ${pdir}
+
+       for module in $(find ${image_pdir}/lib/modules/ -name *.ko -printf '%P\n'); do
+               module=lib/modules/${module}
+               mkdir -p $(dirname ${pdir}/usr/lib/debug/${module})
+               # only keep debug symbols in the debug file
+               ${OBJCOPY} --only-keep-debug ${image_pdir}/${module} ${pdir}/usr/lib/debug/${module}
+               # strip original module from debug symbols
+               ${OBJCOPY} --strip-debug ${image_pdir}/${module}
+               # then add a link to those
+               ${OBJCOPY} --add-gnu-debuglink=${pdir}/usr/lib/debug/${module} ${image_pdir}/${module}
+       done
+
+       # re-sign stripped modules
+       if is_enabled CONFIG_MODULE_SIG_ALL; then
+               ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${image_pdir}" modules_sign
+       fi
+
+       # Build debug package
+       # Different tools want the image in different locations
+       # perf
+       mkdir -p ${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/
+       cp vmlinux ${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/
+       # systemtap
+       mkdir -p ${pdir}/usr/lib/debug/boot/
+       ln -s ../lib/modules/${KERNELRELEASE}/vmlinux ${pdir}/usr/lib/debug/boot/vmlinux-${KERNELRELEASE}
+       # kdump-tools
+       ln -s lib/modules/${KERNELRELEASE}/vmlinux ${pdir}/usr/lib/debug/vmlinux-${KERNELRELEASE}
+}
+
+install_kernel_headers () {
+       pdir=$1
+       version=$2
 
        rm -rf $pdir
 
@@ -89,7 +199,7 @@ deploy_kernel_headers () {
        ln -s /usr/src/linux-headers-$version $pdir/lib/modules/$version/build
 }
 
-deploy_libc_headers () {
+install_libc_headers () {
        pdir=$1
 
        rm -rf $pdir
@@ -104,132 +214,38 @@ deploy_libc_headers () {
        mv $pdir/usr/include/asm $pdir/usr/include/$host_arch/
 }
 
-version=$KERNELRELEASE
-tmpdir=debian/linux-image
-dbg_dir=debian/linux-image-dbg
-packagename=linux-image-$version
-dbg_packagename=$packagename-dbg
-
-if [ "$ARCH" = "um" ] ; then
-       packagename=user-mode-linux-$version
-fi
-
-# Not all arches have the same installed path in debian
-# XXX: have each arch Makefile export a variable of the canonical image install
-# path instead
-case $ARCH in
-um)
-       installed_image_path="usr/bin/linux-$version"
-       ;;
-parisc|mips|powerpc)
-       installed_image_path="boot/vmlinux-$version"
-       ;;
-*)
-       installed_image_path="boot/vmlinuz-$version"
-esac
-
-BUILD_DEBUG=$(if_enabled_echo CONFIG_DEBUG_INFO Yes)
-
-# Setup the directory structure
-rm -rf "$tmpdir" "$dbg_dir" debian/files
-mkdir -m 755 -p "$tmpdir/DEBIAN"
-mkdir -p "$tmpdir/lib" "$tmpdir/boot"
-
-# Install the kernel
-if [ "$ARCH" = "um" ] ; then
-       mkdir -p "$tmpdir/usr/lib/uml/modules/$version" "$tmpdir/usr/bin" "$tmpdir/usr/share/doc/$packagename"
-       cp System.map "$tmpdir/usr/lib/uml/modules/$version/System.map"
-       cp $KCONFIG_CONFIG "$tmpdir/usr/share/doc/$packagename/config"
-       gzip "$tmpdir/usr/share/doc/$packagename/config"
-else
-       cp System.map "$tmpdir/boot/System.map-$version"
-       cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version"
-fi
-cp "$($MAKE -s -f $srctree/Makefile image_name)" "$tmpdir/$installed_image_path"
-
-if is_enabled CONFIG_OF_EARLY_FLATTREE; then
-       # Only some architectures with OF support have this target
-       if [ -d "${srctree}/arch/$SRCARCH/boot/dts" ]; then
-               $MAKE -f $srctree/Makefile INSTALL_DTBS_PATH="$tmpdir/usr/lib/$packagename" dtbs_install
-       fi
-fi
-
-if is_enabled CONFIG_MODULES; then
-       INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_install
-       rm -f "$tmpdir/lib/modules/$version/build"
-       rm -f "$tmpdir/lib/modules/$version/source"
-       if [ "$ARCH" = "um" ] ; then
-               mv "$tmpdir/lib/modules/$version"/* "$tmpdir/usr/lib/uml/modules/$version/"
-               rmdir "$tmpdir/lib/modules/$version"
-       fi
-       if [ -n "$BUILD_DEBUG" ] ; then
-               for module in $(find $tmpdir/lib/modules/ -name *.ko -printf '%P\n'); do
-                       module=lib/modules/$module
-                       mkdir -p $(dirname $dbg_dir/usr/lib/debug/$module)
-                       # only keep debug symbols in the debug file
-                       $OBJCOPY --only-keep-debug $tmpdir/$module $dbg_dir/usr/lib/debug/$module
-                       # strip original module from debug symbols
-                       $OBJCOPY --strip-debug $tmpdir/$module
-                       # then add a link to those
-                       $OBJCOPY --add-gnu-debuglink=$dbg_dir/usr/lib/debug/$module $tmpdir/$module
-               done
-
-               # resign stripped modules
-               if is_enabled CONFIG_MODULE_SIG_ALL; then
-                       INSTALL_MOD_PATH="$tmpdir" $MAKE -f $srctree/Makefile modules_sign
-               fi
-       fi
-fi
-
-# Install the maintainer scripts
-# Note: hook scripts under /etc/kernel are also executed by official Debian
-# kernel packages, as well as kernel packages built using make-kpkg.
-# make-kpkg sets $INITRD to indicate whether an initramfs is wanted, and
-# so do we; recent versions of dracut and initramfs-tools will obey this.
-debhookdir=${KDEB_HOOKDIR:-/etc/kernel}
-for script in postinst postrm preinst prerm ; do
-       mkdir -p "$tmpdir$debhookdir/$script.d"
-       cat <<EOF > "$tmpdir/DEBIAN/$script"
-#!/bin/sh
-
-set -e
-
-# Pass maintainer script parameters to hook scripts
-export DEB_MAINT_PARAMS="\$*"
-
-# Tell initramfs builder whether it's wanted
-export INITRD=$(if_enabled_echo CONFIG_BLK_DEV_INITRD Yes No)
-
-test -d $debhookdir/$script.d && run-parts --arg="$version" --arg="/$installed_image_path" $debhookdir/$script.d
-exit 0
-EOF
-       chmod 755 "$tmpdir/DEBIAN/$script"
+rm -f debian/files
+
+packages_enabled=$(dh_listpackages)
+
+for package in ${packages_enabled}
+do
+       case ${package} in
+       *-dbg)
+               # This must be done after linux-image, that is, we expect the
+               # debug package appears after linux-image in debian/control.
+               install_linux_image_dbg debian/linux-image-dbg debian/linux-image;;
+       linux-image-*|user-mode-linux-*)
+               install_linux_image debian/linux-image ${package};;
+       linux-libc-dev)
+               install_libc_headers debian/linux-libc-dev;;
+       linux-headers-*)
+               install_kernel_headers debian/linux-headers ${package#linux-headers-};;
+       esac
 done
 
-if [ "$ARCH" != "um" ]; then
-       if is_enabled CONFIG_MODULES; then
-               deploy_kernel_headers debian/linux-headers
-               create_package linux-headers-$version debian/linux-headers
-       fi
-
-       deploy_libc_headers debian/linux-libc-dev
-       create_package linux-libc-dev debian/linux-libc-dev
-fi
-
-create_package "$packagename" "$tmpdir"
-
-if [ -n "$BUILD_DEBUG" ] ; then
-       # Build debug package
-       # Different tools want the image in different locations
-       # perf
-       mkdir -p $dbg_dir/usr/lib/debug/lib/modules/$version/
-       cp vmlinux $dbg_dir/usr/lib/debug/lib/modules/$version/
-       # systemtap
-       mkdir -p $dbg_dir/usr/lib/debug/boot/
-       ln -s ../lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/boot/vmlinux-$version
-       # kdump-tools
-       ln -s lib/modules/$version/vmlinux $dbg_dir/usr/lib/debug/vmlinux-$version
-       create_package "$dbg_packagename" "$dbg_dir"
-fi
+for package in ${packages_enabled}
+do
+       case ${package} in
+       *-dbg)
+               create_package ${package} debian/linux-image-dbg;;
+       linux-image-*|user-mode-linux-*)
+               create_package ${package} debian/linux-image;;
+       linux-libc-dev)
+               create_package ${package} debian/linux-libc-dev;;
+       linux-headers-*)
+               create_package ${package} debian/linux-headers;;
+       esac
+done
 
 exit 0
index b079b0d121d47359d447a83d87822072d619da28..7950eff01781a306681985ce5a0a46743c411af5 100755 (executable)
@@ -1,16 +1,14 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0-only
 
-# Set up CROSS_COMPILE if we are cross-compiling, but not called from the
-# kernel toplevel Makefile
-if [ -z "${CROSS_COMPILE}${cross_compiling}" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then
+# Set up CROSS_COMPILE if not defined yet
+if [ "${CROSS_COMPILE+set}" != "set" -a "${DEB_HOST_ARCH}" != "${DEB_BUILD_ARCH}" ]; then
        echo CROSS_COMPILE=${DEB_HOST_GNU_TYPE}-
 fi
 
 version=$(dpkg-parsechangelog -S Version)
-version_upstream="${version%-*}"
-debian_revision="${version#${version_upstream}}"
-debian_revision="${debian_revision#*-}"
+debian_revision="${version##*-}"
 
-echo KERNELRELEASE=${version_upstream}
-echo KBUILD_BUILD_VERSION=${debian_revision}
+if [ "${version}" != "${debian_revision}" ]; then
+       echo KBUILD_BUILD_VERSION=${debian_revision}
+fi
diff --git a/scripts/package/gen-diff-patch b/scripts/package/gen-diff-patch
new file mode 100755 (executable)
index 0000000..8a98b7b
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-only
+
+diff_patch=$1
+
+mkdir -p "$(dirname "${diff_patch}")"
+
+git -C "${srctree:-.}" diff HEAD > "${diff_patch}"
+
+if [ ! -s "${diff_patch}" ] ||
+   [ -z "$(git -C "${srctree:-.}" ls-files --other --exclude-standard | head -n1)" ]; then
+       exit
+fi
+
+# The source tarball, which is generated by 'git archive', contains everything
+# you committed in the repository. If you have local diff ('git diff HEAD'),
+# it will go into ${diff_patch}. If untracked files are remaining, the resulting
+# source package may not be correct.
+#
+# Examples:
+#  - You modified a source file to add #include "new-header.h"
+#    but forgot to add new-header.h
+#  - You modified a Makefile to add 'obj-$(CONFIG_FOO) += new-dirver.o'
+#    but you forgot to add new-driver.c
+#
+# You need to commit them, or at least stage them by 'git add'.
+#
+# This script does not take care of untracked files because doing so would
+# introduce additional complexity. Instead, print a warning message here if
+# untracked files are found.
+# If all untracked files are just garbage, you can ignore this warning.
+echo >&2 "============================ WARNING ============================"
+echo >&2 "Your working tree has diff from HEAD, and also untracked file(s)."
+echo >&2 "Please make sure you did 'git add' for all new files you need in"
+echo >&2 "the source package."
+echo >&2 "================================================================="
index f74380036bb54e0b107e49da9bdaca8c0b89cb04..74b83c9ae0a843bb77cf5c2b51e3b32e3ec715c1 100755 (executable)
@@ -84,14 +84,73 @@ set_debarch() {
        fi
 }
 
+# Create debian/source/ if it is a source package build
+gen_source ()
+{
+       mkdir -p debian/source
+
+       echo "3.0 (quilt)" > debian/source/format
+
+       {
+               echo "diff-ignore"
+               echo "extend-diff-ignore = .*"
+       } > debian/source/local-options
+
+       # Add .config as a patch
+       mkdir -p debian/patches
+       {
+               echo "Subject: Add .config"
+               echo "Author: ${maintainer}"
+               echo
+               echo "--- /dev/null"
+               echo "+++ linux/.config"
+               diff -u /dev/null "${KCONFIG_CONFIG}" | tail -n +3
+       } > debian/patches/config.patch
+       echo config.patch > debian/patches/series
+
+       "${srctree}/scripts/package/gen-diff-patch" debian/patches/diff.patch
+       if [ -s debian/patches/diff.patch ]; then
+               sed -i "
+                       1iSubject: Add local diff
+                       1iAuthor: ${maintainer}
+                       1i
+               " debian/patches/diff.patch
+
+               echo diff.patch >> debian/patches/series
+       else
+               rm -f debian/patches/diff.patch
+       fi
+}
+
 rm -rf debian
+mkdir debian
+
+email=${DEBEMAIL-$EMAIL}
+
+# use email string directly if it contains <email>
+if echo "${email}" | grep -q '<.*>'; then
+       maintainer=${email}
+else
+       # or construct the maintainer string
+       user=${KBUILD_BUILD_USER-$(id -nu)}
+       name=${DEBFULLNAME-${user}}
+       if [ -z "${email}" ]; then
+               buildhost=${KBUILD_BUILD_HOST-$(hostname -f 2>/dev/null || hostname)}
+               email="${user}@${buildhost}"
+       fi
+       maintainer="${name} <${email}>"
+fi
+
+if [ "$1" = --need-source ]; then
+       gen_source
+fi
 
 # Some variables and settings used throughout the script
 version=$KERNELRELEASE
 if [ -n "$KDEB_PKGVERSION" ]; then
        packageversion=$KDEB_PKGVERSION
 else
-       packageversion=$version-$($srctree/init/build-version)
+       packageversion=$(${srctree}/scripts/setlocalversion --no-local ${srctree})-$($srctree/init/build-version)
 fi
 sourcename=${KDEB_SOURCENAME:-linux-upstream}
 
@@ -104,22 +163,6 @@ fi
 debarch=
 set_debarch
 
-email=${DEBEMAIL-$EMAIL}
-
-# use email string directly if it contains <email>
-if echo $email | grep -q '<.*>'; then
-       maintainer=$email
-else
-       # or construct the maintainer string
-       user=${KBUILD_BUILD_USER-$(id -nu)}
-       name=${DEBFULLNAME-$user}
-       if [ -z "$email" ]; then
-               buildhost=${KBUILD_BUILD_HOST-$(hostname -f 2>/dev/null || hostname)}
-               email="$user@$buildhost"
-       fi
-       maintainer="$name <$email>"
-fi
-
 # Try to determine distribution
 if [ -n "$KDEB_CHANGELOG_DIST" ]; then
         distribution=$KDEB_CHANGELOG_DIST
@@ -132,26 +175,6 @@ else
         echo >&2 "Install lsb-release or set \$KDEB_CHANGELOG_DIST explicitly"
 fi
 
-mkdir -p debian/source/
-echo "3.0 (quilt)" > debian/source/format
-
-{
-       echo "diff-ignore"
-       echo "extend-diff-ignore = .*"
-} > debian/source/local-options
-
-# Add .config as a patch
-mkdir -p debian/patches
-{
-       echo "Subject: Add .config"
-       echo "Author: ${maintainer}"
-       echo
-       echo "--- /dev/null"
-       echo "+++ linux/.config"
-       diff -u /dev/null "${KCONFIG_CONFIG}" | tail -n +3
-} > debian/patches/config
-echo config > debian/patches/series
-
 echo $debarch > debian/arch
 extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev:native)"
 extra_build_depends="$extra_build_depends, $(if_enabled_echo CONFIG_SYSTEM_TRUSTED_KEYRING libssl-dev:native)"
@@ -167,7 +190,7 @@ EOF
 
 # Generate copyright file
 cat <<EOF > debian/copyright
-This is a packacked upstream version of the Linux kernel.
+This is a packaged upstream version of the Linux kernel.
 
 The sources may be found at most Linux archive sites, including:
 https://www.kernel.org/pub/linux/kernel
@@ -192,7 +215,7 @@ Section: kernel
 Priority: optional
 Maintainer: $maintainer
 Rules-Requires-Root: no
-Build-Depends: bc, rsync, kmod, cpio, bison, flex $extra_build_depends
+Build-Depends: bc, debhelper, rsync, kmod, cpio, bison, flex $extra_build_depends
 Homepage: https://www.kernel.org/
 
 Package: $packagename-$version
@@ -200,6 +223,10 @@ Architecture: $debarch
 Description: Linux kernel, version $version
  This package contains the Linux kernel, modules and corresponding other
  files, version: $version.
+EOF
+
+if [ "${SRCARCH}" != um ]; then
+cat <<EOF >> debian/control
 
 Package: linux-libc-dev
 Section: devel
@@ -222,6 +249,7 @@ Description: Linux kernel headers for $version on $debarch
  This is useful for people who need to build external modules
 EOF
 fi
+fi
 
 if is_enabled CONFIG_DEBUG_INFO; then
 cat <<EOF >> debian/control
@@ -239,10 +267,12 @@ cat <<EOF > debian/rules
 #!$(command -v $MAKE) -f
 
 srctree ?= .
+KERNELRELEASE = ${KERNELRELEASE}
 
 build-indep:
 build-arch:
        \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} \
+       KERNELRELEASE=\$(KERNELRELEASE) \
        \$(shell \$(srctree)/scripts/package/deb-build-option) \
        olddefconfig all
 
@@ -250,7 +280,9 @@ build: build-arch
 
 binary-indep:
 binary-arch: build-arch
-       \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} intdeb-pkg
+       \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} \
+       KERNELRELEASE=\$(KERNELRELEASE) intdeb-pkg
+
 clean:
        rm -rf debian/files debian/linux-*
        \$(MAKE) -f \$(srctree)/Makefile ARCH=${ARCH} clean
index 3c550960dd39554a0cf60f0e6e3fd123a0eafd46..fc8ad3fbc0a95a96717dc8fd21a81c6ca77502b2 100755 (executable)
@@ -15,15 +15,20 @@ if [ "$1" = prebuilt ]; then
        MAKE="$MAKE -f $srctree/Makefile"
 else
        S=
+
+       mkdir -p rpmbuild/SOURCES
+       cp linux.tar.gz rpmbuild/SOURCES
+       cp "${KCONFIG_CONFIG}" rpmbuild/SOURCES/config
+       "${srctree}/scripts/package/gen-diff-patch" rpmbuild/SOURCES/diff.patch
 fi
 
-if grep -q CONFIG_MODULES=y .config; then
+if grep -q CONFIG_MODULES=y include/config/auto.conf; then
        M=
 else
        M=DEL
 fi
 
-if grep -q CONFIG_DRM=y .config; then
+if grep -q CONFIG_DRM=y include/config/auto.conf; then
        PROVIDES=kernel-drm
 fi
 
@@ -48,7 +53,8 @@ sed -e '/^DEL/d' -e 's/^\t*//' <<EOF
        Vendor: The Linux Community
        URL: https://www.kernel.org
 $S     Source0: linux.tar.gz
-$S     Source1: .config
+$S     Source1: config
+$S     Source2: diff.patch
        Provides: $PROVIDES
 $S     BuildRequires: bc binutils bison dwarves
 $S     BuildRequires: (elfutils-libelf-devel or libelf-devel) flex
@@ -85,7 +91,8 @@ $S$M  against the $__KERNELRELEASE kernel package.
 $S$M
 $S     %prep
 $S     %setup -q -n linux
-$S     cp %{SOURCE1} .
+$S     cp %{SOURCE1} .config
+$S     patch -p1 < %{SOURCE2}
 $S
 $S     %build
 $S     $MAKE %{?_smp_mflags} KERNELRELEASE=$KERNELRELEASE KBUILD_BUILD_VERSION=%{release}
index e54839a42d4b49daf5cc3102e93adab36b59ff50..3d3babac82982b4bfec180b402a7f9e557ceafb4 100755 (executable)
 #
 
 usage() {
-       echo "Usage: $0 [srctree]" >&2
+       echo "Usage: $0 [--no-local] [srctree]" >&2
        exit 1
 }
 
+no_local=false
+if test "$1" = "--no-local"; then
+       no_local=true
+       shift
+fi
+
 srctree=.
 if test $# -gt 0; then
        srctree=$1
@@ -26,14 +32,22 @@ fi
 
 scm_version()
 {
-       local short
+       local short=false
+       local no_dirty=false
        local tag
-       short=false
+
+       while [ $# -gt 0 ];
+       do
+               case "$1" in
+               --short)
+                       short=true;;
+               --no-dirty)
+                       no_dirty=true;;
+               esac
+               shift
+       done
 
        cd "$srctree"
-       if test "$1" = "--short"; then
-               short=true
-       fi
 
        if test -n "$(git rev-parse --show-cdup 2>/dev/null)"; then
                return
@@ -75,6 +89,10 @@ scm_version()
                printf '%s%s' -g "$(echo $head | cut -c1-12)"
        fi
 
+       if ${no_dirty}; then
+               return
+       fi
+
        # Check for uncommitted changes.
        # This script must avoid any write attempt to the source tree, which
        # might be read-only.
@@ -110,11 +128,6 @@ collect_files()
        echo "$res"
 }
 
-if ! test -e include/config/auto.conf; then
-       echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2
-       exit 1
-fi
-
 if [ -z "${KERNELVERSION}" ]; then
        echo "KERNELVERSION is not set" >&2
        exit 1
@@ -126,6 +139,16 @@ if test ! "$srctree" -ef .; then
        file_localversion="${file_localversion}$(collect_files "$srctree"/localversion*)"
 fi
 
+if ${no_local}; then
+       echo "${KERNELVERSION}$(scm_version --no-dirty)"
+       exit 0
+fi
+
+if ! test -e include/config/auto.conf; then
+       echo "Error: kernelrelease not valid - run 'make prepare' to update it" >&2
+       exit 1
+fi
+
 # version string from CONFIG_LOCALVERSION
 config_localversion=$(sed -n 's/^CONFIG_LOCALVERSION=\(.*\)$/\1/p' include/config/auto.conf)
 
index e6db09a779b779c4dfebe6910b2338bf7df6c28d..97abeb9b9a194b2710d4636c7977a0eba7d6a518 100644 (file)
@@ -32,11 +32,6 @@ config SECURITY
 
          If you are unsure how to answer this question, answer N.
 
-config SECURITY_WRITABLE_HOOKS
-       depends on SECURITY
-       bool
-       default n
-
 config SECURITYFS
        bool "Enable the securityfs filesystem"
        help
@@ -110,7 +105,7 @@ config INTEL_TXT
          See <https://www.intel.com/technology/security/> for more information
          about Intel(R) TXT.
          See <http://tboot.sourceforge.net> for more information about tboot.
-         See Documentation/x86/intel_txt.rst for a description of how to enable
+         See Documentation/arch/x86/intel_txt.rst for a description of how to enable
          Intel TXT support in a kernel boot.
 
          If you are unsure as to whether this is required, answer N.
@@ -246,15 +241,17 @@ endchoice
 
 config LSM
        string "Ordered list of enabled LSMs"
-       default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
-       default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
-       default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
-       default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC
-       default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf"
+       default "landlock,lockdown,yama,loadpin,safesetid,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK
+       default "landlock,lockdown,yama,loadpin,safesetid,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR
+       default "landlock,lockdown,yama,loadpin,safesetid,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO
+       default "landlock,lockdown,yama,loadpin,safesetid,bpf" if DEFAULT_SECURITY_DAC
+       default "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,bpf"
        help
          A comma-separated list of LSMs, in initialization order.
-         Any LSMs left off this list will be ignored. This can be
-         controlled at boot with the "lsm=" parameter.
+         Any LSMs left off this list, except for those with order
+         LSM_ORDER_FIRST and LSM_ORDER_LAST, which are always enabled
+         if selected in the kernel configuration, will be ignored.
+         This can be controlled at boot with the "lsm=" parameter.
 
          If unsure, leave this as the default.
 
index d6cc4812ca5372749f8be66d00d2614ea2268a2f..cebba4824e60e5b6532664dafab2c33d53ada007 100644 (file)
@@ -1209,13 +1209,13 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb
 /*
  * The cred blob is a pointer to, not an instance of, an aa_label.
  */
-struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes apparmor_blob_sizes __ro_after_init = {
        .lbs_cred = sizeof(struct aa_label *),
        .lbs_file = sizeof(struct aa_file_ctx),
        .lbs_task = sizeof(struct aa_task_ctx),
 };
 
-static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list apparmor_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
        LSM_HOOK_INIT(capget, apparmor_capget),
@@ -1427,7 +1427,7 @@ static const struct kernel_param_ops param_ops_aaintbool = {
        .get = param_get_aaintbool
 };
 /* Boot time disable flag */
-static int apparmor_enabled __lsm_ro_after_init = 1;
+static int apparmor_enabled __ro_after_init = 1;
 module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
 
 static int __init apparmor_enabled_setup(char *str)
index e5971fa74fd748a7650e5eb5c37bd4bf738a0c45..cfaf1d0e6a5f5143af2cbf93c942db65e9c42fbf 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/lsm_hooks.h>
 #include <linux/bpf_lsm.h>
 
-static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = {
        #define LSM_HOOK(RET, DEFAULT, NAME, ...) \
        LSM_HOOK_INIT(NAME, bpf_lsm_##NAME),
        #include <linux/lsm_hook_defs.h>
@@ -22,7 +22,7 @@ static int __init bpf_lsm_init(void)
        return 0;
 }
 
-struct lsm_blob_sizes bpf_lsm_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes bpf_lsm_blob_sizes __ro_after_init = {
        .lbs_inode = sizeof(struct bpf_storage_blob),
        .lbs_task = sizeof(struct bpf_storage_blob),
 };
index 5bb7d1e962772a3929baa2ef39dfa9dbf3b7475f..0b3fc2f3afe77866d3387f206fe6673a6e9ece14 100644 (file)
@@ -1440,7 +1440,7 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
 
 #ifdef CONFIG_SECURITY
 
-static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list capability_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(capable, cap_capable),
        LSM_HOOK_INIT(settime, cap_settime),
        LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
index bef2b9285fb34f8d06d3d04f33c736959f4f771f..7507d14eacc7942f7f50c377dfcbeb9436e0ba0e 100644 (file)
@@ -216,7 +216,7 @@ static void devcgroup_offline(struct cgroup_subsys_state *css)
 }
 
 /*
- * called from kernel/cgroup.c with cgroup_lock() held.
+ * called from kernel/cgroup/cgroup.c with cgroup_lock() held.
  */
 static struct cgroup_subsys_state *
 devcgroup_css_alloc(struct cgroup_subsys_state *parent_css)
index 599429f99f99fdad01e4d5a8182d50ce33b2c2e0..ec6e0d789da1527fe4f7773b9e1963ff2082ab42 100644 (file)
@@ -68,13 +68,34 @@ config INTEGRITY_MACHINE_KEYRING
        depends on INTEGRITY_ASYMMETRIC_KEYS
        depends on SYSTEM_BLACKLIST_KEYRING
        depends on LOAD_UEFI_KEYS
-       depends on !IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
        help
         If set, provide a keyring to which Machine Owner Keys (MOK) may
         be added. This keyring shall contain just MOK keys.  Unlike keys
         in the platform keyring, keys contained in the .machine keyring will
         be trusted within the kernel.
 
+config INTEGRITY_CA_MACHINE_KEYRING
+       bool "Enforce Machine Keyring CA Restrictions"
+       depends on INTEGRITY_MACHINE_KEYRING
+       default n
+       help
+         The .machine keyring can be configured to enforce CA restriction
+         on any key added to it.  By default no restrictions are in place
+         and all Machine Owner Keys (MOK) are added to the machine keyring.
+         If enabled only CA keys are added to the machine keyring, all
+         other MOK keys load into the platform keyring.
+
+config INTEGRITY_CA_MACHINE_KEYRING_MAX
+       bool "Only CA keys without DigitialSignature usage set"
+       depends on INTEGRITY_CA_MACHINE_KEYRING
+       default n
+       help
+         When selected, only load CA keys are loaded into the machine
+         keyring that contain the CA bit set along with the keyCertSign
+         Usage field.  Keys containing the digitialSignature Usage field
+         will not be loaded. The remaining MOK keys are loaded into the
+         .platform keyring.
+
 config LOAD_UEFI_KEYS
        depends on INTEGRITY_PLATFORM_KEYRING
        depends on EFI
index f2193c531f4a461c3fd51f6df13ae7b8d30a6337..6f31ffe23c48886e2636a98efd2de530aa5d63f9 100644 (file)
@@ -132,7 +132,8 @@ int __init integrity_init_keyring(const unsigned int id)
                | KEY_USR_READ | KEY_USR_SEARCH;
 
        if (id == INTEGRITY_KEYRING_PLATFORM ||
-           id == INTEGRITY_KEYRING_MACHINE) {
+           (id == INTEGRITY_KEYRING_MACHINE &&
+           !IS_ENABLED(CONFIG_INTEGRITY_CA_MACHINE_KEYRING))) {
                restriction = NULL;
                goto out;
        }
@@ -144,7 +145,10 @@ int __init integrity_init_keyring(const unsigned int id)
        if (!restriction)
                return -ENOMEM;
 
-       restriction->check = restrict_link_to_ima;
+       if (id == INTEGRITY_KEYRING_MACHINE)
+               restriction->check = restrict_link_by_ca;
+       else
+               restriction->check = restrict_link_to_ima;
 
        /*
         * MOK keys can only be added through a read-only runtime services
index 8638976f7990b76b44cc30beb74d3ec6ad62325f..c73858e8c6d5137e2e811b2431dd46b1d36b4998 100644 (file)
@@ -98,14 +98,6 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
        struct rb_node *node, *parent = NULL;
        struct integrity_iint_cache *iint, *test_iint;
 
-       /*
-        * The integrity's "iint_cache" is initialized at security_init(),
-        * unless it is not included in the ordered list of LSMs enabled
-        * on the boot command line.
-        */
-       if (!iint_cache)
-               panic("%s: lsm=integrity required.\n", __func__);
-
        iint = integrity_iint_find(inode);
        if (iint)
                return iint;
@@ -182,6 +174,7 @@ static int __init integrity_iintcache_init(void)
 DEFINE_LSM(integrity) = {
        .name = "integrity",
        .init = integrity_iintcache_init,
+       .order = LSM_ORDER_LAST,
 };
 
 
index 2da4404276f0f5a68b0619dd6aa1d06a0fdb7198..07a0ef2baacd856324df852b38bfd087fb4dabbd 100644 (file)
@@ -38,9 +38,12 @@ static void cache_requested_key(struct key *key)
 #ifdef CONFIG_KEYS_REQUEST_CACHE
        struct task_struct *t = current;
 
-       key_put(t->cached_requested_key);
-       t->cached_requested_key = key_get(key);
-       set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
+       /* Do not cache key if it is a kernel thread */
+       if (!(t->flags & PF_KTHREAD)) {
+               key_put(t->cached_requested_key);
+               t->cached_requested_key = key_get(key);
+               set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
+       }
 #endif
 }
 
index ec6c37f04a1919b82c7dc7590d3615697568df4c..13dff2a3154513fa719a33233716b542306dc0de 100644 (file)
@@ -34,7 +34,7 @@ static void hook_cred_free(struct cred *const cred)
                landlock_put_ruleset_deferred(dom);
 }
 
-static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list landlock_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(cred_prepare, hook_cred_prepare),
        LSM_HOOK_INIT(cred_free, hook_cred_free),
 };
index adcea0fe7e68e411633323cf536c1dfe69c59dce..1c0c198f6fdb851815cd04acb9191ff86a6dabd1 100644 (file)
@@ -1280,7 +1280,7 @@ static int hook_file_truncate(struct file *const file)
        return -EACCES;
 }
 
-static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list landlock_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(inode_free_security, hook_inode_free_security),
 
        LSM_HOOK_INIT(sb_delete, hook_sb_delete),
index 4c5b9cd71286125944d8658f36f2802a0e338b6a..8a06d6c492bf3e8237174bd93353682638ff1c21 100644 (file)
@@ -108,7 +108,7 @@ static int hook_ptrace_traceme(struct task_struct *const parent)
        return task_ptrace(parent, current);
 }
 
-static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list landlock_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
 };
index 3f196d2ce4f988c3bef1ff1cbea1b850594d5c0b..0f6113528fa4a869ae79552446f11f47439773e1 100644 (file)
@@ -15,9 +15,9 @@
 #include "ptrace.h"
 #include "setup.h"
 
-bool landlock_initialized __lsm_ro_after_init = false;
+bool landlock_initialized __ro_after_init = false;
 
-struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes landlock_blob_sizes __ro_after_init = {
        .lbs_cred = sizeof(struct landlock_cred_security),
        .lbs_file = sizeof(struct landlock_file_security),
        .lbs_inode = sizeof(struct landlock_inode_security),
index d73a281adf865e00999c9fbe5b7375599bb89f45..b9d773f11232db417298cbdf859331568d64b32f 100644 (file)
@@ -214,7 +214,7 @@ static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
        return loadpin_check(NULL, (enum kernel_read_file_id) id);
 }
 
-static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list loadpin_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
        LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
        LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
index a79b985e917ee642f1b9a7a8350b8a9fc26ff6c8..68d19632aeb7251d0ae40859b169c68693963a74 100644 (file)
@@ -71,7 +71,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
        return 0;
 }
 
-static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list lockdown_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
 };
 
index cf6cc576736f3dbb1d3ad21cf3def26801ec52d4..d5ff7ff45b776d6a352e2fd1fa7e2c79d1602e56 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
  * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
  * Copyright (C) 2016 Mellanox Technologies
+ * Copyright (C) 2023 Microsoft Corporation <paul@paul-moore.com>
  */
 
 #define pr_fmt(fmt) "LSM: " fmt
@@ -41,7 +42,7 @@
  * all security modules to use the same descriptions for auditing
  * purposes.
  */
-const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
+const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {
        [LOCKDOWN_NONE] = "none",
        [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
        [LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",
@@ -74,20 +75,20 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
        [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
 };
 
-struct security_hook_heads security_hook_heads __lsm_ro_after_init;
+struct security_hook_heads security_hook_heads __ro_after_init;
 static BLOCKING_NOTIFIER_HEAD(blocking_lsm_notifier_chain);
 
 static struct kmem_cache *lsm_file_cache;
 static struct kmem_cache *lsm_inode_cache;
 
 char *lsm_names;
-static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
+static struct lsm_blob_sizes blob_sizes __ro_after_init;
 
 /* Boot-time LSM user choice */
 static __initdata const char *chosen_lsm_order;
 static __initdata const char *chosen_major_lsm;
 
-static __initconst const char * const builtin_lsm_order = CONFIG_LSM;
+static __initconst const char *const builtin_lsm_order = CONFIG_LSM;
 
 /* Ordered list of LSMs to initialize. */
 static __initdata struct lsm_info **ordered_lsms;
@@ -284,9 +285,9 @@ static void __init ordered_lsm_parse(const char *order, const char *origin)
                bool found = false;
 
                for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
-                       if (lsm->order == LSM_ORDER_MUTABLE &&
-                           strcmp(lsm->name, name) == 0) {
-                               append_ordered_lsm(lsm, origin);
+                       if (strcmp(lsm->name, name) == 0) {
+                               if (lsm->order == LSM_ORDER_MUTABLE)
+                                       append_ordered_lsm(lsm, origin);
                                found = true;
                        }
                }
@@ -306,6 +307,12 @@ static void __init ordered_lsm_parse(const char *order, const char *origin)
                }
        }
 
+       /* LSM_ORDER_LAST is always last. */
+       for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
+               if (lsm->order == LSM_ORDER_LAST)
+                       append_ordered_lsm(lsm, "   last");
+       }
+
        /* Disable all LSMs not in the ordered list. */
        for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
                if (exists_ordered_lsm(lsm))
@@ -331,7 +338,8 @@ static void __init report_lsm_order(void)
        pr_info("initializing lsm=");
 
        /* Report each enabled LSM name, comma separated. */
-       for (early = __start_early_lsm_info; early < __end_early_lsm_info; early++)
+       for (early = __start_early_lsm_info;
+            early < __end_early_lsm_info; early++)
                if (is_enabled(early))
                        pr_cont("%s%s", first++ == 0 ? "" : ",", early->name);
        for (lsm = ordered_lsms; *lsm; lsm++)
@@ -346,7 +354,7 @@ static void __init ordered_lsm_init(void)
        struct lsm_info **lsm;
 
        ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),
-                               GFP_KERNEL);
+                              GFP_KERNEL);
 
        if (chosen_lsm_order) {
                if (chosen_major_lsm) {
@@ -419,9 +427,9 @@ int __init security_init(void)
 {
        struct lsm_info *lsm;
 
-       init_debug("legacy security=%s\n", chosen_major_lsm ?: " *unspecified*");
+       init_debug("legacy security=%s\n", chosen_major_lsm ? : " *unspecified*");
        init_debug("  CONFIG_LSM=%s\n", builtin_lsm_order);
-       init_debug("boot arg lsm=%s\n", chosen_lsm_order ?: " *unspecified*");
+       init_debug("boot arg lsm=%s\n", chosen_lsm_order ? : " *unspecified*");
 
        /*
         * Append the names of the early LSM modules now that kmalloc() is
@@ -509,7 +517,7 @@ static int lsm_append(const char *new, char **result)
  * Each LSM has to register its hooks with the infrastructure.
  */
 void __init security_add_hooks(struct security_hook_list *hooks, int count,
-                               const char *lsm)
+                              const char *lsm)
 {
        int i;
 
@@ -778,57 +786,157 @@ static int lsm_superblock_alloc(struct super_block *sb)
 
 /* Security operations */
 
+/**
+ * security_binder_set_context_mgr() - Check if becoming binder ctx mgr is ok
+ * @mgr: task credentials of current binder process
+ *
+ * Check whether @mgr is allowed to be the binder context manager.
+ *
+ * Return: Return 0 if permission is granted.
+ */
 int security_binder_set_context_mgr(const struct cred *mgr)
 {
        return call_int_hook(binder_set_context_mgr, 0, mgr);
 }
 
+/**
+ * security_binder_transaction() - Check if a binder transaction is allowed
+ * @from: sending process
+ * @to: receiving process
+ *
+ * Check whether @from is allowed to invoke a binder transaction call to @to.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_binder_transaction(const struct cred *from,
                                const struct cred *to)
 {
        return call_int_hook(binder_transaction, 0, from, to);
 }
 
+/**
+ * security_binder_transfer_binder() - Check if a binder transfer is allowed
+ * @from: sending process
+ * @to: receiving process
+ *
+ * Check whether @from is allowed to transfer a binder reference to @to.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_binder_transfer_binder(const struct cred *from,
                                    const struct cred *to)
 {
        return call_int_hook(binder_transfer_binder, 0, from, to);
 }
 
+/**
+ * security_binder_transfer_file() - Check if a binder file xfer is allowed
+ * @from: sending process
+ * @to: receiving process
+ * @file: file being transferred
+ *
+ * Check whether @from is allowed to transfer @file to @to.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_binder_transfer_file(const struct cred *from,
                                  const struct cred *to, struct file *file)
 {
        return call_int_hook(binder_transfer_file, 0, from, to, file);
 }
 
+/**
+ * security_ptrace_access_check() - Check if tracing is allowed
+ * @child: target process
+ * @mode: PTRACE_MODE flags
+ *
+ * Check permission before allowing the current process to trace the @child
+ * process.  Security modules may also want to perform a process tracing check
+ * during an execve in the set_security or apply_creds hooks of tracing check
+ * during an execve in the bprm_set_creds hook of binprm_security_ops if the
+ * process is being traced and its security attributes would be changed by the
+ * execve.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
 {
        return call_int_hook(ptrace_access_check, 0, child, mode);
 }
 
+/**
+ * security_ptrace_traceme() - Check if tracing is allowed
+ * @parent: tracing process
+ *
+ * Check that the @parent process has sufficient permission to trace the
+ * current process before allowing the current process to present itself to the
+ * @parent process for tracing.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_ptrace_traceme(struct task_struct *parent)
 {
        return call_int_hook(ptrace_traceme, 0, parent);
 }
 
+/**
+ * security_capget() - Get the capability sets for a process
+ * @target: target process
+ * @effective: effective capability set
+ * @inheritable: inheritable capability set
+ * @permitted: permitted capability set
+ *
+ * Get the @effective, @inheritable, and @permitted capability sets for the
+ * @target process.  The hook may also perform permission checking to determine
+ * if the current process is allowed to see the capability sets of the @target
+ * process.
+ *
+ * Return: Returns 0 if the capability sets were successfully obtained.
+ */
 int security_capget(struct task_struct *target,
-                    kernel_cap_t *effective,
-                    kernel_cap_t *inheritable,
-                    kernel_cap_t *permitted)
+                   kernel_cap_t *effective,
+                   kernel_cap_t *inheritable,
+                   kernel_cap_t *permitted)
 {
        return call_int_hook(capget, 0, target,
-                               effective, inheritable, permitted);
+                            effective, inheritable, permitted);
 }
 
+/**
+ * security_capset() - Set the capability sets for a process
+ * @new: new credentials for the target process
+ * @old: current credentials of the target process
+ * @effective: effective capability set
+ * @inheritable: inheritable capability set
+ * @permitted: permitted capability set
+ *
+ * Set the @effective, @inheritable, and @permitted capability sets for the
+ * current process.
+ *
+ * Return: Returns 0 and update @new if permission is granted.
+ */
 int security_capset(struct cred *new, const struct cred *old,
                    const kernel_cap_t *effective,
                    const kernel_cap_t *inheritable,
                    const kernel_cap_t *permitted)
 {
        return call_int_hook(capset, 0, new, old,
-                               effective, inheritable, permitted);
+                            effective, inheritable, permitted);
 }
 
+/**
+ * security_capable() - Check if a process has the necessary capability
+ * @cred: credentials to examine
+ * @ns: user namespace
+ * @cap: capability requested
+ * @opts: capability check options
+ *
+ * Check whether the @tsk process has the @cap capability in the indicated
+ * credentials.  @cap contains the capability <include/linux/capability.h>.
+ * @opts contains options for the capable check <include/linux/security.h>.
+ *
+ * Return: Returns 0 if the capability is granted.
+ */
 int security_capable(const struct cred *cred,
                     struct user_namespace *ns,
                     int cap,
@@ -837,26 +945,78 @@ int security_capable(const struct cred *cred,
        return call_int_hook(capable, 0, cred, ns, cap, opts);
 }
 
+/**
+ * security_quotactl() - Check if a quotactl() syscall is allowed for this fs
+ * @cmds: commands
+ * @type: type
+ * @id: id
+ * @sb: filesystem
+ *
+ * Check whether the quotactl syscall is allowed for this @sb.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
        return call_int_hook(quotactl, 0, cmds, type, id, sb);
 }
 
+/**
+ * security_quota_on() - Check if QUOTAON is allowed for a dentry
+ * @dentry: dentry
+ *
+ * Check whether QUOTAON is allowed for @dentry.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_quota_on(struct dentry *dentry)
 {
        return call_int_hook(quota_on, 0, dentry);
 }
 
+/**
+ * security_syslog() - Check if accessing the kernel message ring is allowed
+ * @type: SYSLOG_ACTION_* type
+ *
+ * Check permission before accessing the kernel message ring or changing
+ * logging to the console.  See the syslog(2) manual page for an explanation of
+ * the @type values.
+ *
+ * Return: Return 0 if permission is granted.
+ */
 int security_syslog(int type)
 {
        return call_int_hook(syslog, 0, type);
 }
 
+/**
+ * security_settime64() - Check if changing the system time is allowed
+ * @ts: new time
+ * @tz: timezone
+ *
+ * Check permission to change the system time, struct timespec64 is defined in
+ * <include/linux/time64.h> and timezone is defined in <include/linux/time.h>.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_settime64(const struct timespec64 *ts, const struct timezone *tz)
 {
        return call_int_hook(settime, 0, ts, tz);
 }
 
+/**
+ * security_vm_enough_memory_mm() - Check if allocating a new mem map is allowed
+ * @mm: mm struct
+ * @pages: number of pages
+ *
+ * Check permissions for allocating a new virtual mapping.  If all LSMs return
+ * a positive value, __vm_enough_memory() will be called with cap_sys_admin
+ * set. If at least one LSM returns 0 or negative, __vm_enough_memory() will be
+ * called with cap_sys_admin cleared.
+ *
+ * Return: Returns 0 if permission is granted by the LSM infrastructure to the
+ *         caller.
+ */
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
 {
        struct security_hook_list *hp;
@@ -880,16 +1040,61 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
        return __vm_enough_memory(mm, pages, cap_sys_admin);
 }
 
+/**
+ * security_bprm_creds_for_exec() - Prepare the credentials for exec()
+ * @bprm: binary program information
+ *
+ * If the setup in prepare_exec_creds did not setup @bprm->cred->security
+ * properly for executing @bprm->file, update the LSM's portion of
+ * @bprm->cred->security to be what commit_creds needs to install for the new
+ * program.  This hook may also optionally check permissions (e.g. for
+ * transitions between security domains).  The hook must set @bprm->secureexec
+ * to 1 if AT_SECURE should be set to request libc enable secure mode.  @bprm
+ * contains the linux_binprm structure.
+ *
+ * Return: Returns 0 if the hook is successful and permission is granted.
+ */
 int security_bprm_creds_for_exec(struct linux_binprm *bprm)
 {
        return call_int_hook(bprm_creds_for_exec, 0, bprm);
 }
 
+/**
+ * security_bprm_creds_from_file() - Update linux_binprm creds based on file
+ * @bprm: binary program information
+ * @file: associated file
+ *
+ * If @file is setpcap, suid, sgid or otherwise marked to change privilege upon
+ * exec, update @bprm->cred to reflect that change. This is called after
+ * finding the binary that will be executed without an interpreter.  This
+ * ensures that the credentials will not be derived from a script that the
+ * binary will need to reopen, which when reopend may end up being a completely
+ * different file.  This hook may also optionally check permissions (e.g. for
+ * transitions between security domains).  The hook must set @bprm->secureexec
+ * to 1 if AT_SECURE should be set to request libc enable secure mode.  The
+ * hook must add to @bprm->per_clear any personality flags that should be
+ * cleared from current->personality.  @bprm contains the linux_binprm
+ * structure.
+ *
+ * Return: Returns 0 if the hook is successful and permission is granted.
+ */
 int security_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file)
 {
        return call_int_hook(bprm_creds_from_file, 0, bprm, file);
 }
 
+/**
+ * security_bprm_check() - Mediate binary handler search
+ * @bprm: binary program information
+ *
+ * This hook mediates the point when a search for a binary handler will begin.
+ * It allows a check against the @bprm->cred->security value which was set in
+ * the preceding creds_for_exec call.  The argv list and envp list are reliably
+ * available in @bprm.  This hook may be called multiple times during a single
+ * execve.  @bprm contains the linux_binprm structure.
+ *
+ * Return: Returns 0 if the hook is successful and permission is granted.
+ */
 int security_bprm_check(struct linux_binprm *bprm)
 {
        int ret;
@@ -900,21 +1105,67 @@ int security_bprm_check(struct linux_binprm *bprm)
        return ima_bprm_check(bprm);
 }
 
+/**
+ * security_bprm_committing_creds() - Install creds for a process during exec()
+ * @bprm: binary program information
+ *
+ * Prepare to install the new security attributes of a process being
+ * transformed by an execve operation, based on the old credentials pointed to
+ * by @current->cred and the information set in @bprm->cred by the
+ * bprm_creds_for_exec hook.  @bprm points to the linux_binprm structure.  This
+ * hook is a good place to perform state changes on the process such as closing
+ * open file descriptors to which access will no longer be granted when the
+ * attributes are changed.  This is called immediately before commit_creds().
+ */
 void security_bprm_committing_creds(struct linux_binprm *bprm)
 {
        call_void_hook(bprm_committing_creds, bprm);
 }
 
+/**
+ * security_bprm_committed_creds() - Tidy up after cred install during exec()
+ * @bprm: binary program information
+ *
+ * Tidy up after the installation of the new security attributes of a process
+ * being transformed by an execve operation.  The new credentials have, by this
+ * point, been set to @current->cred.  @bprm points to the linux_binprm
+ * structure.  This hook is a good place to perform state changes on the
+ * process such as clearing out non-inheritable signal state.  This is called
+ * immediately after commit_creds().
+ */
 void security_bprm_committed_creds(struct linux_binprm *bprm)
 {
        call_void_hook(bprm_committed_creds, bprm);
 }
 
+/**
+ * security_fs_context_dup() - Duplicate a fs_context LSM blob
+ * @fc: destination filesystem context
+ * @src_fc: source filesystem context
+ *
+ * Allocate and attach a security structure to sc->security.  This pointer is
+ * initialised to NULL by the caller.  @fc indicates the new filesystem context.
+ * @src_fc indicates the original filesystem context.
+ *
+ * Return: Returns 0 on success or a negative error code on failure.
+ */
 int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
 {
        return call_int_hook(fs_context_dup, 0, fc, src_fc);
 }
 
+/**
+ * security_fs_context_parse_param() - Configure a filesystem context
+ * @fc: filesystem context
+ * @param: filesystem parameter
+ *
+ * Userspace provided a parameter to configure a superblock.  The LSM can
+ * consume the parameter or return it to the caller for use elsewhere.
+ *
+ * Return: If the parameter is used by the LSM it should return 0, if it is
+ *         returned to the caller -ENOPARAM is returned, otherwise a negative
+ *         error code is returned.
+ */
 int security_fs_context_parse_param(struct fs_context *fc,
                                    struct fs_parameter *param)
 {
@@ -933,6 +1184,16 @@ int security_fs_context_parse_param(struct fs_context *fc,
        return rc;
 }
 
+/**
+ * security_sb_alloc() - Allocate a super_block LSM blob
+ * @sb: filesystem superblock
+ *
+ * Allocate and attach a security structure to the sb->s_security field.  The
+ * s_security field is initialized to NULL when the structure is allocated.
+ * @sb contains the super_block structure to be modified.
+ *
+ * Return: Returns 0 if operation was successful.
+ */
 int security_sb_alloc(struct super_block *sb)
 {
        int rc = lsm_superblock_alloc(sb);
@@ -945,11 +1206,25 @@ int security_sb_alloc(struct super_block *sb)
        return rc;
 }
 
+/**
+ * security_sb_delete() - Release super_block LSM associated objects
+ * @sb: filesystem superblock
+ *
+ * Release objects tied to a superblock (e.g. inodes).  @sb contains the
+ * super_block structure being released.
+ */
 void security_sb_delete(struct super_block *sb)
 {
        call_void_hook(sb_delete, sb);
 }
 
+/**
+ * security_sb_free() - Free a super_block LSM blob
+ * @sb: filesystem superblock
+ *
+ * Deallocate and clear the sb->s_security field.  @sb contains the super_block
+ * structure to be modified.
+ */
 void security_sb_free(struct super_block *sb)
 {
        call_void_hook(sb_free_security, sb);
@@ -957,6 +1232,12 @@ void security_sb_free(struct super_block *sb)
        sb->s_security = NULL;
 }
 
+/**
+ * security_free_mnt_opts() - Free memory associated with mount options
+ * @mnt_opts: LSM processed mount options
+ *
+ * Free memory associated with @mnt_ops.
+ */
 void security_free_mnt_opts(void **mnt_opts)
 {
        if (!*mnt_opts)
@@ -966,12 +1247,31 @@ void security_free_mnt_opts(void **mnt_opts)
 }
 EXPORT_SYMBOL(security_free_mnt_opts);
 
+/**
+ * security_sb_eat_lsm_opts() - Consume LSM mount options
+ * @options: mount options
+ * @mnt_opts: LSM processed mount options
+ *
+ * Eat (scan @options) and save them in @mnt_opts.
+ *
+ * Return: Returns 0 on success, negative values on failure.
+ */
 int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
 {
        return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts);
 }
 EXPORT_SYMBOL(security_sb_eat_lsm_opts);
 
+/**
+ * security_sb_mnt_opts_compat() - Check if new mount options are allowed
+ * @sb: filesystem superblock
+ * @mnt_opts: new mount options
+ *
+ * Determine if the new mount options in @mnt_opts are allowed given the
+ * existing mounted filesystem at @sb.  @sb superblock being compared.
+ *
+ * Return: Returns 0 if options are compatible.
+ */
 int security_sb_mnt_opts_compat(struct super_block *sb,
                                void *mnt_opts)
 {
@@ -979,6 +1279,16 @@ int security_sb_mnt_opts_compat(struct super_block *sb,
 }
 EXPORT_SYMBOL(security_sb_mnt_opts_compat);
 
+/**
+ * security_sb_remount() - Verify no incompatible mount changes during remount
+ * @sb: filesystem superblock
+ * @mnt_opts: (re)mount options
+ *
+ * Extracts security system specific mount options and verifies no changes are
+ * being made to those options.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sb_remount(struct super_block *sb,
                        void *mnt_opts)
 {
@@ -986,69 +1296,184 @@ int security_sb_remount(struct super_block *sb,
 }
 EXPORT_SYMBOL(security_sb_remount);
 
+/**
+ * security_sb_kern_mount() - Check if a kernel mount is allowed
+ * @sb: filesystem superblock
+ *
+ * Mount this @sb if allowed by permissions.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sb_kern_mount(struct super_block *sb)
 {
        return call_int_hook(sb_kern_mount, 0, sb);
 }
 
+/**
+ * security_sb_show_options() - Output the mount options for a superblock
+ * @m: output file
+ * @sb: filesystem superblock
+ *
+ * Show (print on @m) mount options for this @sb.
+ *
+ * Return: Returns 0 on success, negative values on failure.
+ */
 int security_sb_show_options(struct seq_file *m, struct super_block *sb)
 {
        return call_int_hook(sb_show_options, 0, m, sb);
 }
 
+/**
+ * security_sb_statfs() - Check if accessing fs stats is allowed
+ * @dentry: superblock handle
+ *
+ * Check permission before obtaining filesystem statistics for the @mnt
+ * mountpoint.  @dentry is a handle on the superblock for the filesystem.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sb_statfs(struct dentry *dentry)
 {
        return call_int_hook(sb_statfs, 0, dentry);
 }
 
+/**
+ * security_sb_mount() - Check permission for mounting a filesystem
+ * @dev_name: filesystem backing device
+ * @path: mount point
+ * @type: filesystem type
+ * @flags: mount flags
+ * @data: filesystem specific data
+ *
+ * Check permission before an object specified by @dev_name is mounted on the
+ * mount point named by @nd.  For an ordinary mount, @dev_name identifies a
+ * device if the file system type requires a device.  For a remount
+ * (@flags & MS_REMOUNT), @dev_name is irrelevant.  For a loopback/bind mount
+ * (@flags & MS_BIND), @dev_name identifies the        pathname of the object being
+ * mounted.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sb_mount(const char *dev_name, const struct path *path,
-                       const char *type, unsigned long flags, void *data)
+                     const char *type, unsigned long flags, void *data)
 {
        return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data);
 }
 
+/**
+ * security_sb_umount() - Check permission for unmounting a filesystem
+ * @mnt: mounted filesystem
+ * @flags: unmount flags
+ *
+ * Check permission before the @mnt file system is unmounted.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sb_umount(struct vfsmount *mnt, int flags)
 {
        return call_int_hook(sb_umount, 0, mnt, flags);
 }
 
-int security_sb_pivotroot(const struct path *old_path, const struct path *new_path)
+/**
+ * security_sb_pivotroot() - Check permissions for pivoting the rootfs
+ * @old_path: new location for current rootfs
+ * @new_path: location of the new rootfs
+ *
+ * Check permission before pivoting the root filesystem.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_sb_pivotroot(const struct path *old_path,
+                         const struct path *new_path)
 {
        return call_int_hook(sb_pivotroot, 0, old_path, new_path);
 }
 
+/**
+ * security_sb_set_mnt_opts() - Set the mount options for a filesystem
+ * @sb: filesystem superblock
+ * @mnt_opts: binary mount options
+ * @kern_flags: kernel flags (in)
+ * @set_kern_flags: kernel flags (out)
+ *
+ * Set the security relevant mount options used for a superblock.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_sb_set_mnt_opts(struct super_block *sb,
-                               void *mnt_opts,
-                               unsigned long kern_flags,
-                               unsigned long *set_kern_flags)
+                            void *mnt_opts,
+                            unsigned long kern_flags,
+                            unsigned long *set_kern_flags)
 {
        return call_int_hook(sb_set_mnt_opts,
-                               mnt_opts ? -EOPNOTSUPP : 0, sb,
-                               mnt_opts, kern_flags, set_kern_flags);
+                            mnt_opts ? -EOPNOTSUPP : 0, sb,
+                            mnt_opts, kern_flags, set_kern_flags);
 }
 EXPORT_SYMBOL(security_sb_set_mnt_opts);
 
+/**
+ * security_sb_clone_mnt_opts() - Duplicate superblock mount options
+ * @oldsb: source superblock
+ * @newsb: destination superblock
+ * @kern_flags: kernel flags (in)
+ * @set_kern_flags: kernel flags (out)
+ *
+ * Copy all security options from a given superblock to another.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_sb_clone_mnt_opts(const struct super_block *oldsb,
-                               struct super_block *newsb,
-                               unsigned long kern_flags,
-                               unsigned long *set_kern_flags)
+                              struct super_block *newsb,
+                              unsigned long kern_flags,
+                              unsigned long *set_kern_flags)
 {
        return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb,
-                               kern_flags, set_kern_flags);
+                            kern_flags, set_kern_flags);
 }
 EXPORT_SYMBOL(security_sb_clone_mnt_opts);
 
-int security_move_mount(const struct path *from_path, const struct path *to_path)
+/**
+ * security_move_mount() - Check permissions for moving a mount
+ * @from_path: source mount point
+ * @to_path: destination mount point
+ *
+ * Check permission before a mount is moved.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_move_mount(const struct path *from_path,
+                       const struct path *to_path)
 {
        return call_int_hook(move_mount, 0, from_path, to_path);
 }
 
+/**
+ * security_path_notify() - Check if setting a watch is allowed
+ * @path: file path
+ * @mask: event mask
+ * @obj_type: file path type
+ *
+ * Check permissions before setting a watch on events as defined by @mask, on
+ * an object at @path, whose type is defined by @obj_type.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_notify(const struct path *path, u64 mask,
-                               unsigned int obj_type)
+                        unsigned int obj_type)
 {
        return call_int_hook(path_notify, 0, path, mask, obj_type);
 }
 
+/**
+ * security_inode_alloc() - Allocate an inode LSM blob
+ * @inode: the inode
+ *
+ * Allocate and attach a security structure to @inode->i_security.  The
+ * i_security field is initialized to NULL when the inode structure is
+ * allocated.
+ *
+ * Return: Return 0 if operation was successful.
+ */
 int security_inode_alloc(struct inode *inode)
 {
        int rc = lsm_inode_alloc(inode);
@@ -1069,6 +1494,12 @@ static void inode_free_by_rcu(struct rcu_head *head)
        kmem_cache_free(lsm_inode_cache, head);
 }
 
+/**
+ * security_inode_free() - Free an inode's LSM blob
+ * @inode: the inode
+ *
+ * Deallocate the inode security structure and set @inode->i_security to NULL.
+ */
 void security_inode_free(struct inode *inode)
 {
        integrity_inode_free(inode);
@@ -1084,9 +1515,24 @@ void security_inode_free(struct inode *inode)
         */
        if (inode->i_security)
                call_rcu((struct rcu_head *)inode->i_security,
-                               inode_free_by_rcu);
+                        inode_free_by_rcu);
 }
 
+/**
+ * security_dentry_init_security() - Perform dentry initialization
+ * @dentry: the dentry to initialize
+ * @mode: mode used to determine resource type
+ * @name: name of the last path component
+ * @xattr_name: name of the security/LSM xattr
+ * @ctx: pointer to the resulting LSM context
+ * @ctxlen: length of @ctx
+ *
+ * Compute a context for a dentry as the inode is not yet available since NFSv4
+ * has no label backed by an EA anyway.  It is important to note that
+ * @xattr_name does not need to be free'd by the caller, it is a static string.
+ *
+ * Return: Returns 0 on success, negative values on failure.
+ */
 int security_dentry_init_security(struct dentry *dentry, int mode,
                                  const struct qstr *name,
                                  const char **xattr_name, void **ctx,
@@ -1098,7 +1544,8 @@ int security_dentry_init_security(struct dentry *dentry, int mode,
        /*
         * Only one module will provide a security context.
         */
-       hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security, list) {
+       hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security,
+                            list) {
                rc = hp->hook.dentry_init_security(dentry, mode, name,
                                                   xattr_name, ctx, ctxlen);
                if (rc != LSM_RET_DEFAULT(dentry_init_security))
@@ -1108,15 +1555,51 @@ int security_dentry_init_security(struct dentry *dentry, int mode,
 }
 EXPORT_SYMBOL(security_dentry_init_security);
 
+/**
+ * security_dentry_create_files_as() - Perform dentry initialization
+ * @dentry: the dentry to initialize
+ * @mode: mode used to determine resource type
+ * @name: name of the last path component
+ * @old: creds to use for LSM context calculations
+ * @new: creds to modify
+ *
+ * Compute a context for a dentry as the inode is not yet available and set
+ * that context in passed in creds so that new files are created using that
+ * context. Context is calculated using the passed in creds and not the creds
+ * of the caller.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_dentry_create_files_as(struct dentry *dentry, int mode,
                                    struct qstr *name,
                                    const struct cred *old, struct cred *new)
 {
        return call_int_hook(dentry_create_files_as, 0, dentry, mode,
-                               name, old, new);
+                            name, old, new);
 }
 EXPORT_SYMBOL(security_dentry_create_files_as);
 
+/**
+ * security_inode_init_security() - Initialize an inode's LSM context
+ * @inode: the inode
+ * @dir: parent directory
+ * @qstr: last component of the pathname
+ * @initxattrs: callback function to write xattrs
+ * @fs_data: filesystem specific data
+ *
+ * Obtain the security attribute name suffix and value to set on a newly
+ * created inode and set up the incore security field for the new inode.  This
+ * hook is called by the fs code as part of the inode creation transaction and
+ * provides for atomic labeling of the inode, unlike the post_create/mkdir/...
+ * hooks called by the VFS.  The hook function is expected to allocate the name
+ * and value via kmalloc, with the caller being responsible for calling kfree
+ * after using them.  If the security module does not use security attributes
+ * or does not wish to put a security attribute on this particular inode, then
+ * it should return -EOPNOTSUPP to skip this processing.
+ *
+ * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is
+ * needed, or -ENOMEM on memory allocation failure.
+ */
 int security_inode_init_security(struct inode *inode, struct inode *dir,
                                 const struct qstr *qstr,
                                 const initxattrs initxattrs, void *fs_data)
@@ -1134,9 +1617,9 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
        memset(new_xattrs, 0, sizeof(new_xattrs));
        lsm_xattr = new_xattrs;
        ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
-                                               &lsm_xattr->name,
-                                               &lsm_xattr->value,
-                                               &lsm_xattr->value_len);
+                           &lsm_xattr->name,
+                           &lsm_xattr->value,
+                           &lsm_xattr->value_len);
        if (ret)
                goto out;
 
@@ -1152,6 +1635,18 @@ out:
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
+/**
+ * security_inode_init_security_anon() - Initialize an anonymous inode
+ * @inode: the inode
+ * @name: the anonymous inode class
+ * @context_inode: an optional related inode
+ *
+ * Set up the incore security field for the new anonymous inode and return
+ * whether the inode creation is permitted by the security module or not.
+ *
+ * Return: Returns 0 on success, -EACCES if the security module denies the
+ * creation of this inode, or another -errno upon other errors.
+ */
 int security_inode_init_security_anon(struct inode *inode,
                                      const struct qstr *name,
                                      const struct inode *context_inode)
@@ -1160,20 +1655,21 @@ int security_inode_init_security_anon(struct inode *inode,
                             context_inode);
 }
 
-int security_old_inode_init_security(struct inode *inode, struct inode *dir,
-                                    const struct qstr *qstr, const char **name,
-                                    void **value, size_t *len)
-{
-       if (unlikely(IS_PRIVATE(inode)))
-               return -EOPNOTSUPP;
-       return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir,
-                            qstr, name, value, len);
-}
-EXPORT_SYMBOL(security_old_inode_init_security);
-
 #ifdef CONFIG_SECURITY_PATH
-int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode,
-                       unsigned int dev)
+/**
+ * security_path_mknod() - Check if creating a special file is allowed
+ * @dir: parent directory
+ * @dentry: new file
+ * @mode: new file mode
+ * @dev: device number
+ *
+ * Check permissions when creating a file. Note that this hook is called even
+ * if mknod operation is being done for a regular file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_path_mknod(const struct path *dir, struct dentry *dentry,
+                       umode_t mode, unsigned int dev)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
@@ -1181,7 +1677,18 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t m
 }
 EXPORT_SYMBOL(security_path_mknod);
 
-int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode)
+/**
+ * security_path_mkdir() - Check if creating a new directory is allowed
+ * @dir: parent directory
+ * @dentry: new directory
+ * @mode: new directory mode
+ *
+ * Check permissions to create a new directory in the existing directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_path_mkdir(const struct path *dir, struct dentry *dentry,
+                       umode_t mode)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
                return 0;
@@ -1189,6 +1696,15 @@ int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t m
 }
 EXPORT_SYMBOL(security_path_mkdir);
 
+/**
+ * security_path_rmdir() - Check if removing a directory is allowed
+ * @dir: parent directory
+ * @dentry: directory to remove
+ *
+ * Check the permission to remove a directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_rmdir(const struct path *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
@@ -1196,6 +1712,15 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
        return call_int_hook(path_rmdir, 0, dir, dentry);
 }
 
+/**
+ * security_path_unlink() - Check if removing a hard link is allowed
+ * @dir: parent directory
+ * @dentry: file
+ *
+ * Check the permission to remove a hard link to a file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_unlink(const struct path *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
@@ -1204,6 +1729,16 @@ int security_path_unlink(const struct path *dir, struct dentry *dentry)
 }
 EXPORT_SYMBOL(security_path_unlink);
 
+/**
+ * security_path_symlink() - Check if creating a symbolic link is allowed
+ * @dir: parent directory
+ * @dentry: symbolic link
+ * @old_name: file pathname
+ *
+ * Check the permission to create a symbolic link to a file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_symlink(const struct path *dir, struct dentry *dentry,
                          const char *old_name)
 {
@@ -1212,6 +1747,16 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
        return call_int_hook(path_symlink, 0, dir, dentry, old_name);
 }
 
+/**
+ * security_path_link - Check if creating a hard link is allowed
+ * @old_dentry: existing file
+ * @new_dir: new parent directory
+ * @new_dentry: new link
+ *
+ * Check permission before creating a new hard link to a file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
                       struct dentry *new_dentry)
 {
@@ -1220,19 +1765,42 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
        return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
 }
 
+/**
+ * security_path_rename() - Check if renaming a file is allowed
+ * @old_dir: parent directory of the old file
+ * @old_dentry: the old file
+ * @new_dir: parent directory of the new file
+ * @new_dentry: the new file
+ * @flags: flags
+ *
+ * Check for permission to rename a file or directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
                         const struct path *new_dir, struct dentry *new_dentry,
                         unsigned int flags)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
-                    (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
+                    (d_is_positive(new_dentry) &&
+                     IS_PRIVATE(d_backing_inode(new_dentry)))))
                return 0;
 
        return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir,
-                               new_dentry, flags);
+                            new_dentry, flags);
 }
 EXPORT_SYMBOL(security_path_rename);
 
+/**
+ * security_path_truncate() - Check if truncating a file is allowed
+ * @path: file
+ *
+ * Check permission before truncating the file indicated by path.  Note that
+ * truncation permissions may also be checked based on already opened files,
+ * using the security_file_truncate() hook.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_truncate(const struct path *path)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
@@ -1240,6 +1808,17 @@ int security_path_truncate(const struct path *path)
        return call_int_hook(path_truncate, 0, path);
 }
 
+/**
+ * security_path_chmod() - Check if changing the file's mode is allowed
+ * @path: file
+ * @mode: new mode
+ *
+ * Check for permission to change a mode of the file @path. The new mode is
+ * specified in @mode which is a bitmask of constants from
+ * <include/uapi/linux/stat.h>.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_chmod(const struct path *path, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
@@ -1247,6 +1826,16 @@ int security_path_chmod(const struct path *path, umode_t mode)
        return call_int_hook(path_chmod, 0, path, mode);
 }
 
+/**
+ * security_path_chown() - Check if changing the file's owner/group is allowed
+ * @path: file
+ * @uid: file owner
+ * @gid: file group
+ *
+ * Check for permission to change owner/group of a file or directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
@@ -1254,13 +1843,32 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
        return call_int_hook(path_chown, 0, path, uid, gid);
 }
 
+/**
+ * security_path_chroot() - Check if changing the root directory is allowed
+ * @path: directory
+ *
+ * Check for permission to change root directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_path_chroot(const struct path *path)
 {
        return call_int_hook(path_chroot, 0, path);
 }
-#endif
+#endif /* CONFIG_SECURITY_PATH */
 
-int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
+/**
+ * security_inode_create() - Check if creating a file is allowed
+ * @dir: the parent directory
+ * @dentry: the file being created
+ * @mode: requested file mode
+ *
+ * Check permission to create a regular file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_inode_create(struct inode *dir, struct dentry *dentry,
+                         umode_t mode)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
@@ -1268,14 +1876,33 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
 }
 EXPORT_SYMBOL_GPL(security_inode_create);
 
+/**
+ * security_inode_link() - Check if creating a hard link is allowed
+ * @old_dentry: existing file
+ * @dir: new parent directory
+ * @new_dentry: new link
+ *
+ * Check permission before creating a new hard link to a file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
-                        struct dentry *new_dentry)
+                       struct dentry *new_dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
                return 0;
        return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry);
 }
 
+/**
+ * security_inode_unlink() - Check if removing a hard link is allowed
+ * @dir: parent directory
+ * @dentry: file
+ *
+ * Check the permission to remove a hard link to a file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_unlink(struct inode *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1283,14 +1910,35 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry)
        return call_int_hook(inode_unlink, 0, dir, dentry);
 }
 
+/**
+ * security_inode_symlink() - Check if creating a symbolic link is allowed
+ * @dir: parent directory
+ * @dentry: symbolic link
+ * @old_name: existing filename
+ *
+ * Check the permission to create a symbolic link to a file.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_symlink(struct inode *dir, struct dentry *dentry,
-                           const char *old_name)
+                          const char *old_name)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
        return call_int_hook(inode_symlink, 0, dir, dentry, old_name);
 }
 
+/**
+ * security_inode_mkdir() - Check if creation a new director is allowed
+ * @dir: parent directory
+ * @dentry: new directory
+ * @mode: new directory mode
+ *
+ * Check permissions to create a new directory in the existing directory
+ * associated with inode structure @dir.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        if (unlikely(IS_PRIVATE(dir)))
@@ -1299,6 +1947,15 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 EXPORT_SYMBOL_GPL(security_inode_mkdir);
 
+/**
+ * security_inode_rmdir() - Check if removing a directory is allowed
+ * @dir: parent directory
+ * @dentry: directory to be removed
+ *
+ * Check the permission to remove a directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1306,32 +1963,68 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
        return call_int_hook(inode_rmdir, 0, dir, dentry);
 }
 
-int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
+/**
+ * security_inode_mknod() - Check if creating a special file is allowed
+ * @dir: parent directory
+ * @dentry: new file
+ * @mode: new file mode
+ * @dev: device number
+ *
+ * Check permissions when creating a special file (or a socket or a fifo file
+ * created via the mknod system call).  Note that if mknod operation is being
+ * done for a regular file, then the create hook will be called and not this
+ * hook.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
+                        umode_t mode, dev_t dev)
 {
        if (unlikely(IS_PRIVATE(dir)))
                return 0;
        return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev);
 }
 
+/**
+ * security_inode_rename() - Check if renaming a file is allowed
+ * @old_dir: parent directory of the old file
+ * @old_dentry: the old file
+ * @new_dir: parent directory of the new file
+ * @new_dentry: the new file
+ * @flags: flags
+ *
+ * Check for permission to rename a file or directory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
-                          struct inode *new_dir, struct dentry *new_dentry,
-                          unsigned int flags)
+                         struct inode *new_dir, struct dentry *new_dentry,
+                         unsigned int flags)
 {
-        if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
-            (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
+       if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
+                    (d_is_positive(new_dentry) &&
+                     IS_PRIVATE(d_backing_inode(new_dentry)))))
                return 0;
 
        if (flags & RENAME_EXCHANGE) {
                int err = call_int_hook(inode_rename, 0, new_dir, new_dentry,
-                                                    old_dir, old_dentry);
+                                       old_dir, old_dentry);
                if (err)
                        return err;
        }
 
        return call_int_hook(inode_rename, 0, old_dir, old_dentry,
-                                          new_dir, new_dentry);
+                            new_dir, new_dentry);
 }
 
+/**
+ * security_inode_readlink() - Check if reading a symbolic link is allowed
+ * @dentry: link
+ *
+ * Check the permission to read the symbolic link.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_readlink(struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1339,6 +2032,17 @@ int security_inode_readlink(struct dentry *dentry)
        return call_int_hook(inode_readlink, 0, dentry);
 }
 
+/**
+ * security_inode_follow_link() - Check if following a symbolic link is allowed
+ * @dentry: link dentry
+ * @inode: link inode
+ * @rcu: true if in RCU-walk mode
+ *
+ * Check permission to follow a symbolic link when looking up a pathname.  If
+ * @rcu is true, @inode is not stable.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
                               bool rcu)
 {
@@ -1347,6 +2051,20 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
        return call_int_hook(inode_follow_link, 0, dentry, inode, rcu);
 }
 
+/**
+ * security_inode_permission() - Check if accessing an inode is allowed
+ * @inode: inode
+ * @mask: access mask
+ *
+ * Check permission before accessing an inode.  This hook is called by the
+ * existing Linux permission function, so a security module can use it to
+ * provide additional checking for existing Linux permission checks.  Notice
+ * that this hook is called when a file is opened (as well as many other
+ * operations), whereas the file_security_ops permission hook is called when
+ * the actual read/write operations are performed.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_permission(struct inode *inode, int mask)
 {
        if (unlikely(IS_PRIVATE(inode)))
@@ -1354,6 +2072,19 @@ int security_inode_permission(struct inode *inode, int mask)
        return call_int_hook(inode_permission, 0, inode, mask);
 }
 
+/**
+ * security_inode_setattr() - Check if setting file attributes is allowed
+ * @idmap: idmap of the mount
+ * @dentry: file
+ * @attr: new attributes
+ *
+ * Check permission before setting file attributes.  Note that the kernel call
+ * to notify_change is performed from several locations, whenever file
+ * attributes change (such as when a file is truncated, chown/chmod operations,
+ * transferring disk quotas, etc).
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_setattr(struct mnt_idmap *idmap,
                           struct dentry *dentry, struct iattr *attr)
 {
@@ -1368,6 +2099,14 @@ int security_inode_setattr(struct mnt_idmap *idmap,
 }
 EXPORT_SYMBOL_GPL(security_inode_setattr);
 
+/**
+ * security_inode_getattr() - Check if getting file attributes is allowed
+ * @path: file
+ *
+ * Check permission before obtaining file attributes.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_getattr(const struct path *path)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
@@ -1375,6 +2114,19 @@ int security_inode_getattr(const struct path *path)
        return call_int_hook(inode_getattr, 0, path);
 }
 
+/**
+ * security_inode_setxattr() - Check if setting file xattrs is allowed
+ * @idmap: idmap of the mount
+ * @dentry: file
+ * @name: xattr name
+ * @value: xattr value
+ * @size: size of xattr value
+ * @flags: flags
+ *
+ * Check permission before setting the extended attributes.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_setxattr(struct mnt_idmap *idmap,
                            struct dentry *dentry, const char *name,
                            const void *value, size_t size, int flags)
@@ -1400,6 +2152,18 @@ int security_inode_setxattr(struct mnt_idmap *idmap,
        return evm_inode_setxattr(idmap, dentry, name, value, size);
 }
 
+/**
+ * security_inode_set_acl() - Check if setting posix acls is allowed
+ * @idmap: idmap of the mount
+ * @dentry: file
+ * @acl_name: acl name
+ * @kacl: acl struct
+ *
+ * Check permission before setting posix acls, the posix acls in @kacl are
+ * identified by @acl_name.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_set_acl(struct mnt_idmap *idmap,
                           struct dentry *dentry, const char *acl_name,
                           struct posix_acl *kacl)
@@ -1418,6 +2182,17 @@ int security_inode_set_acl(struct mnt_idmap *idmap,
        return evm_inode_set_acl(idmap, dentry, acl_name, kacl);
 }
 
+/**
+ * security_inode_get_acl() - Check if reading posix acls is allowed
+ * @idmap: idmap of the mount
+ * @dentry: file
+ * @acl_name: acl name
+ *
+ * Check permission before getting osix acls, the posix acls are identified by
+ * @acl_name.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_get_acl(struct mnt_idmap *idmap,
                           struct dentry *dentry, const char *acl_name)
 {
@@ -1426,6 +2201,17 @@ int security_inode_get_acl(struct mnt_idmap *idmap,
        return call_int_hook(inode_get_acl, 0, idmap, dentry, acl_name);
 }
 
+/**
+ * security_inode_remove_acl() - Check if removing a posix acl is allowed
+ * @idmap: idmap of the mount
+ * @dentry: file
+ * @acl_name: acl name
+ *
+ * Check permission before removing posix acls, the posix acls are identified
+ * by @acl_name.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_remove_acl(struct mnt_idmap *idmap,
                              struct dentry *dentry, const char *acl_name)
 {
@@ -1442,6 +2228,16 @@ int security_inode_remove_acl(struct mnt_idmap *idmap,
        return evm_inode_remove_acl(idmap, dentry, acl_name);
 }
 
+/**
+ * security_inode_post_setxattr() - Update the inode after a setxattr operation
+ * @dentry: file
+ * @name: xattr name
+ * @value: xattr value
+ * @size: xattr value size
+ * @flags: flags
+ *
+ * Update inode security field after successful setxattr operation.
+ */
 void security_inode_post_setxattr(struct dentry *dentry, const char *name,
                                  const void *value, size_t size, int flags)
 {
@@ -1451,6 +2247,16 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name,
        evm_inode_post_setxattr(dentry, name, value, size);
 }
 
+/**
+ * security_inode_getxattr() - Check if xattr access is allowed
+ * @dentry: file
+ * @name: xattr name
+ *
+ * Check permission before obtaining the extended attributes identified by
+ * @name for @dentry.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_getxattr(struct dentry *dentry, const char *name)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1458,6 +2264,15 @@ int security_inode_getxattr(struct dentry *dentry, const char *name)
        return call_int_hook(inode_getxattr, 0, dentry, name);
 }
 
+/**
+ * security_inode_listxattr() - Check if listing xattrs is allowed
+ * @dentry: file
+ *
+ * Check permission before obtaining the list of extended attribute names for
+ * @dentry.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_listxattr(struct dentry *dentry)
 {
        if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1465,6 +2280,17 @@ int security_inode_listxattr(struct dentry *dentry)
        return call_int_hook(inode_listxattr, 0, dentry);
 }
 
+/**
+ * security_inode_removexattr() - Check if removing an xattr is allowed
+ * @idmap: idmap of the mount
+ * @dentry: file
+ * @name: xattr name
+ *
+ * Check permission before removing the extended attribute identified by @name
+ * for @dentry.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inode_removexattr(struct mnt_idmap *idmap,
                               struct dentry *dentry, const char *name)
 {
@@ -1487,17 +2313,55 @@ int security_inode_removexattr(struct mnt_idmap *idmap,
        return evm_inode_removexattr(idmap, dentry, name);
 }
 
+/**
+ * security_inode_need_killpriv() - Check if security_inode_killpriv() required
+ * @dentry: associated dentry
+ *
+ * Called when an inode has been changed to determine if
+ * security_inode_killpriv() should be called.
+ *
+ * Return: Return <0 on error to abort the inode change operation, return 0 if
+ *         security_inode_killpriv() does not need to be called, return >0 if
+ *         security_inode_killpriv() does need to be called.
+ */
 int security_inode_need_killpriv(struct dentry *dentry)
 {
        return call_int_hook(inode_need_killpriv, 0, dentry);
 }
 
+/**
+ * security_inode_killpriv() - The setuid bit is removed, update LSM state
+ * @idmap: idmap of the mount
+ * @dentry: associated dentry
+ *
+ * The @dentry's setuid bit is being removed.  Remove similar security labels.
+ * Called with the dentry->d_inode->i_mutex held.
+ *
+ * Return: Return 0 on success.  If error is returned, then the operation
+ *         causing setuid bit removal is failed.
+ */
 int security_inode_killpriv(struct mnt_idmap *idmap,
                            struct dentry *dentry)
 {
        return call_int_hook(inode_killpriv, 0, idmap, dentry);
 }
 
+/**
+ * security_inode_getsecurity() - Get the xattr security label of an inode
+ * @idmap: idmap of the mount
+ * @inode: inode
+ * @name: xattr name
+ * @buffer: security label buffer
+ * @alloc: allocation flag
+ *
+ * Retrieve a copy of the extended attribute representation of the security
+ * label associated with @name for @inode via @buffer.  Note that @name is the
+ * remainder of the attribute name after the security prefix has been removed.
+ * @alloc is used to specify if the call should return a value via the buffer
+ * or just the value length.
+ *
+ * Return: Returns size of buffer on success.
+ */
 int security_inode_getsecurity(struct mnt_idmap *idmap,
                               struct inode *inode, const char *name,
                               void **buffer, bool alloc)
@@ -1511,14 +2375,31 @@ int security_inode_getsecurity(struct mnt_idmap *idmap,
         * Only one module will provide an attribute with a given name.
         */
        hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) {
-               rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer, alloc);
+               rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer,
+                                               alloc);
                if (rc != LSM_RET_DEFAULT(inode_getsecurity))
                        return rc;
        }
        return LSM_RET_DEFAULT(inode_getsecurity);
 }
 
-int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
+/**
+ * security_inode_setsecurity() - Set the xattr security label of an inode
+ * @inode: inode
+ * @name: xattr name
+ * @value: security label
+ * @size: length of security label
+ * @flags: flags
+ *
+ * Set the security label associated with @name for @inode from the extended
+ * attribute value @value.  @size indicates the size of the @value in bytes.
+ * @flags may be XATTR_CREATE, XATTR_REPLACE, or 0. Note that @name is the
+ * remainder of the attribute name after the security. prefix has been removed.
+ *
+ * Return: Returns 0 on success.
+ */
+int security_inode_setsecurity(struct inode *inode, const char *name,
+                              const void *value, size_t size, int flags)
 {
        struct security_hook_list *hp;
        int rc;
@@ -1530,14 +2411,28 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void
         */
        hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) {
                rc = hp->hook.inode_setsecurity(inode, name, value, size,
-                                                               flags);
+                                               flags);
                if (rc != LSM_RET_DEFAULT(inode_setsecurity))
                        return rc;
        }
        return LSM_RET_DEFAULT(inode_setsecurity);
 }
 
-int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
+/**
+ * security_inode_listsecurity() - List the xattr security label names
+ * @inode: inode
+ * @buffer: buffer
+ * @buffer_size: size of buffer
+ *
+ * Copy the extended attribute names for the security labels associated with
+ * @inode into @buffer.  The maximum size of @buffer is specified by
+ * @buffer_size.  @buffer may be NULL to request the size of the buffer
+ * required.
+ *
+ * Return: Returns number of bytes used/required on success.
+ */
+int security_inode_listsecurity(struct inode *inode,
+                               char *buffer, size_t buffer_size)
 {
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
@@ -1545,17 +2440,49 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
 }
 EXPORT_SYMBOL(security_inode_listsecurity);
 
+/**
+ * security_inode_getsecid() - Get an inode's secid
+ * @inode: inode
+ * @secid: secid to return
+ *
+ * Get the secid associated with the node.  In case of failure, @secid will be
+ * set to zero.
+ */
 void security_inode_getsecid(struct inode *inode, u32 *secid)
 {
        call_void_hook(inode_getsecid, inode, secid);
 }
 
+/**
+ * security_inode_copy_up() - Create new creds for an overlayfs copy-up op
+ * @src: union dentry of copy-up file
+ * @new: newly created creds
+ *
+ * A file is about to be copied up from lower layer to upper layer of overlay
+ * filesystem. Security module can prepare a set of new creds and modify as
+ * need be and return new creds. Caller will switch to new creds temporarily to
+ * create new file and release newly allocated creds.
+ *
+ * Return: Returns 0 on success or a negative error code on error.
+ */
 int security_inode_copy_up(struct dentry *src, struct cred **new)
 {
        return call_int_hook(inode_copy_up, 0, src, new);
 }
 EXPORT_SYMBOL(security_inode_copy_up);
 
+/**
+ * security_inode_copy_up_xattr() - Filter xattrs in an overlayfs copy-up op
+ * @name: xattr name
+ *
+ * Filter the xattrs being copied up when a unioned file is copied up from a
+ * lower layer to the union/overlay layer.   The caller is responsible for
+ * reading and writing the xattrs, this hook is merely a filter.
+ *
+ * Return: Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP
+ *         if the security module does not know about attribute, or a negative
+ *         error code to abort the copy up.
+ */
 int security_inode_copy_up_xattr(const char *name)
 {
        struct security_hook_list *hp;
@@ -1567,7 +2494,7 @@ int security_inode_copy_up_xattr(const char *name)
         * any other error code incase of an error.
         */
        hlist_for_each_entry(hp,
-               &security_hook_heads.inode_copy_up_xattr, list) {
+                            &security_hook_heads.inode_copy_up_xattr, list) {
                rc = hp->hook.inode_copy_up_xattr(name);
                if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr))
                        return rc;
@@ -1577,12 +2504,41 @@ int security_inode_copy_up_xattr(const char *name)
 }
 EXPORT_SYMBOL(security_inode_copy_up_xattr);
 
+/**
+ * security_kernfs_init_security() - Init LSM context for a kernfs node
+ * @kn_dir: parent kernfs node
+ * @kn: the kernfs node to initialize
+ *
+ * Initialize the security context of a newly created kernfs node based on its
+ * own and its parent's attributes.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_kernfs_init_security(struct kernfs_node *kn_dir,
                                  struct kernfs_node *kn)
 {
        return call_int_hook(kernfs_init_security, 0, kn_dir, kn);
 }
 
+/**
+ * security_file_permission() - Check file permissions
+ * @file: file
+ * @mask: requested permissions
+ *
+ * Check file permissions before accessing an open file.  This hook is called
+ * by various operations that read or write files.  A security module can use
+ * this hook to perform additional checking on these operations, e.g. to
+ * revalidate permissions on use to support privilege bracketing or policy
+ * changes.  Notice that this hook is used when the actual read/write
+ * operations are performed, whereas the inode_security_ops hook is called when
+ * a file is opened (as well as many other operations).  Although this hook can
+ * be used to revalidate permissions for various system call operations that
+ * read or write files, it does not address the revalidation of permissions for
+ * memory-mapped files.  Security modules must handle this separately if they
+ * need such revalidation.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_permission(struct file *file, int mask)
 {
        int ret;
@@ -1594,6 +2550,15 @@ int security_file_permission(struct file *file, int mask)
        return fsnotify_perm(file, mask);
 }
 
+/**
+ * security_file_alloc() - Allocate and init a file's LSM blob
+ * @file: the file
+ *
+ * Allocate and attach a security structure to the file->f_security field.  The
+ * security field is initialized to NULL when the structure is first created.
+ *
+ * Return: Return 0 if the hook is successful and permission is granted.
+ */
 int security_file_alloc(struct file *file)
 {
        int rc = lsm_file_alloc(file);
@@ -1606,6 +2571,12 @@ int security_file_alloc(struct file *file)
        return rc;
 }
 
+/**
+ * security_file_free() - Free a file's LSM blob
+ * @file: the file
+ *
+ * Deallocate and free any security structures stored in file->f_security.
+ */
 void security_file_free(struct file *file)
 {
        void *blob;
@@ -1619,6 +2590,19 @@ void security_file_free(struct file *file)
        }
 }
 
+/**
+ * security_file_ioctl() - Check if an ioctl is allowed
+ * @file: associated file
+ * @cmd: ioctl cmd
+ * @arg: ioctl arguments
+ *
+ * Check permission for an ioctl operation on @file.  Note that @arg sometimes
+ * represents a user space pointer; in other cases, it may be a simple integer
+ * value.  When @arg represents a user space pointer, it should never be used
+ * by the security module.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        return call_int_hook(file_ioctl, 0, file, cmd, arg);
@@ -1658,8 +2642,19 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
        return prot;
 }
 
+/**
+ * security_mmap_file() - Check if mmap'ing a file is allowed
+ * @file: file
+ * @prot: protection applied by the kernel
+ * @flags: flags
+ *
+ * Check permissions for a mmap operation.  The @file may be NULL, e.g. if
+ * mapping anonymous memory.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_mmap_file(struct file *file, unsigned long prot,
-                       unsigned long flags)
+                      unsigned long flags)
 {
        unsigned long prot_adj = mmap_prot(file, prot);
        int ret;
@@ -1670,13 +2665,31 @@ int security_mmap_file(struct file *file, unsigned long prot,
        return ima_file_mmap(file, prot, prot_adj, flags);
 }
 
+/**
+ * security_mmap_addr() - Check if mmap'ing an address is allowed
+ * @addr: address
+ *
+ * Check permissions for a mmap operation at @addr.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_mmap_addr(unsigned long addr)
 {
        return call_int_hook(mmap_addr, 0, addr);
 }
 
+/**
+ * security_file_mprotect() - Check if changing memory protections is allowed
+ * @vma: memory region
+ * @reqprot: application requested protection
+ * @prot: protection applied by the kernel
+ *
+ * Check permissions before changing memory access permissions.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
-                           unsigned long prot)
+                          unsigned long prot)
 {
        int ret;
 
@@ -1686,32 +2699,97 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
        return ima_file_mprotect(vma, prot);
 }
 
+/**
+ * security_file_lock() - Check if a file lock is allowed
+ * @file: file
+ * @cmd: lock operation (e.g. F_RDLCK, F_WRLCK)
+ *
+ * Check permission before performing file locking operations.  Note the hook
+ * mediates both flock and fcntl style locks.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_lock(struct file *file, unsigned int cmd)
 {
        return call_int_hook(file_lock, 0, file, cmd);
 }
 
+/**
+ * security_file_fcntl() - Check if fcntl() op is allowed
+ * @file: file
+ * @cmd: fnctl command
+ * @arg: command argument
+ *
+ * Check permission before allowing the file operation specified by @cmd from
+ * being performed on the file @file.  Note that @arg sometimes represents a
+ * user space pointer; in other cases, it may be a simple integer value.  When
+ * @arg represents a user space pointer, it should never be used by the
+ * security module.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        return call_int_hook(file_fcntl, 0, file, cmd, arg);
 }
 
+/**
+ * security_file_set_fowner() - Set the file owner info in the LSM blob
+ * @file: the file
+ *
+ * Save owner security information (typically from current->security) in
+ * file->f_security for later use by the send_sigiotask hook.
+ *
+ * Return: Returns 0 on success.
+ */
 void security_file_set_fowner(struct file *file)
 {
        call_void_hook(file_set_fowner, file);
 }
 
+/**
+ * security_file_send_sigiotask() - Check if sending SIGIO/SIGURG is allowed
+ * @tsk: target task
+ * @fown: signal sender
+ * @sig: signal to be sent, SIGIO is sent if 0
+ *
+ * Check permission for the file owner @fown to send SIGIO or SIGURG to the
+ * process @tsk.  Note that this hook is sometimes called from interrupt.  Note
+ * that the fown_struct, @fown, is never outside the context of a struct file,
+ * so the file structure (and associated security information) can always be
+ * obtained: container_of(fown, struct file, f_owner).
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_send_sigiotask(struct task_struct *tsk,
-                                 struct fown_struct *fown, int sig)
+                                struct fown_struct *fown, int sig)
 {
        return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig);
 }
 
+/**
+ * security_file_receive() - Check is receiving a file via IPC is allowed
+ * @file: file being received
+ *
+ * This hook allows security modules to control the ability of a process to
+ * receive an open file descriptor via socket IPC.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_receive(struct file *file)
 {
        return call_int_hook(file_receive, 0, file);
 }
 
+/**
+ * security_file_open() - Save open() time state for late use by the LSM
+ * @file:
+ *
+ * Save open-time permission checking state for later use upon file_permission,
+ * and recheck access if anything has changed since inode_permission.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_open(struct file *file)
 {
        int ret;
@@ -1723,11 +2801,30 @@ int security_file_open(struct file *file)
        return fsnotify_perm(file, MAY_OPEN);
 }
 
+/**
+ * security_file_truncate() - Check if truncating a file is allowed
+ * @file: file
+ *
+ * Check permission before truncating a file, i.e. using ftruncate.  Note that
+ * truncation permission may also be checked based on the path, using the
+ * @path_truncate hook.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_file_truncate(struct file *file)
 {
        return call_int_hook(file_truncate, 0, file);
 }
 
+/**
+ * security_task_alloc() - Allocate a task's LSM blob
+ * @task: the task
+ * @clone_flags: flags indicating what is being shared
+ *
+ * Handle allocation of task-related resources.
+ *
+ * Return: Returns a zero on success, negative values on failure.
+ */
 int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
 {
        int rc = lsm_task_alloc(task);
@@ -1740,6 +2837,13 @@ int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
        return rc;
 }
 
+/**
+ * security_task_free() - Free a task's LSM blob and related resources
+ * @task: task
+ *
+ * Handle release of task-related resources.  Note that this can be called from
+ * interrupt context.
+ */
 void security_task_free(struct task_struct *task)
 {
        call_void_hook(task_free, task);
@@ -1748,6 +2852,16 @@ void security_task_free(struct task_struct *task)
        task->security = NULL;
 }
 
+/**
+ * security_cred_alloc_blank() - Allocate the min memory to allow cred_transfer
+ * @cred: credentials
+ * @gfp: gfp flags
+ *
+ * Only allocate sufficient memory and attach to @cred such that
+ * cred_transfer() will not get ENOMEM.
+ *
+ * Return: Returns 0 on success, negative values on failure.
+ */
 int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 {
        int rc = lsm_cred_alloc(cred, gfp);
@@ -1761,6 +2875,12 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
        return rc;
 }
 
+/**
+ * security_cred_free() - Free the cred's LSM blob and associated resources
+ * @cred: credentials
+ *
+ * Deallocate and clear the cred->security field in a set of credentials.
+ */
 void security_cred_free(struct cred *cred)
 {
        /*
@@ -1776,6 +2896,16 @@ void security_cred_free(struct cred *cred)
        cred->security = NULL;
 }
 
+/**
+ * security_prepare_creds() - Prepare a new set of credentials
+ * @new: new credentials
+ * @old: original credentials
+ * @gfp: gfp flags
+ *
+ * Prepare a new set of credentials by copying the data from the old set.
+ *
+ * Return: Returns 0 on success, negative values on failure.
+ */
 int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
 {
        int rc = lsm_cred_alloc(new, gfp);
@@ -1789,11 +2919,26 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
        return rc;
 }
 
+/**
+ * security_transfer_creds() - Transfer creds
+ * @new: target credentials
+ * @old: original credentials
+ *
+ * Transfer data from original creds to new creds.
+ */
 void security_transfer_creds(struct cred *new, const struct cred *old)
 {
        call_void_hook(cred_transfer, new, old);
 }
 
+/**
+ * security_cred_getsecid() - Get the secid from a set of credentials
+ * @c: credentials
+ * @secid: secid value
+ *
+ * Retrieve the security identifier of the cred structure @c.  In case of
+ * failure, @secid will be set to zero.
+ */
 void security_cred_getsecid(const struct cred *c, u32 *secid)
 {
        *secid = 0;
@@ -1801,16 +2946,46 @@ void security_cred_getsecid(const struct cred *c, u32 *secid)
 }
 EXPORT_SYMBOL(security_cred_getsecid);
 
+/**
+ * security_kernel_act_as() - Set the kernel credentials to act as secid
+ * @new: credentials
+ * @secid: secid
+ *
+ * Set the credentials for a kernel service to act as (subjective context).
+ * The current task must be the one that nominated @secid.
+ *
+ * Return: Returns 0 if successful.
+ */
 int security_kernel_act_as(struct cred *new, u32 secid)
 {
        return call_int_hook(kernel_act_as, 0, new, secid);
 }
 
+/**
+ * security_kernel_create_files_as() - Set file creation context using an inode
+ * @new: target credentials
+ * @inode: reference inode
+ *
+ * Set the file creation context in a set of credentials to be the same as the
+ * objective context of the specified inode.  The current task must be the one
+ * that nominated @inode.
+ *
+ * Return: Returns 0 if successful.
+ */
 int security_kernel_create_files_as(struct cred *new, struct inode *inode)
 {
        return call_int_hook(kernel_create_files_as, 0, new, inode);
 }
 
+/**
+ * security_kernel_module_request() - Check is loading a module is allowed
+ * @kmod_name: module name
+ *
+ * Ability to trigger the kernel to automatically upcall to userspace for
+ * userspace to load a kernel module with the given name.
+ *
+ * Return: Returns 0 if successful.
+ */
 int security_kernel_module_request(char *kmod_name)
 {
        int ret;
@@ -1821,6 +2996,16 @@ int security_kernel_module_request(char *kmod_name)
        return integrity_kernel_module_request(kmod_name);
 }
 
+/**
+ * security_kernel_read_file() - Read a file specified by userspace
+ * @file: file
+ * @id: file identifier
+ * @contents: trust if security_kernel_post_read_file() will be called
+ *
+ * Read a file specified by userspace.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_kernel_read_file(struct file *file, enum kernel_read_file_id id,
                              bool contents)
 {
@@ -1833,6 +3018,19 @@ int security_kernel_read_file(struct file *file, enum kernel_read_file_id id,
 }
 EXPORT_SYMBOL_GPL(security_kernel_read_file);
 
+/**
+ * security_kernel_post_read_file() - Read a file specified by userspace
+ * @file: file
+ * @buf: file contents
+ * @size: size of file contents
+ * @id: file identifier
+ *
+ * Read a file specified by userspace.  This must be paired with a prior call
+ * to security_kernel_read_file() call that indicated this hook would also be
+ * called, see security_kernel_read_file() for more information.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
                                   enum kernel_read_file_id id)
 {
@@ -1845,6 +3043,15 @@ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
 }
 EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
 
+/**
+ * security_kernel_load_data() - Load data provided by userspace
+ * @id: data identifier
+ * @contents: true if security_kernel_post_load_data() will be called
+ *
+ * Load data provided by userspace.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_kernel_load_data(enum kernel_load_data_id id, bool contents)
 {
        int ret;
@@ -1856,6 +3063,20 @@ int security_kernel_load_data(enum kernel_load_data_id id, bool contents)
 }
 EXPORT_SYMBOL_GPL(security_kernel_load_data);
 
+/**
+ * security_kernel_post_load_data() - Load userspace data from a non-file source
+ * @buf: data
+ * @size: size of data
+ * @id: data identifier
+ * @description: text description of data, specific to the id value
+ *
+ * Load data provided by a non-file source (usually userspace buffer).  This
+ * must be paired with a prior security_kernel_load_data() call that indicated
+ * this hook would also be called, see security_kernel_load_data() for more
+ * information.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_kernel_post_load_data(char *buf, loff_t size,
                                   enum kernel_load_data_id id,
                                   char *description)
@@ -1870,38 +3091,112 @@ int security_kernel_post_load_data(char *buf, loff_t size,
 }
 EXPORT_SYMBOL_GPL(security_kernel_post_load_data);
 
+/**
+ * security_task_fix_setuid() - Update LSM with new user id attributes
+ * @new: updated credentials
+ * @old: credentials being replaced
+ * @flags: LSM_SETID_* flag values
+ *
+ * Update the module's state after setting one or more of the user identity
+ * attributes of the current process.  The @flags parameter indicates which of
+ * the set*uid system calls invoked this hook.  If @new is the set of
+ * credentials that will be installed.  Modifications should be made to this
+ * rather than to @current->cred.
+ *
+ * Return: Returns 0 on success.
+ */
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
                             int flags)
 {
        return call_int_hook(task_fix_setuid, 0, new, old, flags);
 }
 
+/**
+ * security_task_fix_setgid() - Update LSM with new group id attributes
+ * @new: updated credentials
+ * @old: credentials being replaced
+ * @flags: LSM_SETID_* flag value
+ *
+ * Update the module's state after setting one or more of the group identity
+ * attributes of the current process.  The @flags parameter indicates which of
+ * the set*gid system calls invoked this hook.  @new is the set of credentials
+ * that will be installed.  Modifications should be made to this rather than to
+ * @current->cred.
+ *
+ * Return: Returns 0 on success.
+ */
 int security_task_fix_setgid(struct cred *new, const struct cred *old,
-                                int flags)
+                            int flags)
 {
        return call_int_hook(task_fix_setgid, 0, new, old, flags);
 }
 
+/**
+ * security_task_fix_setgroups() - Update LSM with new supplementary groups
+ * @new: updated credentials
+ * @old: credentials being replaced
+ *
+ * Update the module's state after setting the supplementary group identity
+ * attributes of the current process.  @new is the set of credentials that will
+ * be installed.  Modifications should be made to this rather than to
+ * @current->cred.
+ *
+ * Return: Returns 0 on success.
+ */
 int security_task_fix_setgroups(struct cred *new, const struct cred *old)
 {
        return call_int_hook(task_fix_setgroups, 0, new, old);
 }
 
+/**
+ * security_task_setpgid() - Check if setting the pgid is allowed
+ * @p: task being modified
+ * @pgid: new pgid
+ *
+ * Check permission before setting the process group identifier of the process
+ * @p to @pgid.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_setpgid(struct task_struct *p, pid_t pgid)
 {
        return call_int_hook(task_setpgid, 0, p, pgid);
 }
 
+/**
+ * security_task_getpgid() - Check if getting the pgid is allowed
+ * @p: task
+ *
+ * Check permission before getting the process group identifier of the process
+ * @p.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_getpgid(struct task_struct *p)
 {
        return call_int_hook(task_getpgid, 0, p);
 }
 
+/**
+ * security_task_getsid() - Check if getting the session id is allowed
+ * @p: task
+ *
+ * Check permission before getting the session identifier of the process @p.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_getsid(struct task_struct *p)
 {
        return call_int_hook(task_getsid, 0, p);
 }
 
+/**
+ * security_current_getsecid_subj() - Get the current task's subjective secid
+ * @secid: secid value
+ *
+ * Retrieve the subjective security identifier of the current task and return
+ * it in @secid.  In case of failure, @secid will be set to zero.
+ */
 void security_current_getsecid_subj(u32 *secid)
 {
        *secid = 0;
@@ -1909,6 +3204,14 @@ void security_current_getsecid_subj(u32 *secid)
 }
 EXPORT_SYMBOL(security_current_getsecid_subj);
 
+/**
+ * security_task_getsecid_obj() - Get a task's objective secid
+ * @p: target task
+ * @secid: secid value
+ *
+ * Retrieve the objective security identifier of the task_struct in @p and
+ * return it in @secid. In case of failure, @secid will be set to zero.
+ */
 void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
 {
        *secid = 0;
@@ -1916,56 +3219,159 @@ void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
 }
 EXPORT_SYMBOL(security_task_getsecid_obj);
 
+/**
+ * security_task_setnice() - Check if setting a task's nice value is allowed
+ * @p: target task
+ * @nice: nice value
+ *
+ * Check permission before setting the nice value of @p to @nice.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_setnice(struct task_struct *p, int nice)
 {
        return call_int_hook(task_setnice, 0, p, nice);
 }
 
+/**
+ * security_task_setioprio() - Check if setting a task's ioprio is allowed
+ * @p: target task
+ * @ioprio: ioprio value
+ *
+ * Check permission before setting the ioprio value of @p to @ioprio.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_setioprio(struct task_struct *p, int ioprio)
 {
        return call_int_hook(task_setioprio, 0, p, ioprio);
 }
 
+/**
+ * security_task_getioprio() - Check if getting a task's ioprio is allowed
+ * @p: task
+ *
+ * Check permission before getting the ioprio value of @p.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_getioprio(struct task_struct *p)
 {
        return call_int_hook(task_getioprio, 0, p);
 }
 
+/**
+ * security_task_prlimit() - Check if get/setting resources limits is allowed
+ * @cred: current task credentials
+ * @tcred: target task credentials
+ * @flags: LSM_PRLIMIT_* flag bits indicating a get/set/both
+ *
+ * Check permission before getting and/or setting the resource limits of
+ * another task.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_prlimit(const struct cred *cred, const struct cred *tcred,
                          unsigned int flags)
 {
        return call_int_hook(task_prlimit, 0, cred, tcred, flags);
 }
 
+/**
+ * security_task_setrlimit() - Check if setting a new rlimit value is allowed
+ * @p: target task's group leader
+ * @resource: resource whose limit is being set
+ * @new_rlim: new resource limit
+ *
+ * Check permission before setting the resource limits of process @p for
+ * @resource to @new_rlim.  The old resource limit values can be examined by
+ * dereferencing (p->signal->rlim + resource).
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_setrlimit(struct task_struct *p, unsigned int resource,
-               struct rlimit *new_rlim)
+                           struct rlimit *new_rlim)
 {
        return call_int_hook(task_setrlimit, 0, p, resource, new_rlim);
 }
 
+/**
+ * security_task_setscheduler() - Check if setting sched policy/param is allowed
+ * @p: target task
+ *
+ * Check permission before setting scheduling policy and/or parameters of
+ * process @p.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_setscheduler(struct task_struct *p)
 {
        return call_int_hook(task_setscheduler, 0, p);
 }
 
+/**
+ * security_task_getscheduler() - Check if getting scheduling info is allowed
+ * @p: target task
+ *
+ * Check permission before obtaining scheduling information for process @p.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_getscheduler(struct task_struct *p)
 {
        return call_int_hook(task_getscheduler, 0, p);
 }
 
-int security_task_movememory(struct task_struct *p)
-{
+/**
+ * security_task_movememory() - Check if moving memory is allowed
+ * @p: task
+ *
+ * Check permission before moving memory owned by process @p.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_task_movememory(struct task_struct *p)
+{
        return call_int_hook(task_movememory, 0, p);
 }
 
+/**
+ * security_task_kill() - Check if sending a signal is allowed
+ * @p: target process
+ * @info: signal information
+ * @sig: signal value
+ * @cred: credentials of the signal sender, NULL if @current
+ *
+ * Check permission before sending signal @sig to @p.  @info can be NULL, the
+ * constant 1, or a pointer to a kernel_siginfo structure.  If @info is 1 or
+ * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming from
+ * the kernel and should typically be permitted.  SIGIO signals are handled
+ * separately by the send_sigiotask hook in file_security_ops.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_task_kill(struct task_struct *p, struct kernel_siginfo *info,
-                       int sig, const struct cred *cred)
+                      int sig, const struct cred *cred)
 {
        return call_int_hook(task_kill, 0, p, info, sig, cred);
 }
 
+/**
+ * security_task_prctl() - Check if a prctl op is allowed
+ * @option: operation
+ * @arg2: argument
+ * @arg3: argument
+ * @arg4: argument
+ * @arg5: argument
+ *
+ * Check permission before performing a process control operation on the
+ * current process.
+ *
+ * Return: Return -ENOSYS if no-one wanted to handle this op, any other value
+ *         to cause prctl() to return immediately with that value.
+ */
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
-                        unsigned long arg4, unsigned long arg5)
+                       unsigned long arg4, unsigned long arg5)
 {
        int thisrc;
        int rc = LSM_RET_DEFAULT(task_prctl);
@@ -1982,27 +3388,69 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
        return rc;
 }
 
+/**
+ * security_task_to_inode() - Set the security attributes of a task's inode
+ * @p: task
+ * @inode: inode
+ *
+ * Set the security attributes for an inode based on an associated task's
+ * security attributes, e.g. for /proc/pid inodes.
+ */
 void security_task_to_inode(struct task_struct *p, struct inode *inode)
 {
        call_void_hook(task_to_inode, p, inode);
 }
 
+/**
+ * security_create_user_ns() - Check if creating a new userns is allowed
+ * @cred: prepared creds
+ *
+ * Check permission prior to creating a new user namespace.
+ *
+ * Return: Returns 0 if successful, otherwise < 0 error code.
+ */
 int security_create_user_ns(const struct cred *cred)
 {
        return call_int_hook(userns_create, 0, cred);
 }
 
+/**
+ * security_ipc_permission() - Check if sysv ipc access is allowed
+ * @ipcp: ipc permission structure
+ * @flag: requested permissions
+ *
+ * Check permissions for access to IPC.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
 {
        return call_int_hook(ipc_permission, 0, ipcp, flag);
 }
 
+/**
+ * security_ipc_getsecid() - Get the sysv ipc object's secid
+ * @ipcp: ipc permission structure
+ * @secid: secid pointer
+ *
+ * Get the secid associated with the ipc object.  In case of failure, @secid
+ * will be set to zero.
+ */
 void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
 {
        *secid = 0;
        call_void_hook(ipc_getsecid, ipcp, secid);
 }
 
+/**
+ * security_msg_msg_alloc() - Allocate a sysv ipc message LSM blob
+ * @msg: message structure
+ *
+ * Allocate and attach a security structure to the msg->security field.  The
+ * security field is initialized to NULL when the structure is first created.
+ *
+ * Return: Return 0 if operation was successful and permission is granted.
+ */
 int security_msg_msg_alloc(struct msg_msg *msg)
 {
        int rc = lsm_msg_msg_alloc(msg);
@@ -2015,6 +3463,12 @@ int security_msg_msg_alloc(struct msg_msg *msg)
        return rc;
 }
 
+/**
+ * security_msg_msg_free() - Free a sysv ipc message LSM blob
+ * @msg: message structure
+ *
+ * Deallocate the security structure for this message.
+ */
 void security_msg_msg_free(struct msg_msg *msg)
 {
        call_void_hook(msg_msg_free_security, msg);
@@ -2022,6 +3476,15 @@ void security_msg_msg_free(struct msg_msg *msg)
        msg->security = NULL;
 }
 
+/**
+ * security_msg_queue_alloc() - Allocate a sysv ipc msg queue LSM blob
+ * @msq: sysv ipc permission structure
+ *
+ * Allocate and attach a security structure to @msg. The security field is
+ * initialized to NULL when the structure is first created.
+ *
+ * Return: Returns 0 if operation was successful and permission is granted.
+ */
 int security_msg_queue_alloc(struct kern_ipc_perm *msq)
 {
        int rc = lsm_ipc_alloc(msq);
@@ -2034,6 +3497,12 @@ int security_msg_queue_alloc(struct kern_ipc_perm *msq)
        return rc;
 }
 
+/**
+ * security_msg_queue_free() - Free a sysv ipc msg queue LSM blob
+ * @msq: sysv ipc permission structure
+ *
+ * Deallocate security field @perm->security for the message queue.
+ */
 void security_msg_queue_free(struct kern_ipc_perm *msq)
 {
        call_void_hook(msg_queue_free_security, msq);
@@ -2041,28 +3510,84 @@ void security_msg_queue_free(struct kern_ipc_perm *msq)
        msq->security = NULL;
 }
 
+/**
+ * security_msg_queue_associate() - Check if a msg queue operation is allowed
+ * @msq: sysv ipc permission structure
+ * @msqflg: operation flags
+ *
+ * Check permission when a message queue is requested through the msgget system
+ * call. This hook is only called when returning the message queue identifier
+ * for an existing message queue, not when a new message queue is created.
+ *
+ * Return: Return 0 if permission is granted.
+ */
 int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
 {
        return call_int_hook(msg_queue_associate, 0, msq, msqflg);
 }
 
+/**
+ * security_msg_queue_msgctl() - Check if a msg queue operation is allowed
+ * @msq: sysv ipc permission structure
+ * @cmd: operation
+ *
+ * Check permission when a message control operation specified by @cmd is to be
+ * performed on the message queue with permissions.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
 {
        return call_int_hook(msg_queue_msgctl, 0, msq, cmd);
 }
 
+/**
+ * security_msg_queue_msgsnd() - Check if sending a sysv ipc message is allowed
+ * @msq: sysv ipc permission structure
+ * @msg: message
+ * @msqflg: operation flags
+ *
+ * Check permission before a message, @msg, is enqueued on the message queue
+ * with permissions specified in @msq.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
-                              struct msg_msg *msg, int msqflg)
+                             struct msg_msg *msg, int msqflg)
 {
        return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg);
 }
 
+/**
+ * security_msg_queue_msgrcv() - Check if receiving a sysv ipc msg is allowed
+ * @msq: sysv ipc permission structure
+ * @msg: message
+ * @target: target task
+ * @type: type of message requested
+ * @mode: operation flags
+ *
+ * Check permission before a message, @msg, is removed from the message        queue.
+ * The @target task structure contains a pointer to the process that will be
+ * receiving the message (not equal to the current process when inline receives
+ * are being performed).
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
-                              struct task_struct *target, long type, int mode)
+                             struct task_struct *target, long type, int mode)
 {
        return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode);
 }
 
+/**
+ * security_shm_alloc() - Allocate a sysv shm LSM blob
+ * @shp: sysv ipc permission structure
+ *
+ * Allocate and attach a security structure to the @shp security field.  The
+ * security field is initialized to NULL when the structure is first created.
+ *
+ * Return: Returns 0 if operation was successful and permission is granted.
+ */
 int security_shm_alloc(struct kern_ipc_perm *shp)
 {
        int rc = lsm_ipc_alloc(shp);
@@ -2075,6 +3600,12 @@ int security_shm_alloc(struct kern_ipc_perm *shp)
        return rc;
 }
 
+/**
+ * security_shm_free() - Free a sysv shm LSM blob
+ * @shp: sysv ipc permission structure
+ *
+ * Deallocate the security structure @perm->security for the memory segment.
+ */
 void security_shm_free(struct kern_ipc_perm *shp)
 {
        call_void_hook(shm_free_security, shp);
@@ -2082,21 +3613,65 @@ void security_shm_free(struct kern_ipc_perm *shp)
        shp->security = NULL;
 }
 
+/**
+ * security_shm_associate() - Check if a sysv shm operation is allowed
+ * @shp: sysv ipc permission structure
+ * @shmflg: operation flags
+ *
+ * Check permission when a shared memory region is requested through the shmget
+ * system call. This hook is only called when returning the shared memory
+ * region identifier for an existing region, not when a new shared memory
+ * region is created.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
 {
        return call_int_hook(shm_associate, 0, shp, shmflg);
 }
 
+/**
+ * security_shm_shmctl() - Check if a sysv shm operation is allowed
+ * @shp: sysv ipc permission structure
+ * @cmd: operation
+ *
+ * Check permission when a shared memory control operation specified by @cmd is
+ * to be performed on the shared memory region with permissions in @shp.
+ *
+ * Return: Return 0 if permission is granted.
+ */
 int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
 {
        return call_int_hook(shm_shmctl, 0, shp, cmd);
 }
 
-int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg)
+/**
+ * security_shm_shmat() - Check if a sysv shm attach operation is allowed
+ * @shp: sysv ipc permission structure
+ * @shmaddr: address of memory region to attach
+ * @shmflg: operation flags
+ *
+ * Check permissions prior to allowing the shmat system call to attach the
+ * shared memory segment with permissions @shp to the data segment of the
+ * calling process. The attaching address is specified by @shmaddr.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_shm_shmat(struct kern_ipc_perm *shp,
+                      char __user *shmaddr, int shmflg)
 {
        return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg);
 }
 
+/**
+ * security_sem_alloc() - Allocate a sysv semaphore LSM blob
+ * @sma: sysv ipc permission structure
+ *
+ * Allocate and attach a security structure to the @sma security field. The
+ * security field is initialized to NULL when the structure is first created.
+ *
+ * Return: Returns 0 if operation was successful and permission is granted.
+ */
 int security_sem_alloc(struct kern_ipc_perm *sma)
 {
        int rc = lsm_ipc_alloc(sma);
@@ -2109,6 +3684,12 @@ int security_sem_alloc(struct kern_ipc_perm *sma)
        return rc;
 }
 
+/**
+ * security_sem_free() - Free a sysv semaphore LSM blob
+ * @sma: sysv ipc permission structure
+ *
+ * Deallocate security structure @sma->security for the semaphore.
+ */
 void security_sem_free(struct kern_ipc_perm *sma)
 {
        call_void_hook(sem_free_security, sma);
@@ -2116,22 +3697,62 @@ void security_sem_free(struct kern_ipc_perm *sma)
        sma->security = NULL;
 }
 
+/**
+ * security_sem_associate() - Check if a sysv semaphore operation is allowed
+ * @sma: sysv ipc permission structure
+ * @semflg: operation flags
+ *
+ * Check permission when a semaphore is requested through the semget system
+ * call. This hook is only called when returning the semaphore identifier for
+ * an existing semaphore, not when a new one must be created.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
 {
        return call_int_hook(sem_associate, 0, sma, semflg);
 }
 
+/**
+ * security_sem_semctl() - Check if a sysv semaphore operation is allowed
+ * @sma: sysv ipc permission structure
+ * @cmd: operation
+ *
+ * Check permission when a semaphore operation specified by @cmd is to be
+ * performed on the semaphore.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
 {
        return call_int_hook(sem_semctl, 0, sma, cmd);
 }
 
+/**
+ * security_sem_semop() - Check if a sysv semaphore operation is allowed
+ * @sma: sysv ipc permission structure
+ * @sops: operations to perform
+ * @nsops: number of operations
+ * @alter: flag indicating changes will be made
+ *
+ * Check permissions before performing operations on members of the semaphore
+ * set. If the @alter flag is nonzero, the semaphore set may be modified.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
-                       unsigned nsops, int alter)
+                      unsigned nsops, int alter)
 {
        return call_int_hook(sem_semop, 0, sma, sops, nsops, alter);
 }
 
+/**
+ * security_d_instantiate() - Populate an inode's LSM state based on a dentry
+ * @dentry: dentry
+ * @inode: inode
+ *
+ * Fill in @inode security information for a @dentry if allowed.
+ */
 void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 {
        if (unlikely(inode && IS_PRIVATE(inode)))
@@ -2140,6 +3761,17 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode)
 }
 EXPORT_SYMBOL(security_d_instantiate);
 
+/**
+ * security_getprocattr() - Read an attribute for a task
+ * @p: the task
+ * @lsm: LSM name
+ * @name: attribute name
+ * @value: attribute value
+ *
+ * Read attribute @name for task @p and store it into @value if allowed.
+ *
+ * Return: Returns the length of @value on success, a negative value otherwise.
+ */
 int security_getprocattr(struct task_struct *p, const char *lsm,
                         const char *name, char **value)
 {
@@ -2153,6 +3785,18 @@ int security_getprocattr(struct task_struct *p, const char *lsm,
        return LSM_RET_DEFAULT(getprocattr);
 }
 
+/**
+ * security_setprocattr() - Set an attribute for a task
+ * @lsm: LSM name
+ * @name: attribute name
+ * @value: attribute value
+ * @size: attribute value size
+ *
+ * Write (set) the current task's attribute @name to @value, size @size if
+ * allowed.
+ *
+ * Return: Returns bytes written on success, a negative value otherwise.
+ */
 int security_setprocattr(const char *lsm, const char *name, void *value,
                         size_t size)
 {
@@ -2166,17 +3810,51 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
        return LSM_RET_DEFAULT(setprocattr);
 }
 
+/**
+ * security_netlink_send() - Save info and check if netlink sending is allowed
+ * @sk: sending socket
+ * @skb: netlink message
+ *
+ * Save security information for a netlink message so that permission checking
+ * can be performed when the message is processed.  The security information
+ * can be saved using the eff_cap field of the netlink_skb_parms structure.
+ * Also may be used to provide fine grained control over message transmission.
+ *
+ * Return: Returns 0 if the information was successfully saved and message is
+ *         allowed to be transmitted.
+ */
 int security_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
        return call_int_hook(netlink_send, 0, sk, skb);
 }
 
+/**
+ * security_ismaclabel() - Check is the named attribute is a MAC label
+ * @name: full extended attribute name
+ *
+ * Check if the extended attribute specified by @name represents a MAC label.
+ *
+ * Return: Returns 1 if name is a MAC attribute otherwise returns 0.
+ */
 int security_ismaclabel(const char *name)
 {
        return call_int_hook(ismaclabel, 0, name);
 }
 EXPORT_SYMBOL(security_ismaclabel);
 
+/**
+ * security_secid_to_secctx() - Convert a secid to a secctx
+ * @secid: secid
+ * @secdata: secctx
+ * @seclen: secctx length
+ *
+ * Convert secid to security context.  If @secdata is NULL the length of the
+ * result will be returned in @seclen, but no @secdata will be returned.  This
+ * does mean that the length could change between calls to check the length and
+ * the next call which actually allocates and returns the @secdata.
+ *
+ * Return: Return 0 on success, error on failure.
+ */
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
        struct security_hook_list *hp;
@@ -2196,6 +3874,16 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 }
 EXPORT_SYMBOL(security_secid_to_secctx);
 
+/**
+ * security_secctx_to_secid() - Convert a secctx to a secid
+ * @secdata: secctx
+ * @seclen: length of secctx
+ * @secid: secid
+ *
+ * Convert security context to secid.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
        *secid = 0;
@@ -2203,30 +3891,86 @@ int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 }
 EXPORT_SYMBOL(security_secctx_to_secid);
 
+/**
+ * security_release_secctx() - Free a secctx buffer
+ * @secdata: secctx
+ * @seclen: length of secctx
+ *
+ * Release the security context.
+ */
 void security_release_secctx(char *secdata, u32 seclen)
 {
        call_void_hook(release_secctx, secdata, seclen);
 }
 EXPORT_SYMBOL(security_release_secctx);
 
+/**
+ * security_inode_invalidate_secctx() - Invalidate an inode's security label
+ * @inode: inode
+ *
+ * Notify the security module that it must revalidate the security context of
+ * an inode.
+ */
 void security_inode_invalidate_secctx(struct inode *inode)
 {
        call_void_hook(inode_invalidate_secctx, inode);
 }
 EXPORT_SYMBOL(security_inode_invalidate_secctx);
 
+/**
+ * security_inode_notifysecctx() - Nofify the LSM of an inode's security label
+ * @inode: inode
+ * @ctx: secctx
+ * @ctxlen: length of secctx
+ *
+ * Notify the security module of what the security context of an inode should
+ * be.  Initializes the incore security context managed by the security module
+ * for this inode.  Example usage: NFS client invokes this hook to initialize
+ * the security context in its incore inode to the value provided by the server
+ * for the file when the server returned the file's attributes to the client.
+ * Must be called with inode->i_mutex locked.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
 {
        return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen);
 }
 EXPORT_SYMBOL(security_inode_notifysecctx);
 
+/**
+ * security_inode_setsecctx() - Change the security label of an inode
+ * @dentry: inode
+ * @ctx: secctx
+ * @ctxlen: length of secctx
+ *
+ * Change the security context of an inode.  Updates the incore security
+ * context managed by the security module and invokes the fs code as needed
+ * (via __vfs_setxattr_noperm) to update any backing xattrs that represent the
+ * context.  Example usage: NFS server invokes this hook to change the security
+ * context in its incore inode and on the backing filesystem to a value
+ * provided by the client on a SETATTR operation.  Must be called with
+ * inode->i_mutex locked.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
 {
        return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen);
 }
 EXPORT_SYMBOL(security_inode_setsecctx);
 
+/**
+ * security_inode_getsecctx() - Get the security label of an inode
+ * @inode: inode
+ * @ctx: secctx
+ * @ctxlen: length of secctx
+ *
+ * On success, returns 0 and fills out @ctx and @ctxlen with the security
+ * context for the given @inode.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
 {
        return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen);
@@ -2234,6 +3978,16 @@ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
 EXPORT_SYMBOL(security_inode_getsecctx);
 
 #ifdef CONFIG_WATCH_QUEUE
+/**
+ * security_post_notification() - Check if a watch notification can be posted
+ * @w_cred: credentials of the task that set the watch
+ * @cred: credentials of the task which triggered the watch
+ * @n: the notification
+ *
+ * Check to see if a watch notification can be posted to a particular queue.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_post_notification(const struct cred *w_cred,
                               const struct cred *cred,
                               struct watch_notification *n)
@@ -2243,106 +3997,336 @@ int security_post_notification(const struct cred *w_cred,
 #endif /* CONFIG_WATCH_QUEUE */
 
 #ifdef CONFIG_KEY_NOTIFICATIONS
+/**
+ * security_watch_key() - Check if a task is allowed to watch for key events
+ * @key: the key to watch
+ *
+ * Check to see if a process is allowed to watch for event notifications from
+ * a key or keyring.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_watch_key(struct key *key)
 {
        return call_int_hook(watch_key, 0, key);
 }
-#endif
+#endif /* CONFIG_KEY_NOTIFICATIONS */
 
 #ifdef CONFIG_SECURITY_NETWORK
-
-int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
+/**
+ * security_unix_stream_connect() - Check if a AF_UNIX stream is allowed
+ * @sock: originating sock
+ * @other: peer sock
+ * @newsk: new sock
+ *
+ * Check permissions before establishing a Unix domain stream connection
+ * between @sock and @other.
+ *
+ * The @unix_stream_connect and @unix_may_send hooks were necessary because
+ * Linux provides an alternative to the conventional file name space for Unix
+ * domain sockets.  Whereas binding and connecting to sockets in the file name
+ * space is mediated by the typical file permissions (and caught by the mknod
+ * and permission hooks in inode_security_ops), binding and connecting to
+ * sockets in the abstract name space is completely unmediated.  Sufficient
+ * control of Unix domain sockets in the abstract name space isn't possible
+ * using only the socket layer hooks, since we need to know the actual target
+ * socket, which is not looked up until we are inside the af_unix code.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_unix_stream_connect(struct sock *sock, struct sock *other,
+                                struct sock *newsk)
 {
        return call_int_hook(unix_stream_connect, 0, sock, other, newsk);
 }
 EXPORT_SYMBOL(security_unix_stream_connect);
 
+/**
+ * security_unix_may_send() - Check if AF_UNIX socket can send datagrams
+ * @sock: originating sock
+ * @other: peer sock
+ *
+ * Check permissions before connecting or sending datagrams from @sock to
+ * @other.
+ *
+ * The @unix_stream_connect and @unix_may_send hooks were necessary because
+ * Linux provides an alternative to the conventional file name space for Unix
+ * domain sockets.  Whereas binding and connecting to sockets in the file name
+ * space is mediated by the typical file permissions (and caught by the mknod
+ * and permission hooks in inode_security_ops), binding and connecting to
+ * sockets in the abstract name space is completely unmediated.  Sufficient
+ * control of Unix domain sockets in the abstract name space isn't possible
+ * using only the socket layer hooks, since we need to know the actual target
+ * socket, which is not looked up until we are inside the af_unix code.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_unix_may_send(struct socket *sock,  struct socket *other)
 {
        return call_int_hook(unix_may_send, 0, sock, other);
 }
 EXPORT_SYMBOL(security_unix_may_send);
 
+/**
+ * security_socket_create() - Check if creating a new socket is allowed
+ * @family: protocol family
+ * @type: communications type
+ * @protocol: requested protocol
+ * @kern: set to 1 if a kernel socket is requested
+ *
+ * Check permissions prior to creating a new socket.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_create(int family, int type, int protocol, int kern)
 {
        return call_int_hook(socket_create, 0, family, type, protocol, kern);
 }
 
+/**
+ * security_socket_post_create() - Initialize a newly created socket
+ * @sock: socket
+ * @family: protocol family
+ * @type: communications type
+ * @protocol: requested protocol
+ * @kern: set to 1 if a kernel socket is requested
+ *
+ * This hook allows a module to update or allocate a per-socket security
+ * structure. Note that the security field was not added directly to the socket
+ * structure, but rather, the socket security information is stored in the
+ * associated inode.  Typically, the inode alloc_security hook will allocate
+ * and attach security information to SOCK_INODE(sock)->i_security.  This hook
+ * may be used to update the SOCK_INODE(sock)->i_security field with additional
+ * information that wasn't available when the inode was allocated.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_post_create(struct socket *sock, int family,
                                int type, int protocol, int kern)
 {
        return call_int_hook(socket_post_create, 0, sock, family, type,
-                                               protocol, kern);
+                            protocol, kern);
 }
 
+/**
+ * security_socket_socketpair() - Check if creating a socketpair is allowed
+ * @socka: first socket
+ * @sockb: second socket
+ *
+ * Check permissions before creating a fresh pair of sockets.
+ *
+ * Return: Returns 0 if permission is granted and the connection was
+ *         established.
+ */
 int security_socket_socketpair(struct socket *socka, struct socket *sockb)
 {
        return call_int_hook(socket_socketpair, 0, socka, sockb);
 }
 EXPORT_SYMBOL(security_socket_socketpair);
 
-int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
+/**
+ * security_socket_bind() - Check if a socket bind operation is allowed
+ * @sock: socket
+ * @address: requested bind address
+ * @addrlen: length of address
+ *
+ * Check permission before socket protocol layer bind operation is performed
+ * and the socket @sock is bound to the address specified in the @address
+ * parameter.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_socket_bind(struct socket *sock,
+                        struct sockaddr *address, int addrlen)
 {
        return call_int_hook(socket_bind, 0, sock, address, addrlen);
 }
 
-int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
+/**
+ * security_socket_connect() - Check if a socket connect operation is allowed
+ * @sock: socket
+ * @address: address of remote connection point
+ * @addrlen: length of address
+ *
+ * Check permission before socket protocol layer connect operation attempts to
+ * connect socket @sock to a remote address, @address.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_socket_connect(struct socket *sock,
+                           struct sockaddr *address, int addrlen)
 {
        return call_int_hook(socket_connect, 0, sock, address, addrlen);
 }
 
+/**
+ * security_socket_listen() - Check if a socket is allowed to listen
+ * @sock: socket
+ * @backlog: connection queue size
+ *
+ * Check permission before socket protocol layer listen operation.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_listen(struct socket *sock, int backlog)
 {
        return call_int_hook(socket_listen, 0, sock, backlog);
 }
 
+/**
+ * security_socket_accept() - Check if a socket is allowed to accept connections
+ * @sock: listening socket
+ * @newsock: newly creation connection socket
+ *
+ * Check permission before accepting a new connection.  Note that the new
+ * socket, @newsock, has been created and some information copied to it, but
+ * the accept operation has not actually been performed.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_accept(struct socket *sock, struct socket *newsock)
 {
        return call_int_hook(socket_accept, 0, sock, newsock);
 }
 
+/**
+ * security_socket_sendmsg() - Check is sending a message is allowed
+ * @sock: sending socket
+ * @msg: message to send
+ * @size: size of message
+ *
+ * Check permission before transmitting a message to another socket.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
 {
        return call_int_hook(socket_sendmsg, 0, sock, msg, size);
 }
 
+/**
+ * security_socket_recvmsg() - Check if receiving a message is allowed
+ * @sock: receiving socket
+ * @msg: message to receive
+ * @size: size of message
+ * @flags: operational flags
+ *
+ * Check permission before receiving a message from a socket.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
                            int size, int flags)
 {
        return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags);
 }
 
+/**
+ * security_socket_getsockname() - Check if reading the socket addr is allowed
+ * @sock: socket
+ *
+ * Check permission before reading the local address (name) of the socket
+ * object.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_getsockname(struct socket *sock)
 {
        return call_int_hook(socket_getsockname, 0, sock);
 }
 
+/**
+ * security_socket_getpeername() - Check if reading the peer's addr is allowed
+ * @sock: socket
+ *
+ * Check permission before the remote address (name) of a socket object.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_getpeername(struct socket *sock)
 {
        return call_int_hook(socket_getpeername, 0, sock);
 }
 
+/**
+ * security_socket_getsockopt() - Check if reading a socket option is allowed
+ * @sock: socket
+ * @level: option's protocol level
+ * @optname: option name
+ *
+ * Check permissions before retrieving the options associated with socket
+ * @sock.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_getsockopt(struct socket *sock, int level, int optname)
 {
        return call_int_hook(socket_getsockopt, 0, sock, level, optname);
 }
 
+/**
+ * security_socket_setsockopt() - Check if setting a socket option is allowed
+ * @sock: socket
+ * @level: option's protocol level
+ * @optname: option name
+ *
+ * Check permissions before setting the options associated with socket @sock.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_setsockopt(struct socket *sock, int level, int optname)
 {
        return call_int_hook(socket_setsockopt, 0, sock, level, optname);
 }
 
+/**
+ * security_socket_shutdown() - Checks if shutting down the socket is allowed
+ * @sock: socket
+ * @how: flag indicating how sends and receives are handled
+ *
+ * Checks permission before all or part of a connection on the socket @sock is
+ * shut down.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_socket_shutdown(struct socket *sock, int how)
 {
        return call_int_hook(socket_shutdown, 0, sock, how);
 }
 
+/**
+ * security_sock_rcv_skb() - Check if an incoming network packet is allowed
+ * @sk: destination sock
+ * @skb: incoming packet
+ *
+ * Check permissions on incoming network packets.  This hook is distinct from
+ * Netfilter's IP input hooks since it is the first time that the incoming
+ * sk_buff @skb has been associated with a particular socket, @sk.  Must not
+ * sleep inside this hook because some callers hold spinlocks.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        return call_int_hook(socket_sock_rcv_skb, 0, sk, skb);
 }
 EXPORT_SYMBOL(security_sock_rcv_skb);
 
+/**
+ * security_socket_getpeersec_stream() - Get the remote peer label
+ * @sock: socket
+ * @optval: destination buffer
+ * @optlen: size of peer label copied into the buffer
+ * @len: maximum size of the destination buffer
+ *
+ * This hook allows the security module to provide peer socket security state
+ * for unix or connected tcp sockets to userspace via getsockopt SO_GETPEERSEC.
+ * For tcp sockets this can be meaningful if the socket is associated with an
+ * ipsec SA.
+ *
+ * Return: Returns 0 if all is well, otherwise, typical getsockopt return
+ *         values.
+ */
 int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval,
                                      sockptr_t optlen, unsigned int len)
 {
@@ -2350,23 +4334,62 @@ int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval,
                             optval, optlen, len);
 }
 
-int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
+/**
+ * security_socket_getpeersec_dgram() - Get the remote peer label
+ * @sock: socket
+ * @skb: datagram packet
+ * @secid: remote peer label secid
+ *
+ * This hook allows the security module to provide peer socket security state
+ * for udp sockets on a per-packet basis to userspace via getsockopt
+ * SO_GETPEERSEC. The application must first have indicated the IP_PASSSEC
+ * option via getsockopt. It can then retrieve the security state returned by
+ * this hook for a packet via the SCM_SECURITY ancillary message type.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
+int security_socket_getpeersec_dgram(struct socket *sock,
+                                    struct sk_buff *skb, u32 *secid)
 {
        return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock,
                             skb, secid);
 }
 EXPORT_SYMBOL(security_socket_getpeersec_dgram);
 
+/**
+ * security_sk_alloc() - Allocate and initialize a sock's LSM blob
+ * @sk: sock
+ * @family: protocol family
+ * @priority: gfp flags
+ *
+ * Allocate and attach a security structure to the sk->sk_security field, which
+ * is used to copy security attributes between local stream sockets.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
 {
        return call_int_hook(sk_alloc_security, 0, sk, family, priority);
 }
 
+/**
+ * security_sk_free() - Free the sock's LSM blob
+ * @sk: sock
+ *
+ * Deallocate security structure.
+ */
 void security_sk_free(struct sock *sk)
 {
        call_void_hook(sk_free_security, sk);
 }
 
+/**
+ * security_sk_clone() - Clone a sock's LSM state
+ * @sk: original sock
+ * @newsk: target sock
+ *
+ * Clone/copy security structure.
+ */
 void security_sk_clone(const struct sock *sk, struct sock *newsk)
 {
        call_void_hook(sk_clone_security, sk, newsk);
@@ -2379,6 +4402,13 @@ void security_sk_classify_flow(struct sock *sk, struct flowi_common *flic)
 }
 EXPORT_SYMBOL(security_sk_classify_flow);
 
+/**
+ * security_req_classify_flow() - Set a flow's secid based on request_sock
+ * @req: request_sock
+ * @flic: target flow
+ *
+ * Sets @flic's secid to @req's secid.
+ */
 void security_req_classify_flow(const struct request_sock *req,
                                struct flowi_common *flic)
 {
@@ -2386,92 +4416,215 @@ void security_req_classify_flow(const struct request_sock *req,
 }
 EXPORT_SYMBOL(security_req_classify_flow);
 
+/**
+ * security_sock_graft() - Reconcile LSM state when grafting a sock on a socket
+ * @sk: sock being grafted
+ * @parent: target parent socket
+ *
+ * Sets @parent's inode secid to @sk's secid and update @sk with any necessary
+ * LSM state from @parent.
+ */
 void security_sock_graft(struct sock *sk, struct socket *parent)
 {
        call_void_hook(sock_graft, sk, parent);
 }
 EXPORT_SYMBOL(security_sock_graft);
 
+/**
+ * security_inet_conn_request() - Set request_sock state using incoming connect
+ * @sk: parent listening sock
+ * @skb: incoming connection
+ * @req: new request_sock
+ *
+ * Initialize the @req LSM state based on @sk and the incoming connect in @skb.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_inet_conn_request(const struct sock *sk,
-                       struct sk_buff *skb, struct request_sock *req)
+                              struct sk_buff *skb, struct request_sock *req)
 {
        return call_int_hook(inet_conn_request, 0, sk, skb, req);
 }
 EXPORT_SYMBOL(security_inet_conn_request);
 
+/**
+ * security_inet_csk_clone() - Set new sock LSM state based on request_sock
+ * @newsk: new sock
+ * @req: connection request_sock
+ *
+ * Set that LSM state of @sock using the LSM state from @req.
+ */
 void security_inet_csk_clone(struct sock *newsk,
-                       const struct request_sock *req)
+                            const struct request_sock *req)
 {
        call_void_hook(inet_csk_clone, newsk, req);
 }
 
+/**
+ * security_inet_conn_established() - Update sock's LSM state with connection
+ * @sk: sock
+ * @skb: connection packet
+ *
+ * Update @sock's LSM state to represent a new connection from @skb.
+ */
 void security_inet_conn_established(struct sock *sk,
-                       struct sk_buff *skb)
+                                   struct sk_buff *skb)
 {
        call_void_hook(inet_conn_established, sk, skb);
 }
 EXPORT_SYMBOL(security_inet_conn_established);
 
+/**
+ * security_secmark_relabel_packet() - Check if setting a secmark is allowed
+ * @secid: new secmark value
+ *
+ * Check if the process should be allowed to relabel packets to @secid.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_secmark_relabel_packet(u32 secid)
 {
        return call_int_hook(secmark_relabel_packet, 0, secid);
 }
 EXPORT_SYMBOL(security_secmark_relabel_packet);
 
+/**
+ * security_secmark_refcount_inc() - Increment the secmark labeling rule count
+ *
+ * Tells the LSM to increment the number of secmark labeling rules loaded.
+ */
 void security_secmark_refcount_inc(void)
 {
        call_void_hook(secmark_refcount_inc);
 }
 EXPORT_SYMBOL(security_secmark_refcount_inc);
 
+/**
+ * security_secmark_refcount_dec() - Decrement the secmark labeling rule count
+ *
+ * Tells the LSM to decrement the number of secmark labeling rules loaded.
+ */
 void security_secmark_refcount_dec(void)
 {
        call_void_hook(secmark_refcount_dec);
 }
 EXPORT_SYMBOL(security_secmark_refcount_dec);
 
+/**
+ * security_tun_dev_alloc_security() - Allocate a LSM blob for a TUN device
+ * @security: pointer to the LSM blob
+ *
+ * This hook allows a module to allocate a security structure for a TUN        device,
+ * returning the pointer in @security.
+ *
+ * Return: Returns a zero on success, negative values on failure.
+ */
 int security_tun_dev_alloc_security(void **security)
 {
        return call_int_hook(tun_dev_alloc_security, 0, security);
 }
 EXPORT_SYMBOL(security_tun_dev_alloc_security);
 
+/**
+ * security_tun_dev_free_security() - Free a TUN device LSM blob
+ * @security: LSM blob
+ *
+ * This hook allows a module to free the security structure for a TUN device.
+ */
 void security_tun_dev_free_security(void *security)
 {
        call_void_hook(tun_dev_free_security, security);
 }
 EXPORT_SYMBOL(security_tun_dev_free_security);
 
+/**
+ * security_tun_dev_create() - Check if creating a TUN device is allowed
+ *
+ * Check permissions prior to creating a new TUN device.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_tun_dev_create(void)
 {
        return call_int_hook(tun_dev_create, 0);
 }
 EXPORT_SYMBOL(security_tun_dev_create);
 
+/**
+ * security_tun_dev_attach_queue() - Check if attaching a TUN queue is allowed
+ * @security: TUN device LSM blob
+ *
+ * Check permissions prior to attaching to a TUN device queue.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_tun_dev_attach_queue(void *security)
 {
        return call_int_hook(tun_dev_attach_queue, 0, security);
 }
 EXPORT_SYMBOL(security_tun_dev_attach_queue);
 
+/**
+ * security_tun_dev_attach() - Update TUN device LSM state on attach
+ * @sk: associated sock
+ * @security: TUN device LSM blob
+ *
+ * This hook can be used by the module to update any security state associated
+ * with the TUN device's sock structure.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_tun_dev_attach(struct sock *sk, void *security)
 {
        return call_int_hook(tun_dev_attach, 0, sk, security);
 }
 EXPORT_SYMBOL(security_tun_dev_attach);
 
+/**
+ * security_tun_dev_open() - Update TUN device LSM state on open
+ * @security: TUN device LSM blob
+ *
+ * This hook can be used by the module to update any security state associated
+ * with the TUN device's security structure.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_tun_dev_open(void *security)
 {
        return call_int_hook(tun_dev_open, 0, security);
 }
 EXPORT_SYMBOL(security_tun_dev_open);
 
-int security_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb)
+/**
+ * security_sctp_assoc_request() - Update the LSM on a SCTP association req
+ * @asoc: SCTP association
+ * @skb: packet requesting the association
+ *
+ * Passes the @asoc and @chunk->skb of the association INIT packet to the LSM.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
+int security_sctp_assoc_request(struct sctp_association *asoc,
+                               struct sk_buff *skb)
 {
        return call_int_hook(sctp_assoc_request, 0, asoc, skb);
 }
 EXPORT_SYMBOL(security_sctp_assoc_request);
 
+/**
+ * security_sctp_bind_connect() - Validate a list of addrs for a SCTP option
+ * @sk: socket
+ * @optname: SCTP option to validate
+ * @address: list of IP addresses to validate
+ * @addrlen: length of the address list
+ *
+ * Validiate permissions required for each address associated with sock        @sk.
+ * Depending on @optname, the addresses will be treated as either a connect or
+ * bind service. The @addrlen is calculated on each IPv4 and IPv6 address using
+ * sizeof(struct sockaddr_in) or sizeof(struct sockaddr_in6).
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_sctp_bind_connect(struct sock *sk, int optname,
                               struct sockaddr *address, int addrlen)
 {
@@ -2480,6 +4633,16 @@ int security_sctp_bind_connect(struct sock *sk, int optname,
 }
 EXPORT_SYMBOL(security_sctp_bind_connect);
 
+/**
+ * security_sctp_sk_clone() - Clone a SCTP sock's LSM state
+ * @asoc: SCTP association
+ * @sk: original sock
+ * @newsk: target sock
+ *
+ * Called whenever a new socket is created by accept(2) (i.e. a TCP style
+ * socket) or when a socket is 'peeled off' e.g userspace calls
+ * sctp_peeloff(3).
+ */
 void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
                            struct sock *newsk)
 {
@@ -2487,6 +4650,16 @@ void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk,
 }
 EXPORT_SYMBOL(security_sctp_sk_clone);
 
+/**
+ * security_sctp_assoc_established() - Update LSM state when assoc established
+ * @asoc: SCTP association
+ * @skb: packet establishing the association
+ *
+ * Passes the @asoc and @chunk->skb of the association COOKIE_ACK packet to the
+ * security module.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_sctp_assoc_established(struct sctp_association *asoc,
                                    struct sk_buff *skb)
 {
@@ -2497,25 +4670,60 @@ EXPORT_SYMBOL(security_sctp_assoc_established);
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_INFINIBAND
-
+/**
+ * security_ib_pkey_access() - Check if access to an IB pkey is allowed
+ * @sec: LSM blob
+ * @subnet_prefix: subnet prefix of the port
+ * @pkey: IB pkey
+ *
+ * Check permission to access a pkey when modifing a QP.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey)
 {
        return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey);
 }
 EXPORT_SYMBOL(security_ib_pkey_access);
 
-int security_ib_endport_manage_subnet(void *sec, const char *dev_name, u8 port_num)
+/**
+ * security_ib_endport_manage_subnet() - Check if SMPs traffic is allowed
+ * @sec: LSM blob
+ * @dev_name: IB device name
+ * @port_num: port number
+ *
+ * Check permissions to send and receive SMPs on a end port.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_ib_endport_manage_subnet(void *sec,
+                                     const char *dev_name, u8 port_num)
 {
-       return call_int_hook(ib_endport_manage_subnet, 0, sec, dev_name, port_num);
+       return call_int_hook(ib_endport_manage_subnet, 0, sec,
+                            dev_name, port_num);
 }
 EXPORT_SYMBOL(security_ib_endport_manage_subnet);
 
+/**
+ * security_ib_alloc_security() - Allocate an Infiniband LSM blob
+ * @sec: LSM blob
+ *
+ * Allocate a security structure for Infiniband objects.
+ *
+ * Return: Returns 0 on success, non-zero on failure.
+ */
 int security_ib_alloc_security(void **sec)
 {
        return call_int_hook(ib_alloc_security, 0, sec);
 }
 EXPORT_SYMBOL(security_ib_alloc_security);
 
+/**
+ * security_ib_free_security() - Free an Infiniband LSM blob
+ * @sec: LSM blob
+ *
+ * Deallocate an Infiniband security structure.
+ */
 void security_ib_free_security(void *sec)
 {
        call_void_hook(ib_free_security, sec);
@@ -2524,7 +4732,17 @@ EXPORT_SYMBOL(security_ib_free_security);
 #endif /* CONFIG_SECURITY_INFINIBAND */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
-
+/**
+ * security_xfrm_policy_alloc() - Allocate a xfrm policy LSM blob
+ * @ctxp: xfrm security context being added to the SPD
+ * @sec_ctx: security label provided by userspace
+ * @gfp: gfp flags
+ *
+ * Allocate a security structure to the xp->security field; the security field
+ * is initialized to NULL when the xfrm_policy is allocated.
+ *
+ * Return:  Return 0 if operation was successful.
+ */
 int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
                               struct xfrm_user_sec_ctx *sec_ctx,
                               gfp_t gfp)
@@ -2533,23 +4751,58 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
 }
 EXPORT_SYMBOL(security_xfrm_policy_alloc);
 
+/**
+ * security_xfrm_policy_clone() - Clone xfrm policy LSM state
+ * @old_ctx: xfrm security context
+ * @new_ctxp: target xfrm security context
+ *
+ * Allocate a security structure in new_ctxp that contains the information from
+ * the old_ctx structure.
+ *
+ * Return: Return 0 if operation was successful.
+ */
 int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
-                             struct xfrm_sec_ctx **new_ctxp)
+                              struct xfrm_sec_ctx **new_ctxp)
 {
        return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp);
 }
 
+/**
+ * security_xfrm_policy_free() - Free a xfrm security context
+ * @ctx: xfrm security context
+ *
+ * Free LSM resources associated with @ctx.
+ */
 void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
 {
        call_void_hook(xfrm_policy_free_security, ctx);
 }
 EXPORT_SYMBOL(security_xfrm_policy_free);
 
+/**
+ * security_xfrm_policy_delete() - Check if deleting a xfrm policy is allowed
+ * @ctx: xfrm security context
+ *
+ * Authorize deletion of a SPD entry.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
 {
        return call_int_hook(xfrm_policy_delete_security, 0, ctx);
 }
 
+/**
+ * security_xfrm_state_alloc() - Allocate a xfrm state LSM blob
+ * @x: xfrm state being added to the SAD
+ * @sec_ctx: security label provided by userspace
+ *
+ * Allocate a security structure to the @x->security field; the security field
+ * is initialized to NULL when the xfrm_state is allocated. Set the context to
+ * correspond to @sec_ctx.
+ *
+ * Return: Return 0 if operation was successful.
+ */
 int security_xfrm_state_alloc(struct xfrm_state *x,
                              struct xfrm_user_sec_ctx *sec_ctx)
 {
@@ -2557,28 +4810,76 @@ int security_xfrm_state_alloc(struct xfrm_state *x,
 }
 EXPORT_SYMBOL(security_xfrm_state_alloc);
 
+/**
+ * security_xfrm_state_alloc_acquire() - Allocate a xfrm state LSM blob
+ * @x: xfrm state being added to the SAD
+ * @polsec: associated policy's security context
+ * @secid: secid from the flow
+ *
+ * Allocate a security structure to the x->security field; the security field
+ * is initialized to NULL when the xfrm_state is allocated.  Set the context to
+ * correspond to secid.
+ *
+ * Return: Returns 0 if operation was successful.
+ */
 int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
                                      struct xfrm_sec_ctx *polsec, u32 secid)
 {
        return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid);
 }
 
+/**
+ * security_xfrm_state_delete() - Check if deleting a xfrm state is allowed
+ * @x: xfrm state
+ *
+ * Authorize deletion of x->security.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_xfrm_state_delete(struct xfrm_state *x)
 {
        return call_int_hook(xfrm_state_delete_security, 0, x);
 }
 EXPORT_SYMBOL(security_xfrm_state_delete);
 
+/**
+ * security_xfrm_state_free() - Free a xfrm state
+ * @x: xfrm state
+ *
+ * Deallocate x->security.
+ */
 void security_xfrm_state_free(struct xfrm_state *x)
 {
        call_void_hook(xfrm_state_free_security, x);
 }
 
+/**
+ * security_xfrm_policy_lookup() - Check if using a xfrm policy is allowed
+ * @ctx: target xfrm security context
+ * @fl_secid: flow secid used to authorize access
+ *
+ * Check permission when a flow selects a xfrm_policy for processing XFRMs on a
+ * packet.  The hook is called when selecting either a per-socket policy or a
+ * generic xfrm policy.
+ *
+ * Return: Return 0 if permission is granted, -ESRCH otherwise, or -errno on
+ *         other errors.
+ */
 int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid)
 {
        return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid);
 }
 
+/**
+ * security_xfrm_state_pol_flow_match() - Check for a xfrm match
+ * @x: xfrm state to match
+ * @xp: xfrm policy to check for a match
+ * @flic: flow to check for a match.
+ *
+ * Check @xp and @flic for a match with @x.
+ *
+ * Return: Returns 1 if there is a match.
+ */
 int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
                                       struct xfrm_policy *xp,
                                       const struct flowi_common *flic)
@@ -2596,13 +4897,22 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
         * using the macro
         */
        hlist_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match,
-                               list) {
+                            list) {
                rc = hp->hook.xfrm_state_pol_flow_match(x, xp, flic);
                break;
        }
        return rc;
 }
 
+/**
+ * security_xfrm_decode_session() - Determine the xfrm secid for a packet
+ * @skb: xfrm packet
+ * @secid: secid
+ *
+ * Decode the packet in @skb and return the security label in @secid.
+ *
+ * Return: Return 0 if all xfrms used have the same secid.
+ */
 int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
 {
        return call_int_hook(xfrm_decode_session, 0, skb, secid, 1);
@@ -2611,58 +4921,135 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
 void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic)
 {
        int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid,
-                               0);
+                              0);
 
        BUG_ON(rc);
 }
 EXPORT_SYMBOL(security_skb_classify_flow);
-
 #endif /* CONFIG_SECURITY_NETWORK_XFRM */
 
 #ifdef CONFIG_KEYS
-
+/**
+ * security_key_alloc() - Allocate and initialize a kernel key LSM blob
+ * @key: key
+ * @cred: credentials
+ * @flags: allocation flags
+ *
+ * Permit allocation of a key and assign security data. Note that key does not
+ * have a serial number assigned at this point.
+ *
+ * Return: Return 0 if permission is granted, -ve error otherwise.
+ */
 int security_key_alloc(struct key *key, const struct cred *cred,
                       unsigned long flags)
 {
        return call_int_hook(key_alloc, 0, key, cred, flags);
 }
 
+/**
+ * security_key_free() - Free a kernel key LSM blob
+ * @key: key
+ *
+ * Notification of destruction; free security data.
+ */
 void security_key_free(struct key *key)
 {
        call_void_hook(key_free, key);
 }
 
+/**
+ * security_key_permission() - Check if a kernel key operation is allowed
+ * @key_ref: key reference
+ * @cred: credentials of actor requesting access
+ * @need_perm: requested permissions
+ *
+ * See whether a specific operational right is granted to a process on a key.
+ *
+ * Return: Return 0 if permission is granted, -ve error otherwise.
+ */
 int security_key_permission(key_ref_t key_ref, const struct cred *cred,
                            enum key_need_perm need_perm)
 {
        return call_int_hook(key_permission, 0, key_ref, cred, need_perm);
 }
 
-int security_key_getsecurity(struct key *key, char **_buffer)
+/**
+ * security_key_getsecurity() - Get the key's security label
+ * @key: key
+ * @buffer: security label buffer
+ *
+ * Get a textual representation of the security context attached to a key for
+ * the purposes of honouring KEYCTL_GETSECURITY.  This function allocates the
+ * storage for the NUL-terminated string and the caller should free it.
+ *
+ * Return: Returns the length of @buffer (including terminating NUL) or -ve if
+ *         an error occurs.  May also return 0 (and a NULL buffer pointer) if
+ *         there is no security label assigned to the key.
+ */
+int security_key_getsecurity(struct key *key, char **buffer)
 {
-       *_buffer = NULL;
-       return call_int_hook(key_getsecurity, 0, key, _buffer);
+       *buffer = NULL;
+       return call_int_hook(key_getsecurity, 0, key, buffer);
 }
-
 #endif /* CONFIG_KEYS */
 
 #ifdef CONFIG_AUDIT
-
+/**
+ * security_audit_rule_init() - Allocate and init an LSM audit rule struct
+ * @field: audit action
+ * @op: rule operator
+ * @rulestr: rule context
+ * @lsmrule: receive buffer for audit rule struct
+ *
+ * Allocate and initialize an LSM audit rule structure.
+ *
+ * Return: Return 0 if @lsmrule has been successfully set, -EINVAL in case of
+ *         an invalid rule.
+ */
 int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
 {
        return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule);
 }
 
+/**
+ * security_audit_rule_known() - Check if an audit rule contains LSM fields
+ * @krule: audit rule
+ *
+ * Specifies whether given @krule contains any fields related to the current
+ * LSM.
+ *
+ * Return: Returns 1 in case of relation found, 0 otherwise.
+ */
 int security_audit_rule_known(struct audit_krule *krule)
 {
        return call_int_hook(audit_rule_known, 0, krule);
 }
 
+/**
+ * security_audit_rule_free() - Free an LSM audit rule struct
+ * @lsmrule: audit rule struct
+ *
+ * Deallocate the LSM audit rule structure previously allocated by
+ * audit_rule_init().
+ */
 void security_audit_rule_free(void *lsmrule)
 {
        call_void_hook(audit_rule_free, lsmrule);
 }
 
+/**
+ * security_audit_rule_match() - Check if a label matches an audit rule
+ * @secid: security label
+ * @field: LSM audit field
+ * @op: matching operator
+ * @lsmrule: audit rule
+ *
+ * Determine if given @secid matches a rule previously approved by
+ * security_audit_rule_known().
+ *
+ * Return: Returns 1 if secid matches the rule, 0 if it does not, -ERRNO on
+ *         failure.
+ */
 int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
 {
        return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
@@ -2670,36 +5057,110 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
 #endif /* CONFIG_AUDIT */
 
 #ifdef CONFIG_BPF_SYSCALL
+/**
+ * security_bpf() - Check if the bpf syscall operation is allowed
+ * @cmd: command
+ * @attr: bpf attribute
+ * @size: size
+ *
+ * Do a initial check for all bpf syscalls after the attribute is copied into
+ * the kernel. The actual security module can implement their own rules to
+ * check the specific cmd they need.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_bpf(int cmd, union bpf_attr *attr, unsigned int size)
 {
        return call_int_hook(bpf, 0, cmd, attr, size);
 }
+
+/**
+ * security_bpf_map() - Check if access to a bpf map is allowed
+ * @map: bpf map
+ * @fmode: mode
+ *
+ * Do a check when the kernel generates and returns a file descriptor for eBPF
+ * maps.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_bpf_map(struct bpf_map *map, fmode_t fmode)
 {
        return call_int_hook(bpf_map, 0, map, fmode);
 }
+
+/**
+ * security_bpf_prog() - Check if access to a bpf program is allowed
+ * @prog: bpf program
+ *
+ * Do a check when the kernel generates and returns a file descriptor for eBPF
+ * programs.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_bpf_prog(struct bpf_prog *prog)
 {
        return call_int_hook(bpf_prog, 0, prog);
 }
+
+/**
+ * security_bpf_map_alloc() - Allocate a bpf map LSM blob
+ * @map: bpf map
+ *
+ * Initialize the security field inside bpf map.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_bpf_map_alloc(struct bpf_map *map)
 {
        return call_int_hook(bpf_map_alloc_security, 0, map);
 }
+
+/**
+ * security_bpf_prog_alloc() - Allocate a bpf program LSM blob
+ * @aux: bpf program aux info struct
+ *
+ * Initialize the security field inside bpf program.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
 {
        return call_int_hook(bpf_prog_alloc_security, 0, aux);
 }
+
+/**
+ * security_bpf_map_free() - Free a bpf map's LSM blob
+ * @map: bpf map
+ *
+ * Clean up the security information stored inside bpf map.
+ */
 void security_bpf_map_free(struct bpf_map *map)
 {
        call_void_hook(bpf_map_free_security, map);
 }
+
+/**
+ * security_bpf_prog_free() - Free a bpf program's LSM blob
+ * @aux: bpf program aux info struct
+ *
+ * Clean up the security information stored inside bpf prog.
+ */
 void security_bpf_prog_free(struct bpf_prog_aux *aux)
 {
        call_void_hook(bpf_prog_free_security, aux);
 }
 #endif /* CONFIG_BPF_SYSCALL */
 
+/**
+ * security_locked_down() - Check if a kernel feature is allowed
+ * @what: requested kernel feature
+ *
+ * Determine whether a kernel feature that potentially enables arbitrary code
+ * execution in kernel space should be permitted.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_locked_down(enum lockdown_reason what)
 {
        return call_int_hook(locked_down, 0, what);
@@ -2707,26 +5168,65 @@ int security_locked_down(enum lockdown_reason what)
 EXPORT_SYMBOL(security_locked_down);
 
 #ifdef CONFIG_PERF_EVENTS
+/**
+ * security_perf_event_open() - Check if a perf event open is allowed
+ * @attr: perf event attribute
+ * @type: type of event
+ *
+ * Check whether the @type of perf_event_open syscall is allowed.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_perf_event_open(struct perf_event_attr *attr, int type)
 {
        return call_int_hook(perf_event_open, 0, attr, type);
 }
 
+/**
+ * security_perf_event_alloc() - Allocate a perf event LSM blob
+ * @event: perf event
+ *
+ * Allocate and save perf_event security info.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
 int security_perf_event_alloc(struct perf_event *event)
 {
        return call_int_hook(perf_event_alloc, 0, event);
 }
 
+/**
+ * security_perf_event_free() - Free a perf event LSM blob
+ * @event: perf event
+ *
+ * Release (free) perf_event security info.
+ */
 void security_perf_event_free(struct perf_event *event)
 {
        call_void_hook(perf_event_free, event);
 }
 
+/**
+ * security_perf_event_read() - Check if reading a perf event label is allowed
+ * @event: perf event
+ *
+ * Read perf_event security info if allowed.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_perf_event_read(struct perf_event *event)
 {
        return call_int_hook(perf_event_read, 0, event);
 }
 
+/**
+ * security_perf_event_write() - Check if writing a perf event label is allowed
+ * @event: perf event
+ *
+ * Write perf_event security info if allowed.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_perf_event_write(struct perf_event *event)
 {
        return call_int_hook(perf_event_write, 0, event);
@@ -2734,15 +5234,41 @@ int security_perf_event_write(struct perf_event *event)
 #endif /* CONFIG_PERF_EVENTS */
 
 #ifdef CONFIG_IO_URING
+/**
+ * security_uring_override_creds() - Check if overriding creds is allowed
+ * @new: new credentials
+ *
+ * Check if the current task, executing an io_uring operation, is allowed to
+ * override it's credentials with @new.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_uring_override_creds(const struct cred *new)
 {
        return call_int_hook(uring_override_creds, 0, new);
 }
 
+/**
+ * security_uring_sqpoll() - Check if IORING_SETUP_SQPOLL is allowed
+ *
+ * Check whether the current task is allowed to spawn a io_uring polling thread
+ * (IORING_SETUP_SQPOLL).
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_uring_sqpoll(void)
 {
        return call_int_hook(uring_sqpoll, 0);
 }
+
+/**
+ * security_uring_cmd() - Check if a io_uring passthrough command is allowed
+ * @ioucmd: command
+ *
+ * Check whether the file_operations uring_cmd is allowed to run.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
 int security_uring_cmd(struct io_uring_cmd *ioucmd)
 {
        return call_int_hook(uring_cmd, 0, ioucmd);
index 9e921fc725386ed9c79511012a2679b6ecb52bb1..95a186ec0fcb70beb5f510563c3711ab5eb7ee7a 100644 (file)
@@ -23,30 +23,6 @@ config SECURITY_SELINUX_BOOTPARAM
 
          If you are unsure how to answer this question, answer N.
 
-config SECURITY_SELINUX_DISABLE
-       bool "NSA SELinux runtime disable"
-       depends on SECURITY_SELINUX
-       select SECURITY_WRITABLE_HOOKS
-       default n
-       help
-         This option enables writing to a selinuxfs node 'disable', which
-         allows SELinux to be disabled at runtime prior to the policy load.
-         SELinux will then remain disabled until the next boot.
-         This option is similar to the selinux=0 boot parameter, but is to
-         support runtime disabling of SELinux, e.g. from /sbin/init, for
-         portability across platforms where boot parameters are difficult
-         to employ.
-
-         NOTE: selecting this option will disable the '__ro_after_init'
-         kernel hardening feature for security hooks.   Please consider
-         using the selinux=0 boot parameter instead of enabling this
-         option.
-
-         WARNING: this option is deprecated and will be removed in a future
-         kernel release.
-
-         If you are unsure how to answer this question, answer N.
-
 config SECURITY_SELINUX_DEVELOP
        bool "NSA SELinux Development Support"
        depends on SECURITY_SELINUX
@@ -70,29 +46,6 @@ config SECURITY_SELINUX_AVC_STATS
          /sys/fs/selinux/avc/cache_stats, which may be monitored via
          tools such as avcstat.
 
-config SECURITY_SELINUX_CHECKREQPROT_VALUE
-       int "NSA SELinux checkreqprot default value"
-       depends on SECURITY_SELINUX
-       range 0 1
-       default 0
-       help
-         This option sets the default value for the 'checkreqprot' flag
-         that determines whether SELinux checks the protection requested
-         by the application or the protection that will be applied by the
-         kernel (including any implied execute for read-implies-exec) for
-         mmap and mprotect calls.  If this option is set to 0 (zero),
-         SELinux will default to checking the protection that will be applied
-         by the kernel.  If this option is set to 1 (one), SELinux will
-         default to checking the protection requested by the application.
-         The checkreqprot flag may be changed from the default via the
-         'checkreqprot=' boot parameter.  It may also be changed at runtime
-         via /sys/fs/selinux/checkreqprot if authorized by policy.
-
-         WARNING: this option is deprecated and will be removed in a future
-         kernel release.
-
-         If you are unsure how to answer this question, answer 0.
-
 config SECURITY_SELINUX_SIDTAB_HASH_BITS
        int "NSA SELinux sidtab hashtable size"
        depends on SECURITY_SELINUX
index 77616244488264e697cf82e3c2582c5a0b17adad..0aecf9334ec31e9df00fd5d81a06dc202a66327e 100644 (file)
@@ -23,8 +23,8 @@ ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
 $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
 
 quiet_cmd_flask = GEN     $(obj)/flask.h $(obj)/av_permissions.h
-      cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h
+      cmd_flask = $< $(obj)/flask.h $(obj)/av_permissions.h
 
 targets += flask.h av_permissions.h
-$(obj)/flask.h: $(src)/include/classmap.h FORCE
+$(obj)/flask.h $(obj)/av_permissions.h &: scripts/selinux/genheaders/genheaders FORCE
        $(call if_changed,flask)
index 9a43af0ebd7de7685f557a8d1ebb54153c3f5938..eaed5c2da02b34d4ae4ce10f32722a1adb1dd637 100644 (file)
@@ -93,7 +93,7 @@ struct selinux_avc {
 
 static struct selinux_avc selinux_avc;
 
-void selinux_avc_init(struct selinux_avc **avc)
+void selinux_avc_init(void)
 {
        int i;
 
@@ -104,18 +104,16 @@ void selinux_avc_init(struct selinux_avc **avc)
        }
        atomic_set(&selinux_avc.avc_cache.active_nodes, 0);
        atomic_set(&selinux_avc.avc_cache.lru_hint, 0);
-       *avc = &selinux_avc;
 }
 
-unsigned int avc_get_cache_threshold(struct selinux_avc *avc)
+unsigned int avc_get_cache_threshold(void)
 {
-       return avc->avc_cache_threshold;
+       return selinux_avc.avc_cache_threshold;
 }
 
-void avc_set_cache_threshold(struct selinux_avc *avc,
-                            unsigned int cache_threshold)
+void avc_set_cache_threshold(unsigned int cache_threshold)
 {
-       avc->avc_cache_threshold = cache_threshold;
+       selinux_avc.avc_cache_threshold = cache_threshold;
 }
 
 static struct avc_callback_node *avc_callbacks __ro_after_init;
@@ -150,7 +148,7 @@ void __init avc_init(void)
                                        0, SLAB_PANIC, NULL);
 }
 
-int avc_get_hash_stats(struct selinux_avc *avc, char *page)
+int avc_get_hash_stats(char *page)
 {
        int i, chain_len, max_chain_len, slots_used;
        struct avc_node *node;
@@ -161,7 +159,7 @@ int avc_get_hash_stats(struct selinux_avc *avc, char *page)
        slots_used = 0;
        max_chain_len = 0;
        for (i = 0; i < AVC_CACHE_SLOTS; i++) {
-               head = &avc->avc_cache.slots[i];
+               head = &selinux_avc.avc_cache.slots[i];
                if (!hlist_empty(head)) {
                        slots_used++;
                        chain_len = 0;
@@ -176,7 +174,7 @@ int avc_get_hash_stats(struct selinux_avc *avc, char *page)
 
        return scnprintf(page, PAGE_SIZE, "entries: %d\nbuckets used: %d/%d\n"
                         "longest chain: %d\n",
-                        atomic_read(&avc->avc_cache.active_nodes),
+                        atomic_read(&selinux_avc.avc_cache.active_nodes),
                         slots_used, AVC_CACHE_SLOTS, max_chain_len);
 }
 
@@ -414,8 +412,7 @@ static inline u32 avc_xperms_audit_required(u32 requested,
        return audited;
 }
 
-static inline int avc_xperms_audit(struct selinux_state *state,
-                                  u32 ssid, u32 tsid, u16 tclass,
+static inline int avc_xperms_audit(u32 ssid, u32 tsid, u16 tclass,
                                   u32 requested, struct av_decision *avd,
                                   struct extended_perms_decision *xpd,
                                   u8 perm, int result,
@@ -427,7 +424,7 @@ static inline int avc_xperms_audit(struct selinux_state *state,
                        requested, avd, xpd, perm, result, &denied);
        if (likely(!audited))
                return 0;
-       return slow_avc_audit(state, ssid, tsid, tclass, requested,
+       return slow_avc_audit(ssid, tsid, tclass, requested,
                        audited, denied, result, ad);
 }
 
@@ -439,30 +436,29 @@ static void avc_node_free(struct rcu_head *rhead)
        avc_cache_stats_incr(frees);
 }
 
-static void avc_node_delete(struct selinux_avc *avc, struct avc_node *node)
+static void avc_node_delete(struct avc_node *node)
 {
        hlist_del_rcu(&node->list);
        call_rcu(&node->rhead, avc_node_free);
-       atomic_dec(&avc->avc_cache.active_nodes);
+       atomic_dec(&selinux_avc.avc_cache.active_nodes);
 }
 
-static void avc_node_kill(struct selinux_avc *avc, struct avc_node *node)
+static void avc_node_kill(struct avc_node *node)
 {
        avc_xperms_free(node->ae.xp_node);
        kmem_cache_free(avc_node_cachep, node);
        avc_cache_stats_incr(frees);
-       atomic_dec(&avc->avc_cache.active_nodes);
+       atomic_dec(&selinux_avc.avc_cache.active_nodes);
 }
 
-static void avc_node_replace(struct selinux_avc *avc,
-                            struct avc_node *new, struct avc_node *old)
+static void avc_node_replace(struct avc_node *new, struct avc_node *old)
 {
        hlist_replace_rcu(&old->list, &new->list);
        call_rcu(&old->rhead, avc_node_free);
-       atomic_dec(&avc->avc_cache.active_nodes);
+       atomic_dec(&selinux_avc.avc_cache.active_nodes);
 }
 
-static inline int avc_reclaim_node(struct selinux_avc *avc)
+static inline int avc_reclaim_node(void)
 {
        struct avc_node *node;
        int hvalue, try, ecx;
@@ -471,17 +467,17 @@ static inline int avc_reclaim_node(struct selinux_avc *avc)
        spinlock_t *lock;
 
        for (try = 0, ecx = 0; try < AVC_CACHE_SLOTS; try++) {
-               hvalue = atomic_inc_return(&avc->avc_cache.lru_hint) &
+               hvalue = atomic_inc_return(&selinux_avc.avc_cache.lru_hint) &
                        (AVC_CACHE_SLOTS - 1);
-               head = &avc->avc_cache.slots[hvalue];
-               lock = &avc->avc_cache.slots_lock[hvalue];
+               head = &selinux_avc.avc_cache.slots[hvalue];
+               lock = &selinux_avc.avc_cache.slots_lock[hvalue];
 
                if (!spin_trylock_irqsave(lock, flags))
                        continue;
 
                rcu_read_lock();
                hlist_for_each_entry(node, head, list) {
-                       avc_node_delete(avc, node);
+                       avc_node_delete(node);
                        avc_cache_stats_incr(reclaims);
                        ecx++;
                        if (ecx >= AVC_CACHE_RECLAIM) {
@@ -497,7 +493,7 @@ out:
        return ecx;
 }
 
-static struct avc_node *avc_alloc_node(struct selinux_avc *avc)
+static struct avc_node *avc_alloc_node(void)
 {
        struct avc_node *node;
 
@@ -508,9 +504,9 @@ static struct avc_node *avc_alloc_node(struct selinux_avc *avc)
        INIT_HLIST_NODE(&node->list);
        avc_cache_stats_incr(allocations);
 
-       if (atomic_inc_return(&avc->avc_cache.active_nodes) >
-           avc->avc_cache_threshold)
-               avc_reclaim_node(avc);
+       if (atomic_inc_return(&selinux_avc.avc_cache.active_nodes) >
+           selinux_avc.avc_cache_threshold)
+               avc_reclaim_node();
 
 out:
        return node;
@@ -524,15 +520,14 @@ static void avc_node_populate(struct avc_node *node, u32 ssid, u32 tsid, u16 tcl
        memcpy(&node->ae.avd, avd, sizeof(node->ae.avd));
 }
 
-static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
-                                              u32 ssid, u32 tsid, u16 tclass)
+static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass)
 {
        struct avc_node *node, *ret = NULL;
        int hvalue;
        struct hlist_head *head;
 
        hvalue = avc_hash(ssid, tsid, tclass);
-       head = &avc->avc_cache.slots[hvalue];
+       head = &selinux_avc.avc_cache.slots[hvalue];
        hlist_for_each_entry_rcu(node, head, list) {
                if (ssid == node->ae.ssid &&
                    tclass == node->ae.tclass &&
@@ -547,7 +542,6 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
 
 /**
  * avc_lookup - Look up an AVC entry.
- * @avc: the access vector cache
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -558,13 +552,12 @@ static inline struct avc_node *avc_search_node(struct selinux_avc *avc,
  * then this function returns the avc_node.
  * Otherwise, this function returns NULL.
  */
-static struct avc_node *avc_lookup(struct selinux_avc *avc,
-                                  u32 ssid, u32 tsid, u16 tclass)
+static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass)
 {
        struct avc_node *node;
 
        avc_cache_stats_incr(lookups);
-       node = avc_search_node(avc, ssid, tsid, tclass);
+       node = avc_search_node(ssid, tsid, tclass);
 
        if (node)
                return node;
@@ -573,8 +566,7 @@ static struct avc_node *avc_lookup(struct selinux_avc *avc,
        return NULL;
 }
 
-static int avc_latest_notif_update(struct selinux_avc *avc,
-                                  int seqno, int is_insert)
+static int avc_latest_notif_update(int seqno, int is_insert)
 {
        int ret = 0;
        static DEFINE_SPINLOCK(notif_lock);
@@ -582,14 +574,14 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
 
        spin_lock_irqsave(&notif_lock, flag);
        if (is_insert) {
-               if (seqno < avc->avc_cache.latest_notif) {
+               if (seqno < selinux_avc.avc_cache.latest_notif) {
                        pr_warn("SELinux: avc:  seqno %d < latest_notif %d\n",
-                              seqno, avc->avc_cache.latest_notif);
+                              seqno, selinux_avc.avc_cache.latest_notif);
                        ret = -EAGAIN;
                }
        } else {
-               if (seqno > avc->avc_cache.latest_notif)
-                       avc->avc_cache.latest_notif = seqno;
+               if (seqno > selinux_avc.avc_cache.latest_notif)
+                       selinux_avc.avc_cache.latest_notif = seqno;
        }
        spin_unlock_irqrestore(&notif_lock, flag);
 
@@ -598,7 +590,6 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
 
 /**
  * avc_insert - Insert an AVC entry.
- * @avc: the access vector cache
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -612,13 +603,10 @@ static int avc_latest_notif_update(struct selinux_avc *avc,
  * response to a security_compute_av() call.  If the
  * sequence number @avd->seqno is not less than the latest
  * revocation notification, then the function copies
- * the access vectors into a cache entry, returns
- * avc_node inserted. Otherwise, this function returns NULL.
+ * the access vectors into a cache entry.
  */
-static struct avc_node *avc_insert(struct selinux_avc *avc,
-                                  u32 ssid, u32 tsid, u16 tclass,
-                                  struct av_decision *avd,
-                                  struct avc_xperms_node *xp_node)
+static void avc_insert(u32 ssid, u32 tsid, u16 tclass,
+                      struct av_decision *avd, struct avc_xperms_node *xp_node)
 {
        struct avc_node *pos, *node = NULL;
        int hvalue;
@@ -626,35 +614,35 @@ static struct avc_node *avc_insert(struct selinux_avc *avc,
        spinlock_t *lock;
        struct hlist_head *head;
 
-       if (avc_latest_notif_update(avc, avd->seqno, 1))
-               return NULL;
+       if (avc_latest_notif_update(avd->seqno, 1))
+               return;
 
-       node = avc_alloc_node(avc);
+       node = avc_alloc_node();
        if (!node)
-               return NULL;
+               return;
 
        avc_node_populate(node, ssid, tsid, tclass, avd);
        if (avc_xperms_populate(node, xp_node)) {
-               avc_node_kill(avc, node);
-               return NULL;
+               avc_node_kill(node);
+               return;
        }
 
        hvalue = avc_hash(ssid, tsid, tclass);
-       head = &avc->avc_cache.slots[hvalue];
-       lock = &avc->avc_cache.slots_lock[hvalue];
+       head = &selinux_avc.avc_cache.slots[hvalue];
+       lock = &selinux_avc.avc_cache.slots_lock[hvalue];
        spin_lock_irqsave(lock, flag);
        hlist_for_each_entry(pos, head, list) {
                if (pos->ae.ssid == ssid &&
                        pos->ae.tsid == tsid &&
                        pos->ae.tclass == tclass) {
-                       avc_node_replace(avc, node, pos);
+                       avc_node_replace(node, pos);
                        goto found;
                }
        }
        hlist_add_head_rcu(&node->list, head);
 found:
        spin_unlock_irqrestore(lock, flag);
-       return node;
+       return;
 }
 
 /**
@@ -715,14 +703,14 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
        u32 tcontext_len;
        int rc;
 
-       rc = security_sid_to_context(sad->state, sad->ssid, &scontext,
+       rc = security_sid_to_context(sad->ssid, &scontext,
                                     &scontext_len);
        if (rc)
                audit_log_format(ab, " ssid=%d", sad->ssid);
        else
                audit_log_format(ab, " scontext=%s", scontext);
 
-       rc = security_sid_to_context(sad->state, sad->tsid, &tcontext,
+       rc = security_sid_to_context(sad->tsid, &tcontext,
                                     &tcontext_len);
        if (rc)
                audit_log_format(ab, " tsid=%d", sad->tsid);
@@ -740,7 +728,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
        kfree(scontext);
 
        /* in case of invalid context report also the actual context string */
-       rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext,
+       rc = security_sid_to_context_inval(sad->ssid, &scontext,
                                           &scontext_len);
        if (!rc && scontext) {
                if (scontext_len && scontext[scontext_len - 1] == '\0')
@@ -750,7 +738,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
                kfree(scontext);
        }
 
-       rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext,
+       rc = security_sid_to_context_inval(sad->tsid, &scontext,
                                           &scontext_len);
        if (!rc && scontext) {
                if (scontext_len && scontext[scontext_len - 1] == '\0')
@@ -766,8 +754,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
  * Note that it is non-blocking and can be called from under
  * rcu_read_lock().
  */
-noinline int slow_avc_audit(struct selinux_state *state,
-                           u32 ssid, u32 tsid, u16 tclass,
+noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
                            u32 requested, u32 audited, u32 denied, int result,
                            struct common_audit_data *a)
 {
@@ -789,7 +776,6 @@ noinline int slow_avc_audit(struct selinux_state *state,
        sad.audited = audited;
        sad.denied = denied;
        sad.result = result;
-       sad.state = state;
 
        a->selinux_audit_data = &sad;
 
@@ -827,7 +813,6 @@ out:
 
 /**
  * avc_update_node - Update an AVC entry
- * @avc: the access vector cache
  * @event : Updating event
  * @perms : Permission mask bits
  * @driver: xperm driver information
@@ -844,8 +829,7 @@ out:
  * otherwise, this function updates the AVC entry. The original AVC-entry object
  * will release later by RCU.
  */
-static int avc_update_node(struct selinux_avc *avc,
-                          u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
+static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
                           u32 tsid, u16 tclass, u32 seqno,
                           struct extended_perms_decision *xpd,
                           u32 flags)
@@ -856,7 +840,7 @@ static int avc_update_node(struct selinux_avc *avc,
        struct hlist_head *head;
        spinlock_t *lock;
 
-       node = avc_alloc_node(avc);
+       node = avc_alloc_node();
        if (!node) {
                rc = -ENOMEM;
                goto out;
@@ -865,8 +849,8 @@ static int avc_update_node(struct selinux_avc *avc,
        /* Lock the target slot */
        hvalue = avc_hash(ssid, tsid, tclass);
 
-       head = &avc->avc_cache.slots[hvalue];
-       lock = &avc->avc_cache.slots_lock[hvalue];
+       head = &selinux_avc.avc_cache.slots[hvalue];
+       lock = &selinux_avc.avc_cache.slots_lock[hvalue];
 
        spin_lock_irqsave(lock, flag);
 
@@ -882,7 +866,7 @@ static int avc_update_node(struct selinux_avc *avc,
 
        if (!orig) {
                rc = -ENOENT;
-               avc_node_kill(avc, node);
+               avc_node_kill(node);
                goto out_unlock;
        }
 
@@ -895,7 +879,7 @@ static int avc_update_node(struct selinux_avc *avc,
        if (orig->ae.xp_node) {
                rc = avc_xperms_populate(node, orig->ae.xp_node);
                if (rc) {
-                       avc_node_kill(avc, node);
+                       avc_node_kill(node);
                        goto out_unlock;
                }
        }
@@ -926,7 +910,7 @@ static int avc_update_node(struct selinux_avc *avc,
                avc_add_xperms_decision(node, xpd);
                break;
        }
-       avc_node_replace(avc, node, orig);
+       avc_node_replace(node, orig);
 out_unlock:
        spin_unlock_irqrestore(lock, flag);
 out:
@@ -935,9 +919,8 @@ out:
 
 /**
  * avc_flush - Flush the cache
- * @avc: the access vector cache
  */
-static void avc_flush(struct selinux_avc *avc)
+static void avc_flush(void)
 {
        struct hlist_head *head;
        struct avc_node *node;
@@ -946,8 +929,8 @@ static void avc_flush(struct selinux_avc *avc)
        int i;
 
        for (i = 0; i < AVC_CACHE_SLOTS; i++) {
-               head = &avc->avc_cache.slots[i];
-               lock = &avc->avc_cache.slots_lock[i];
+               head = &selinux_avc.avc_cache.slots[i];
+               lock = &selinux_avc.avc_cache.slots_lock[i];
 
                spin_lock_irqsave(lock, flag);
                /*
@@ -956,7 +939,7 @@ static void avc_flush(struct selinux_avc *avc)
                 */
                rcu_read_lock();
                hlist_for_each_entry(node, head, list)
-                       avc_node_delete(avc, node);
+                       avc_node_delete(node);
                rcu_read_unlock();
                spin_unlock_irqrestore(lock, flag);
        }
@@ -964,15 +947,14 @@ static void avc_flush(struct selinux_avc *avc)
 
 /**
  * avc_ss_reset - Flush the cache and revalidate migrated permissions.
- * @avc: the access vector cache
  * @seqno: policy sequence number
  */
-int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
+int avc_ss_reset(u32 seqno)
 {
        struct avc_callback_node *c;
        int rc = 0, tmprc;
 
-       avc_flush(avc);
+       avc_flush();
 
        for (c = avc_callbacks; c; c = c->next) {
                if (c->events & AVC_CALLBACK_RESET) {
@@ -984,34 +966,32 @@ int avc_ss_reset(struct selinux_avc *avc, u32 seqno)
                }
        }
 
-       avc_latest_notif_update(avc, seqno, 0);
+       avc_latest_notif_update(seqno, 0);
        return rc;
 }
 
-/*
- * Slow-path helper function for avc_has_perm_noaudit,
- * when the avc_node lookup fails. We get called with
- * the RCU read lock held, and need to return with it
- * still held, but drop if for the security compute.
+/**
+ * avc_compute_av - Add an entry to the AVC based on the security policy
+ * @ssid: subject
+ * @tsid: object/target
+ * @tclass: object class
+ * @avd: access vector decision
+ * @xp_node: AVC extended permissions node
  *
- * Don't inline this, since it's the slow-path and just
- * results in a bigger stack frame.
+ * Slow-path helper function for avc_has_perm_noaudit, when the avc_node lookup
+ * fails.  Don't inline this, since it's the slow-path and just results in a
+ * bigger stack frame.
  */
-static noinline
-struct avc_node *avc_compute_av(struct selinux_state *state,
-                               u32 ssid, u32 tsid,
-                               u16 tclass, struct av_decision *avd,
-                               struct avc_xperms_node *xp_node)
+static noinline void avc_compute_av(u32 ssid, u32 tsid, u16 tclass,
+                                   struct av_decision *avd,
+                                   struct avc_xperms_node *xp_node)
 {
-       rcu_read_unlock();
        INIT_LIST_HEAD(&xp_node->xpd_head);
-       security_compute_av(state, ssid, tsid, tclass, avd, &xp_node->xp);
-       rcu_read_lock();
-       return avc_insert(state->avc, ssid, tsid, tclass, avd, xp_node);
+       security_compute_av(ssid, tsid, tclass, avd, &xp_node->xp);
+       avc_insert(ssid, tsid, tclass, avd, xp_node);
 }
 
-static noinline int avc_denied(struct selinux_state *state,
-                              u32 ssid, u32 tsid,
+static noinline int avc_denied(u32 ssid, u32 tsid,
                               u16 tclass, u32 requested,
                               u8 driver, u8 xperm, unsigned int flags,
                               struct av_decision *avd)
@@ -1019,11 +999,11 @@ static noinline int avc_denied(struct selinux_state *state,
        if (flags & AVC_STRICT)
                return -EACCES;
 
-       if (enforcing_enabled(state) &&
+       if (enforcing_enabled() &&
            !(avd->flags & AVD_FLAGS_PERMISSIVE))
                return -EACCES;
 
-       avc_update_node(state->avc, AVC_CALLBACK_GRANT, requested, driver,
+       avc_update_node(AVC_CALLBACK_GRANT, requested, driver,
                        xperm, ssid, tsid, tclass, avd->seqno, NULL, flags);
        return 0;
 }
@@ -1035,8 +1015,7 @@ static noinline int avc_denied(struct selinux_state *state,
  * as-is the case with ioctls, then multiple may be chained together and the
  * driver field is used to specify which set contains the permission.
  */
-int avc_has_extended_perms(struct selinux_state *state,
-                          u32 ssid, u32 tsid, u16 tclass, u32 requested,
+int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
                           u8 driver, u8 xperm, struct common_audit_data *ad)
 {
        struct avc_node *node;
@@ -1057,9 +1036,9 @@ int avc_has_extended_perms(struct selinux_state *state,
 
        rcu_read_lock();
 
-       node = avc_lookup(state->avc, ssid, tsid, tclass);
+       node = avc_lookup(ssid, tsid, tclass);
        if (unlikely(!node)) {
-               avc_compute_av(state, ssid, tsid, tclass, &avd, xp_node);
+               avc_compute_av(ssid, tsid, tclass, &avd, xp_node);
        } else {
                memcpy(&avd, &node->ae.avd, sizeof(avd));
                xp_node = node->ae.xp_node;
@@ -1083,10 +1062,10 @@ int avc_has_extended_perms(struct selinux_state *state,
                        goto decision;
                }
                rcu_read_unlock();
-               security_compute_xperms_decision(state, ssid, tsid, tclass,
+               security_compute_xperms_decision(ssid, tsid, tclass,
                                                 driver, &local_xpd);
                rcu_read_lock();
-               avc_update_node(state->avc, AVC_CALLBACK_ADD_XPERMS, requested,
+               avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested,
                                driver, xperm, ssid, tsid, tclass, avd.seqno,
                                &local_xpd, 0);
        } else {
@@ -1100,21 +1079,48 @@ int avc_has_extended_perms(struct selinux_state *state,
 decision:
        denied = requested & ~(avd.allowed);
        if (unlikely(denied))
-               rc = avc_denied(state, ssid, tsid, tclass, requested,
+               rc = avc_denied(ssid, tsid, tclass, requested,
                                driver, xperm, AVC_EXTENDED_PERMS, &avd);
 
        rcu_read_unlock();
 
-       rc2 = avc_xperms_audit(state, ssid, tsid, tclass, requested,
+       rc2 = avc_xperms_audit(ssid, tsid, tclass, requested,
                        &avd, xpd, xperm, rc, ad);
        if (rc2)
                return rc2;
        return rc;
 }
 
+/**
+ * avc_perm_nonode - Add an entry to the AVC
+ * @ssid: subject
+ * @tsid: object/target
+ * @tclass: object class
+ * @requested: requested permissions
+ * @flags: AVC flags
+ * @avd: access vector decision
+ *
+ * This is the "we have no node" part of avc_has_perm_noaudit(), which is
+ * unlikely and needs extra stack space for the new node that we generate, so
+ * don't inline it.
+ */
+static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass,
+                                   u32 requested, unsigned int flags,
+                                   struct av_decision *avd)
+{
+       u32 denied;
+       struct avc_xperms_node xp_node;
+
+       avc_compute_av(ssid, tsid, tclass, avd, &xp_node);
+       denied = requested & ~(avd->allowed);
+       if (unlikely(denied))
+               return avc_denied(ssid, tsid, tclass, requested, 0, 0,
+                                 flags, avd);
+       return 0;
+}
+
 /**
  * avc_has_perm_noaudit - Check permissions but perform no auditing.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -1133,40 +1139,36 @@ decision:
  * auditing, e.g. in cases where a lock must be held for the check but
  * should be released for the auditing.
  */
-inline int avc_has_perm_noaudit(struct selinux_state *state,
-                               u32 ssid, u32 tsid,
+inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                                u16 tclass, u32 requested,
                                unsigned int flags,
                                struct av_decision *avd)
 {
-       struct avc_node *node;
-       struct avc_xperms_node xp_node;
-       int rc = 0;
        u32 denied;
+       struct avc_node *node;
 
        if (WARN_ON(!requested))
                return -EACCES;
 
        rcu_read_lock();
+       node = avc_lookup(ssid, tsid, tclass);
+       if (unlikely(!node)) {
+               rcu_read_unlock();
+               return avc_perm_nonode(ssid, tsid, tclass, requested,
+                                      flags, avd);
+       }
+       denied = requested & ~node->ae.avd.allowed;
+       memcpy(avd, &node->ae.avd, sizeof(*avd));
+       rcu_read_unlock();
 
-       node = avc_lookup(state->avc, ssid, tsid, tclass);
-       if (unlikely(!node))
-               avc_compute_av(state, ssid, tsid, tclass, avd, &xp_node);
-       else
-               memcpy(avd, &node->ae.avd, sizeof(*avd));
-
-       denied = requested & ~(avd->allowed);
        if (unlikely(denied))
-               rc = avc_denied(state, ssid, tsid, tclass, requested, 0, 0,
-                               flags, avd);
-
-       rcu_read_unlock();
-       return rc;
+               return avc_denied(ssid, tsid, tclass, requested, 0, 0,
+                                 flags, avd);
+       return 0;
 }
 
 /**
  * avc_has_perm - Check permissions and perform any appropriate auditing.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -1181,25 +1183,25 @@ inline int avc_has_perm_noaudit(struct selinux_state *state,
  * permissions are granted, -%EACCES if any permissions are denied, or
  * another -errno upon other errors.
  */
-int avc_has_perm(struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass,
+int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
                 u32 requested, struct common_audit_data *auditdata)
 {
        struct av_decision avd;
        int rc, rc2;
 
-       rc = avc_has_perm_noaudit(state, ssid, tsid, tclass, requested, 0,
+       rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0,
                                  &avd);
 
-       rc2 = avc_audit(state, ssid, tsid, tclass, requested, &avd, rc,
+       rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc,
                        auditdata);
        if (rc2)
                return rc2;
        return rc;
 }
 
-u32 avc_policy_seqno(struct selinux_state *state)
+u32 avc_policy_seqno(void)
 {
-       return state->avc->avc_cache.latest_notif;
+       return selinux_avc.avc_cache.latest_notif;
 }
 
 void avc_disable(void)
@@ -1216,7 +1218,7 @@ void avc_disable(void)
         * the cache and get that memory back.
         */
        if (avc_node_cachep) {
-               avc_flush(selinux_state.avc);
+               avc_flush();
                /* kmem_cache_destroy(avc_node_cachep); */
        }
 }
index 9a5bdfc2131471b4b74ba68ee224d0002942f5aa..79b4890e9936dc1ee9e046c8020a22e018ac7990 100644 (file)
@@ -136,17 +136,13 @@ static int __init selinux_enabled_setup(char *str)
 __setup("selinux=", selinux_enabled_setup);
 #endif
 
-static unsigned int selinux_checkreqprot_boot =
-       CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
-
 static int __init checkreqprot_setup(char *str)
 {
        unsigned long checkreqprot;
 
        if (!kstrtoul(str, 0, &checkreqprot)) {
-               selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
                if (checkreqprot)
-                       pr_err("SELinux: checkreqprot set to 1 via kernel parameter.  This is deprecated and will be rejected in a future kernel release.\n");
+                       pr_err("SELinux: checkreqprot set to 1 via kernel parameter.  This is no longer supported.\n");
        }
        return 1;
 }
@@ -257,7 +253,7 @@ static int __inode_security_revalidate(struct inode *inode,
 
        might_sleep_if(may_sleep);
 
-       if (selinux_initialized(&selinux_state) &&
+       if (selinux_initialized() &&
            isec->initialized != LABEL_INITIALIZED) {
                if (!may_sleep)
                        return -ECHILD;
@@ -403,14 +399,12 @@ static int may_context_mount_sb_relabel(u32 sid,
        const struct task_security_struct *tsec = selinux_cred(cred);
        int rc;
 
-       rc = avc_has_perm(&selinux_state,
-                         tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+       rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__RELABELFROM, NULL);
        if (rc)
                return rc;
 
-       rc = avc_has_perm(&selinux_state,
-                         tsec->sid, sid, SECCLASS_FILESYSTEM,
+       rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__RELABELTO, NULL);
        return rc;
 }
@@ -421,14 +415,12 @@ static int may_context_mount_inode_relabel(u32 sid,
 {
        const struct task_security_struct *tsec = selinux_cred(cred);
        int rc;
-       rc = avc_has_perm(&selinux_state,
-                         tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+       rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__RELABELFROM, NULL);
        if (rc)
                return rc;
 
-       rc = avc_has_perm(&selinux_state,
-                         sid, sbsec->sid, SECCLASS_FILESYSTEM,
+       rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__ASSOCIATE, NULL);
        return rc;
 }
@@ -511,7 +503,7 @@ static int sb_check_xattr_support(struct super_block *sb)
 
 fallback:
        /* No xattr support - try to fallback to genfs if possible. */
-       rc = security_genfs_sid(&selinux_state, sb->s_type->name, "/",
+       rc = security_genfs_sid(sb->s_type->name, "/",
                                SECCLASS_DIR, &sid);
        if (rc)
                return -EOPNOTSUPP;
@@ -615,7 +607,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
 
        mutex_lock(&sbsec->lock);
 
-       if (!selinux_initialized(&selinux_state)) {
+       if (!selinux_initialized()) {
                if (!opts) {
                        /* Defer initialization until selinux_complete_init,
                           after the initial policy is loaded and the security
@@ -716,7 +708,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                 * Determine the labeling behavior to use for this
                 * filesystem type.
                 */
-               rc = security_fs_use(&selinux_state, sb);
+               rc = security_fs_use(sb);
                if (rc) {
                        pr_warn("%s: security_fs_use(%s) returned %d\n",
                                        __func__, sb->s_type->name, rc);
@@ -741,8 +733,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                }
                if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
                        sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
-                       rc = security_transition_sid(&selinux_state,
-                                                    current_sid(),
+                       rc = security_transition_sid(current_sid(),
                                                     current_sid(),
                                                     SECCLASS_FILE, NULL,
                                                     &sbsec->mntpoint_sid);
@@ -881,7 +872,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
         * if the parent was able to be mounted it clearly had no special lsm
         * mount options.  thus we can safely deal with this superblock later
         */
-       if (!selinux_initialized(&selinux_state))
+       if (!selinux_initialized())
                return 0;
 
        /*
@@ -911,7 +902,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
 
        if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
                !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
-               rc = security_fs_use(&selinux_state, newsb);
+               rc = security_fs_use(newsb);
                if (rc)
                        goto out;
        }
@@ -960,7 +951,7 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
        if (!s)
                return -EINVAL;
 
-       if (!selinux_initialized(&selinux_state)) {
+       if (!selinux_initialized()) {
                pr_warn("SELinux: Unable to set superblock options before the security server is initialized\n");
                return -EINVAL;
        }
@@ -997,7 +988,7 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
                WARN_ON(1);
                return -EINVAL;
        }
-       rc = security_context_str_to_sid(&selinux_state, s, dst_sid, GFP_KERNEL);
+       rc = security_context_str_to_sid(s, dst_sid, GFP_KERNEL);
        if (rc)
                pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n",
                        s, rc);
@@ -1014,8 +1005,7 @@ static int show_sid(struct seq_file *m, u32 sid)
        u32 len;
        int rc;
 
-       rc = security_sid_to_context(&selinux_state, sid,
-                                            &context, &len);
+       rc = security_sid_to_context(sid, &context, &len);
        if (!rc) {
                bool has_comma = strchr(context, ',');
 
@@ -1038,7 +1028,7 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
        if (!(sbsec->flags & SE_SBINITIALIZED))
                return 0;
 
-       if (!selinux_initialized(&selinux_state))
+       if (!selinux_initialized())
                return 0;
 
        if (sbsec->flags & FSCONTEXT_MNT) {
@@ -1292,7 +1282,7 @@ static int selinux_genfs_get_sid(struct dentry *dentry,
                                path++;
                        }
                }
-               rc = security_genfs_sid(&selinux_state, sb->s_type->name,
+               rc = security_genfs_sid(sb->s_type->name,
                                        path, tclass, sid);
                if (rc == -ENOENT) {
                        /* No match in policy, mark as unlabeled. */
@@ -1347,7 +1337,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
                return 0;
        }
 
-       rc = security_context_to_sid_default(&selinux_state, context, rc, sid,
+       rc = security_context_to_sid_default(context, rc, sid,
                                             def_sid, GFP_NOFS);
        if (rc) {
                char *dev = inode->i_sb->s_id;
@@ -1454,7 +1444,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                sid = sbsec->sid;
 
                /* Try to obtain a transition SID. */
-               rc = security_transition_sid(&selinux_state, task_sid, sid,
+               rc = security_transition_sid(task_sid, sid,
                                             sclass, NULL, &sid);
                if (rc)
                        goto out;
@@ -1599,11 +1589,9 @@ static int cred_has_capability(const struct cred *cred,
                return -EINVAL;
        }
 
-       rc = avc_has_perm_noaudit(&selinux_state,
-                                 sid, sid, sclass, av, 0, &avd);
+       rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
        if (!(opts & CAP_OPT_NOAUDIT)) {
-               int rc2 = avc_audit(&selinux_state,
-                                   sid, sid, sclass, av, &avd, rc, &ad);
+               int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
                if (rc2)
                        return rc2;
        }
@@ -1629,8 +1617,7 @@ static int inode_has_perm(const struct cred *cred,
        sid = cred_sid(cred);
        isec = selinux_inode(inode);
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, isec->sclass, perms, adp);
+       return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
 }
 
 /* Same as inode_has_perm, but pass explicit audit data containing
@@ -1703,8 +1690,7 @@ static int file_has_perm(const struct cred *cred,
        ad.u.file = file;
 
        if (sid != fsec->sid) {
-               rc = avc_has_perm(&selinux_state,
-                                 sid, fsec->sid,
+               rc = avc_has_perm(sid, fsec->sid,
                                  SECCLASS_FD,
                                  FD__USE,
                                  &ad);
@@ -1747,7 +1733,7 @@ selinux_determine_inode_label(const struct task_security_struct *tsec,
                *_new_isid = tsec->create_sid;
        } else {
                const struct inode_security_struct *dsec = inode_security(dir);
-               return security_transition_sid(&selinux_state, tsec->sid,
+               return security_transition_sid(tsec->sid,
                                               dsec->sid, tclass,
                                               name, _new_isid);
        }
@@ -1775,8 +1761,7 @@ static int may_create(struct inode *dir,
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
 
-       rc = avc_has_perm(&selinux_state,
-                         sid, dsec->sid, SECCLASS_DIR,
+       rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
                          DIR__ADD_NAME | DIR__SEARCH,
                          &ad);
        if (rc)
@@ -1787,13 +1772,11 @@ static int may_create(struct inode *dir,
        if (rc)
                return rc;
 
-       rc = avc_has_perm(&selinux_state,
-                         sid, newsid, tclass, FILE__CREATE, &ad);
+       rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
        if (rc)
                return rc;
 
-       return avc_has_perm(&selinux_state,
-                           newsid, sbsec->sid,
+       return avc_has_perm(newsid, sbsec->sid,
                            SECCLASS_FILESYSTEM,
                            FILESYSTEM__ASSOCIATE, &ad);
 }
@@ -1822,8 +1805,7 @@ static int may_link(struct inode *dir,
 
        av = DIR__SEARCH;
        av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
-       rc = avc_has_perm(&selinux_state,
-                         sid, dsec->sid, SECCLASS_DIR, av, &ad);
+       rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
        if (rc)
                return rc;
 
@@ -1843,8 +1825,7 @@ static int may_link(struct inode *dir,
                return 0;
        }
 
-       rc = avc_has_perm(&selinux_state,
-                         sid, isec->sid, isec->sclass, av, &ad);
+       rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
        return rc;
 }
 
@@ -1868,19 +1849,16 @@ static inline int may_rename(struct inode *old_dir,
        ad.type = LSM_AUDIT_DATA_DENTRY;
 
        ad.u.dentry = old_dentry;
-       rc = avc_has_perm(&selinux_state,
-                         sid, old_dsec->sid, SECCLASS_DIR,
+       rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
                          DIR__REMOVE_NAME | DIR__SEARCH, &ad);
        if (rc)
                return rc;
-       rc = avc_has_perm(&selinux_state,
-                         sid, old_isec->sid,
+       rc = avc_has_perm(sid, old_isec->sid,
                          old_isec->sclass, FILE__RENAME, &ad);
        if (rc)
                return rc;
        if (old_is_dir && new_dir != old_dir) {
-               rc = avc_has_perm(&selinux_state,
-                                 sid, old_isec->sid,
+               rc = avc_has_perm(sid, old_isec->sid,
                                  old_isec->sclass, DIR__REPARENT, &ad);
                if (rc)
                        return rc;
@@ -1890,15 +1868,13 @@ static inline int may_rename(struct inode *old_dir,
        av = DIR__ADD_NAME | DIR__SEARCH;
        if (d_is_positive(new_dentry))
                av |= DIR__REMOVE_NAME;
-       rc = avc_has_perm(&selinux_state,
-                         sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
+       rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
        if (rc)
                return rc;
        if (d_is_positive(new_dentry)) {
                new_isec = backing_inode_security(new_dentry);
                new_is_dir = d_is_dir(new_dentry);
-               rc = avc_has_perm(&selinux_state,
-                                 sid, new_isec->sid,
+               rc = avc_has_perm(sid, new_isec->sid,
                                  new_isec->sclass,
                                  (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
                if (rc)
@@ -1918,8 +1894,7 @@ static int superblock_has_perm(const struct cred *cred,
        u32 sid = cred_sid(cred);
 
        sbsec = selinux_superblock(sb);
-       return avc_has_perm(&selinux_state,
-                           sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
+       return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
 }
 
 /* Convert a Linux mode and permission mask to an access vector. */
@@ -1993,8 +1968,7 @@ static inline u32 open_file_to_av(struct file *file)
 
 static int selinux_binder_set_context_mgr(const struct cred *mgr)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), cred_sid(mgr), SECCLASS_BINDER,
+       return avc_has_perm(current_sid(), cred_sid(mgr), SECCLASS_BINDER,
                            BINDER__SET_CONTEXT_MGR, NULL);
 }
 
@@ -2007,22 +1981,20 @@ static int selinux_binder_transaction(const struct cred *from,
        int rc;
 
        if (mysid != fromsid) {
-               rc = avc_has_perm(&selinux_state,
-                                 mysid, fromsid, SECCLASS_BINDER,
+               rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
                                  BINDER__IMPERSONATE, NULL);
                if (rc)
                        return rc;
        }
 
-       return avc_has_perm(&selinux_state, fromsid, tosid,
+       return avc_has_perm(fromsid, tosid,
                            SECCLASS_BINDER, BINDER__CALL, NULL);
 }
 
 static int selinux_binder_transfer_binder(const struct cred *from,
                                          const struct cred *to)
 {
-       return avc_has_perm(&selinux_state,
-                           cred_sid(from), cred_sid(to),
+       return avc_has_perm(cred_sid(from), cred_sid(to),
                            SECCLASS_BINDER, BINDER__TRANSFER,
                            NULL);
 }
@@ -2042,8 +2014,7 @@ static int selinux_binder_transfer_file(const struct cred *from,
        ad.u.path = file->f_path;
 
        if (sid != fsec->sid) {
-               rc = avc_has_perm(&selinux_state,
-                                 sid, fsec->sid,
+               rc = avc_has_perm(sid, fsec->sid,
                                  SECCLASS_FD,
                                  FD__USE,
                                  &ad);
@@ -2061,8 +2032,7 @@ static int selinux_binder_transfer_file(const struct cred *from,
                return 0;
 
        isec = backing_inode_security(dentry);
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, isec->sclass, file_to_av(file),
+       return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
                            &ad);
 }
 
@@ -2073,26 +2043,24 @@ static int selinux_ptrace_access_check(struct task_struct *child,
        u32 csid = task_sid_obj(child);
 
        if (mode & PTRACE_MODE_READ)
-               return avc_has_perm(&selinux_state,
-                                   sid, csid, SECCLASS_FILE, FILE__READ, NULL);
+               return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ,
+                               NULL);
 
-       return avc_has_perm(&selinux_state,
-                           sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
+       return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE,
+                       NULL);
 }
 
 static int selinux_ptrace_traceme(struct task_struct *parent)
 {
-       return avc_has_perm(&selinux_state,
-                           task_sid_obj(parent), task_sid_obj(current),
+       return avc_has_perm(task_sid_obj(parent), task_sid_obj(current),
                            SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
 }
 
 static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(target), SECCLASS_PROCESS,
-                           PROCESS__GETCAP, NULL);
+       return avc_has_perm(current_sid(), task_sid_obj(target),
+                       SECCLASS_PROCESS, PROCESS__GETCAP, NULL);
 }
 
 static int selinux_capset(struct cred *new, const struct cred *old,
@@ -2100,8 +2068,7 @@ static int selinux_capset(struct cred *new, const struct cred *old,
                          const kernel_cap_t *inheritable,
                          const kernel_cap_t *permitted)
 {
-       return avc_has_perm(&selinux_state,
-                           cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
+       return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
                            PROCESS__SETCAP, NULL);
 }
 
@@ -2168,21 +2135,18 @@ static int selinux_syslog(int type)
        switch (type) {
        case SYSLOG_ACTION_READ_ALL:    /* Read last kernel messages */
        case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
-               return avc_has_perm(&selinux_state,
-                                   current_sid(), SECINITSID_KERNEL,
+               return avc_has_perm(current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
        case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
        case SYSLOG_ACTION_CONSOLE_ON:  /* Enable logging to console */
        /* Set level of messages printed to console */
        case SYSLOG_ACTION_CONSOLE_LEVEL:
-               return avc_has_perm(&selinux_state,
-                                   current_sid(), SECINITSID_KERNEL,
+               return avc_has_perm(current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
                                    NULL);
        }
        /* All other syslog types */
-       return avc_has_perm(&selinux_state,
-                           current_sid(), SECINITSID_KERNEL,
+       return avc_has_perm(current_sid(), SECINITSID_KERNEL,
                            SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
 }
 
@@ -2249,8 +2213,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
                        av |= PROCESS2__NNP_TRANSITION;
                if (nosuid)
                        av |= PROCESS2__NOSUID_TRANSITION;
-               rc = avc_has_perm(&selinux_state,
-                                 old_tsec->sid, new_tsec->sid,
+               rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
                                  SECCLASS_PROCESS2, av, NULL);
                if (!rc)
                        return 0;
@@ -2261,7 +2224,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
         * i.e. SIDs that are guaranteed to only be allowed a subset
         * of the permissions of the current SID.
         */
-       rc = security_bounded_transition(&selinux_state, old_tsec->sid,
+       rc = security_bounded_transition(old_tsec->sid,
                                         new_tsec->sid);
        if (!rc)
                return 0;
@@ -2312,7 +2275,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
                        return rc;
        } else {
                /* Check for a default transition on this program. */
-               rc = security_transition_sid(&selinux_state, old_tsec->sid,
+               rc = security_transition_sid(old_tsec->sid,
                                             isec->sid, SECCLASS_PROCESS, NULL,
                                             &new_tsec->sid);
                if (rc)
@@ -2331,29 +2294,25 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
        ad.u.file = bprm->file;
 
        if (new_tsec->sid == old_tsec->sid) {
-               rc = avc_has_perm(&selinux_state,
-                                 old_tsec->sid, isec->sid,
+               rc = avc_has_perm(old_tsec->sid, isec->sid,
                                  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
                if (rc)
                        return rc;
        } else {
                /* Check permissions for the transition. */
-               rc = avc_has_perm(&selinux_state,
-                                 old_tsec->sid, new_tsec->sid,
+               rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
                                  SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
                if (rc)
                        return rc;
 
-               rc = avc_has_perm(&selinux_state,
-                                 new_tsec->sid, isec->sid,
+               rc = avc_has_perm(new_tsec->sid, isec->sid,
                                  SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
                if (rc)
                        return rc;
 
                /* Check for shared state */
                if (bprm->unsafe & LSM_UNSAFE_SHARE) {
-                       rc = avc_has_perm(&selinux_state,
-                                         old_tsec->sid, new_tsec->sid,
+                       rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
                                          SECCLASS_PROCESS, PROCESS__SHARE,
                                          NULL);
                        if (rc)
@@ -2365,8 +2324,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
                if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
                        u32 ptsid = ptrace_parent_sid();
                        if (ptsid != 0) {
-                               rc = avc_has_perm(&selinux_state,
-                                                 ptsid, new_tsec->sid,
+                               rc = avc_has_perm(ptsid, new_tsec->sid,
                                                  SECCLASS_PROCESS,
                                                  PROCESS__PTRACE, NULL);
                                if (rc)
@@ -2380,8 +2338,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
                /* Enable secure mode for SIDs transitions unless
                   the noatsecure permission is granted between
                   the two SIDs, i.e. ahp returns 0. */
-               rc = avc_has_perm(&selinux_state,
-                                 old_tsec->sid, new_tsec->sid,
+               rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
                                  SECCLASS_PROCESS, PROCESS__NOATSECURE,
                                  NULL);
                bprm->secureexec |= !!rc;
@@ -2473,8 +2430,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm)
         * higher than the default soft limit for cases where the default is
         * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
         */
-       rc = avc_has_perm(&selinux_state,
-                         new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
+       rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
                          PROCESS__RLIMITINH, NULL);
        if (rc) {
                /* protect against do_prlimit() */
@@ -2513,8 +2469,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm)
         * This must occur _after_ the task SID has been updated so that any
         * kill done after the flush will be checked against the new SID.
         */
-       rc = avc_has_perm(&selinux_state,
-                         osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
+       rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
        if (rc) {
                clear_itimer();
 
@@ -2841,7 +2796,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
        if (xattr_name)
                *xattr_name = XATTR_NAME_SELINUX;
 
-       return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
+       return security_sid_to_context(newsid, (char **)ctx,
                                       ctxlen);
 }
 
@@ -2895,7 +2850,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
                isec->initialized = LABEL_INITIALIZED;
        }
 
-       if (!selinux_initialized(&selinux_state) ||
+       if (!selinux_initialized() ||
            !(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
 
@@ -2903,7 +2858,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
                *name = XATTR_SELINUX_SUFFIX;
 
        if (value && len) {
-               rc = security_sid_to_context_force(&selinux_state, newsid,
+               rc = security_sid_to_context_force(newsid,
                                                   &context, &clen);
                if (rc)
                        return rc;
@@ -2923,7 +2878,7 @@ static int selinux_inode_init_security_anon(struct inode *inode,
        struct inode_security_struct *isec;
        int rc;
 
-       if (unlikely(!selinux_initialized(&selinux_state)))
+       if (unlikely(!selinux_initialized()))
                return 0;
 
        isec = selinux_inode(inode);
@@ -2947,7 +2902,7 @@ static int selinux_inode_init_security_anon(struct inode *inode,
        } else {
                isec->sclass = SECCLASS_ANON_INODE;
                rc = security_transition_sid(
-                       &selinux_state, tsec->sid, tsec->sid,
+                       tsec->sid, tsec->sid,
                        isec->sclass, name, &isec->sid);
                if (rc)
                        return rc;
@@ -2962,8 +2917,7 @@ static int selinux_inode_init_security_anon(struct inode *inode,
        ad.type = LSM_AUDIT_DATA_ANONINODE;
        ad.u.anonclass = name ? (const char *)name->name : "?";
 
-       return avc_has_perm(&selinux_state,
-                           tsec->sid,
+       return avc_has_perm(tsec->sid,
                            isec->sid,
                            isec->sclass,
                            FILE__CREATE,
@@ -3035,8 +2989,7 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct inode *inode,
        if (IS_ERR(isec))
                return PTR_ERR(isec);
 
-       return avc_has_perm(&selinux_state,
-                                 sid, isec->sid, isec->sclass, FILE__READ, &ad);
+       return avc_has_perm(sid, isec->sid, isec->sclass, FILE__READ, &ad);
 }
 
 static noinline int audit_inode_permission(struct inode *inode,
@@ -3049,8 +3002,7 @@ static noinline int audit_inode_permission(struct inode *inode,
        ad.type = LSM_AUDIT_DATA_INODE;
        ad.u.inode = inode;
 
-       return slow_avc_audit(&selinux_state,
-                           current_sid(), isec->sid, isec->sclass, perms,
+       return slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
                            audited, denied, result, &ad);
 }
 
@@ -3085,8 +3037,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
        if (IS_ERR(isec))
                return PTR_ERR(isec);
 
-       rc = avc_has_perm_noaudit(&selinux_state,
-                                 sid, isec->sid, isec->sclass, perms, 0,
+       rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0,
                                  &avd);
        audited = avc_audit_required(perms, &avd, rc,
                                     from_access ? FILE__AUDIT_ACCESS : 0,
@@ -3166,7 +3117,7 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap,
                return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
        }
 
-       if (!selinux_initialized(&selinux_state))
+       if (!selinux_initialized())
                return (inode_owner_or_capable(idmap, inode) ? 0 : -EPERM);
 
        sbsec = selinux_superblock(inode->i_sb);
@@ -3180,13 +3131,12 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap,
        ad.u.dentry = dentry;
 
        isec = backing_inode_security(dentry);
-       rc = avc_has_perm(&selinux_state,
-                         sid, isec->sid, isec->sclass,
+       rc = avc_has_perm(sid, isec->sid, isec->sclass,
                          FILE__RELABELFROM, &ad);
        if (rc)
                return rc;
 
-       rc = security_context_to_sid(&selinux_state, value, size, &newsid,
+       rc = security_context_to_sid(value, size, &newsid,
                                     GFP_KERNEL);
        if (rc == -EINVAL) {
                if (!has_cap_mac_admin(true)) {
@@ -3215,25 +3165,23 @@ static int selinux_inode_setxattr(struct mnt_idmap *idmap,
 
                        return rc;
                }
-               rc = security_context_to_sid_force(&selinux_state, value,
+               rc = security_context_to_sid_force(value,
                                                   size, &newsid);
        }
        if (rc)
                return rc;
 
-       rc = avc_has_perm(&selinux_state,
-                         sid, newsid, isec->sclass,
+       rc = avc_has_perm(sid, newsid, isec->sclass,
                          FILE__RELABELTO, &ad);
        if (rc)
                return rc;
 
-       rc = security_validate_transition(&selinux_state, isec->sid, newsid,
+       rc = security_validate_transition(isec->sid, newsid,
                                          sid, isec->sclass);
        if (rc)
                return rc;
 
-       return avc_has_perm(&selinux_state,
-                           newsid,
+       return avc_has_perm(newsid,
                            sbsec->sid,
                            SECCLASS_FILESYSTEM,
                            FILESYSTEM__ASSOCIATE,
@@ -3273,7 +3221,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
                return;
        }
 
-       if (!selinux_initialized(&selinux_state)) {
+       if (!selinux_initialized()) {
                /* If we haven't even been initialized, then we can't validate
                 * against a policy, so leave the label as invalid. It may
                 * resolve to a valid label on the next revalidation try if
@@ -3282,7 +3230,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
                return;
        }
 
-       rc = security_context_to_sid_force(&selinux_state, value, size,
+       rc = security_context_to_sid_force(value, size,
                                           &newsid);
        if (rc) {
                pr_err("SELinux:  unable to map context to SID"
@@ -3326,7 +3274,7 @@ static int selinux_inode_removexattr(struct mnt_idmap *idmap,
                return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
        }
 
-       if (!selinux_initialized(&selinux_state))
+       if (!selinux_initialized())
                return 0;
 
        /* No one is allowed to remove a SELinux security label.
@@ -3396,7 +3344,7 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap,
         * If we're not initialized yet, then we can't validate contexts, so
         * just let vfs_getxattr fall back to using the on-disk xattr.
         */
-       if (!selinux_initialized(&selinux_state) ||
+       if (!selinux_initialized() ||
            strcmp(name, XATTR_SELINUX_SUFFIX))
                return -EOPNOTSUPP;
 
@@ -3411,11 +3359,10 @@ static int selinux_inode_getsecurity(struct mnt_idmap *idmap,
         */
        isec = inode_security(inode);
        if (has_cap_mac_admin(false))
-               error = security_sid_to_context_force(&selinux_state,
-                                                     isec->sid, &context,
+               error = security_sid_to_context_force(isec->sid, &context,
                                                      &size);
        else
-               error = security_sid_to_context(&selinux_state, isec->sid,
+               error = security_sid_to_context(isec->sid,
                                                &context, &size);
        if (error)
                return error;
@@ -3447,7 +3394,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
        if (!value || !size)
                return -EACCES;
 
-       rc = security_context_to_sid(&selinux_state, value, size, &newsid,
+       rc = security_context_to_sid(value, size, &newsid,
                                     GFP_KERNEL);
        if (rc)
                return rc;
@@ -3464,7 +3411,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
 {
        const int len = sizeof(XATTR_NAME_SELINUX);
 
-       if (!selinux_initialized(&selinux_state))
+       if (!selinux_initialized())
                return 0;
 
        if (buffer && len <= buffer_size)
@@ -3540,7 +3487,7 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
                return rc;
        }
 
-       rc = security_context_to_sid(&selinux_state, context, clen, &parent_sid,
+       rc = security_context_to_sid(context, clen, &parent_sid,
                                     GFP_KERNEL);
        kfree(context);
        if (rc)
@@ -3555,14 +3502,14 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
                q.name = kn->name;
                q.hash_len = hashlen_string(kn_dir, kn->name);
 
-               rc = security_transition_sid(&selinux_state, tsec->sid,
+               rc = security_transition_sid(tsec->sid,
                                             parent_sid, secclass, &q,
                                             &newsid);
                if (rc)
                        return rc;
        }
 
-       rc = security_sid_to_context_force(&selinux_state, newsid,
+       rc = security_sid_to_context_force(newsid,
                                           &context, &clen);
        if (rc)
                return rc;
@@ -3602,7 +3549,7 @@ static int selinux_file_permission(struct file *file, int mask)
 
        isec = inode_security(inode);
        if (sid == fsec->sid && fsec->isid == isec->sid &&
-           fsec->pseqno == avc_policy_seqno(&selinux_state))
+           fsec->pseqno == avc_policy_seqno())
                /* No change since file_open check. */
                return 0;
 
@@ -3643,8 +3590,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
        ad.u.op->path = file->f_path;
 
        if (ssid != fsec->sid) {
-               rc = avc_has_perm(&selinux_state,
-                                 ssid, fsec->sid,
+               rc = avc_has_perm(ssid, fsec->sid,
                                SECCLASS_FD,
                                FD__USE,
                                &ad);
@@ -3656,8 +3602,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
                return 0;
 
        isec = inode_security(inode);
-       rc = avc_has_extended_perms(&selinux_state,
-                                   ssid, isec->sid, isec->sclass,
+       rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
                                    requested, driver, xperm, &ad);
 out:
        return rc;
@@ -3726,8 +3671,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
                 * private file mapping that will also be writable.
                 * This has an additional check.
                 */
-               rc = avc_has_perm(&selinux_state,
-                                 sid, sid, SECCLASS_PROCESS,
+               rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
                                  PROCESS__EXECMEM, NULL);
                if (rc)
                        goto error;
@@ -3757,15 +3701,15 @@ static int selinux_mmap_addr(unsigned long addr)
 
        if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
                u32 sid = current_sid();
-               rc = avc_has_perm(&selinux_state,
-                                 sid, sid, SECCLASS_MEMPROTECT,
+               rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
                                  MEMPROTECT__MMAP_ZERO, NULL);
        }
 
        return rc;
 }
 
-static int selinux_mmap_file(struct file *file, unsigned long reqprot,
+static int selinux_mmap_file(struct file *file,
+                            unsigned long reqprot __always_unused,
                             unsigned long prot, unsigned long flags)
 {
        struct common_audit_data ad;
@@ -3780,37 +3724,29 @@ static int selinux_mmap_file(struct file *file, unsigned long reqprot,
                        return rc;
        }
 
-       if (checkreqprot_get(&selinux_state))
-               prot = reqprot;
-
        return file_map_prot_check(file, prot,
                                   (flags & MAP_TYPE) == MAP_SHARED);
 }
 
 static int selinux_file_mprotect(struct vm_area_struct *vma,
-                                unsigned long reqprot,
+                                unsigned long reqprot __always_unused,
                                 unsigned long prot)
 {
        const struct cred *cred = current_cred();
        u32 sid = cred_sid(cred);
 
-       if (checkreqprot_get(&selinux_state))
-               prot = reqprot;
-
        if (default_noexec &&
            (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
                int rc = 0;
                if (vma->vm_start >= vma->vm_mm->start_brk &&
                    vma->vm_end <= vma->vm_mm->brk) {
-                       rc = avc_has_perm(&selinux_state,
-                                         sid, sid, SECCLASS_PROCESS,
+                       rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
                                          PROCESS__EXECHEAP, NULL);
                } else if (!vma->vm_file &&
                           ((vma->vm_start <= vma->vm_mm->start_stack &&
                             vma->vm_end >= vma->vm_mm->start_stack) ||
                            vma_is_stack_for_current(vma))) {
-                       rc = avc_has_perm(&selinux_state,
-                                         sid, sid, SECCLASS_PROCESS,
+                       rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
                                          PROCESS__EXECSTACK, NULL);
                } else if (vma->vm_file && vma->anon_vma) {
                        /*
@@ -3902,8 +3838,7 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
        else
                perm = signal_to_av(signum);
 
-       return avc_has_perm(&selinux_state,
-                           fsec->fown_sid, sid,
+       return avc_has_perm(fsec->fown_sid, sid,
                            SECCLASS_PROCESS, perm, NULL);
 }
 
@@ -3929,7 +3864,7 @@ static int selinux_file_open(struct file *file)
         * struct as its SID.
         */
        fsec->isid = isec->sid;
-       fsec->pseqno = avc_policy_seqno(&selinux_state);
+       fsec->pseqno = avc_policy_seqno();
        /*
         * Since the inode label or policy seqno may have changed
         * between the selinux_inode_permission check and the saving
@@ -3948,8 +3883,7 @@ static int selinux_task_alloc(struct task_struct *task,
 {
        u32 sid = current_sid();
 
-       return avc_has_perm(&selinux_state,
-                           sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
+       return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
 }
 
 /*
@@ -3991,8 +3925,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)
        u32 sid = current_sid();
        int ret;
 
-       ret = avc_has_perm(&selinux_state,
-                          sid, secid,
+       ret = avc_has_perm(sid, secid,
                           SECCLASS_KERNEL_SERVICE,
                           KERNEL_SERVICE__USE_AS_OVERRIDE,
                           NULL);
@@ -4016,8 +3949,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
        u32 sid = current_sid();
        int ret;
 
-       ret = avc_has_perm(&selinux_state,
-                          sid, isec->sid,
+       ret = avc_has_perm(sid, isec->sid,
                           SECCLASS_KERNEL_SERVICE,
                           KERNEL_SERVICE__CREATE_FILES_AS,
                           NULL);
@@ -4034,8 +3966,7 @@ static int selinux_kernel_module_request(char *kmod_name)
        ad.type = LSM_AUDIT_DATA_KMOD;
        ad.u.kmod_name = kmod_name;
 
-       return avc_has_perm(&selinux_state,
-                           current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
+       return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
                            SYSTEM__MODULE_REQUEST, &ad);
 }
 
@@ -4049,8 +3980,7 @@ static int selinux_kernel_module_from_file(struct file *file)
 
        /* init_module */
        if (file == NULL)
-               return avc_has_perm(&selinux_state,
-                                   sid, sid, SECCLASS_SYSTEM,
+               return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
                                        SYSTEM__MODULE_LOAD, NULL);
 
        /* finit_module */
@@ -4060,15 +3990,13 @@ static int selinux_kernel_module_from_file(struct file *file)
 
        fsec = selinux_file(file);
        if (sid != fsec->sid) {
-               rc = avc_has_perm(&selinux_state,
-                                 sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
+               rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
                if (rc)
                        return rc;
        }
 
        isec = inode_security(file_inode(file));
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_SYSTEM,
+       return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
                                SYSTEM__MODULE_LOAD, &ad);
 }
 
@@ -4106,22 +4034,19 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
 
 static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__SETPGID, NULL);
 }
 
 static int selinux_task_getpgid(struct task_struct *p)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__GETPGID, NULL);
 }
 
 static int selinux_task_getsid(struct task_struct *p)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__GETSESSION, NULL);
 }
 
@@ -4137,22 +4062,19 @@ static void selinux_task_getsecid_obj(struct task_struct *p, u32 *secid)
 
 static int selinux_task_setnice(struct task_struct *p, int nice)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
 }
 
 static int selinux_task_setioprio(struct task_struct *p, int ioprio)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
 }
 
 static int selinux_task_getioprio(struct task_struct *p)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__GETSCHED, NULL);
 }
 
@@ -4167,8 +4089,7 @@ static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcre
                av |= PROCESS__SETRLIMIT;
        if (flags & LSM_PRLIMIT_READ)
                av |= PROCESS__GETRLIMIT;
-       return avc_has_perm(&selinux_state,
-                           cred_sid(cred), cred_sid(tcred),
+       return avc_has_perm(cred_sid(cred), cred_sid(tcred),
                            SECCLASS_PROCESS, av, NULL);
 }
 
@@ -4182,8 +4103,7 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
           later be used as a safe reset point for the soft limit
           upon context transitions.  See selinux_bprm_committing_creds. */
        if (old_rlim->rlim_max != new_rlim->rlim_max)
-               return avc_has_perm(&selinux_state,
-                                   current_sid(), task_sid_obj(p),
+               return avc_has_perm(current_sid(), task_sid_obj(p),
                                    SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
 
        return 0;
@@ -4191,22 +4111,19 @@ static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource,
 
 static int selinux_task_setscheduler(struct task_struct *p)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
 }
 
 static int selinux_task_getscheduler(struct task_struct *p)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__GETSCHED, NULL);
 }
 
 static int selinux_task_movememory(struct task_struct *p)
 {
-       return avc_has_perm(&selinux_state,
-                           current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
+       return avc_has_perm(current_sid(), task_sid_obj(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
 }
 
@@ -4224,8 +4141,7 @@ static int selinux_task_kill(struct task_struct *p, struct kernel_siginfo *info,
                secid = current_sid();
        else
                secid = cred_sid(cred);
-       return avc_has_perm(&selinux_state,
-                           secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL);
+       return avc_has_perm(secid, task_sid_obj(p), SECCLASS_PROCESS, perm, NULL);
 }
 
 static void selinux_task_to_inode(struct task_struct *p,
@@ -4245,8 +4161,8 @@ static int selinux_userns_create(const struct cred *cred)
 {
        u32 sid = current_sid();
 
-       return avc_has_perm(&selinux_state, sid, sid, SECCLASS_USER_NAMESPACE,
-                                               USER_NAMESPACE__CREATE, NULL);
+       return avc_has_perm(sid, sid, SECCLASS_USER_NAMESPACE,
+                       USER_NAMESPACE__CREATE, NULL);
 }
 
 /* Returns error only if unable to parse addresses */
@@ -4504,7 +4420,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        if (unlikely(err))
                return -EACCES;
 
-       err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
+       err = security_net_peersid_resolve(nlbl_sid,
                                           nlbl_type, xfrm_sid, sid);
        if (unlikely(err)) {
                pr_warn(
@@ -4533,7 +4449,7 @@ static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
        int err = 0;
 
        if (skb_sid != SECSID_NULL)
-               err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
+               err = security_sid_mls_copy(sk_sid, skb_sid,
                                            conn_sid);
        else
                *conn_sid = sk_sid;
@@ -4551,7 +4467,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
                return 0;
        }
 
-       return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
+       return security_transition_sid(tsec->sid, tsec->sid,
                                       secclass, NULL, socksid);
 }
 
@@ -4568,8 +4484,7 @@ static int sock_has_perm(struct sock *sk, u32 perms)
        ad.u.net = &net;
        ad.u.net->sk = sk;
 
-       return avc_has_perm(&selinux_state,
-                           current_sid(), sksec->sid, sksec->sclass, perms,
+       return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
                            &ad);
 }
 
@@ -4589,8 +4504,7 @@ static int selinux_socket_create(int family, int type,
        if (rc)
                return rc;
 
-       return avc_has_perm(&selinux_state,
-                           tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
+       return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
 }
 
 static int selinux_socket_post_create(struct socket *sock, int family,
@@ -4719,8 +4633,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                                      snum, &sid);
                                if (err)
                                        goto out;
-                               err = avc_has_perm(&selinux_state,
-                                                  sksec->sid, sid,
+                               err = avc_has_perm(sksec->sid, sid,
                                                   sksec->sclass,
                                                   SOCKET__NAME_BIND, &ad);
                                if (err)
@@ -4759,8 +4672,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                else
                        ad.u.net->v6info.saddr = addr6->sin6_addr;
 
-               err = avc_has_perm(&selinux_state,
-                                  sksec->sid, sid,
+               err = avc_has_perm(sksec->sid, sid,
                                   sksec->sclass, node_perm, &ad);
                if (err)
                        goto out;
@@ -4858,8 +4770,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
                ad.u.net = &net;
                ad.u.net->dport = htons(snum);
                ad.u.net->family = address->sa_family;
-               err = avc_has_perm(&selinux_state,
-                                  sksec->sid, sid, sksec->sclass, perm, &ad);
+               err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
                if (err)
                        return err;
        }
@@ -4971,8 +4882,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
        ad.u.net = &net;
        ad.u.net->sk = other;
 
-       err = avc_has_perm(&selinux_state,
-                          sksec_sock->sid, sksec_other->sid,
+       err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
                           sksec_other->sclass,
                           UNIX_STREAM_SOCKET__CONNECTTO, &ad);
        if (err)
@@ -4980,7 +4890,7 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
 
        /* server child socket */
        sksec_new->peer_sid = sksec_sock->sid;
-       err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
+       err = security_sid_mls_copy(sksec_other->sid,
                                    sksec_sock->sid, &sksec_new->sid);
        if (err)
                return err;
@@ -5003,8 +4913,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
        ad.u.net = &net;
        ad.u.net->sk = other->sk;
 
-       return avc_has_perm(&selinux_state,
-                           ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
+       return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
                            &ad);
 }
 
@@ -5019,8 +4928,7 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
        err = sel_netif_sid(ns, ifindex, &if_sid);
        if (err)
                return err;
-       err = avc_has_perm(&selinux_state,
-                          peer_sid, if_sid,
+       err = avc_has_perm(peer_sid, if_sid,
                           SECCLASS_NETIF, NETIF__INGRESS, ad);
        if (err)
                return err;
@@ -5028,8 +4936,7 @@ static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
        err = sel_netnode_sid(addrp, family, &node_sid);
        if (err)
                return err;
-       return avc_has_perm(&selinux_state,
-                           peer_sid, node_sid,
+       return avc_has_perm(peer_sid, node_sid,
                            SECCLASS_NODE, NODE__RECVFROM, ad);
 }
 
@@ -5052,8 +4959,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
                return err;
 
        if (selinux_secmark_enabled()) {
-               err = avc_has_perm(&selinux_state,
-                                  sk_sid, skb->secmark, SECCLASS_PACKET,
+               err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
                                   PACKET__RECV, &ad);
                if (err)
                        return err;
@@ -5118,8 +5024,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                        selinux_netlbl_err(skb, family, err, 0);
                        return err;
                }
-               err = avc_has_perm(&selinux_state,
-                                  sk_sid, peer_sid, SECCLASS_PEER,
+               err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
                if (err) {
                        selinux_netlbl_err(skb, family, err, 0);
@@ -5128,8 +5033,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
        }
 
        if (secmark_active) {
-               err = avc_has_perm(&selinux_state,
-                                  sk_sid, skb->secmark, SECCLASS_PACKET,
+               err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
                                   PACKET__RECV, &ad);
                if (err)
                        return err;
@@ -5155,7 +5059,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock,
        if (peer_sid == SECSID_NULL)
                return -ENOPROTOOPT;
 
-       err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
+       err = security_sid_to_context(peer_sid, &scontext,
                                      &scontext_len);
        if (err)
                return err;
@@ -5312,8 +5216,7 @@ static int selinux_sctp_process_new_assoc(struct sctp_association *asoc,
                ad.type = LSM_AUDIT_DATA_NET;
                ad.u.net = &net;
                ad.u.net->sk = asoc->base.sk;
-               err = avc_has_perm(&selinux_state,
-                                  sksec->peer_sid, asoc->peer_secid,
+               err = avc_has_perm(sksec->peer_sid, asoc->peer_secid,
                                   sksec->sclass, SCTP_SOCKET__ASSOCIATION,
                                   &ad);
                if (err)
@@ -5534,8 +5437,7 @@ static int selinux_secmark_relabel_packet(u32 sid)
        __tsec = selinux_cred(current_cred());
        tsid = __tsec->sid;
 
-       return avc_has_perm(&selinux_state,
-                           tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
+       return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
                            NULL);
 }
 
@@ -5584,8 +5486,7 @@ static int selinux_tun_dev_create(void)
         * connections unlike traditional sockets - check the TUN driver to
         * get a better understanding of why this socket is special */
 
-       return avc_has_perm(&selinux_state,
-                           sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
+       return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
                            NULL);
 }
 
@@ -5593,8 +5494,7 @@ static int selinux_tun_dev_attach_queue(void *security)
 {
        struct tun_security_struct *tunsec = security;
 
-       return avc_has_perm(&selinux_state,
-                           current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
+       return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
                            TUN_SOCKET__ATTACH_QUEUE, NULL);
 }
 
@@ -5622,13 +5522,11 @@ static int selinux_tun_dev_open(void *security)
        u32 sid = current_sid();
        int err;
 
-       err = avc_has_perm(&selinux_state,
-                          sid, tunsec->sid, SECCLASS_TUN_SOCKET,
+       err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
                           TUN_SOCKET__RELABELFROM, NULL);
        if (err)
                return err;
-       err = avc_has_perm(&selinux_state,
-                          sid, sid, SECCLASS_TUN_SOCKET,
+       err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
                           TUN_SOCKET__RELABELTO, NULL);
        if (err)
                return err;
@@ -5682,8 +5580,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb,
        }
 
        if (secmark_active)
-               if (avc_has_perm(&selinux_state,
-                                peer_sid, skb->secmark,
+               if (avc_has_perm(peer_sid, skb->secmark,
                                 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
                        return NF_DROP;
 
@@ -5763,8 +5660,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
                return NF_DROP;
 
        if (selinux_secmark_enabled())
-               if (avc_has_perm(&selinux_state,
-                                sksec->sid, skb->secmark,
+               if (avc_has_perm(sksec->sid, skb->secmark,
                                 SECCLASS_PACKET, PACKET__SEND, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
 
@@ -5889,8 +5785,7 @@ static unsigned int selinux_ip_postroute(void *priv,
                return NF_DROP;
 
        if (secmark_active)
-               if (avc_has_perm(&selinux_state,
-                                peer_sid, skb->secmark,
+               if (avc_has_perm(peer_sid, skb->secmark,
                                 SECCLASS_PACKET, secmark_perm, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
 
@@ -5900,15 +5795,13 @@ static unsigned int selinux_ip_postroute(void *priv,
 
                if (sel_netif_sid(state->net, ifindex, &if_sid))
                        return NF_DROP;
-               if (avc_has_perm(&selinux_state,
-                                peer_sid, if_sid,
+               if (avc_has_perm(peer_sid, if_sid,
                                 SECCLASS_NETIF, NETIF__EGRESS, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
 
                if (sel_netnode_sid(addrp, family, &node_sid))
                        return NF_DROP;
-               if (avc_has_perm(&selinux_state,
-                                peer_sid, node_sid,
+               if (avc_has_perm(peer_sid, node_sid,
                                 SECCLASS_NODE, NODE__SENDTO, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
        }
@@ -5953,8 +5846,8 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
                                sk->sk_protocol, nlh->nlmsg_type,
                                secclass_map[sclass - 1].name,
                                task_pid_nr(current), current->comm);
-                       if (enforcing_enabled(&selinux_state) &&
-                           !security_get_allow_unknown(&selinux_state))
+                       if (enforcing_enabled() &&
+                           !security_get_allow_unknown())
                                return rc;
                        rc = 0;
                } else if (rc == -ENOENT) {
@@ -5993,8 +5886,7 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = ipc_perms->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, isec->sclass, perms, &ad);
+       return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
 }
 
 static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
@@ -6020,8 +5912,7 @@ static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_MSGQ,
+       return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
                            MSGQ__CREATE, &ad);
 }
 
@@ -6036,8 +5927,7 @@ static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_MSGQ,
+       return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
                            MSGQ__ASSOCIATE, &ad);
 }
 
@@ -6050,8 +5940,7 @@ static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
        case IPC_INFO:
        case MSG_INFO:
                /* No specific object, just general system-wide information. */
-               return avc_has_perm(&selinux_state,
-                                   current_sid(), SECINITSID_KERNEL,
+               return avc_has_perm(current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
        case IPC_STAT:
        case MSG_STAT:
@@ -6091,7 +5980,7 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
                 * Compute new sid based on current process and
                 * message queue this message will be stored in
                 */
-               rc = security_transition_sid(&selinux_state, sid, isec->sid,
+               rc = security_transition_sid(sid, isec->sid,
                                             SECCLASS_MSG, NULL, &msec->sid);
                if (rc)
                        return rc;
@@ -6101,18 +5990,15 @@ static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *m
        ad.u.ipc_id = msq->key;
 
        /* Can this process write to the queue? */
-       rc = avc_has_perm(&selinux_state,
-                         sid, isec->sid, SECCLASS_MSGQ,
+       rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__WRITE, &ad);
        if (!rc)
                /* Can this process send the message */
-               rc = avc_has_perm(&selinux_state,
-                                 sid, msec->sid, SECCLASS_MSG,
+               rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
                                  MSG__SEND, &ad);
        if (!rc)
                /* Can the message be put in the queue? */
-               rc = avc_has_perm(&selinux_state,
-                                 msec->sid, isec->sid, SECCLASS_MSGQ,
+               rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
                                  MSGQ__ENQUEUE, &ad);
 
        return rc;
@@ -6134,12 +6020,10 @@ static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *m
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->key;
 
-       rc = avc_has_perm(&selinux_state,
-                         sid, isec->sid,
+       rc = avc_has_perm(sid, isec->sid,
                          SECCLASS_MSGQ, MSGQ__READ, &ad);
        if (!rc)
-               rc = avc_has_perm(&selinux_state,
-                                 sid, msec->sid,
+               rc = avc_has_perm(sid, msec->sid,
                                  SECCLASS_MSG, MSG__RECEIVE, &ad);
        return rc;
 }
@@ -6157,8 +6041,7 @@ static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_SHM,
+       return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
                            SHM__CREATE, &ad);
 }
 
@@ -6173,8 +6056,7 @@ static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_SHM,
+       return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
                            SHM__ASSOCIATE, &ad);
 }
 
@@ -6188,8 +6070,7 @@ static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
        case IPC_INFO:
        case SHM_INFO:
                /* No specific object, just general system-wide information. */
-               return avc_has_perm(&selinux_state,
-                                   current_sid(), SECINITSID_KERNEL,
+               return avc_has_perm(current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
        case IPC_STAT:
        case SHM_STAT:
@@ -6240,8 +6121,7 @@ static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_SEM,
+       return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
                            SEM__CREATE, &ad);
 }
 
@@ -6256,8 +6136,7 @@ static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->key;
 
-       return avc_has_perm(&selinux_state,
-                           sid, isec->sid, SECCLASS_SEM,
+       return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
                            SEM__ASSOCIATE, &ad);
 }
 
@@ -6271,8 +6150,7 @@ static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
        case IPC_INFO:
        case SEM_INFO:
                /* No specific object, just general system-wide information. */
-               return avc_has_perm(&selinux_state,
-                                   current_sid(), SECINITSID_KERNEL,
+               return avc_has_perm(current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
        case GETPID:
        case GETNCNT:
@@ -6359,8 +6237,7 @@ static int selinux_getprocattr(struct task_struct *p,
        __tsec = selinux_cred(__task_cred(p));
 
        if (current != p) {
-               error = avc_has_perm(&selinux_state,
-                                    current_sid(), __tsec->sid,
+               error = avc_has_perm(current_sid(), __tsec->sid,
                                     SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
                if (error)
                        goto bad;
@@ -6387,7 +6264,7 @@ static int selinux_getprocattr(struct task_struct *p,
        if (!sid)
                return 0;
 
-       error = security_sid_to_context(&selinux_state, sid, value, &len);
+       error = security_sid_to_context(sid, value, &len);
        if (error)
                return error;
        return len;
@@ -6409,24 +6286,19 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
         * Basic control over ability to set these attributes at all.
         */
        if (!strcmp(name, "exec"))
-               error = avc_has_perm(&selinux_state,
-                                    mysid, mysid, SECCLASS_PROCESS,
+               error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETEXEC, NULL);
        else if (!strcmp(name, "fscreate"))
-               error = avc_has_perm(&selinux_state,
-                                    mysid, mysid, SECCLASS_PROCESS,
+               error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETFSCREATE, NULL);
        else if (!strcmp(name, "keycreate"))
-               error = avc_has_perm(&selinux_state,
-                                    mysid, mysid, SECCLASS_PROCESS,
+               error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETKEYCREATE, NULL);
        else if (!strcmp(name, "sockcreate"))
-               error = avc_has_perm(&selinux_state,
-                                    mysid, mysid, SECCLASS_PROCESS,
+               error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETSOCKCREATE, NULL);
        else if (!strcmp(name, "current"))
-               error = avc_has_perm(&selinux_state,
-                                    mysid, mysid, SECCLASS_PROCESS,
+               error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETCURRENT, NULL);
        else
                error = -EINVAL;
@@ -6439,7 +6311,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
                        str[size-1] = 0;
                        size--;
                }
-               error = security_context_to_sid(&selinux_state, value, size,
+               error = security_context_to_sid(value, size,
                                                &sid, GFP_KERNEL);
                if (error == -EINVAL && !strcmp(name, "fscreate")) {
                        if (!has_cap_mac_admin(true)) {
@@ -6463,9 +6335,8 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
 
                                return error;
                        }
-                       error = security_context_to_sid_force(
-                                                     &selinux_state,
-                                                     value, size, &sid);
+                       error = security_context_to_sid_force(value, size,
+                                                       &sid);
                }
                if (error)
                        return error;
@@ -6488,7 +6359,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
                tsec->create_sid = sid;
        } else if (!strcmp(name, "keycreate")) {
                if (sid) {
-                       error = avc_has_perm(&selinux_state, mysid, sid,
+                       error = avc_has_perm(mysid, sid,
                                             SECCLASS_KEY, KEY__CREATE, NULL);
                        if (error)
                                goto abort_change;
@@ -6503,15 +6374,13 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
 
                /* Only allow single threaded processes to change context */
                if (!current_is_single_threaded()) {
-                       error = security_bounded_transition(&selinux_state,
-                                                           tsec->sid, sid);
+                       error = security_bounded_transition(tsec->sid, sid);
                        if (error)
                                goto abort_change;
                }
 
                /* Check permissions for the transition. */
-               error = avc_has_perm(&selinux_state,
-                                    tsec->sid, sid, SECCLASS_PROCESS,
+               error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
                                     PROCESS__DYNTRANSITION, NULL);
                if (error)
                        goto abort_change;
@@ -6520,8 +6389,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
                   Otherwise, leave SID unchanged and fail. */
                ptsid = ptrace_parent_sid();
                if (ptsid != 0) {
-                       error = avc_has_perm(&selinux_state,
-                                            ptsid, sid, SECCLASS_PROCESS,
+                       error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
                                             PROCESS__PTRACE, NULL);
                        if (error)
                                goto abort_change;
@@ -6548,13 +6416,13 @@ static int selinux_ismaclabel(const char *name)
 
 static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
 {
-       return security_sid_to_context(&selinux_state, secid,
+       return security_sid_to_context(secid,
                                       secdata, seclen);
 }
 
 static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
-       return security_context_to_sid(&selinux_state, secdata, seclen,
+       return security_context_to_sid(secdata, seclen,
                                       secid, GFP_KERNEL);
 }
 
@@ -6674,8 +6542,7 @@ static int selinux_key_permission(key_ref_t key_ref,
        key = key_ref_to_ptr(key_ref);
        ksec = key->security;
 
-       return avc_has_perm(&selinux_state,
-                           sid, ksec->sid, SECCLASS_KEY, perm, NULL);
+       return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
 }
 
 static int selinux_key_getsecurity(struct key *key, char **_buffer)
@@ -6685,7 +6552,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
        unsigned len;
        int rc;
 
-       rc = security_sid_to_context(&selinux_state, ksec->sid,
+       rc = security_sid_to_context(ksec->sid,
                                     &context, &len);
        if (!rc)
                rc = len;
@@ -6699,8 +6566,7 @@ static int selinux_watch_key(struct key *key)
        struct key_security_struct *ksec = key->security;
        u32 sid = current_sid();
 
-       return avc_has_perm(&selinux_state,
-                           sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL);
+       return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, KEY__VIEW, NULL);
 }
 #endif
 #endif
@@ -6722,8 +6588,7 @@ static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
        ibpkey.subnet_prefix = subnet_prefix;
        ibpkey.pkey = pkey_val;
        ad.u.ibpkey = &ibpkey;
-       return avc_has_perm(&selinux_state,
-                           sec->sid, sid,
+       return avc_has_perm(sec->sid, sid,
                            SECCLASS_INFINIBAND_PKEY,
                            INFINIBAND_PKEY__ACCESS, &ad);
 }
@@ -6737,7 +6602,7 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
        struct ib_security_struct *sec = ib_sec;
        struct lsm_ibendport_audit ibendport;
 
-       err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
+       err = security_ib_endport_sid(dev_name, port_num,
                                      &sid);
 
        if (err)
@@ -6747,8 +6612,7 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
        ibendport.dev_name = dev_name;
        ibendport.port = port_num;
        ad.u.ibendport = &ibendport;
-       return avc_has_perm(&selinux_state,
-                           sec->sid, sid,
+       return avc_has_perm(sec->sid, sid,
                            SECCLASS_INFINIBAND_ENDPORT,
                            INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
 }
@@ -6781,13 +6645,11 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,
 
        switch (cmd) {
        case BPF_MAP_CREATE:
-               ret = avc_has_perm(&selinux_state,
-                                  sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
+               ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
                                   NULL);
                break;
        case BPF_PROG_LOAD:
-               ret = avc_has_perm(&selinux_state,
-                                  sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
+               ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
                                   NULL);
                break;
        default:
@@ -6827,16 +6689,14 @@ static int bpf_fd_pass(struct file *file, u32 sid)
        if (file->f_op == &bpf_map_fops) {
                map = file->private_data;
                bpfsec = map->security;
-               ret = avc_has_perm(&selinux_state,
-                                  sid, bpfsec->sid, SECCLASS_BPF,
+               ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
                                   bpf_map_fmode_to_av(file->f_mode), NULL);
                if (ret)
                        return ret;
        } else if (file->f_op == &bpf_prog_fops) {
                prog = file->private_data;
                bpfsec = prog->aux->security;
-               ret = avc_has_perm(&selinux_state,
-                                  sid, bpfsec->sid, SECCLASS_BPF,
+               ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
                                   BPF__PROG_RUN, NULL);
                if (ret)
                        return ret;
@@ -6850,8 +6710,7 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
        struct bpf_security_struct *bpfsec;
 
        bpfsec = map->security;
-       return avc_has_perm(&selinux_state,
-                           sid, bpfsec->sid, SECCLASS_BPF,
+       return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
                            bpf_map_fmode_to_av(fmode), NULL);
 }
 
@@ -6861,8 +6720,7 @@ static int selinux_bpf_prog(struct bpf_prog *prog)
        struct bpf_security_struct *bpfsec;
 
        bpfsec = prog->aux->security;
-       return avc_has_perm(&selinux_state,
-                           sid, bpfsec->sid, SECCLASS_BPF,
+       return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
                            BPF__PROG_RUN, NULL);
 }
 
@@ -6911,7 +6769,7 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 }
 #endif
 
-struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
        .lbs_cred = sizeof(struct task_security_struct),
        .lbs_file = sizeof(struct file_security_struct),
        .lbs_inode = sizeof(struct inode_security_struct),
@@ -6936,7 +6794,7 @@ static int selinux_perf_event_open(struct perf_event_attr *attr, int type)
        else
                return -EINVAL;
 
-       return avc_has_perm(&selinux_state, sid, sid, SECCLASS_PERF_EVENT,
+       return avc_has_perm(sid, sid, SECCLASS_PERF_EVENT,
                            requested, NULL);
 }
 
@@ -6967,7 +6825,7 @@ static int selinux_perf_event_read(struct perf_event *event)
        struct perf_event_security_struct *perfsec = event->security;
        u32 sid = current_sid();
 
-       return avc_has_perm(&selinux_state, sid, perfsec->sid,
+       return avc_has_perm(sid, perfsec->sid,
                            SECCLASS_PERF_EVENT, PERF_EVENT__READ, NULL);
 }
 
@@ -6976,7 +6834,7 @@ static int selinux_perf_event_write(struct perf_event *event)
        struct perf_event_security_struct *perfsec = event->security;
        u32 sid = current_sid();
 
-       return avc_has_perm(&selinux_state, sid, perfsec->sid,
+       return avc_has_perm(sid, perfsec->sid,
                            SECCLASS_PERF_EVENT, PERF_EVENT__WRITE, NULL);
 }
 #endif
@@ -6991,7 +6849,7 @@ static int selinux_perf_event_write(struct perf_event *event)
  */
 static int selinux_uring_override_creds(const struct cred *new)
 {
-       return avc_has_perm(&selinux_state, current_sid(), cred_sid(new),
+       return avc_has_perm(current_sid(), cred_sid(new),
                            SECCLASS_IO_URING, IO_URING__OVERRIDE_CREDS, NULL);
 }
 
@@ -7005,7 +6863,7 @@ static int selinux_uring_sqpoll(void)
 {
        int sid = current_sid();
 
-       return avc_has_perm(&selinux_state, sid, sid,
+       return avc_has_perm(sid, sid,
                            SECCLASS_IO_URING, IO_URING__SQPOLL, NULL);
 }
 
@@ -7027,7 +6885,7 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
        ad.type = LSM_AUDIT_DATA_FILE;
        ad.u.file = file;
 
-       return avc_has_perm(&selinux_state, current_sid(), isec->sid,
+       return avc_has_perm(current_sid(), isec->sid,
                            SECCLASS_IO_URING, IO_URING__CMD, &ad);
 }
 #endif /* CONFIG_IO_URING */
@@ -7047,7 +6905,7 @@ static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
  * safely. Breaking the ordering rules above might lead to NULL pointer derefs
  * when disabling SELinux at runtime.
  */
-static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list selinux_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
        LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
        LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
@@ -7334,11 +7192,8 @@ static __init int selinux_init(void)
        pr_info("SELinux:  Initializing.\n");
 
        memset(&selinux_state, 0, sizeof(selinux_state));
-       enforcing_set(&selinux_state, selinux_enforcing_boot);
-       if (CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE)
-               pr_err("SELinux: CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE is non-zero.  This is deprecated and will be rejected in a future kernel release.\n");
-       checkreqprot_set(&selinux_state, selinux_checkreqprot_boot);
-       selinux_avc_init(&selinux_state.avc);
+       enforcing_set(selinux_enforcing_boot);
+       selinux_avc_init();
        mutex_init(&selinux_state.status_lock);
        mutex_init(&selinux_state.policy_mutex);
 
@@ -7398,7 +7253,6 @@ DEFINE_LSM(selinux) = {
 };
 
 #if defined(CONFIG_NETFILTER)
-
 static const struct nf_hook_ops selinux_nf_ops[] = {
        {
                .hook =         selinux_ip_postroute,
@@ -7473,56 +7327,4 @@ static int __init selinux_nf_ip_init(void)
        return 0;
 }
 __initcall(selinux_nf_ip_init);
-
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-static void selinux_nf_ip_exit(void)
-{
-       pr_debug("SELinux:  Unregistering netfilter hooks\n");
-
-       unregister_pernet_subsys(&selinux_net_ops);
-}
-#endif
-
-#else /* CONFIG_NETFILTER */
-
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-#define selinux_nf_ip_exit()
-#endif
-
 #endif /* CONFIG_NETFILTER */
-
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-int selinux_disable(struct selinux_state *state)
-{
-       if (selinux_initialized(state)) {
-               /* Not permitted after initial policy load. */
-               return -EINVAL;
-       }
-
-       if (selinux_disabled(state)) {
-               /* Only do this once. */
-               return -EINVAL;
-       }
-
-       selinux_mark_disabled(state);
-
-       pr_info("SELinux:  Disabled at runtime.\n");
-
-       /*
-        * Unregister netfilter hooks.
-        * Must be done before security_delete_hooks() to avoid breaking
-        * runtime disable.
-        */
-       selinux_nf_ip_exit();
-
-       security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
-
-       /* Try to destroy the avc node cache */
-       avc_disable();
-
-       /* Unregister selinuxfs. */
-       exit_sel_fs();
-
-       return 0;
-}
-#endif
index 5839ca7bb9c75807097ddb558d199101dfdb7a55..48f537b41c583235d08bf2985c4fb45da9078bec 100644 (file)
@@ -141,7 +141,7 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid)
                return 0;
        }
 
-       ret = security_ib_pkey_sid(&selinux_state, subnet_prefix, pkey_num,
+       ret = security_ib_pkey_sid(subnet_prefix, pkey_num,
                                   sid);
        if (ret)
                goto out;
index a915b89d55b0c1281d60acd22241cae79f4a0659..7daf59667f5975daa2fc565843b35185ff001e86 100644 (file)
 /*
  * selinux_ima_collect_state - Read selinux configuration settings
  *
- * @state: selinux_state
- *
  * On success returns the configuration settings string.
  * On error, returns NULL.
  */
-static char *selinux_ima_collect_state(struct selinux_state *state)
+static char *selinux_ima_collect_state(void)
 {
        const char *on = "=1;", *off = "=0;";
        char *buf;
@@ -39,26 +37,27 @@ static char *selinux_ima_collect_state(struct selinux_state *state)
        rc = strscpy(buf, "initialized", buf_len);
        WARN_ON(rc < 0);
 
-       rc = strlcat(buf, selinux_initialized(state) ? on : off, buf_len);
+       rc = strlcat(buf, selinux_initialized() ? on : off, buf_len);
        WARN_ON(rc >= buf_len);
 
        rc = strlcat(buf, "enforcing", buf_len);
        WARN_ON(rc >= buf_len);
 
-       rc = strlcat(buf, enforcing_enabled(state) ? on : off, buf_len);
+       rc = strlcat(buf, enforcing_enabled() ? on : off, buf_len);
        WARN_ON(rc >= buf_len);
 
        rc = strlcat(buf, "checkreqprot", buf_len);
        WARN_ON(rc >= buf_len);
 
-       rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len);
+       rc = strlcat(buf, checkreqprot_get() ? on : off, buf_len);
        WARN_ON(rc >= buf_len);
 
        for (i = 0; i < __POLICYDB_CAP_MAX; i++) {
                rc = strlcat(buf, selinux_policycap_names[i], buf_len);
                WARN_ON(rc >= buf_len);
 
-               rc = strlcat(buf, state->policycap[i] ? on : off, buf_len);
+               rc = strlcat(buf, selinux_state.policycap[i] ? on : off,
+                       buf_len);
                WARN_ON(rc >= buf_len);
        }
 
@@ -67,19 +66,17 @@ static char *selinux_ima_collect_state(struct selinux_state *state)
 
 /*
  * selinux_ima_measure_state_locked - Measure SELinux state and hash of policy
- *
- * @state: selinux state struct
  */
-void selinux_ima_measure_state_locked(struct selinux_state *state)
+void selinux_ima_measure_state_locked(void)
 {
        char *state_str = NULL;
        void *policy = NULL;
        size_t policy_len;
        int rc = 0;
 
-       lockdep_assert_held(&state->policy_mutex);
+       lockdep_assert_held(&selinux_state.policy_mutex);
 
-       state_str = selinux_ima_collect_state(state);
+       state_str = selinux_ima_collect_state();
        if (!state_str) {
                pr_err("SELinux: %s: failed to read state.\n", __func__);
                return;
@@ -94,10 +91,10 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
        /*
         * Measure SELinux policy only after initialization is completed.
         */
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return;
 
-       rc = security_read_state_kernel(state, &policy, &policy_len);
+       rc = security_read_state_kernel(&policy, &policy_len);
        if (rc) {
                pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc);
                return;
@@ -112,14 +109,12 @@ void selinux_ima_measure_state_locked(struct selinux_state *state)
 
 /*
  * selinux_ima_measure_state - Measure SELinux state and hash of policy
- *
- * @state: selinux state struct
  */
-void selinux_ima_measure_state(struct selinux_state *state)
+void selinux_ima_measure_state(void)
 {
-       lockdep_assert_not_held(&state->policy_mutex);
+       lockdep_assert_not_held(&selinux_state.policy_mutex);
 
-       mutex_lock(&state->policy_mutex);
-       selinux_ima_measure_state_locked(state);
-       mutex_unlock(&state->policy_mutex);
+       mutex_lock(&selinux_state.policy_mutex);
+       selinux_ima_measure_state_locked();
+       mutex_unlock(&selinux_state.policy_mutex);
 }
index 5525b94fd2664f3631eb26e9facfc5310e854b45..9301222c8e55d22f9ef507036abf3ef30ef1f364 100644 (file)
@@ -52,7 +52,6 @@ struct selinux_audit_data {
        u32 audited;
        u32 denied;
        int result;
-       struct selinux_state *state;
 } __randomize_layout;
 
 /*
@@ -97,14 +96,12 @@ static inline u32 avc_audit_required(u32 requested,
        return audited;
 }
 
-int slow_avc_audit(struct selinux_state *state,
-                  u32 ssid, u32 tsid, u16 tclass,
+int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
                   u32 requested, u32 audited, u32 denied, int result,
                   struct common_audit_data *a);
 
 /**
  * avc_audit - Audit the granting or denial of permissions.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -122,8 +119,7 @@ int slow_avc_audit(struct selinux_state *state,
  * be performed under a lock, to allow the lock to be released
  * before calling the auditing code.
  */
-static inline int avc_audit(struct selinux_state *state,
-                           u32 ssid, u32 tsid,
+static inline int avc_audit(u32 ssid, u32 tsid,
                            u16 tclass, u32 requested,
                            struct av_decision *avd,
                            int result,
@@ -133,30 +129,27 @@ static inline int avc_audit(struct selinux_state *state,
        audited = avc_audit_required(requested, avd, result, 0, &denied);
        if (likely(!audited))
                return 0;
-       return slow_avc_audit(state, ssid, tsid, tclass,
+       return slow_avc_audit(ssid, tsid, tclass,
                              requested, audited, denied, result,
                              a);
 }
 
 #define AVC_STRICT 1 /* Ignore permissive mode. */
 #define AVC_EXTENDED_PERMS 2   /* update extended permissions */
-int avc_has_perm_noaudit(struct selinux_state *state,
-                        u32 ssid, u32 tsid,
+int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                         u16 tclass, u32 requested,
                         unsigned flags,
                         struct av_decision *avd);
 
-int avc_has_perm(struct selinux_state *state,
-                u32 ssid, u32 tsid,
+int avc_has_perm(u32 ssid, u32 tsid,
                 u16 tclass, u32 requested,
                 struct common_audit_data *auditdata);
 
-int avc_has_extended_perms(struct selinux_state *state,
-                          u32 ssid, u32 tsid, u16 tclass, u32 requested,
+int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
                           u8 driver, u8 perm, struct common_audit_data *ad);
 
 
-u32 avc_policy_seqno(struct selinux_state *state);
+u32 avc_policy_seqno(void);
 
 #define AVC_CALLBACK_GRANT             1
 #define AVC_CALLBACK_TRY_REVOKE                2
@@ -171,11 +164,9 @@ u32 avc_policy_seqno(struct selinux_state *state);
 int avc_add_callback(int (*callback)(u32 event), u32 events);
 
 /* Exported to selinuxfs */
-struct selinux_avc;
-int avc_get_hash_stats(struct selinux_avc *avc, char *page);
-unsigned int avc_get_cache_threshold(struct selinux_avc *avc);
-void avc_set_cache_threshold(struct selinux_avc *avc,
-                            unsigned int cache_threshold);
+int avc_get_hash_stats(char *page);
+unsigned int avc_get_cache_threshold(void);
+void avc_set_cache_threshold(unsigned int cache_threshold);
 
 /* Attempt to free avc node cache */
 void avc_disable(void);
index 42912c917fd40c53b4278cd5e820ac3e4686add4..b9668be7b44337e9cf8ddd4e14308b178511ea89 100644 (file)
@@ -9,8 +9,7 @@
 
 #include <linux/types.h>
 
-struct selinux_avc;
-int avc_ss_reset(struct selinux_avc *avc, u32 seqno);
+int avc_ss_reset(u32 seqno);
 
 /* Class/perm mapping support */
 struct security_class_mapping {
index b09343346e3fe435d81e31283ff8dcbcef4bc134..693a654714eb5fd1ede9c8c6a08b4f639a3036d0 100644 (file)
@@ -16,8 +16,8 @@
 int security_get_bools(struct selinux_policy *policy,
                       u32 *len, char ***names, int **values);
 
-int security_set_bools(struct selinux_state *state, u32 len, int *values);
+int security_set_bools(u32 len, int *values);
 
-int security_get_bool_value(struct selinux_state *state, u32 index);
+int security_get_bool_value(u32 index);
 
 #endif
index 75ca92b4a4622c031ab5d7b568773c13011520c1..05e04172c86d8703c6e682078b7185e3ec390428 100644 (file)
 #include "security.h"
 
 #ifdef CONFIG_IMA
-extern void selinux_ima_measure_state(struct selinux_state *selinux_state);
-extern void selinux_ima_measure_state_locked(
-                       struct selinux_state *selinux_state);
+extern void selinux_ima_measure_state(void);
+extern void selinux_ima_measure_state_locked(void);
 #else
-static inline void selinux_ima_measure_state(struct selinux_state *selinux_state)
+static inline void selinux_ima_measure_state(void)
 {
 }
-static inline void selinux_ima_measure_state_locked(
-                       struct selinux_state *selinux_state)
+static inline void selinux_ima_measure_state_locked(void)
 {
 }
 #endif
index 393aff41d3ef89db689738b45b17f9d8c5958fb4..8746fafeb778996c20938b5911be68e1b152838c 100644 (file)
@@ -86,94 +86,65 @@ extern int selinux_enabled_boot;
 /* limitation of boundary depth  */
 #define POLICYDB_BOUNDS_MAXDEPTH       4
 
-struct selinux_avc;
 struct selinux_policy;
 
 struct selinux_state {
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-       bool disabled;
-#endif
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
        bool enforcing;
 #endif
-       bool checkreqprot;
        bool initialized;
        bool policycap[__POLICYDB_CAP_MAX];
 
        struct page *status_page;
        struct mutex status_lock;
 
-       struct selinux_avc *avc;
        struct selinux_policy __rcu *policy;
        struct mutex policy_mutex;
 } __randomize_layout;
 
-void selinux_avc_init(struct selinux_avc **avc);
+void selinux_avc_init(void);
 
 extern struct selinux_state selinux_state;
 
-static inline bool selinux_initialized(const struct selinux_state *state)
+static inline bool selinux_initialized(void)
 {
        /* do a synchronized load to avoid race conditions */
-       return smp_load_acquire(&state->initialized);
+       return smp_load_acquire(&selinux_state.initialized);
 }
 
-static inline void selinux_mark_initialized(struct selinux_state *state)
+static inline void selinux_mark_initialized(void)
 {
        /* do a synchronized write to avoid race conditions */
-       smp_store_release(&state->initialized, true);
+       smp_store_release(&selinux_state.initialized, true);
 }
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
-static inline bool enforcing_enabled(struct selinux_state *state)
+static inline bool enforcing_enabled(void)
 {
-       return READ_ONCE(state->enforcing);
+       return READ_ONCE(selinux_state.enforcing);
 }
 
-static inline void enforcing_set(struct selinux_state *state, bool value)
+static inline void enforcing_set(bool value)
 {
-       WRITE_ONCE(state->enforcing, value);
+       WRITE_ONCE(selinux_state.enforcing, value);
 }
 #else
-static inline bool enforcing_enabled(struct selinux_state *state)
+static inline bool enforcing_enabled(void)
 {
        return true;
 }
 
-static inline void enforcing_set(struct selinux_state *state, bool value)
+static inline void enforcing_set(bool value)
 {
 }
 #endif
 
-static inline bool checkreqprot_get(const struct selinux_state *state)
-{
-       return READ_ONCE(state->checkreqprot);
-}
-
-static inline void checkreqprot_set(struct selinux_state *state, bool value)
+static inline bool checkreqprot_get(void)
 {
-       if (value)
-               pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-checkreqprot\n");
-       WRITE_ONCE(state->checkreqprot, value);
+       /* non-zero/true checkreqprot values are no longer supported */
+       return 0;
 }
 
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-static inline bool selinux_disabled(struct selinux_state *state)
-{
-       return READ_ONCE(state->disabled);
-}
-
-static inline void selinux_mark_disabled(struct selinux_state *state)
-{
-       WRITE_ONCE(state->disabled, true);
-}
-#else
-static inline bool selinux_disabled(struct selinux_state *state)
-{
-       return false;
-}
-#endif
-
 static inline bool selinux_policycap_netpeer(void)
 {
        struct selinux_state *state = &selinux_state;
@@ -237,20 +208,14 @@ struct selinux_load_state {
        struct selinux_policy_convert_data *convert_data;
 };
 
-int security_mls_enabled(struct selinux_state *state);
-int security_load_policy(struct selinux_state *state,
-                        void *data, size_t len,
+int security_mls_enabled(void);
+int security_load_policy(void *data, size_t len,
                         struct selinux_load_state *load_state);
-void selinux_policy_commit(struct selinux_state *state,
-                          struct selinux_load_state *load_state);
-void selinux_policy_cancel(struct selinux_state *state,
-                          struct selinux_load_state *load_state);
-int security_read_policy(struct selinux_state *state,
-                        void **data, size_t *len);
-int security_read_state_kernel(struct selinux_state *state,
-                              void **data, size_t *len);
-int security_policycap_supported(struct selinux_state *state,
-                                unsigned int req_cap);
+void selinux_policy_commit(struct selinux_load_state *load_state);
+void selinux_policy_cancel(struct selinux_load_state *load_state);
+int security_read_policy(void **data, size_t *len);
+int security_read_state_kernel(void **data, size_t *len);
+int security_policycap_supported(unsigned int req_cap);
 
 #define SEL_VEC_MAX 32
 struct av_decision {
@@ -287,94 +252,68 @@ struct extended_perms {
 /* definitions of av_decision.flags */
 #define AVD_FLAGS_PERMISSIVE   0x0001
 
-void security_compute_av(struct selinux_state *state,
-                        u32 ssid, u32 tsid,
+void security_compute_av(u32 ssid, u32 tsid,
                         u16 tclass, struct av_decision *avd,
                         struct extended_perms *xperms);
 
-void security_compute_xperms_decision(struct selinux_state *state,
-                                     u32 ssid, u32 tsid, u16 tclass,
+void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass,
                                      u8 driver,
                                      struct extended_perms_decision *xpermd);
 
-void security_compute_av_user(struct selinux_state *state,
-                             u32 ssid, u32 tsid,
+void security_compute_av_user(u32 ssid, u32 tsid,
                              u16 tclass, struct av_decision *avd);
 
-int security_transition_sid(struct selinux_state *state,
-                           u32 ssid, u32 tsid, u16 tclass,
+int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
                            const struct qstr *qstr, u32 *out_sid);
 
-int security_transition_sid_user(struct selinux_state *state,
-                                u32 ssid, u32 tsid, u16 tclass,
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
                                 const char *objname, u32 *out_sid);
 
-int security_member_sid(struct selinux_state *state, u32 ssid, u32 tsid,
-                       u16 tclass, u32 *out_sid);
+int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
 
-int security_change_sid(struct selinux_state *state, u32 ssid, u32 tsid,
-                       u16 tclass, u32 *out_sid);
+int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid);
 
-int security_sid_to_context(struct selinux_state *state, u32 sid,
-                           char **scontext, u32 *scontext_len);
+int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
 
-int security_sid_to_context_force(struct selinux_state *state,
-                                 u32 sid, char **scontext, u32 *scontext_len);
+int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
 
-int security_sid_to_context_inval(struct selinux_state *state,
-                                 u32 sid, char **scontext, u32 *scontext_len);
+int security_sid_to_context_inval(u32 sid, char **scontext, u32 *scontext_len);
 
-int security_context_to_sid(struct selinux_state *state,
-                           const char *scontext, u32 scontext_len,
+int security_context_to_sid(const char *scontext, u32 scontext_len,
                            u32 *out_sid, gfp_t gfp);
 
-int security_context_str_to_sid(struct selinux_state *state,
-                               const char *scontext, u32 *out_sid, gfp_t gfp);
+int security_context_str_to_sid(const char *scontext, u32 *out_sid, gfp_t gfp);
 
-int security_context_to_sid_default(struct selinux_state *state,
-                                   const char *scontext, u32 scontext_len,
+int security_context_to_sid_default(const char *scontext, u32 scontext_len,
                                    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
 
-int security_context_to_sid_force(struct selinux_state *state,
-                                 const char *scontext, u32 scontext_len,
+int security_context_to_sid_force(const char *scontext, u32 scontext_len,
                                  u32 *sid);
 
-int security_get_user_sids(struct selinux_state *state,
-                          u32 callsid, char *username,
-                          u32 **sids, u32 *nel);
+int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel);
 
-int security_port_sid(struct selinux_state *state,
-                     u8 protocol, u16 port, u32 *out_sid);
+int security_port_sid(u8 protocol, u16 port, u32 *out_sid);
 
-int security_ib_pkey_sid(struct selinux_state *state,
-                        u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
+int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid);
 
-int security_ib_endport_sid(struct selinux_state *state,
-                           const char *dev_name, u8 port_num, u32 *out_sid);
+int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid);
 
-int security_netif_sid(struct selinux_state *state,
-                      char *name, u32 *if_sid);
+int security_netif_sid(char *name, u32 *if_sid);
 
-int security_node_sid(struct selinux_state *state,
-                     u16 domain, void *addr, u32 addrlen,
+int security_node_sid(u16 domain, void *addr, u32 addrlen,
                      u32 *out_sid);
 
-int security_validate_transition(struct selinux_state *state,
-                                u32 oldsid, u32 newsid, u32 tasksid,
+int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
                                 u16 tclass);
 
-int security_validate_transition_user(struct selinux_state *state,
-                                     u32 oldsid, u32 newsid, u32 tasksid,
+int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
                                      u16 tclass);
 
-int security_bounded_transition(struct selinux_state *state,
-                               u32 oldsid, u32 newsid);
+int security_bounded_transition(u32 oldsid, u32 newsid);
 
-int security_sid_mls_copy(struct selinux_state *state,
-                         u32 sid, u32 mls_sid, u32 *new_sid);
+int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
 
-int security_net_peersid_resolve(struct selinux_state *state,
-                                u32 nlbl_sid, u32 nlbl_type,
+int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
                                 u32 xfrm_sid,
                                 u32 *peer_sid);
 
@@ -382,8 +321,8 @@ int security_get_classes(struct selinux_policy *policy,
                         char ***classes, int *nclasses);
 int security_get_permissions(struct selinux_policy *policy,
                             char *class, char ***perms, int *nperms);
-int security_get_reject_unknown(struct selinux_state *state);
-int security_get_allow_unknown(struct selinux_state *state);
+int security_get_reject_unknown(void);
+int security_get_allow_unknown(void);
 
 #define SECURITY_FS_USE_XATTR          1 /* use xattr */
 #define SECURITY_FS_USE_TRANS          2 /* use transition SIDs, e.g. devpts/tmpfs */
@@ -394,10 +333,9 @@ int security_get_allow_unknown(struct selinux_state *state);
 #define SECURITY_FS_USE_NATIVE         7 /* use native label support */
 #define SECURITY_FS_USE_MAX            7 /* Highest SECURITY_FS_USE_XXX */
 
-int security_fs_use(struct selinux_state *state, struct super_block *sb);
+int security_fs_use(struct super_block *sb);
 
-int security_genfs_sid(struct selinux_state *state,
-                      const char *fstype, const char *path, u16 sclass,
+int security_genfs_sid(const char *fstype, const char *path, u16 sclass,
                       u32 *sid);
 
 int selinux_policy_genfs_sid(struct selinux_policy *policy,
@@ -405,23 +343,19 @@ int selinux_policy_genfs_sid(struct selinux_policy *policy,
                       u32 *sid);
 
 #ifdef CONFIG_NETLABEL
-int security_netlbl_secattr_to_sid(struct selinux_state *state,
-                                  struct netlbl_lsm_secattr *secattr,
+int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                                   u32 *sid);
 
-int security_netlbl_sid_to_secattr(struct selinux_state *state,
-                                  u32 sid,
+int security_netlbl_sid_to_secattr(u32 sid,
                                   struct netlbl_lsm_secattr *secattr);
 #else
-static inline int security_netlbl_secattr_to_sid(struct selinux_state *state,
-                                           struct netlbl_lsm_secattr *secattr,
+static inline int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                                            u32 *sid)
 {
        return -EIDRM;
 }
 
-static inline int security_netlbl_sid_to_secattr(struct selinux_state *state,
-                                        u32 sid,
+static inline int security_netlbl_sid_to_secattr(u32 sid,
                                         struct netlbl_lsm_secattr *secattr)
 {
        return -ENOENT;
@@ -433,7 +367,7 @@ const char *security_get_initial_sid_context(u32 sid);
 /*
  * status notifier using mmap interface
  */
-extern struct page *selinux_kernel_status_page(struct selinux_state *state);
+extern struct page *selinux_kernel_status_page(void);
 
 #define SELINUX_KERNEL_STATUS_VERSION  1
 struct selinux_kernel_status {
@@ -447,12 +381,9 @@ struct selinux_kernel_status {
         */
 } __packed;
 
-extern void selinux_status_update_setenforce(struct selinux_state *state,
-                                            int enforcing);
-extern void selinux_status_update_policyload(struct selinux_state *state,
-                                            int seqno);
+extern void selinux_status_update_setenforce(int enforcing);
+extern void selinux_status_update_policyload(int seqno);
 extern void selinux_complete_init(void);
-extern int selinux_disable(struct selinux_state *state);
 extern void exit_sel_fs(void);
 extern struct path selinux_null;
 extern void selnl_notify_setenforce(int val);
@@ -462,6 +393,6 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
 extern void avtab_cache_init(void);
 extern void ebitmap_cache_init(void);
 extern void hashtab_cache_init(void);
-extern int security_sidtab_hash_stats(struct selinux_state *state, char *page);
+extern int security_sidtab_hash_stats(char *page);
 
 #endif /* _SELINUX_SECURITY_H_ */
index 1ab03efe74947a33d368ab3b21b335c3ca07324d..adbe9bea2d268259cf491047484942056ce06d74 100644 (file)
@@ -153,7 +153,7 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid)
                goto out;
        }
 
-       ret = security_netif_sid(&selinux_state, dev->name, sid);
+       ret = security_netif_sid(dev->name, sid);
        if (ret != 0)
                goto out;
        new = kzalloc(sizeof(*new), GFP_ATOMIC);
index 1321f15799e2f8bf29cefe064facc663db4275a9..767c670d33ead380b6035e06d181a028a9c140d6 100644 (file)
@@ -46,7 +46,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
 {
        int rc;
 
-       rc = security_netlbl_secattr_to_sid(&selinux_state, secattr, sid);
+       rc = security_netlbl_secattr_to_sid(secattr, sid);
        if (rc == 0 &&
            (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
            (secattr->flags & NETLBL_SECATTR_CACHE))
@@ -77,8 +77,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
        secattr = netlbl_secattr_alloc(GFP_ATOMIC);
        if (secattr == NULL)
                return NULL;
-       rc = security_netlbl_sid_to_secattr(&selinux_state, sksec->sid,
-                                           secattr);
+       rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
        if (rc != 0) {
                netlbl_secattr_free(secattr);
                return NULL;
@@ -245,8 +244,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
        if (secattr == NULL) {
                secattr = &secattr_storage;
                netlbl_secattr_init(secattr);
-               rc = security_netlbl_sid_to_secattr(&selinux_state, sid,
-                                                   secattr);
+               rc = security_netlbl_sid_to_secattr(sid, secattr);
                if (rc != 0)
                        goto skbuff_setsid_return;
        }
@@ -283,8 +281,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_association *asoc,
                return 0;
 
        netlbl_secattr_init(&secattr);
-       rc = security_netlbl_sid_to_secattr(&selinux_state,
-                                           asoc->secid, &secattr);
+       rc = security_netlbl_sid_to_secattr(asoc->secid, &secattr);
        if (rc != 0)
                goto assoc_request_return;
 
@@ -332,8 +329,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
                return 0;
 
        netlbl_secattr_init(&secattr);
-       rc = security_netlbl_sid_to_secattr(&selinux_state, req->secid,
-                                           &secattr);
+       rc = security_netlbl_sid_to_secattr(req->secid, &secattr);
        if (rc != 0)
                goto inet_conn_request_return;
        rc = netlbl_req_setattr(req, &secattr);
@@ -463,8 +459,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
                perm = RAWIP_SOCKET__RECVFROM;
        }
 
-       rc = avc_has_perm(&selinux_state,
-                         sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
+       rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
        if (rc == 0)
                return 0;
 
index 0ac7df9a93677f403fa59f90c36f4fdae8699323..5c8c77e50aadfac077f3039f705afc948fc2685e 100644 (file)
@@ -204,13 +204,13 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
        new = kzalloc(sizeof(*new), GFP_ATOMIC);
        switch (family) {
        case PF_INET:
-               ret = security_node_sid(&selinux_state, PF_INET,
+               ret = security_node_sid(PF_INET,
                                        addr, sizeof(struct in_addr), sid);
                if (new)
                        new->nsec.addr.ipv4 = *(__be32 *)addr;
                break;
        case PF_INET6:
-               ret = security_node_sid(&selinux_state, PF_INET6,
+               ret = security_node_sid(PF_INET6,
                                        addr, sizeof(struct in6_addr), sid);
                if (new)
                        new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
index 8eec6347cf012bbd1d286507d032e4890867b1e2..2e22ad9c2bd0d116668985e0fb579b5934df9394 100644 (file)
@@ -148,7 +148,7 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
                return 0;
        }
 
-       ret = security_port_sid(&selinux_state, protocol, pnum, sid);
+       ret = security_port_sid(protocol, pnum, sid);
        if (ret != 0)
                goto out;
        new = kzalloc(sizeof(*new), GFP_ATOMIC);
index 18498979a640933e1be2438afff7c5fbe9bf4c3d..69a583b91fc57c5ff04a2f66155278c6156e6ea5 100644 (file)
@@ -77,7 +77,6 @@ struct selinux_fs_info {
        bool policy_opened;
        struct dentry *policycap_dir;
        unsigned long last_ino;
-       struct selinux_state *state;
        struct super_block *sb;
 };
 
@@ -90,7 +89,6 @@ static int selinux_fs_info_create(struct super_block *sb)
                return -ENOMEM;
 
        fsi->last_ino = SEL_INO_NEXT - 1;
-       fsi->state = &selinux_state;
        fsi->sb = sb;
        sb->s_fs_info = fsi;
        return 0;
@@ -125,12 +123,11 @@ static void selinux_fs_info_free(struct super_block *sb)
 static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
        char tmpbuf[TMPBUFLEN];
        ssize_t length;
 
        length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
-                          enforcing_enabled(fsi->state));
+                          enforcing_enabled());
        return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
@@ -139,8 +136,6 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *page = NULL;
        ssize_t length;
        int old_value, new_value;
@@ -162,10 +157,9 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
 
        new_value = !!new_value;
 
-       old_value = enforcing_enabled(state);
+       old_value = enforcing_enabled();
        if (new_value != old_value) {
-               length = avc_has_perm(&selinux_state,
-                                     current_sid(), SECINITSID_SECURITY,
+               length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                                      SECCLASS_SECURITY, SECURITY__SETENFORCE,
                                      NULL);
                if (length)
@@ -176,15 +170,15 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
                        new_value, old_value,
                        from_kuid(&init_user_ns, audit_get_loginuid(current)),
                        audit_get_sessionid(current));
-               enforcing_set(state, new_value);
+               enforcing_set(new_value);
                if (new_value)
-                       avc_ss_reset(state->avc, 0);
+                       avc_ss_reset(0);
                selnl_notify_setenforce(new_value);
-               selinux_status_update_setenforce(state, new_value);
+               selinux_status_update_setenforce(new_value);
                if (!new_value)
                        call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
 
-               selinux_ima_measure_state(state);
+               selinux_ima_measure_state();
        }
        length = count;
 out:
@@ -204,14 +198,12 @@ static const struct file_operations sel_enforce_ops = {
 static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
                                        size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char tmpbuf[TMPBUFLEN];
        ssize_t length;
        ino_t ino = file_inode(filp)->i_ino;
        int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ?
-               security_get_reject_unknown(state) :
-               !security_get_allow_unknown(state);
+               security_get_reject_unknown() :
+               !security_get_allow_unknown();
 
        length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown);
        return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
@@ -224,8 +216,7 @@ static const struct file_operations sel_handle_unknown_ops = {
 
 static int sel_open_handle_status(struct inode *inode, struct file *filp)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
-       struct page    *status = selinux_kernel_status_page(fsi->state);
+       struct page    *status = selinux_kernel_status_page();
 
        if (!status)
                return -ENOMEM;
@@ -276,25 +267,13 @@ static const struct file_operations sel_handle_status_ops = {
        .llseek         = generic_file_llseek,
 };
 
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static ssize_t sel_write_disable(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
        char *page;
        ssize_t length;
        int new_value;
-       int enforcing;
-
-       /* NOTE: we are now officially considering runtime disable as
-        *       deprecated, and using it will become increasingly painful
-        *       (e.g. sleeping/blocking) as we progress through future
-        *       kernel releases until eventually it is removed
-        */
-       pr_err("SELinux:  Runtime disable is deprecated, use selinux=0 on the kernel cmdline.\n");
-       pr_err("SELinux:  https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-runtime-disable\n");
-       ssleep(15);
 
        if (count >= PAGE_SIZE)
                return -ENOMEM;
@@ -307,31 +286,21 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
        if (IS_ERR(page))
                return PTR_ERR(page);
 
-       length = -EINVAL;
-       if (sscanf(page, "%d", &new_value) != 1)
+       if (sscanf(page, "%d", &new_value) != 1) {
+               length = -EINVAL;
                goto out;
+       }
+       length = count;
 
        if (new_value) {
-               enforcing = enforcing_enabled(fsi->state);
-               length = selinux_disable(fsi->state);
-               if (length)
-                       goto out;
-               audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
-                       "enforcing=%d old_enforcing=%d auid=%u ses=%u"
-                       " enabled=0 old-enabled=1 lsm=selinux res=1",
-                       enforcing, enforcing,
-                       from_kuid(&init_user_ns, audit_get_loginuid(current)),
-                       audit_get_sessionid(current));
+               pr_err("SELinux: https://github.com/SELinuxProject/selinux-kernel/wiki/DEPRECATE-runtime-disable\n");
+               pr_err("SELinux: Runtime disable is not supported, use selinux=0 on the kernel cmdline.\n");
        }
 
-       length = count;
 out:
        kfree(page);
        return length;
 }
-#else
-#define sel_write_disable NULL
-#endif
 
 static const struct file_operations sel_disable_ops = {
        .write          = sel_write_disable,
@@ -375,12 +344,11 @@ static void sel_remove_entries(struct dentry *de);
 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
        char tmpbuf[TMPBUFLEN];
        ssize_t length;
 
        length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
-                          security_mls_enabled(fsi->state));
+                          security_mls_enabled());
        return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
@@ -397,16 +365,14 @@ struct policy_load_memory {
 static int sel_open_policy(struct inode *inode, struct file *filp)
 {
        struct selinux_fs_info *fsi = inode->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        struct policy_load_memory *plm = NULL;
        int rc;
 
        BUG_ON(filp->private_data);
 
-       mutex_lock(&fsi->state->policy_mutex);
+       mutex_lock(&selinux_state.policy_mutex);
 
-       rc = avc_has_perm(&selinux_state,
-                         current_sid(), SECINITSID_SECURITY,
+       rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                          SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
        if (rc)
                goto err;
@@ -420,7 +386,7 @@ static int sel_open_policy(struct inode *inode, struct file *filp)
        if (!plm)
                goto err;
 
-       rc = security_read_policy(state, &plm->data, &plm->len);
+       rc = security_read_policy(&plm->data, &plm->len);
        if (rc)
                goto err;
 
@@ -434,11 +400,11 @@ static int sel_open_policy(struct inode *inode, struct file *filp)
 
        filp->private_data = plm;
 
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
 
        return 0;
 err:
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
 
        if (plm)
                vfree(plm->data);
@@ -467,8 +433,7 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf,
        struct policy_load_memory *plm = filp->private_data;
        int ret;
 
-       ret = avc_has_perm(&selinux_state,
-                          current_sid(), SECINITSID_SECURITY,
+       ret = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                          SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
        if (ret)
                return ret;
@@ -621,10 +586,9 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
        ssize_t length;
        void *data = NULL;
 
-       mutex_lock(&fsi->state->policy_mutex);
+       mutex_lock(&selinux_state.policy_mutex);
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL);
        if (length)
                goto out;
@@ -643,7 +607,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
        if (copy_from_user(data, buf, count) != 0)
                goto out;
 
-       length = security_load_policy(fsi->state, data, count, &load_state);
+       length = security_load_policy(data, count, &load_state);
        if (length) {
                pr_warn_ratelimited("SELinux: failed to load policy\n");
                goto out;
@@ -652,11 +616,11 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
        length = sel_make_policy_nodes(fsi, load_state.policy);
        if (length) {
                pr_warn_ratelimited("SELinux: failed to initialize selinuxfs\n");
-               selinux_policy_cancel(fsi->state, &load_state);
+               selinux_policy_cancel(&load_state);
                goto out;
        }
 
-       selinux_policy_commit(fsi->state, &load_state);
+       selinux_policy_commit(&load_state);
 
        length = count;
 
@@ -665,7 +629,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
                from_kuid(&init_user_ns, audit_get_loginuid(current)),
                audit_get_sessionid(current));
 out:
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
        vfree(data);
        return length;
 }
@@ -677,23 +641,20 @@ static const struct file_operations sel_load_ops = {
 
 static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *canon = NULL;
        u32 sid, len;
        ssize_t length;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL);
        if (length)
                goto out;
 
-       length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL);
+       length = security_context_to_sid(buf, size, &sid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_sid_to_context(state, sid, &canon, &len);
+       length = security_sid_to_context(sid, &canon, &len);
        if (length)
                goto out;
 
@@ -714,25 +675,22 @@ out:
 static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
                                     size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
        char tmpbuf[TMPBUFLEN];
        ssize_t length;
 
        length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
-                          checkreqprot_get(fsi->state));
+                          checkreqprot_get());
        return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
                                      size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
        char *page;
        ssize_t length;
        unsigned int new_value;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT,
                              NULL);
        if (length)
@@ -749,24 +707,21 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
        if (IS_ERR(page))
                return PTR_ERR(page);
 
-       length = -EINVAL;
-       if (sscanf(page, "%u", &new_value) != 1)
+       if (sscanf(page, "%u", &new_value) != 1) {
+               length = -EINVAL;
                goto out;
+       }
+       length = count;
 
        if (new_value) {
                char comm[sizeof(current->comm)];
 
                memcpy(comm, current->comm, sizeof(comm));
-               pr_err("SELinux: %s (%d) set checkreqprot to 1. This is deprecated and will be rejected in a future kernel release.\n",
+               pr_err("SELinux: %s (%d) set checkreqprot to 1. This is no longer supported.\n",
                       comm, current->pid);
        }
 
-       checkreqprot_set(fsi->state, (new_value ? 1 : 0));
-       if (new_value)
-               ssleep(15);
-       length = count;
-
-       selinux_ima_measure_state(fsi->state);
+       selinux_ima_measure_state();
 
 out:
        kfree(page);
@@ -782,16 +737,13 @@ static ssize_t sel_write_validatetrans(struct file *file,
                                        const char __user *buf,
                                        size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *oldcon = NULL, *newcon = NULL, *taskcon = NULL;
        char *req = NULL;
        u32 osid, nsid, tsid;
        u16 tclass;
        int rc;
 
-       rc = avc_has_perm(&selinux_state,
-                         current_sid(), SECINITSID_SECURITY,
+       rc = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                          SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL);
        if (rc)
                goto out;
@@ -829,19 +781,19 @@ static ssize_t sel_write_validatetrans(struct file *file,
        if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4)
                goto out;
 
-       rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL);
+       rc = security_context_str_to_sid(oldcon, &osid, GFP_KERNEL);
        if (rc)
                goto out;
 
-       rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL);
+       rc = security_context_str_to_sid(newcon, &nsid, GFP_KERNEL);
        if (rc)
                goto out;
 
-       rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL);
+       rc = security_context_str_to_sid(taskcon, &tsid, GFP_KERNEL);
        if (rc)
                goto out;
 
-       rc = security_validate_transition_user(state, osid, nsid, tsid, tclass);
+       rc = security_validate_transition_user(osid, nsid, tsid, tclass);
        if (!rc)
                rc = count;
 out:
@@ -911,16 +863,13 @@ static const struct file_operations transaction_ops = {
 
 static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *scon = NULL, *tcon = NULL;
        u32 ssid, tsid;
        u16 tclass;
        struct av_decision avd;
        ssize_t length;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL);
        if (length)
                goto out;
@@ -939,15 +888,15 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
                goto out;
 
-       length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
+       length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
+       length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
        if (length)
                goto out;
 
-       security_compute_av_user(state, ssid, tsid, tclass, &avd);
+       security_compute_av_user(ssid, tsid, tclass, &avd);
 
        length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
                          "%x %x %x %x %u %x",
@@ -962,8 +911,6 @@ out:
 
 static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *scon = NULL, *tcon = NULL;
        char *namebuf = NULL, *objname = NULL;
        u32 ssid, tsid, newsid;
@@ -973,8 +920,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
        u32 len;
        int nargs;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE,
                              NULL);
        if (length)
@@ -1030,20 +976,20 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
                objname = namebuf;
        }
 
-       length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
+       length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
+       length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_transition_sid_user(state, ssid, tsid, tclass,
+       length = security_transition_sid_user(ssid, tsid, tclass,
                                              objname, &newsid);
        if (length)
                goto out;
 
-       length = security_sid_to_context(state, newsid, &newcon, &len);
+       length = security_sid_to_context(newsid, &newcon, &len);
        if (length)
                goto out;
 
@@ -1066,8 +1012,6 @@ out:
 
 static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *scon = NULL, *tcon = NULL;
        u32 ssid, tsid, newsid;
        u16 tclass;
@@ -1075,8 +1019,7 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
        char *newcon = NULL;
        u32 len;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL,
                              NULL);
        if (length)
@@ -1096,19 +1039,19 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
                goto out;
 
-       length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
+       length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
+       length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_change_sid(state, ssid, tsid, tclass, &newsid);
+       length = security_change_sid(ssid, tsid, tclass, &newsid);
        if (length)
                goto out;
 
-       length = security_sid_to_context(state, newsid, &newcon, &len);
+       length = security_sid_to_context(newsid, &newcon, &len);
        if (length)
                goto out;
 
@@ -1127,8 +1070,6 @@ out:
 
 static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *con = NULL, *user = NULL, *ptr;
        u32 sid, *sids = NULL;
        ssize_t length;
@@ -1136,8 +1077,7 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
        int i, rc;
        u32 len, nsids;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__COMPUTE_USER,
                              NULL);
        if (length)
@@ -1157,18 +1097,18 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s", con, user) != 2)
                goto out;
 
-       length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL);
+       length = security_context_str_to_sid(con, &sid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_get_user_sids(state, sid, user, &sids, &nsids);
+       length = security_get_user_sids(sid, user, &sids, &nsids);
        if (length)
                goto out;
 
        length = sprintf(buf, "%u", nsids) + 1;
        ptr = buf + length;
        for (i = 0; i < nsids; i++) {
-               rc = security_sid_to_context(state, sids[i], &newcon, &len);
+               rc = security_sid_to_context(sids[i], &newcon, &len);
                if (rc) {
                        length = rc;
                        goto out;
@@ -1192,8 +1132,6 @@ out:
 
 static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *scon = NULL, *tcon = NULL;
        u32 ssid, tsid, newsid;
        u16 tclass;
@@ -1201,8 +1139,7 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
        char *newcon = NULL;
        u32 len;
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER,
                              NULL);
        if (length)
@@ -1222,19 +1159,19 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
        if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
                goto out;
 
-       length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
+       length = security_context_str_to_sid(scon, &ssid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
+       length = security_context_str_to_sid(tcon, &tsid, GFP_KERNEL);
        if (length)
                goto out;
 
-       length = security_member_sid(state, ssid, tsid, tclass, &newsid);
+       length = security_member_sid(ssid, tsid, tclass, &newsid);
        if (length)
                goto out;
 
-       length = security_sid_to_context(state, newsid, &newcon, &len);
+       length = security_sid_to_context(newsid, &newcon, &len);
        if (length)
                goto out;
 
@@ -1276,7 +1213,7 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
        unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
        const char *name = filep->f_path.dentry->d_name.name;
 
-       mutex_lock(&fsi->state->policy_mutex);
+       mutex_lock(&selinux_state.policy_mutex);
 
        ret = -EINVAL;
        if (index >= fsi->bool_num || strcmp(name,
@@ -1288,21 +1225,21 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
        if (!page)
                goto out_unlock;
 
-       cur_enforcing = security_get_bool_value(fsi->state, index);
+       cur_enforcing = security_get_bool_value(index);
        if (cur_enforcing < 0) {
                ret = cur_enforcing;
                goto out_unlock;
        }
        length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
                          fsi->bool_pending_values[index]);
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
        ret = simple_read_from_buffer(buf, count, ppos, page, length);
 out_free:
        free_page((unsigned long)page);
        return ret;
 
 out_unlock:
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
        goto out_free;
 }
 
@@ -1327,10 +1264,9 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
        if (IS_ERR(page))
                return PTR_ERR(page);
 
-       mutex_lock(&fsi->state->policy_mutex);
+       mutex_lock(&selinux_state.policy_mutex);
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__SETBOOL,
                              NULL);
        if (length)
@@ -1352,7 +1288,7 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
        length = count;
 
 out:
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
        kfree(page);
        return length;
 }
@@ -1383,10 +1319,9 @@ static ssize_t sel_commit_bools_write(struct file *filep,
        if (IS_ERR(page))
                return PTR_ERR(page);
 
-       mutex_lock(&fsi->state->policy_mutex);
+       mutex_lock(&selinux_state.policy_mutex);
 
-       length = avc_has_perm(&selinux_state,
-                             current_sid(), SECINITSID_SECURITY,
+       length = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                              SECCLASS_SECURITY, SECURITY__SETBOOL,
                              NULL);
        if (length)
@@ -1398,14 +1333,14 @@ static ssize_t sel_commit_bools_write(struct file *filep,
 
        length = 0;
        if (new_value && fsi->bool_pending_values)
-               length = security_set_bools(fsi->state, fsi->bool_num,
+               length = security_set_bools(fsi->bool_num,
                                            fsi->bool_pending_values);
 
        if (!length)
                length = count;
 
 out:
-       mutex_unlock(&fsi->state->policy_mutex);
+       mutex_unlock(&selinux_state.policy_mutex);
        kfree(page);
        return length;
 }
@@ -1503,13 +1438,11 @@ out:
 static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
                                            size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char tmpbuf[TMPBUFLEN];
        ssize_t length;
 
        length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
-                          avc_get_cache_threshold(state->avc));
+                          avc_get_cache_threshold());
        return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
@@ -1518,14 +1451,11 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
                                             size_t count, loff_t *ppos)
 
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *page;
        ssize_t ret;
        unsigned int new_value;
 
-       ret = avc_has_perm(&selinux_state,
-                          current_sid(), SECINITSID_SECURITY,
+       ret = avc_has_perm(current_sid(), SECINITSID_SECURITY,
                           SECCLASS_SECURITY, SECURITY__SETSECPARAM,
                           NULL);
        if (ret)
@@ -1546,7 +1476,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
        if (sscanf(page, "%u", &new_value) != 1)
                goto out;
 
-       avc_set_cache_threshold(state->avc, new_value);
+       avc_set_cache_threshold(new_value);
 
        ret = count;
 out:
@@ -1557,8 +1487,6 @@ out:
 static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
                                       size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *page;
        ssize_t length;
 
@@ -1566,7 +1494,7 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
        if (!page)
                return -ENOMEM;
 
-       length = avc_get_hash_stats(state->avc, page);
+       length = avc_get_hash_stats(page);
        if (length >= 0)
                length = simple_read_from_buffer(buf, count, ppos, page, length);
        free_page((unsigned long)page);
@@ -1577,8 +1505,6 @@ static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
 static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf,
                                        size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
-       struct selinux_state *state = fsi->state;
        char *page;
        ssize_t length;
 
@@ -1586,7 +1512,7 @@ static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf,
        if (!page)
                return -ENOMEM;
 
-       length = security_sidtab_hash_stats(state, page);
+       length = security_sidtab_hash_stats(page);
        if (length >= 0)
                length = simple_read_from_buffer(buf, count, ppos, page,
                                                length);
@@ -1752,13 +1678,12 @@ static int sel_make_ss_files(struct dentry *dir)
 static ssize_t sel_read_initcon(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
        char *con;
        u32 sid, len;
        ssize_t ret;
 
        sid = file_inode(file)->i_ino&SEL_INO_MASK;
-       ret = security_sid_to_context(fsi->state, sid, &con, &len);
+       ret = security_sid_to_context(sid, &con, &len);
        if (ret)
                return ret;
 
@@ -1852,13 +1777,12 @@ static const struct file_operations sel_perm_ops = {
 static ssize_t sel_read_policycap(struct file *file, char __user *buf,
                                  size_t count, loff_t *ppos)
 {
-       struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
        int value;
        char tmpbuf[TMPBUFLEN];
        ssize_t length;
        unsigned long i_ino = file_inode(file)->i_ino;
 
-       value = security_policycap_supported(fsi->state, i_ino & SEL_INO_MASK);
+       value = security_policycap_supported(i_ino & SEL_INO_MASK);
        length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value);
 
        return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
@@ -2249,13 +2173,3 @@ static int __init init_sel_fs(void)
 }
 
 __initcall(init_sel_fs);
-
-#ifdef CONFIG_SECURITY_SELINUX_DISABLE
-void exit_sel_fs(void)
-{
-       sysfs_remove_mount_point(fs_kobj, "selinux");
-       dput(selinux_null.dentry);
-       kern_unmount(selinuxfs_mount);
-       unregister_filesystem(&sel_fs_type);
-}
-#endif
index 0092b29022f5e46c2d29193c1a8d35e1941d6001..f14d1ffe54c5dc7b4461906f5dcdc3650321f920 100644 (file)
@@ -235,16 +235,16 @@ static void map_decision(struct selinux_map *map,
        }
 }
 
-int security_mls_enabled(struct selinux_state *state)
+int security_mls_enabled(void)
 {
        int mls_enabled;
        struct selinux_policy *policy;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        mls_enabled = policy->policydb.mls_enabled;
        rcu_read_unlock();
        return mls_enabled;
@@ -713,8 +713,7 @@ static void context_struct_compute_av(struct policydb *policydb,
                                 tclass, avd);
 }
 
-static int security_validtrans_handle_fail(struct selinux_state *state,
-                                       struct selinux_policy *policy,
+static int security_validtrans_handle_fail(struct selinux_policy *policy,
                                        struct sidtab_entry *oentry,
                                        struct sidtab_entry *nentry,
                                        struct sidtab_entry *tentry,
@@ -740,13 +739,12 @@ out:
        kfree(n);
        kfree(t);
 
-       if (!enforcing_enabled(state))
+       if (!enforcing_enabled())
                return 0;
        return -EPERM;
 }
 
-static int security_compute_validatetrans(struct selinux_state *state,
-                                         u32 oldsid, u32 newsid, u32 tasksid,
+static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
                                          u16 orig_tclass, bool user)
 {
        struct selinux_policy *policy;
@@ -761,12 +759,12 @@ static int security_compute_validatetrans(struct selinux_state *state,
        int rc = 0;
 
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
 
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -813,8 +811,7 @@ static int security_compute_validatetrans(struct selinux_state *state,
                        if (user)
                                rc = -EPERM;
                        else
-                               rc = security_validtrans_handle_fail(state,
-                                                               policy,
+                               rc = security_validtrans_handle_fail(policy,
                                                                oentry,
                                                                nentry,
                                                                tentry,
@@ -829,19 +826,17 @@ out:
        return rc;
 }
 
-int security_validate_transition_user(struct selinux_state *state,
-                                     u32 oldsid, u32 newsid, u32 tasksid,
+int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
                                      u16 tclass)
 {
-       return security_compute_validatetrans(state, oldsid, newsid, tasksid,
+       return security_compute_validatetrans(oldsid, newsid, tasksid,
                                              tclass, true);
 }
 
-int security_validate_transition(struct selinux_state *state,
-                                u32 oldsid, u32 newsid, u32 tasksid,
+int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
                                 u16 orig_tclass)
 {
-       return security_compute_validatetrans(state, oldsid, newsid, tasksid,
+       return security_compute_validatetrans(oldsid, newsid, tasksid,
                                              orig_tclass, false);
 }
 
@@ -851,12 +846,10 @@ int security_validate_transition(struct selinux_state *state,
  * It returns 0, if @newsid is bounded by @oldsid.
  * Otherwise, it returns error code.
  *
- * @state: SELinux state
  * @oldsid : current security identifier
  * @newsid : destinated security identifier
  */
-int security_bounded_transition(struct selinux_state *state,
-                               u32 old_sid, u32 new_sid)
+int security_bounded_transition(u32 old_sid, u32 new_sid)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -866,11 +859,11 @@ int security_bounded_transition(struct selinux_state *state,
        int index;
        int rc;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -1004,8 +997,7 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
        }
 }
 
-void security_compute_xperms_decision(struct selinux_state *state,
-                                     u32 ssid,
+void security_compute_xperms_decision(u32 ssid,
                                      u32 tsid,
                                      u16 orig_tclass,
                                      u8 driver,
@@ -1029,10 +1021,10 @@ void security_compute_xperms_decision(struct selinux_state *state,
        memset(xpermd->dontaudit->p, 0, sizeof(xpermd->dontaudit->p));
 
        rcu_read_lock();
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                goto allow;
 
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -1091,7 +1083,6 @@ allow:
 
 /**
  * security_compute_av - Compute access vector decisions.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @orig_tclass: target security class
@@ -1101,8 +1092,7 @@ allow:
  * Compute a set of access vector decisions based on the
  * SID pair (@ssid, @tsid) for the permissions in @tclass.
  */
-void security_compute_av(struct selinux_state *state,
-                        u32 ssid,
+void security_compute_av(u32 ssid,
                         u32 tsid,
                         u16 orig_tclass,
                         struct av_decision *avd,
@@ -1115,10 +1105,10 @@ void security_compute_av(struct selinux_state *state,
        struct context *scontext = NULL, *tcontext = NULL;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        avd_init(policy, avd);
        xperms->len = 0;
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                goto allow;
 
        policydb = &policy->policydb;
@@ -1160,8 +1150,7 @@ allow:
        goto out;
 }
 
-void security_compute_av_user(struct selinux_state *state,
-                             u32 ssid,
+void security_compute_av_user(u32 ssid,
                              u32 tsid,
                              u16 tclass,
                              struct av_decision *avd)
@@ -1172,9 +1161,9 @@ void security_compute_av_user(struct selinux_state *state,
        struct context *scontext = NULL, *tcontext = NULL;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        avd_init(policy, avd);
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                goto allow;
 
        policydb = &policy->policydb;
@@ -1290,19 +1279,19 @@ static int sidtab_entry_to_string(struct policydb *p,
 
 #include "initial_sid_to_string.h"
 
-int security_sidtab_hash_stats(struct selinux_state *state, char *page)
+int security_sidtab_hash_stats(char *page)
 {
        struct selinux_policy *policy;
        int rc;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                pr_err("SELinux: %s:  called before initial load_policy\n",
                       __func__);
                return -EINVAL;
        }
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        rc = sidtab_hash_stats(policy->sidtab, page);
        rcu_read_unlock();
 
@@ -1316,8 +1305,7 @@ const char *security_get_initial_sid_context(u32 sid)
        return initial_sid_to_string[sid];
 }
 
-static int security_sid_to_context_core(struct selinux_state *state,
-                                       u32 sid, char **scontext,
+static int security_sid_to_context_core(u32 sid, char **scontext,
                                        u32 *scontext_len, int force,
                                        int only_invalid)
 {
@@ -1331,7 +1319,7 @@ static int security_sid_to_context_core(struct selinux_state *state,
                *scontext = NULL;
        *scontext_len  = 0;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                if (sid <= SECINITSID_NUM) {
                        char *scontextp;
                        const char *s = initial_sid_to_string[sid];
@@ -1352,7 +1340,7 @@ static int security_sid_to_context_core(struct selinux_state *state,
                return -EINVAL;
        }
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -1380,7 +1368,6 @@ out_unlock:
 
 /**
  * security_sid_to_context - Obtain a context for a given SID.
- * @state: SELinux state
  * @sid: security identifier, SID
  * @scontext: security context
  * @scontext_len: length in bytes
@@ -1389,24 +1376,22 @@ out_unlock:
  * into a dynamically allocated string of the correct size.  Set @scontext
  * to point to this string and set @scontext_len to the length of the string.
  */
-int security_sid_to_context(struct selinux_state *state,
-                           u32 sid, char **scontext, u32 *scontext_len)
+int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
 {
-       return security_sid_to_context_core(state, sid, scontext,
+       return security_sid_to_context_core(sid, scontext,
                                            scontext_len, 0, 0);
 }
 
-int security_sid_to_context_force(struct selinux_state *state, u32 sid,
+int security_sid_to_context_force(u32 sid,
                                  char **scontext, u32 *scontext_len)
 {
-       return security_sid_to_context_core(state, sid, scontext,
+       return security_sid_to_context_core(sid, scontext,
                                            scontext_len, 1, 0);
 }
 
 /**
  * security_sid_to_context_inval - Obtain a context for a given SID if it
  *                                 is invalid.
- * @state: SELinux state
  * @sid: security identifier, SID
  * @scontext: security context
  * @scontext_len: length in bytes
@@ -1417,10 +1402,10 @@ int security_sid_to_context_force(struct selinux_state *state, u32 sid,
  * this string (or NULL if the context is valid) and set @scontext_len to
  * the length of the string (or 0 if the context is valid).
  */
-int security_sid_to_context_inval(struct selinux_state *state, u32 sid,
+int security_sid_to_context_inval(u32 sid,
                                  char **scontext, u32 *scontext_len)
 {
-       return security_sid_to_context_core(state, sid, scontext,
+       return security_sid_to_context_core(sid, scontext,
                                            scontext_len, 1, 1);
 }
 
@@ -1505,8 +1490,7 @@ out:
        return rc;
 }
 
-static int security_context_to_sid_core(struct selinux_state *state,
-                                       const char *scontext, u32 scontext_len,
+static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
                                        u32 *sid, u32 def_sid, gfp_t gfp_flags,
                                        int force)
 {
@@ -1526,7 +1510,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
        if (!scontext2)
                return -ENOMEM;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                int i;
 
                for (i = 1; i < SECINITSID_NUM; i++) {
@@ -1551,7 +1535,7 @@ static int security_context_to_sid_core(struct selinux_state *state,
        }
 retry:
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
        rc = string_to_context_struct(policydb, sidtab, scontext2,
@@ -1583,7 +1567,6 @@ out:
 
 /**
  * security_context_to_sid - Obtain a SID for a given security context.
- * @state: SELinux state
  * @scontext: security context
  * @scontext_len: length in bytes
  * @sid: security identifier, SID
@@ -1594,18 +1577,16 @@ out:
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid(struct selinux_state *state,
-                           const char *scontext, u32 scontext_len, u32 *sid,
+int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid,
                            gfp_t gfp)
 {
-       return security_context_to_sid_core(state, scontext, scontext_len,
+       return security_context_to_sid_core(scontext, scontext_len,
                                            sid, SECSID_NULL, gfp, 0);
 }
 
-int security_context_str_to_sid(struct selinux_state *state,
-                               const char *scontext, u32 *sid, gfp_t gfp)
+int security_context_str_to_sid(const char *scontext, u32 *sid, gfp_t gfp)
 {
-       return security_context_to_sid(state, scontext, strlen(scontext),
+       return security_context_to_sid(scontext, strlen(scontext),
                                       sid, gfp);
 }
 
@@ -1613,7 +1594,6 @@ int security_context_str_to_sid(struct selinux_state *state,
  * security_context_to_sid_default - Obtain a SID for a given security context,
  * falling back to specified default if needed.
  *
- * @state: SELinux state
  * @scontext: security context
  * @scontext_len: length in bytes
  * @sid: security identifier, SID
@@ -1629,24 +1609,21 @@ int security_context_str_to_sid(struct selinux_state *state,
  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
  * memory is available, or 0 on success.
  */
-int security_context_to_sid_default(struct selinux_state *state,
-                                   const char *scontext, u32 scontext_len,
+int security_context_to_sid_default(const char *scontext, u32 scontext_len,
                                    u32 *sid, u32 def_sid, gfp_t gfp_flags)
 {
-       return security_context_to_sid_core(state, scontext, scontext_len,
+       return security_context_to_sid_core(scontext, scontext_len,
                                            sid, def_sid, gfp_flags, 1);
 }
 
-int security_context_to_sid_force(struct selinux_state *state,
-                                 const char *scontext, u32 scontext_len,
+int security_context_to_sid_force(const char *scontext, u32 scontext_len,
                                  u32 *sid)
 {
-       return security_context_to_sid_core(state, scontext, scontext_len,
+       return security_context_to_sid_core(scontext, scontext_len,
                                            sid, SECSID_NULL, GFP_KERNEL, 1);
 }
 
 static int compute_sid_handle_invalid_context(
-       struct selinux_state *state,
        struct selinux_policy *policy,
        struct sidtab_entry *sentry,
        struct sidtab_entry *tentry,
@@ -1679,7 +1656,7 @@ out:
        kfree(s);
        kfree(t);
        kfree(n);
-       if (!enforcing_enabled(state))
+       if (!enforcing_enabled())
                return 0;
        return -EACCES;
 }
@@ -1714,8 +1691,7 @@ static void filename_compute_type(struct policydb *policydb,
        }
 }
 
-static int security_compute_sid(struct selinux_state *state,
-                               u32 ssid,
+static int security_compute_sid(u32 ssid,
                                u32 tsid,
                                u16 orig_tclass,
                                u32 specified,
@@ -1736,7 +1712,7 @@ static int security_compute_sid(struct selinux_state *state,
        int rc = 0;
        bool sock;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                switch (orig_tclass) {
                case SECCLASS_PROCESS: /* kernel value */
                        *out_sid = ssid;
@@ -1754,7 +1730,7 @@ retry:
 
        rcu_read_lock();
 
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
 
        if (kern) {
                tclass = unmap_class(&policy->map, orig_tclass);
@@ -1886,7 +1862,7 @@ retry:
 
        /* Check the validity of the context. */
        if (!policydb_context_isvalid(policydb, &newcontext)) {
-               rc = compute_sid_handle_invalid_context(state, policy, sentry,
+               rc = compute_sid_handle_invalid_context(policy, sentry,
                                                        tentry, tclass,
                                                        &newcontext);
                if (rc)
@@ -1908,7 +1884,6 @@ out:
 
 /**
  * security_transition_sid - Compute the SID for a new subject/object.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -1921,27 +1896,24 @@ out:
  * if insufficient memory is available, or %0 if the new SID was
  * computed successfully.
  */
-int security_transition_sid(struct selinux_state *state,
-                           u32 ssid, u32 tsid, u16 tclass,
+int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
                            const struct qstr *qstr, u32 *out_sid)
 {
-       return security_compute_sid(state, ssid, tsid, tclass,
+       return security_compute_sid(ssid, tsid, tclass,
                                    AVTAB_TRANSITION,
                                    qstr ? qstr->name : NULL, out_sid, true);
 }
 
-int security_transition_sid_user(struct selinux_state *state,
-                                u32 ssid, u32 tsid, u16 tclass,
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
                                 const char *objname, u32 *out_sid)
 {
-       return security_compute_sid(state, ssid, tsid, tclass,
+       return security_compute_sid(ssid, tsid, tclass,
                                    AVTAB_TRANSITION,
                                    objname, out_sid, false);
 }
 
 /**
  * security_member_sid - Compute the SID for member selection.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -1953,20 +1925,18 @@ int security_transition_sid_user(struct selinux_state *state,
  * if insufficient memory is available, or %0 if the SID was
  * computed successfully.
  */
-int security_member_sid(struct selinux_state *state,
-                       u32 ssid,
+int security_member_sid(u32 ssid,
                        u32 tsid,
                        u16 tclass,
                        u32 *out_sid)
 {
-       return security_compute_sid(state, ssid, tsid, tclass,
+       return security_compute_sid(ssid, tsid, tclass,
                                    AVTAB_MEMBER, NULL,
                                    out_sid, false);
 }
 
 /**
  * security_change_sid - Compute the SID for object relabeling.
- * @state: SELinux state
  * @ssid: source security identifier
  * @tsid: target security identifier
  * @tclass: target security class
@@ -1978,26 +1948,23 @@ int security_member_sid(struct selinux_state *state,
  * if insufficient memory is available, or %0 if the SID was
  * computed successfully.
  */
-int security_change_sid(struct selinux_state *state,
-                       u32 ssid,
+int security_change_sid(u32 ssid,
                        u32 tsid,
                        u16 tclass,
                        u32 *out_sid)
 {
-       return security_compute_sid(state,
-                                   ssid, tsid, tclass, AVTAB_CHANGE, NULL,
+       return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
                                    out_sid, false);
 }
 
 static inline int convert_context_handle_invalid_context(
-       struct selinux_state *state,
        struct policydb *policydb,
        struct context *context)
 {
        char *s;
        u32 len;
 
-       if (enforcing_enabled(state))
+       if (enforcing_enabled())
                return -EINVAL;
 
        if (!context_struct_to_string(policydb, context, &s, &len)) {
@@ -2115,8 +2082,7 @@ int services_convert_context(struct convert_context_args *args,
 
        /* Check the validity of the new context. */
        if (!policydb_context_isvalid(args->newp, newc)) {
-               rc = convert_context_handle_invalid_context(args->state,
-                                                           args->oldp, oldc);
+               rc = convert_context_handle_invalid_context(args->oldp, oldc);
                if (rc)
                        goto bad;
        }
@@ -2135,8 +2101,7 @@ bad:
        return 0;
 }
 
-static void security_load_policycaps(struct selinux_state *state,
-                               struct selinux_policy *policy)
+static void security_load_policycaps(struct selinux_policy *policy)
 {
        struct policydb *p;
        unsigned int i;
@@ -2144,8 +2109,8 @@ static void security_load_policycaps(struct selinux_state *state,
 
        p = &policy->policydb;
 
-       for (i = 0; i < ARRAY_SIZE(state->policycap); i++)
-               WRITE_ONCE(state->policycap[i],
+       for (i = 0; i < ARRAY_SIZE(selinux_state.policycap); i++)
+               WRITE_ONCE(selinux_state.policycap[i],
                        ebitmap_get_bit(&p->policycaps, i));
 
        for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
@@ -2181,9 +2146,9 @@ static void selinux_policy_cond_free(struct selinux_policy *policy)
        kfree(policy);
 }
 
-void selinux_policy_cancel(struct selinux_state *state,
-                          struct selinux_load_state *load_state)
+void selinux_policy_cancel(struct selinux_load_state *load_state)
 {
+       struct selinux_state *state = &selinux_state;
        struct selinux_policy *oldpolicy;
 
        oldpolicy = rcu_dereference_protected(state->policy,
@@ -2194,21 +2159,20 @@ void selinux_policy_cancel(struct selinux_state *state,
        kfree(load_state->convert_data);
 }
 
-static void selinux_notify_policy_change(struct selinux_state *state,
-                                       u32 seqno)
+static void selinux_notify_policy_change(u32 seqno)
 {
        /* Flush external caches and notify userspace of policy load */
-       avc_ss_reset(state->avc, seqno);
+       avc_ss_reset(seqno);
        selnl_notify_policyload(seqno);
-       selinux_status_update_policyload(state, seqno);
+       selinux_status_update_policyload(seqno);
        selinux_netlbl_cache_invalidate();
        selinux_xfrm_notify_policyload();
-       selinux_ima_measure_state_locked(state);
+       selinux_ima_measure_state_locked();
 }
 
-void selinux_policy_commit(struct selinux_state *state,
-                          struct selinux_load_state *load_state)
+void selinux_policy_commit(struct selinux_load_state *load_state)
 {
+       struct selinux_state *state = &selinux_state;
        struct selinux_policy *oldpolicy, *newpolicy = load_state->policy;
        unsigned long flags;
        u32 seqno;
@@ -2241,15 +2205,15 @@ void selinux_policy_commit(struct selinux_state *state,
        }
 
        /* Load the policycaps from the new policy */
-       security_load_policycaps(state, newpolicy);
+       security_load_policycaps(newpolicy);
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                /*
                 * After first policy load, the security server is
                 * marked as initialized and ready to handle requests and
                 * any objects created prior to policy load are then labeled.
                 */
-               selinux_mark_initialized(state);
+               selinux_mark_initialized();
                selinux_complete_init();
        }
 
@@ -2259,12 +2223,11 @@ void selinux_policy_commit(struct selinux_state *state,
        kfree(load_state->convert_data);
 
        /* Notify others of the policy change */
-       selinux_notify_policy_change(state, seqno);
+       selinux_notify_policy_change(seqno);
 }
 
 /**
  * security_load_policy - Load a security policy configuration.
- * @state: SELinux state
  * @data: binary policy data
  * @len: length of data in bytes
  * @load_state: policy load state
@@ -2274,9 +2237,10 @@ void selinux_policy_commit(struct selinux_state *state,
  * This function will flush the access vector cache after
  * loading the new policy.
  */
-int security_load_policy(struct selinux_state *state, void *data, size_t len,
+int security_load_policy(void *data, size_t len,
                         struct selinux_load_state *load_state)
 {
+       struct selinux_state *state = &selinux_state;
        struct selinux_policy *newpolicy, *oldpolicy;
        struct selinux_policy_convert_data *convert_data;
        int rc = 0;
@@ -2308,7 +2272,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
                goto err_mapping;
        }
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                /* First policy load, so no need to preserve state from old policy */
                load_state->policy = newpolicy;
                load_state->convert_data = NULL;
@@ -2336,7 +2300,6 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len,
                goto err_free_isids;
        }
 
-       convert_data->args.state = state;
        convert_data->args.oldp = &oldpolicy->policydb;
        convert_data->args.newp = &newpolicy->policydb;
 
@@ -2410,13 +2373,11 @@ static int ocontext_to_sid(struct sidtab *sidtab, struct ocontext *c,
 
 /**
  * security_port_sid - Obtain the SID for a port.
- * @state: SELinux state
  * @protocol: protocol number
  * @port: port number
  * @out_sid: security identifier
  */
-int security_port_sid(struct selinux_state *state,
-                     u8 protocol, u16 port, u32 *out_sid)
+int security_port_sid(u8 protocol, u16 port, u32 *out_sid)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -2424,7 +2385,7 @@ int security_port_sid(struct selinux_state *state,
        struct ocontext *c;
        int rc;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *out_sid = SECINITSID_PORT;
                return 0;
        }
@@ -2432,7 +2393,7 @@ int security_port_sid(struct selinux_state *state,
 retry:
        rc = 0;
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -2464,13 +2425,11 @@ out:
 
 /**
  * security_ib_pkey_sid - Obtain the SID for a pkey.
- * @state: SELinux state
  * @subnet_prefix: Subnet Prefix
  * @pkey_num: pkey number
  * @out_sid: security identifier
  */
-int security_ib_pkey_sid(struct selinux_state *state,
-                        u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
+int security_ib_pkey_sid(u64 subnet_prefix, u16 pkey_num, u32 *out_sid)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -2478,7 +2437,7 @@ int security_ib_pkey_sid(struct selinux_state *state,
        struct ocontext *c;
        int rc;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *out_sid = SECINITSID_UNLABELED;
                return 0;
        }
@@ -2486,7 +2445,7 @@ int security_ib_pkey_sid(struct selinux_state *state,
 retry:
        rc = 0;
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -2518,13 +2477,11 @@ out:
 
 /**
  * security_ib_endport_sid - Obtain the SID for a subnet management interface.
- * @state: SELinux state
  * @dev_name: device name
  * @port_num: port number
  * @out_sid: security identifier
  */
-int security_ib_endport_sid(struct selinux_state *state,
-                           const char *dev_name, u8 port_num, u32 *out_sid)
+int security_ib_endport_sid(const char *dev_name, u8 port_num, u32 *out_sid)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -2532,7 +2489,7 @@ int security_ib_endport_sid(struct selinux_state *state,
        struct ocontext *c;
        int rc;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *out_sid = SECINITSID_UNLABELED;
                return 0;
        }
@@ -2540,7 +2497,7 @@ int security_ib_endport_sid(struct selinux_state *state,
 retry:
        rc = 0;
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -2573,12 +2530,10 @@ out:
 
 /**
  * security_netif_sid - Obtain the SID for a network interface.
- * @state: SELinux state
  * @name: interface name
  * @if_sid: interface SID
  */
-int security_netif_sid(struct selinux_state *state,
-                      char *name, u32 *if_sid)
+int security_netif_sid(char *name, u32 *if_sid)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -2586,7 +2541,7 @@ int security_netif_sid(struct selinux_state *state,
        int rc;
        struct ocontext *c;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *if_sid = SECINITSID_NETIF;
                return 0;
        }
@@ -2594,7 +2549,7 @@ int security_netif_sid(struct selinux_state *state,
 retry:
        rc = 0;
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -2636,14 +2591,12 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
 
 /**
  * security_node_sid - Obtain the SID for a node (host).
- * @state: SELinux state
  * @domain: communication domain aka address family
  * @addrp: address
  * @addrlen: address length in bytes
  * @out_sid: security identifier
  */
-int security_node_sid(struct selinux_state *state,
-                     u16 domain,
+int security_node_sid(u16 domain,
                      void *addrp,
                      u32 addrlen,
                      u32 *out_sid)
@@ -2654,14 +2607,14 @@ int security_node_sid(struct selinux_state *state,
        int rc;
        struct ocontext *c;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *out_sid = SECINITSID_NODE;
                return 0;
        }
 
 retry:
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -2725,7 +2678,6 @@ out:
 
 /**
  * security_get_user_sids - Obtain reachable SIDs for a user.
- * @state: SELinux state
  * @fromsid: starting SID
  * @username: username
  * @sids: array of reachable SIDs for user
@@ -2738,8 +2690,7 @@ out:
  * number of elements in the array.
  */
 
-int security_get_user_sids(struct selinux_state *state,
-                          u32 fromsid,
+int security_get_user_sids(u32 fromsid,
                           char *username,
                           u32 **sids,
                           u32 *nel)
@@ -2758,7 +2709,7 @@ int security_get_user_sids(struct selinux_state *state,
        *sids = NULL;
        *nel = 0;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL);
@@ -2768,7 +2719,7 @@ int security_get_user_sids(struct selinux_state *state,
 retry:
        mynel = 0;
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -2834,8 +2785,7 @@ out_unlock:
        }
        for (i = 0, j = 0; i < mynel; i++) {
                struct av_decision dummy_avd;
-               rc = avc_has_perm_noaudit(state,
-                                         fromsid, mysids[i],
+               rc = avc_has_perm_noaudit(fromsid, mysids[i],
                                          SECCLASS_PROCESS, /* kernel value */
                                          PROCESS__TRANSITION, AVC_STRICT,
                                          &dummy_avd);
@@ -2908,7 +2858,6 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
 
 /**
  * security_genfs_sid - Obtain a SID for a file in a filesystem
- * @state: SELinux state
  * @fstype: filesystem type
  * @path: path from root of mount
  * @orig_sclass: file security class
@@ -2917,8 +2866,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
  * Acquire policy_rwlock before calling __security_genfs_sid() and release
  * it afterward.
  */
-int security_genfs_sid(struct selinux_state *state,
-                      const char *fstype,
+int security_genfs_sid(const char *fstype,
                       const char *path,
                       u16 orig_sclass,
                       u32 *sid)
@@ -2926,14 +2874,14 @@ int security_genfs_sid(struct selinux_state *state,
        struct selinux_policy *policy;
        int retval;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *sid = SECINITSID_UNLABELED;
                return 0;
        }
 
        do {
                rcu_read_lock();
-               policy = rcu_dereference(state->policy);
+               policy = rcu_dereference(selinux_state.policy);
                retval = __security_genfs_sid(policy, fstype, path,
                                              orig_sclass, sid);
                rcu_read_unlock();
@@ -2953,10 +2901,9 @@ int selinux_policy_genfs_sid(struct selinux_policy *policy,
 
 /**
  * security_fs_use - Determine how to handle labeling for a filesystem.
- * @state: SELinux state
  * @sb: superblock in question
  */
-int security_fs_use(struct selinux_state *state, struct super_block *sb)
+int security_fs_use(struct super_block *sb)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -2966,7 +2913,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
        struct superblock_security_struct *sbsec = selinux_superblock(sb);
        const char *fstype = sb->s_type->name;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                sbsec->behavior = SECURITY_FS_USE_NONE;
                sbsec->sid = SECINITSID_UNLABELED;
                return 0;
@@ -2974,7 +2921,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb)
 
 retry:
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -3067,13 +3014,14 @@ err:
 }
 
 
-int security_set_bools(struct selinux_state *state, u32 len, int *values)
+int security_set_bools(u32 len, int *values)
 {
+       struct selinux_state *state = &selinux_state;
        struct selinux_policy *newpolicy, *oldpolicy;
        int rc;
        u32 i, seqno = 0;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return -EINVAL;
 
        oldpolicy = rcu_dereference_protected(state->policy,
@@ -3134,23 +3082,22 @@ int security_set_bools(struct selinux_state *state, u32 len, int *values)
        selinux_policy_cond_free(oldpolicy);
 
        /* Notify others of the policy change */
-       selinux_notify_policy_change(state, seqno);
+       selinux_notify_policy_change(seqno);
        return 0;
 }
 
-int security_get_bool_value(struct selinux_state *state,
-                           u32 index)
+int security_get_bool_value(u32 index)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
        int rc;
        u32 len;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
 
        rc = -EFAULT;
@@ -3197,8 +3144,7 @@ out:
  * security_sid_mls_copy() - computes a new sid based on the given
  * sid and the mls portion of mls_sid.
  */
-int security_sid_mls_copy(struct selinux_state *state,
-                         u32 sid, u32 mls_sid, u32 *new_sid)
+int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
@@ -3210,7 +3156,7 @@ int security_sid_mls_copy(struct selinux_state *state,
        u32 len;
        int rc;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *new_sid = sid;
                return 0;
        }
@@ -3220,7 +3166,7 @@ retry:
        context_init(&newcon);
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -3254,7 +3200,7 @@ retry:
 
        /* Check the validity of the new context. */
        if (!policydb_context_isvalid(policydb, &newcon)) {
-               rc = convert_context_handle_invalid_context(state, policydb,
+               rc = convert_context_handle_invalid_context(policydb,
                                                        &newcon);
                if (rc) {
                        if (!context_struct_to_string(policydb, &newcon, &s,
@@ -3288,7 +3234,6 @@ out_unlock:
 
 /**
  * security_net_peersid_resolve - Compare and resolve two network peer SIDs
- * @state: SELinux state
  * @nlbl_sid: NetLabel SID
  * @nlbl_type: NetLabel labeling protocol type
  * @xfrm_sid: XFRM SID
@@ -3308,8 +3253,7 @@ out_unlock:
  *   multiple, inconsistent labels |    -<errno>     |    SECSID_NULL
  *
  */
-int security_net_peersid_resolve(struct selinux_state *state,
-                                u32 nlbl_sid, u32 nlbl_type,
+int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
                                 u32 xfrm_sid,
                                 u32 *peer_sid)
 {
@@ -3337,11 +3281,11 @@ int security_net_peersid_resolve(struct selinux_state *state,
                return 0;
        }
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -3482,31 +3426,31 @@ err:
        return rc;
 }
 
-int security_get_reject_unknown(struct selinux_state *state)
+int security_get_reject_unknown(void)
 {
        struct selinux_policy *policy;
        int value;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        value = policy->policydb.reject_unknown;
        rcu_read_unlock();
        return value;
 }
 
-int security_get_allow_unknown(struct selinux_state *state)
+int security_get_allow_unknown(void)
 {
        struct selinux_policy *policy;
        int value;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        value = policy->policydb.allow_unknown;
        rcu_read_unlock();
        return value;
@@ -3514,7 +3458,6 @@ int security_get_allow_unknown(struct selinux_state *state)
 
 /**
  * security_policycap_supported - Check for a specific policy capability
- * @state: SELinux state
  * @req_cap: capability
  *
  * Description:
@@ -3523,17 +3466,16 @@ int security_get_allow_unknown(struct selinux_state *state)
  * supported, false (0) if it isn't supported.
  *
  */
-int security_policycap_supported(struct selinux_state *state,
-                                unsigned int req_cap)
+int security_policycap_supported(unsigned int req_cap)
 {
        struct selinux_policy *policy;
        int rc;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        rc = ebitmap_get_bit(&policy->policydb.policycaps, req_cap);
        rcu_read_unlock();
 
@@ -3569,7 +3511,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 
        *rule = NULL;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return -EOPNOTSUPP;
 
        switch (field) {
@@ -3696,7 +3638,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
                return -ENOENT;
        }
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
@@ -3849,7 +3791,6 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
 
 /**
  * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
- * @state: SELinux state
  * @secattr: the NetLabel packet security attributes
  * @sid: the SELinux SID
  *
@@ -3863,8 +3804,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
  * failure.
  *
  */
-int security_netlbl_secattr_to_sid(struct selinux_state *state,
-                                  struct netlbl_lsm_secattr *secattr,
+int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                                   u32 *sid)
 {
        struct selinux_policy *policy;
@@ -3874,7 +3814,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
        struct context *ctx;
        struct context ctx_new;
 
-       if (!selinux_initialized(state)) {
+       if (!selinux_initialized()) {
                *sid = SECSID_NULL;
                return 0;
        }
@@ -3882,7 +3822,7 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state,
 retry:
        rc = 0;
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
        sidtab = policy->sidtab;
 
@@ -3932,7 +3872,6 @@ out:
 
 /**
  * security_netlbl_sid_to_secattr - Convert a SELinux SID to a NetLabel secattr
- * @state: SELinux state
  * @sid: the SELinux SID
  * @secattr: the NetLabel packet security attributes
  *
@@ -3941,19 +3880,18 @@ out:
  * Returns zero on success, negative values on failure.
  *
  */
-int security_netlbl_sid_to_secattr(struct selinux_state *state,
-                                  u32 sid, struct netlbl_lsm_secattr *secattr)
+int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
 {
        struct selinux_policy *policy;
        struct policydb *policydb;
        int rc;
        struct context *ctx;
 
-       if (!selinux_initialized(state))
+       if (!selinux_initialized())
                return 0;
 
        rcu_read_lock();
-       policy = rcu_dereference(state->policy);
+       policy = rcu_dereference(selinux_state.policy);
        policydb = &policy->policydb;
 
        rc = -ENOENT;
@@ -4003,14 +3941,13 @@ static int __security_read_policy(struct selinux_policy *policy,
 
 /**
  * security_read_policy - read the policy.
- * @state: selinux_state
  * @data: binary policy data
  * @len: length of data in bytes
  *
  */
-int security_read_policy(struct selinux_state *state,
-                        void **data, size_t *len)
+int security_read_policy(void **data, size_t *len)
 {
+       struct selinux_state *state = &selinux_state;
        struct selinux_policy *policy;
 
        policy = rcu_dereference_protected(
@@ -4028,7 +3965,6 @@ int security_read_policy(struct selinux_state *state,
 
 /**
  * security_read_state_kernel - read the policy.
- * @state: selinux_state
  * @data: binary policy data
  * @len: length of data in bytes
  *
@@ -4038,10 +3974,10 @@ int security_read_policy(struct selinux_state *state,
  *
  * This function must be called with policy_mutex held.
  */
-int security_read_state_kernel(struct selinux_state *state,
-                              void **data, size_t *len)
+int security_read_state_kernel(void **data, size_t *len)
 {
        int err;
+       struct selinux_state *state = &selinux_state;
        struct selinux_policy *policy;
 
        policy = rcu_dereference_protected(
index c4301626487fc1476828db94e1a40a14de2ae830..8a9b85f44b664b392e2e93504c17ce2f5322f9e4 100644 (file)
@@ -30,7 +30,6 @@ struct selinux_policy {
 } __randomize_layout;
 
 struct convert_context_args {
-       struct selinux_state *state;
        struct policydb *oldp;
        struct policydb *newp;
 };
index 4bc8f809934c84deb6e72ceed8078d7782aa18fd..19ef929a075cb06af660e1b9a35fe3518065ae90 100644 (file)
  * It returns a reference to selinux_status_page. If the status page is
  * not allocated yet, it also tries to allocate it at the first time.
  */
-struct page *selinux_kernel_status_page(struct selinux_state *state)
+struct page *selinux_kernel_status_page(void)
 {
        struct selinux_kernel_status   *status;
        struct page                    *result = NULL;
 
-       mutex_lock(&state->status_lock);
-       if (!state->status_page) {
-               state->status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+       mutex_lock(&selinux_state.status_lock);
+       if (!selinux_state.status_page) {
+               selinux_state.status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
 
-               if (state->status_page) {
-                       status = page_address(state->status_page);
+               if (selinux_state.status_page) {
+                       status = page_address(selinux_state.status_page);
 
                        status->version = SELINUX_KERNEL_STATUS_VERSION;
                        status->sequence = 0;
-                       status->enforcing = enforcing_enabled(state);
+                       status->enforcing = enforcing_enabled();
                        /*
                         * NOTE: the next policyload event shall set
                         * a positive value on the status->policyload,
@@ -62,11 +62,11 @@ struct page *selinux_kernel_status_page(struct selinux_state *state)
                         */
                        status->policyload = 0;
                        status->deny_unknown =
-                               !security_get_allow_unknown(state);
+                               !security_get_allow_unknown();
                }
        }
-       result = state->status_page;
-       mutex_unlock(&state->status_lock);
+       result = selinux_state.status_page;
+       mutex_unlock(&selinux_state.status_lock);
 
        return result;
 }
@@ -76,14 +76,13 @@ struct page *selinux_kernel_status_page(struct selinux_state *state)
  *
  * It updates status of the current enforcing/permissive mode.
  */
-void selinux_status_update_setenforce(struct selinux_state *state,
-                                     int enforcing)
+void selinux_status_update_setenforce(int enforcing)
 {
        struct selinux_kernel_status   *status;
 
-       mutex_lock(&state->status_lock);
-       if (state->status_page) {
-               status = page_address(state->status_page);
+       mutex_lock(&selinux_state.status_lock);
+       if (selinux_state.status_page) {
+               status = page_address(selinux_state.status_page);
 
                status->sequence++;
                smp_wmb();
@@ -93,7 +92,7 @@ void selinux_status_update_setenforce(struct selinux_state *state,
                smp_wmb();
                status->sequence++;
        }
-       mutex_unlock(&state->status_lock);
+       mutex_unlock(&selinux_state.status_lock);
 }
 
 /*
@@ -102,23 +101,22 @@ void selinux_status_update_setenforce(struct selinux_state *state,
  * It updates status of the times of policy reloaded, and current
  * setting of deny_unknown.
  */
-void selinux_status_update_policyload(struct selinux_state *state,
-                                     int seqno)
+void selinux_status_update_policyload(int seqno)
 {
        struct selinux_kernel_status   *status;
 
-       mutex_lock(&state->status_lock);
-       if (state->status_page) {
-               status = page_address(state->status_page);
+       mutex_lock(&selinux_state.status_lock);
+       if (selinux_state.status_page) {
+               status = page_address(selinux_state.status_page);
 
                status->sequence++;
                smp_wmb();
 
                status->policyload = seqno;
-               status->deny_unknown = !security_get_allow_unknown(state);
+               status->deny_unknown = !security_get_allow_unknown();
 
                smp_wmb();
                status->sequence++;
        }
-       mutex_unlock(&state->status_lock);
+       mutex_unlock(&selinux_state.status_lock);
 }
index c576832febc67d63d6a14de2c366553649d113a8..1fca42c4d0ae36c753278c429d25ec6029fdb2d5 100644 (file)
@@ -98,13 +98,12 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
        ctx->ctx_len = str_len;
        memcpy(ctx->ctx_str, &uctx[1], str_len);
        ctx->ctx_str[str_len] = '\0';
-       rc = security_context_to_sid(&selinux_state, ctx->ctx_str, str_len,
+       rc = security_context_to_sid(ctx->ctx_str, str_len,
                                     &ctx->ctx_sid, gfp);
        if (rc)
                goto err;
 
-       rc = avc_has_perm(&selinux_state,
-                         tsec->sid, ctx->ctx_sid,
+       rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
                          SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
        if (rc)
                goto err;
@@ -140,8 +139,7 @@ static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
        if (!ctx)
                return 0;
 
-       return avc_has_perm(&selinux_state,
-                           tsec->sid, ctx->ctx_sid,
+       return avc_has_perm(tsec->sid, ctx->ctx_sid,
                            SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
                            NULL);
 }
@@ -163,8 +161,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid)
        if (!selinux_authorizable_ctx(ctx))
                return -EINVAL;
 
-       rc = avc_has_perm(&selinux_state,
-                         fl_secid, ctx->ctx_sid,
+       rc = avc_has_perm(fl_secid, ctx->ctx_sid,
                          SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
        return (rc == -EACCES ? -ESRCH : rc);
 }
@@ -205,7 +202,7 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
        /* We don't need a separate SA Vs. policy polmatch check since the SA
         * is now of the same label as the flow and a flow Vs. policy polmatch
         * check had already happened in selinux_xfrm_policy_lookup() above. */
-       return (avc_has_perm(&selinux_state, flic_sid, state_sid,
+       return (avc_has_perm(flic_sid, state_sid,
                             SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
                             NULL) ? 0 : 1);
 }
@@ -355,7 +352,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
        if (secid == 0)
                return -EINVAL;
 
-       rc = security_sid_to_context(&selinux_state, secid, &ctx_str,
+       rc = security_sid_to_context(secid, &ctx_str,
                                     &str_len);
        if (rc)
                return rc;
@@ -424,8 +421,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
        /* This check even when there's no association involved is intended,
         * according to Trent Jaeger, to make sure a process can't engage in
         * non-IPsec communication unless explicitly allowed by policy. */
-       return avc_has_perm(&selinux_state,
-                           sk_sid, peer_sid,
+       return avc_has_perm(sk_sid, peer_sid,
                            SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
 }
 
@@ -468,6 +464,6 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
        /* This check even when there's no association involved is intended,
         * according to Trent Jaeger, to make sure a process can't engage in
         * non-IPsec communication unless explicitly allowed by policy. */
-       return avc_has_perm(&selinux_state, sk_sid, SECINITSID_UNLABELED,
+       return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
                            SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
 }
index cfcbb748da2534c24088e5805ec8d1458c228457..7a3e9ab137d85bcf4b0fa11604cb2e095b59dfe3 100644 (file)
@@ -550,23 +550,22 @@ static int smack_sb_alloc_security(struct super_block *sb)
 }
 
 struct smack_mnt_opts {
-       const char *fsdefault, *fsfloor, *fshat, *fsroot, *fstransmute;
+       const char *fsdefault;
+       const char *fsfloor;
+       const char *fshat;
+       const char *fsroot;
+       const char *fstransmute;
 };
 
 static void smack_free_mnt_opts(void *mnt_opts)
 {
-       struct smack_mnt_opts *opts = mnt_opts;
-       kfree(opts->fsdefault);
-       kfree(opts->fsfloor);
-       kfree(opts->fshat);
-       kfree(opts->fsroot);
-       kfree(opts->fstransmute);
-       kfree(opts);
+       kfree(mnt_opts);
 }
 
 static int smack_add_opt(int token, const char *s, void **mnt_opts)
 {
        struct smack_mnt_opts *opts = *mnt_opts;
+       struct smack_known *skp;
 
        if (!opts) {
                opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
@@ -577,31 +576,35 @@ static int smack_add_opt(int token, const char *s, void **mnt_opts)
        if (!s)
                return -ENOMEM;
 
+       skp = smk_import_entry(s, 0);
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
+
        switch (token) {
        case Opt_fsdefault:
                if (opts->fsdefault)
                        goto out_opt_err;
-               opts->fsdefault = s;
+               opts->fsdefault = skp->smk_known;
                break;
        case Opt_fsfloor:
                if (opts->fsfloor)
                        goto out_opt_err;
-               opts->fsfloor = s;
+               opts->fsfloor = skp->smk_known;
                break;
        case Opt_fshat:
                if (opts->fshat)
                        goto out_opt_err;
-               opts->fshat = s;
+               opts->fshat = skp->smk_known;
                break;
        case Opt_fsroot:
                if (opts->fsroot)
                        goto out_opt_err;
-               opts->fsroot = s;
+               opts->fsroot = skp->smk_known;
                break;
        case Opt_fstransmute:
                if (opts->fstransmute)
                        goto out_opt_err;
-               opts->fstransmute = s;
+               opts->fstransmute = skp->smk_known;
                break;
        }
        return 0;
@@ -629,33 +632,14 @@ static int smack_fs_context_dup(struct fs_context *fc,
        fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
        if (!fc->security)
                return -ENOMEM;
+
        dst = fc->security;
+       dst->fsdefault = src->fsdefault;
+       dst->fsfloor = src->fsfloor;
+       dst->fshat = src->fshat;
+       dst->fsroot = src->fsroot;
+       dst->fstransmute = src->fstransmute;
 
-       if (src->fsdefault) {
-               dst->fsdefault = kstrdup(src->fsdefault, GFP_KERNEL);
-               if (!dst->fsdefault)
-                       return -ENOMEM;
-       }
-       if (src->fsfloor) {
-               dst->fsfloor = kstrdup(src->fsfloor, GFP_KERNEL);
-               if (!dst->fsfloor)
-                       return -ENOMEM;
-       }
-       if (src->fshat) {
-               dst->fshat = kstrdup(src->fshat, GFP_KERNEL);
-               if (!dst->fshat)
-                       return -ENOMEM;
-       }
-       if (src->fsroot) {
-               dst->fsroot = kstrdup(src->fsroot, GFP_KERNEL);
-               if (!dst->fsroot)
-                       return -ENOMEM;
-       }
-       if (src->fstransmute) {
-               dst->fstransmute = kstrdup(src->fstransmute, GFP_KERNEL);
-               if (!dst->fstransmute)
-                       return -ENOMEM;
-       }
        return 0;
 }
 
@@ -712,8 +696,8 @@ static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts)
                if (token != Opt_error) {
                        arg = kmemdup_nul(arg, from + len - arg, GFP_KERNEL);
                        rc = smack_add_opt(token, arg, mnt_opts);
+                       kfree(arg);
                        if (unlikely(rc)) {
-                               kfree(arg);
                                if (*mnt_opts)
                                        smack_free_mnt_opts(*mnt_opts);
                                *mnt_opts = NULL;
@@ -1477,7 +1461,7 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap,
        struct socket_smack *ssp;
        struct socket *sock;
        struct super_block *sbp;
-       struct inode *ip = (struct inode *)inode;
+       struct inode *ip = inode;
        struct smack_known *isp;
 
        if (strcmp(name, XATTR_SMACK_SUFFIX) == 0)
@@ -4847,7 +4831,7 @@ static int smack_uring_cmd(struct io_uring_cmd *ioucmd)
 
 #endif /* CONFIG_IO_URING */
 
-struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes smack_blob_sizes __ro_after_init = {
        .lbs_cred = sizeof(struct task_smack),
        .lbs_file = sizeof(struct smack_known *),
        .lbs_inode = sizeof(struct inode_smack),
@@ -4856,7 +4840,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
        .lbs_superblock = sizeof(struct superblock_smack),
 };
 
-static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list smack_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
        LSM_HOOK_INIT(syslog, smack_syslog),
index 7cf8fdbb29bfd8642d437aee1b28b730d8a62654..610c1536cf70ca482b0fecf2db086a04e63a7b40 100644 (file)
@@ -271,7 +271,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
                /* +18 is for " symlink.target=\"%s\"" */
                len += 18 + strlen(symlink);
        }
-       len = tomoyo_round2(len);
+       len = kmalloc_size_roundup(len);
        buf = kzalloc(len, GFP_NOFS);
        if (!buf)
                goto out;
@@ -382,12 +382,12 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
                goto out;
        }
        entry->log = buf;
-       len = tomoyo_round2(strlen(buf) + 1);
+       len = kmalloc_size_roundup(strlen(buf) + 1);
        /*
         * The entry->size is used for memory quota checks.
         * Don't go beyond strlen(entry->log).
         */
-       entry->size = len + tomoyo_round2(sizeof(*entry));
+       entry->size = len + kmalloc_size_roundup(sizeof(*entry));
        spin_lock(&tomoyo_log_lock);
        if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] &&
            tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >=
index f4cd9b58b20547ec29bdfef8a77421b0cb5b596f..969d4aa6fd556f38f09ae7cb573973fd5a209479 100644 (file)
@@ -2094,7 +2094,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
                tomoyo_add_entry(r->domain, entry.query);
                goto out;
        }
-       len = tomoyo_round2(entry.query_len);
+       len = kmalloc_size_roundup(entry.query_len);
        entry.domain = r->domain;
        spin_lock(&tomoyo_query_list_lock);
        if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] &&
index ca285f3627053330c1a39ebfe932cc3f2b88b424..a539b2cbb5c45a036b1a508d132bd0e1ba91c3db 100644 (file)
@@ -1276,50 +1276,6 @@ static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void)
        return tomoyo_domain()->ns;
 }
 
-#if defined(CONFIG_SLOB)
-
-/**
- * tomoyo_round2 - Round up to power of 2 for calculating memory usage.
- *
- * @size: Size to be rounded up.
- *
- * Returns @size.
- *
- * Since SLOB does not round up, this function simply returns @size.
- */
-static inline int tomoyo_round2(size_t size)
-{
-       return size;
-}
-
-#else
-
-/**
- * tomoyo_round2 - Round up to power of 2 for calculating memory usage.
- *
- * @size: Size to be rounded up.
- *
- * Returns rounded size.
- *
- * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of
- * (e.g.) 128 bytes.
- */
-static inline int tomoyo_round2(size_t size)
-{
-#if PAGE_SIZE == 4096
-       size_t bsize = 32;
-#else
-       size_t bsize = 64;
-#endif
-       if (!size)
-               return 0;
-       while (size > bsize)
-               bsize <<= 1;
-       return bsize;
-}
-
-#endif
-
 /**
  * list_for_each_cookie - iterate over a list with cookie.
  * @pos:        the &struct list_head to use as a loop cursor.
index af04a7b7eb28544ca435e2cdc286b1ef6732e3ab..25006fddc964b44174ac1871b497ae18df002881 100644 (file)
@@ -499,7 +499,7 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
        return tomoyo_socket_sendmsg_permission(sock, msg, size);
 }
 
-struct lsm_blob_sizes tomoyo_blob_sizes __lsm_ro_after_init = {
+struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = {
        .lbs_task = sizeof(struct tomoyo_task),
 };
 
@@ -546,7 +546,7 @@ static void tomoyo_task_free(struct task_struct *task)
  * tomoyo_security_ops is a "struct security_operations" which is used for
  * registering TOMOYO.
  */
-static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list tomoyo_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
        LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
        LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
@@ -583,7 +583,7 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
 /* Lock for GC. */
 DEFINE_SRCU(tomoyo_ss);
 
-int tomoyo_enabled __lsm_ro_after_init = 1;
+int tomoyo_enabled __ro_after_init = 1;
 
 /**
  * tomoyo_init - Register TOMOYO Linux as a LSM module.
index 06e226166aab3a7e6d8e544ff3f6db05890f326b..478be269571ab167106032402139e2776a4e71d7 100644 (file)
@@ -421,7 +421,7 @@ static int yama_ptrace_traceme(struct task_struct *parent)
        return rc;
 }
 
-static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
+static struct security_hook_list yama_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
        LSM_HOOK_INIT(task_prctl, yama_task_prctl),
index 8b6aeb8a78f7d3ac2819cda7b2781e1ec5035067..02fd65993e7e52e269b6a7fec59d48d3e5e5fda4 100644 (file)
@@ -2155,6 +2155,8 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream,
                ret = substream->ops->ack(substream);
                if (ret < 0) {
                        runtime->control->appl_ptr = old_appl_ptr;
+                       if (ret == -EPIPE)
+                               __snd_pcm_xrun(substream);
                        return ret;
                }
        }
index 331380c2438bcfa470fe5b48bf35dedbd571d53e..5868661d461bc85c8ad2abfd60e4533fa04cd680 100644 (file)
@@ -3521,6 +3521,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
        unsigned long i;
        void __user **bufs;
        snd_pcm_uframes_t frames;
+       const struct iovec *iov = iter_iov(to);
 
        pcm_file = iocb->ki_filp->private_data;
        substream = pcm_file->substream;
@@ -3530,18 +3531,20 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
        if (runtime->state == SNDRV_PCM_STATE_OPEN ||
            runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
                return -EBADFD;
-       if (!iter_is_iovec(to))
+       if (!to->user_backed)
                return -EINVAL;
        if (to->nr_segs > 1024 || to->nr_segs != runtime->channels)
                return -EINVAL;
-       if (!frame_aligned(runtime, to->iov->iov_len))
+       if (!frame_aligned(runtime, iov->iov_len))
                return -EINVAL;
-       frames = bytes_to_samples(runtime, to->iov->iov_len);
+       frames = bytes_to_samples(runtime, iov->iov_len);
        bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
        if (bufs == NULL)
                return -ENOMEM;
-       for (i = 0; i < to->nr_segs; ++i)
-               bufs[i] = to->iov[i].iov_base;
+       for (i = 0; i < to->nr_segs; ++i) {
+               bufs[i] = iov->iov_base;
+               iov++;
+       }
        result = snd_pcm_lib_readv(substream, bufs, frames);
        if (result > 0)
                result = frames_to_bytes(runtime, result);
@@ -3558,6 +3561,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
        unsigned long i;
        void __user **bufs;
        snd_pcm_uframes_t frames;
+       const struct iovec *iov = iter_iov(from);
 
        pcm_file = iocb->ki_filp->private_data;
        substream = pcm_file->substream;
@@ -3567,17 +3571,19 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
        if (runtime->state == SNDRV_PCM_STATE_OPEN ||
            runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
                return -EBADFD;
-       if (!iter_is_iovec(from))
+       if (!from->user_backed)
                return -EINVAL;
        if (from->nr_segs > 128 || from->nr_segs != runtime->channels ||
-           !frame_aligned(runtime, from->iov->iov_len))
+           !frame_aligned(runtime, iov->iov_len))
                return -EINVAL;
-       frames = bytes_to_samples(runtime, from->iov->iov_len);
+       frames = bytes_to_samples(runtime, iov->iov_len);
        bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
        if (bufs == NULL)
                return -ENOMEM;
-       for (i = 0; i < from->nr_segs; ++i)
-               bufs[i] = from->iov[i].iov_base;
+       for (i = 0; i < from->nr_segs; ++i) {
+               bufs[i] = iov->iov_base;
+               iov++;
+       }
        result = snd_pcm_lib_writev(substream, bufs, frames);
        if (result > 0)
                result = frames_to_bytes(runtime, result);
index 53e094cc411f8676678f424e321f16c66dabeb21..dfe783d01d7d20cb4295625cecc8d5953f3607b3 100644 (file)
@@ -490,7 +490,7 @@ int snd_tscm_stream_start_duplex(struct snd_tscm *tscm, unsigned int rate)
                // packet is important for media clock recovery.
                err = amdtp_domain_start(&tscm->domain, tx_init_skip_cycles, true, true);
                if (err < 0)
-                       return err;
+                       goto error;
 
                if (!amdtp_domain_wait_ready(&tscm->domain, READY_TIMEOUT_MS)) {
                        err = -ETIMEDOUT;
index ae31bb1275940453efb026410e5673d1e53a9d1e..317bdf6dcbef42f0954a7b8e3b757b5c8dcf8185 100644 (file)
@@ -472,6 +472,15 @@ static const struct config_entry config_table[] = {
        },
 #endif
 
+/* Meteor Lake */
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_METEORLAKE)
+       /* Meteorlake-P */
+       {
+               .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+               .device = 0x7e28,
+       },
+#endif
+
 };
 
 static const struct config_entry *snd_intel_dsp_find_config
index 65012af6a36e4f0c3307340de764cb8f426d4bb2..f58b14b490455040a4dd8449cd6768fc990ab421 100644 (file)
@@ -561,10 +561,13 @@ int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active)
        if (snd_BUG_ON(!cs8427))
                return -ENXIO;
        chip = cs8427->private_data;
-       if (active)
+       if (active) {
                memcpy(chip->playback.pcm_status,
                       chip->playback.def_status, 24);
-       chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+               chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       } else {
+               chip->playback.pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+       }
        snd_ctl_notify(cs8427->bus->card,
                       SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
                       &chip->playback.pcm_ctl->id);
index 27e11b5f70b97dc982867df42074fc35142517d3..c7d7eff86727f83672560c87fbf5e62114f67f91 100644 (file)
@@ -430,7 +430,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
                pao = hpi_find_adapter(phm->adapter_index);
        } else {
                /* subsys messages don't address an adapter */
-               _HPI_6205(NULL, phm, phr);
+               phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
                return;
        }
 
index 48af77ae8020f5a5c2ecca1c2bd974cc186f1779..6ec394fb1846845464b5e80158ce401ea4c03fcd 100644 (file)
@@ -1236,7 +1236,7 @@ static int snd_emu10k1_capture_mic_close(struct snd_pcm_substream *substream)
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
 
-       emu->capture_interrupt = NULL;
+       emu->capture_mic_interrupt = NULL;
        emu->pcm_capture_mic_substream = NULL;
        return 0;
 }
@@ -1344,7 +1344,7 @@ static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream)
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
 
-       emu->capture_interrupt = NULL;
+       emu->capture_efx_interrupt = NULL;
        emu->pcm_capture_efx_substream = NULL;
        return 0;
 }
@@ -1781,17 +1781,21 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
        struct snd_kcontrol *kctl;
        int err;
 
-       err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm);
+       err = snd_pcm_new(emu->card, "emu10k1 efx", device, emu->audigy ? 0 : 8, 1, &pcm);
        if (err < 0)
                return err;
 
        pcm->private_data = emu;
 
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
+       if (!emu->audigy)
+               snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
 
        pcm->info_flags = 0;
-       strcpy(pcm->name, "Multichannel Capture/PT Playback");
+       if (emu->audigy)
+               strcpy(pcm->name, "Multichannel Capture");
+       else
+               strcpy(pcm->name, "Multichannel Capture/PT Playback");
        emu->pcm_efx = pcm;
 
        /* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs 
index 81c4a45254ff2e33ee71f2a2a328b144954ff911..77a592f219472d9a472fa33d5e18a4fc6818350d 100644 (file)
@@ -328,14 +328,15 @@ enum {
 #define needs_eld_notify_link(chip)    false
 #endif
 
-#define CONTROLLER_IN_GPU(pci) (((pci)->device == 0x0a0c) || \
+#define CONTROLLER_IN_GPU(pci) (((pci)->vendor == 0x8086) &&         \
+                                      (((pci)->device == 0x0a0c) || \
                                        ((pci)->device == 0x0c0c) || \
                                        ((pci)->device == 0x0d0c) || \
                                        ((pci)->device == 0x160c) || \
                                        ((pci)->device == 0x490d) || \
                                        ((pci)->device == 0x4f90) || \
                                        ((pci)->device == 0x4f91) || \
-                                       ((pci)->device == 0x4f92))
+                                       ((pci)->device == 0x4f92)))
 
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
 
index acde4cd58785e0cbaa8196bbacead97826e822ac..099722ebaed83901df9c23904baa13e2bd9734b3 100644 (file)
@@ -4228,8 +4228,10 @@ static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
 
        for (i = 0; i < TUNING_CTLS_COUNT; i++)
                if (nid == ca0132_tuning_ctls[i].nid)
-                       break;
+                       goto found;
 
+       return -EINVAL;
+found:
        snd_hda_power_up(codec);
        dspio_set_param(codec, ca0132_tuning_ctls[i].mid, 0x20,
                        ca0132_tuning_ctls[i].req,
index 75e1d00074b9fa29465e65bf09f6fcd823ca082e..a889cccdd607cff8848892ba8505724c0a94687b 100644 (file)
@@ -980,7 +980,10 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
-       SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_PINCFG_LENOVO_NOTEBOOK),
+       /* NOTE: we'd need to extend the quirk for 17aa:3977 as the same
+        * PCI SSID is used on multiple Lenovo models
+        */
+       SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI),
@@ -1003,6 +1006,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
        { .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" },
        { .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" },
        { .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" },
+       { .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" },
        {}
 };
 
index 9ea633fe93393531e5df51912c39a9b04528b458..5c6980394dcec2e2d92730e0cbb54eb7b73f2277 100644 (file)
@@ -81,6 +81,7 @@ struct hdmi_spec_per_pin {
        struct delayed_work work;
        struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/
        int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */
+       int prev_pcm_idx; /* previously assigned pcm index */
        int repoll_count;
        bool setup; /* the stream has been set up by prepare callback */
        bool silent_stream;
@@ -1380,9 +1381,17 @@ static void hdmi_attach_hda_pcm(struct hdmi_spec *spec,
        /* pcm already be attached to the pin */
        if (per_pin->pcm)
                return;
+       /* try the previously used slot at first */
+       idx = per_pin->prev_pcm_idx;
+       if (idx >= 0) {
+               if (!test_bit(idx, &spec->pcm_bitmap))
+                       goto found;
+               per_pin->prev_pcm_idx = -1; /* no longer valid, clear it */
+       }
        idx = hdmi_find_pcm_slot(spec, per_pin);
        if (idx == -EBUSY)
                return;
+ found:
        per_pin->pcm_idx = idx;
        per_pin->pcm = get_hdmi_pcm(spec, idx);
        set_bit(idx, &spec->pcm_bitmap);
@@ -1398,6 +1407,7 @@ static void hdmi_detach_hda_pcm(struct hdmi_spec *spec,
                return;
        idx = per_pin->pcm_idx;
        per_pin->pcm_idx = -1;
+       per_pin->prev_pcm_idx = idx; /* remember the previous index */
        per_pin->pcm = NULL;
        if (idx >= 0 && idx < spec->pcm_used)
                clear_bit(idx, &spec->pcm_bitmap);
@@ -1924,6 +1934,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
 
                per_pin->pcm = NULL;
                per_pin->pcm_idx = -1;
+               per_pin->prev_pcm_idx = -1;
                per_pin->pin_nid = pin_nid;
                per_pin->pin_nid_idx = spec->num_nids;
                per_pin->dev_id = i;
@@ -4593,7 +4604,7 @@ HDA_CODEC_ENTRY(0x80862814, "DG1 HDMI",   patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862815, "Alderlake HDMI",  patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862816, "Rocketlake HDMI", patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x80862818, "Raptorlake HDMI", patch_i915_tgl_hdmi),
-HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI",        patch_i915_adlp_hdmi),
+HDA_CODEC_ENTRY(0x80862819, "DG2 HDMI",        patch_i915_tgl_hdmi),
 HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x8086281b, "Elkhartlake HDMI",        patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x8086281c, "Alderlake-P HDMI", patch_i915_adlp_hdmi),
index 3c629f4ae08076c966f45e952a4b4ede60368570..f70d6a33421d2efce7d7c86b0c7f78364c75c254 100644 (file)
@@ -2624,6 +2624,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+       SND_PCI_QUIRK(0x1558, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
@@ -2631,6 +2632,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x65e5, "Clevo PC50D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+       SND_PCI_QUIRK(0x1558, 0x66a2, "Clevo PE60RNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
@@ -2651,6 +2653,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0xd502, "Clevo PD50SNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
@@ -6957,6 +6960,8 @@ enum {
        ALC269_FIXUP_DELL_M101Z,
        ALC269_FIXUP_SKU_IGNORE,
        ALC269_FIXUP_ASUS_G73JW,
+       ALC269_FIXUP_ASUS_N7601ZM_PINS,
+       ALC269_FIXUP_ASUS_N7601ZM,
        ALC269_FIXUP_LENOVO_EAPD,
        ALC275_FIXUP_SONY_HWEQ,
        ALC275_FIXUP_SONY_DISABLE_AAMIX,
@@ -7253,6 +7258,29 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                }
        },
+       [ALC269_FIXUP_ASUS_N7601ZM_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x03A11050 },
+                       { 0x1a, 0x03A11C30 },
+                       { 0x21, 0x03211420 },
+                       { }
+               }
+       },
+       [ALC269_FIXUP_ASUS_N7601ZM] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x20, AC_VERB_SET_COEF_INDEX, 0x62},
+                       {0x20, AC_VERB_SET_PROC_COEF, 0xa007},
+                       {0x20, AC_VERB_SET_COEF_INDEX, 0x10},
+                       {0x20, AC_VERB_SET_PROC_COEF, 0x8420},
+                       {0x20, AC_VERB_SET_COEF_INDEX, 0x0f},
+                       {0x20, AC_VERB_SET_PROC_COEF, 0x7774},
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_ASUS_N7601ZM_PINS,
+       },
        [ALC269_FIXUP_LENOVO_EAPD] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -9260,7 +9288,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0a62, "Dell Precision 5560", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x0ac9, "Dell Precision 3260", ALC295_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
        SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
@@ -9441,12 +9468,15 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8b47, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8b65, "HP ProBook 455 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8b66, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
        SND_PCI_QUIRK(0x103c, 0x8b7a, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b7d, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b87, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b8a, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b8b, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b8d, "HP", ALC236_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8b8f, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
@@ -9461,6 +9491,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1043, 0x12a3, "Asus N7691ZM", ALC269_FIXUP_ASUS_N7601ZM),
        SND_PCI_QUIRK(0x1043, 0x12af, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2),
        SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC),
@@ -9539,6 +9570,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
        SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
        SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
@@ -9573,6 +9605,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -9607,6 +9640,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL5[03]RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL50NU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -9655,6 +9689,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@@ -9707,6 +9744,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x511e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
+       SND_PCI_QUIRK(0x17aa, 0x9e56, "Lenovo ZhaoYang CF4620Z", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK),
        SND_PCI_QUIRK(0x1849, 0xa233, "Positivo Master C6300", ALC269_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS),
index a794a01a68ca60e55bcd0ab653a0db3e6c3ffcc5..61258b0aac8d65a51206c2fd4f269e197003eec5 100644 (file)
@@ -1707,6 +1707,7 @@ static const struct snd_pci_quirk stac925x_fixup_tbl[] = {
 };
 
 static const struct hda_pintbl ref92hd73xx_pin_configs[] = {
+       // Port A-H
        { 0x0a, 0x02214030 },
        { 0x0b, 0x02a19040 },
        { 0x0c, 0x01a19020 },
@@ -1715,9 +1716,12 @@ static const struct hda_pintbl ref92hd73xx_pin_configs[] = {
        { 0x0f, 0x01014010 },
        { 0x10, 0x01014020 },
        { 0x11, 0x01014030 },
+       // CD in
        { 0x12, 0x02319040 },
+       // Digial Mic ins
        { 0x13, 0x90a000f0 },
        { 0x14, 0x90a000f0 },
+       // Digital outs
        { 0x22, 0x01452050 },
        { 0x23, 0x01452050 },
        {}
@@ -1758,6 +1762,7 @@ static const struct hda_pintbl alienware_m17x_pin_configs[] = {
 };
 
 static const struct hda_pintbl intel_dg45id_pin_configs[] = {
+       // Analog outputs
        { 0x0a, 0x02214230 },
        { 0x0b, 0x02A19240 },
        { 0x0c, 0x01013214 },
@@ -1765,6 +1770,9 @@ static const struct hda_pintbl intel_dg45id_pin_configs[] = {
        { 0x0e, 0x01A19250 },
        { 0x0f, 0x01011212 },
        { 0x10, 0x01016211 },
+       // Digital output
+       { 0x22, 0x01451380 },
+       { 0x23, 0x40f000f0 },
        {}
 };
 
@@ -1955,6 +1963,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
                                "DFI LanParty", STAC_92HD73XX_REF),
        SND_PCI_QUIRK(PCI_VENDOR_ID_DFI, 0x3101,
                                "DFI LanParty", STAC_92HD73XX_REF),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5001,
+                               "Intel DP45SG", STAC_92HD73XX_INTEL),
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5002,
                                "Intel DG45ID", STAC_92HD73XX_INTEL),
        SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5003,
index 1e198e4d57b8d53ac29ec472fb0098aba5481ff3..82d4e0fda91be6a0bfac709c780405d47277afd8 100644 (file)
@@ -170,7 +170,7 @@ static int snd_card_ymfpci_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+       err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
                           sizeof(*chip), &card);
        if (err < 0)
                return err;
index c80114c0ad7bf051ecdd872f37885159d7c46301..b492c32ce07049aaff4c941be5fef2f76cd9bdb8 100644 (file)
@@ -2165,7 +2165,7 @@ static int snd_ymfpci_memalloc(struct snd_ymfpci *chip)
        chip->work_base = ptr;
        chip->work_base_addr = ptr_addr;
        
-       snd_BUG_ON(ptr + chip->work_size !=
+       snd_BUG_ON(ptr + PAGE_ALIGN(chip->work_size) !=
                   chip->work_ptr->area + chip->work_ptr->bytes);
 
        snd_ymfpci_writel(chip, YDSXGR_PLAYCTRLBASE, chip->bank_base_playback_addr);
index 4a69ce702360c547e3fc904b1a15d6823227d0c2..0acdf0156f075d02a701868ce67690990302e452 100644 (file)
@@ -269,6 +269,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "8A43"),
                }
        },
+       {
+               .driver_data = &acp6x_card,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+                       DMI_MATCH(DMI_BOARD_NAME, "8A22"),
+               }
+       },
        {}
 };
 
index 0068780fe0a745f423832971427b10c0617d4133..1c1f211a8e2e7aa28ab29f20f035bd100ea4b475 100644 (file)
@@ -2022,6 +2022,11 @@ static int da7213_i2c_probe(struct i2c_client *i2c)
        return ret;
 }
 
+static void da7213_i2c_remove(struct i2c_client *i2c)
+{
+       pm_runtime_disable(&i2c->dev);
+}
+
 static int __maybe_unused da7213_runtime_suspend(struct device *dev)
 {
        struct da7213_priv *da7213 = dev_get_drvdata(dev);
@@ -2065,6 +2070,7 @@ static struct i2c_driver da7213_i2c_driver = {
                .pm = &da7213_pm,
        },
        .probe_new      = da7213_i2c_probe,
+       .remove         = da7213_i2c_remove,
        .id_table       = da7213_i2c_id,
 };
 
index 4a4f09f924bc510ff54fff1cf02a008bca82d982..e3d398b8f54e4f0cd343e2bc56d5cf9295073eae 100644 (file)
@@ -968,6 +968,8 @@ int da7219_aad_init(struct snd_soc_component *component)
        INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
        INIT_WORK(&da7219_aad->jack_det_work, da7219_aad_jack_det_work);
 
+       mutex_init(&da7219_aad->jack_det_mutex);
+
        ret = request_threaded_irq(da7219_aad->irq, da7219_aad_pre_irq_thread,
                                   da7219_aad_irq_thread,
                                   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
index ed4f7cdda04ffe37f8e03c5fa091dd5a6e0e78aa..8b6b7602969488cd1511d6b05b68416c28833f7e 100644 (file)
@@ -436,23 +436,28 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_device *hdev,
        return 0;
 }
 
-static int hdac_hdmi_set_tdm_slot(struct snd_soc_dai *dai,
-               unsigned int tx_mask, unsigned int rx_mask,
-               int slots, int slot_width)
+static int hdac_hdmi_set_stream(struct snd_soc_dai *dai,
+                               void *stream, int direction)
 {
        struct hdac_hdmi_priv *hdmi = snd_soc_dai_get_drvdata(dai);
        struct hdac_device *hdev = hdmi->hdev;
        struct hdac_hdmi_dai_port_map *dai_map;
        struct hdac_hdmi_pcm *pcm;
+       struct hdac_stream *hstream;
 
-       dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, tx_mask);
+       if (!stream)
+               return -EINVAL;
+
+       hstream = (struct hdac_stream *)stream;
+
+       dev_dbg(&hdev->dev, "%s: strm_tag: %d\n", __func__, hstream->stream_tag);
 
        dai_map = &hdmi->dai_map[dai->id];
 
        pcm = hdac_hdmi_get_pcm_from_cvt(hdmi, dai_map->cvt);
 
        if (pcm)
-               pcm->stream_tag = (tx_mask << 4);
+               pcm->stream_tag = (hstream->stream_tag << 4);
 
        return 0;
 }
@@ -1544,7 +1549,7 @@ static const struct snd_soc_dai_ops hdmi_dai_ops = {
        .startup = hdac_hdmi_pcm_open,
        .shutdown = hdac_hdmi_pcm_close,
        .hw_params = hdac_hdmi_set_hw_params,
-       .set_tdm_slot = hdac_hdmi_set_tdm_slot,
+       .set_stream = hdac_hdmi_set_stream,
 };
 
 /*
index 01e8ffda2a4bf37655fc38b1b07fee22b14be197..6d980fbc4207780ccc966df8378f70cf554f4cd4 100644 (file)
@@ -428,8 +428,13 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream,
 {
        struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
        bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       bool has_capture = !hcp->hcd.no_i2s_capture;
+       bool has_playback = !hcp->hcd.no_i2s_playback;
        int ret = 0;
 
+       if (!((has_playback && tx) || (has_capture && !tx)))
+               return 0;
+
        mutex_lock(&hcp->lock);
        if (hcp->busy) {
                dev_err(dai->dev, "Only one simultaneous stream supported!\n");
@@ -468,6 +473,12 @@ static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *dai)
 {
        struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);
+       bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       bool has_capture = !hcp->hcd.no_i2s_capture;
+       bool has_playback = !hcp->hcd.no_i2s_playback;
+
+       if (!((has_playback && tx) || (has_capture && !tx)))
+               return;
 
        hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;
        hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);
index a73a7d7a1c0a853915c8d70466f5f160fd33928f..faba4237bd3da84050326b98de2f9682e79c5571 100644 (file)
@@ -3670,9 +3670,9 @@ static int __maybe_unused rx_macro_runtime_suspend(struct device *dev)
        regcache_cache_only(rx->regmap, true);
        regcache_mark_dirty(rx->regmap);
 
-       clk_disable_unprepare(rx->mclk);
-       clk_disable_unprepare(rx->npl);
        clk_disable_unprepare(rx->fsgen);
+       clk_disable_unprepare(rx->npl);
+       clk_disable_unprepare(rx->mclk);
 
        return 0;
 }
index bf27bdd5be2067a867c0ea48bda09a1372ab6a94..589c490a8c48798fd0d9365bcc54eb135eb63728 100644 (file)
@@ -242,7 +242,7 @@ enum {
 
 struct tx_mute_work {
        struct tx_macro *tx;
-       u32 decimator;
+       u8 decimator;
        struct delayed_work dwork;
 };
 
@@ -635,7 +635,7 @@ exit:
        return 0;
 }
 
-static bool is_amic_enabled(struct snd_soc_component *component, int decimator)
+static bool is_amic_enabled(struct snd_soc_component *component, u8 decimator)
 {
        u16 adc_mux_reg, adc_reg, adc_n;
 
@@ -849,7 +849,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
                               struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-       unsigned int decimator;
+       u8 decimator;
        u16 tx_vol_ctl_reg, dec_cfg_reg, hpf_gate_reg, tx_gain_ctl_reg;
        u8 hpf_cut_off_freq;
        int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
@@ -1064,7 +1064,8 @@ static int tx_macro_hw_params(struct snd_pcm_substream *substream,
                              struct snd_soc_dai *dai)
 {
        struct snd_soc_component *component = dai->component;
-       u32 decimator, sample_rate;
+       u32 sample_rate;
+       u8 decimator;
        int tx_fs_rate;
        struct tx_macro *tx = snd_soc_component_get_drvdata(component);
 
@@ -1128,7 +1129,7 @@ static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
 {
        struct snd_soc_component *component = dai->component;
        struct tx_macro *tx = snd_soc_component_get_drvdata(component);
-       u16 decimator;
+       u8 decimator;
 
        /* active decimator not set yet */
        if (tx->active_decimator[dai->id] == -1)
@@ -2097,9 +2098,9 @@ static int __maybe_unused tx_macro_runtime_suspend(struct device *dev)
        regcache_cache_only(tx->regmap, true);
        regcache_mark_dirty(tx->regmap);
 
-       clk_disable_unprepare(tx->mclk);
-       clk_disable_unprepare(tx->npl);
        clk_disable_unprepare(tx->fsgen);
+       clk_disable_unprepare(tx->npl);
+       clk_disable_unprepare(tx->mclk);
 
        return 0;
 }
index ba7480f3831e2cc7e86734802a1ef4f61f7c0b36..3f6f1bdd4e030af22bc363c38933c3f60affc23e 100644 (file)
@@ -2506,9 +2506,9 @@ static int __maybe_unused wsa_macro_runtime_suspend(struct device *dev)
        regcache_cache_only(wsa->regmap, true);
        regcache_mark_dirty(wsa->regmap);
 
-       clk_disable_unprepare(wsa->mclk);
-       clk_disable_unprepare(wsa->npl);
        clk_disable_unprepare(wsa->fsgen);
+       clk_disable_unprepare(wsa->npl);
+       clk_disable_unprepare(wsa->mclk);
 
        return 0;
 }
index f90a6a7ba83b8cb122a8192c197f6e4d57788dc6..fde055c6c89466b361b441814c70ec9a89ee8653 100644 (file)
@@ -31,7 +31,7 @@ static int max98373_dac_event(struct snd_soc_dapm_widget *w,
                        MAX98373_GLOBAL_EN_MASK, 1);
                usleep_range(30000, 31000);
                break;
-       case SND_SOC_DAPM_POST_PMD:
+       case SND_SOC_DAPM_PRE_PMD:
                regmap_update_bits(max98373->regmap,
                        MAX98373_R20FF_GLOBAL_SHDN,
                        MAX98373_GLOBAL_EN_MASK, 0);
@@ -64,7 +64,7 @@ static const struct snd_kcontrol_new max98373_spkfb_control =
 static const struct snd_soc_dapm_widget max98373_dapm_widgets[] = {
 SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback",
        MAX98373_R202B_PCM_RX_EN, 0, 0, max98373_dac_event,
-       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0,
        &max98373_dai_controls),
 SND_SOC_DAPM_OUTPUT("BE_OUT"),
index 614eceda6b9e3181b184beb16eb3c0c5612f787f..33b67db8794e367b5a0d4e7e5d603b8a1f48bb2a 100644 (file)
@@ -294,6 +294,10 @@ config SND_SOC_IMX_SGTL5000
          Say Y if you want to add support for SoC audio on an i.MX board with
          a sgtl5000 codec.
 
+         Note that this is an old driver. Consider enabling
+         SND_SOC_FSL_ASOC_CARD and SND_SOC_SGTL5000 to use the newer
+         driver.
+
 config SND_SOC_IMX_SPDIF
        tristate "SoC Audio support for i.MX boards with S/PDIF"
        select SND_SOC_IMX_PCM_DMA
index 3b81a465814a1f777ed0820a853fbd93eceaf018..05a7d1588d204b60a3f41abd9982a20a5527f996 100644 (file)
@@ -209,14 +209,19 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
                be_chan = soc_component_to_pcm(component_be)->chan[substream->stream];
                tmp_chan = be_chan;
        }
-       if (!tmp_chan)
-               tmp_chan = dma_request_slave_channel(dev_be, tx ? "tx" : "rx");
+       if (!tmp_chan) {
+               tmp_chan = dma_request_chan(dev_be, tx ? "tx" : "rx");
+               if (IS_ERR(tmp_chan)) {
+                       dev_err(dev, "failed to request DMA channel for Back-End\n");
+                       return -EINVAL;
+               }
+       }
 
        /*
         * An EDMA DEV_TO_DEV channel is fixed and bound with DMA event of each
         * peripheral, unlike SDMA channel that is allocated dynamically. So no
         * need to configure dma_request and dma_request2, but get dma_chan of
-        * Back-End device directly via dma_request_slave_channel.
+        * Back-End device directly via dma_request_chan.
         */
        if (!asrc->use_edma) {
                /* Get DMA request of Back-End */
index 1b197478b3d90eda6d348852339c6eabdacdb1b5..990bba0be1fb1cb2b8edae47ce9347f27250a6e9 100644 (file)
@@ -1546,7 +1546,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = {
        .use_imx_pcm = true,
        .use_edma = true,
        .fifo_depth = 64,
-       .pins = 1,
+       .pins = 4,
        .reg_offset = 0,
        .mclk0_is_mclk1 = false,
        .flags = 0,
index acd43b6108e9979a7b881a4c8a19c87bb43a76fc..1a1d572cc1d028626bf7a68e950883b0ddb67062 100644 (file)
@@ -117,6 +117,26 @@ static void avs_da7219_codec_exit(struct snd_soc_pcm_runtime *rtd)
        snd_soc_component_set_jack(asoc_rtd_to_codec(rtd, 0)->component, NULL, NULL);
 }
 
+static int
+avs_da7219_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *rate, *channels;
+       struct snd_mask *fmt;
+
+       rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+       channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+       fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+       /* The ADSP will convert the FE rate to 48k, stereo */
+       rate->min = rate->max = 48000;
+       channels->min = channels->max = 2;
+
+       /* set SSP0 to 24 bit */
+       snd_mask_none(fmt);
+       snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
+       return 0;
+}
+
 static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
                               struct snd_soc_dai_link **dai_link)
 {
@@ -148,6 +168,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
        dl->num_platforms = 1;
        dl->id = 0;
        dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS;
+       dl->be_hw_params_fixup = avs_da7219_be_fixup;
        dl->init = avs_da7219_codec_init;
        dl->exit = avs_da7219_codec_exit;
        dl->nonatomic = 1;
index 921f42caf7e09d0547a69e8aa460ec5cf3181d9f..183123d08c5a3b4e39f693d7ab13f14c49b96434 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/soc-acpi.h>
 #include <sound/soc-dapm.h>
@@ -24,6 +25,26 @@ static const struct snd_soc_dapm_route card_base_routes[] = {
        { "Spk", NULL, "Speaker" },
 };
 
+static int
+avs_max98357a_be_fixup(struct snd_soc_pcm_runtime *runrime, struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *rate, *channels;
+       struct snd_mask *fmt;
+
+       rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+       channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+       fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+       /* The ADSP will convert the FE rate to 48k, stereo */
+       rate->min = rate->max = 48000;
+       channels->min = channels->max = 2;
+
+       /* set SSP0 to 16 bit */
+       snd_mask_none(fmt);
+       snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE);
+       return 0;
+}
+
 static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
                               struct snd_soc_dai_link **dai_link)
 {
@@ -55,6 +76,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
        dl->num_platforms = 1;
        dl->id = 0;
        dl->dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS;
+       dl->be_hw_params_fixup = avs_max98357a_be_fixup;
        dl->nonatomic = 1;
        dl->no_pcm = 1;
        dl->dpcm_playback = 1;
index b31fa931ba8b6a848406e391ee3d28ddcf4f960e..b69fc5567135d5330c7a4cc75c0bf2e037ea043d 100644 (file)
@@ -33,15 +33,15 @@ avs_nau8825_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *co
                return -EINVAL;
        }
 
-       if (!SND_SOC_DAPM_EVENT_ON(event)) {
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000,
+                                            SND_SOC_CLOCK_IN);
+       else
                ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN);
-               if (ret < 0) {
-                       dev_err(card->dev, "set sysclk err = %d\n", ret);
-                       return ret;
-               }
-       }
+       if (ret < 0)
+               dev_err(card->dev, "Set sysclk failed: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 static const struct snd_kcontrol_new card_controls[] = {
index 473e9fe5d0bf746ae4c3446d4a9ab23f007bf838..b2c2ba93dcb5606b1d5febad49a1420614b44334 100644 (file)
@@ -169,6 +169,27 @@ static const struct snd_soc_ops avs_rt5682_ops = {
        .hw_params = avs_rt5682_hw_params,
 };
 
+static int
+avs_rt5682_be_fixup(struct snd_soc_pcm_runtime *runtime, struct snd_pcm_hw_params *params)
+{
+       struct snd_interval *rate, *channels;
+       struct snd_mask *fmt;
+
+       rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+       channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+       fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+
+       /* The ADSP will convert the FE rate to 48k, stereo */
+       rate->min = rate->max = 48000;
+       channels->min = channels->max = 2;
+
+       /* set SSPN to 24 bit */
+       snd_mask_none(fmt);
+       snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
+
+       return 0;
+}
+
 static int avs_create_dai_link(struct device *dev, const char *platform_name, int ssp_port,
                               struct snd_soc_dai_link **dai_link)
 {
@@ -201,6 +222,7 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
        dl->id = 0;
        dl->init = avs_rt5682_codec_init;
        dl->exit = avs_rt5682_codec_exit;
+       dl->be_hw_params_fixup = avs_rt5682_be_fixup;
        dl->ops = &avs_rt5682_ops;
        dl->nonatomic = 1;
        dl->no_pcm = 1;
index c5db6961276240c0d90d6a08c7189aa8bd153a18..2b7f5ad92aca7b885ba0686f829fe9262067f6da 100644 (file)
@@ -15,7 +15,6 @@
 #include <sound/soc-acpi.h>
 #include "../../../codecs/nau8825.h"
 
-#define SKL_NUVOTON_CODEC_DAI  "nau8825-hifi"
 #define SKL_SSM_CODEC_DAI      "ssm4567-hifi"
 
 static struct snd_soc_codec_conf card_codec_conf[] = {
@@ -34,41 +33,11 @@ static const struct snd_kcontrol_new card_controls[] = {
        SOC_DAPM_PIN_SWITCH("Right Speaker"),
 };
 
-static int
-platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *control, int event)
-{
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct snd_soc_card *card = dapm->card;
-       struct snd_soc_dai *codec_dai;
-       int ret;
-
-       codec_dai = snd_soc_card_get_codec_dai(card, SKL_NUVOTON_CODEC_DAI);
-       if (!codec_dai) {
-               dev_err(card->dev, "Codec dai not found\n");
-               return -EINVAL;
-       }
-
-       if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_MCLK, 24000000,
-                                            SND_SOC_CLOCK_IN);
-               if (ret < 0)
-                       dev_err(card->dev, "set sysclk err = %d\n", ret);
-       } else {
-               ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_INTERNAL, 0, SND_SOC_CLOCK_IN);
-               if (ret < 0)
-                       dev_err(card->dev, "set sysclk err = %d\n", ret);
-       }
-
-       return ret;
-}
-
 static const struct snd_soc_dapm_widget card_widgets[] = {
        SND_SOC_DAPM_SPK("Left Speaker", NULL),
        SND_SOC_DAPM_SPK("Right Speaker", NULL),
        SND_SOC_DAPM_SPK("DP1", NULL),
        SND_SOC_DAPM_SPK("DP2", NULL),
-       SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control,
-                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route card_base_routes[] = {
index 79e0039c79a388f911d90f71f5025aa8a6bf452b..5a12940ef9070819f693e00cb0c338088f439aad 100644 (file)
@@ -533,6 +533,18 @@ static int byt_rt5640_aif1_hw_params(struct snd_pcm_substream *substream,
 
 /* Please keep this list alphabetically sorted */
 static const struct dmi_system_id byt_rt5640_quirk_table[] = {
+       {       /* Acer Iconia One 7 B1-750 */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "VESPA2"),
+               },
+               .driver_data = (void *)(BYT_RT5640_DMIC1_MAP |
+                                       BYT_RT5640_JD_SRC_JD1_IN4P |
+                                       BYT_RT5640_OVCD_TH_1500UA |
+                                       BYT_RT5640_OVCD_SF_0P75 |
+                                       BYT_RT5640_SSP0_AIF1 |
+                                       BYT_RT5640_MCLK_EN),
+       },
        {       /* Acer Iconia Tab 8 W1-810 */
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
index d2ed807abde9590b1968aaf9d1b2c90803ae5b3c..767fa89d08708519d32027540b7d289771532527 100644 (file)
@@ -213,6 +213,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
                                        SOF_SDW_PCH_DMIC |
                                        RT711_JD1),
        },
+       {
+               /* NUC15 'Rooks County' LAPRC510 and LAPRC710 skews */
+               .callback = sof_sdw_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Intel(R) Client Systems"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LAPRC"),
+               },
+               .driver_data = (void *)(SOF_SDW_TGL_HDMI |
+                                       SOF_SDW_PCH_DMIC |
+                                       RT711_JD2_100K),
+       },
        /* TigerLake-SDCA devices */
        {
                .callback = sof_sdw_quirk_cb,
index 56ee5fef66a8be93b1eafdb210b698d9aa0c1ec8..d8c80041388a7346e76499ea687a661f68a3f70c 100644 (file)
@@ -354,6 +354,20 @@ static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link3[] = {
        {}
 };
 
+static const struct snd_soc_acpi_link_adr adl_sdw_rt711_link0_rt1316_link2[] = {
+       {
+               .mask = BIT(0),
+               .num_adr = ARRAY_SIZE(rt711_sdca_0_adr),
+               .adr_d = rt711_sdca_0_adr,
+       },
+       {
+               .mask = BIT(2),
+               .num_adr = ARRAY_SIZE(rt1316_2_single_adr),
+               .adr_d = rt1316_2_single_adr,
+       },
+       {}
+};
+
 static const struct snd_soc_acpi_adr_device mx8373_2_adr[] = {
        {
                .adr = 0x000223019F837300ull,
@@ -559,7 +573,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
        {
                .comp_ids = &essx_83x6,
                .drv_name = "sof-essx8336",
-               .sof_tplg_filename = "sof-adl-es83x6", /* the tplg suffix is added at run time */
+               .sof_tplg_filename = "sof-adl-es8336", /* the tplg suffix is added at run time */
                .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
                                        SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
                                        SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
@@ -624,6 +638,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = {
                .drv_name = "sof_sdw",
                .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l3.tplg",
        },
+       {
+               .link_mask = 0x5, /* 2 active links required */
+               .links = adl_sdw_rt711_link0_rt1316_link2,
+               .drv_name = "sof_sdw",
+               .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l2.tplg",
+       },
        {
                .link_mask = 0x1, /* link0 required */
                .links = adl_rvp,
index 3aa63aac4a68e28540b06e5af4ca4ed151407a2a..81554d20265897e319fc3cf34d9191960c2bbe51 100644 (file)
@@ -184,9 +184,9 @@ int q6prm_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, int clk_
                          unsigned int freq)
 {
        if (freq)
-               return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq);
+               return q6prm_request_lpass_clock(dev, clk_id, clk_attr, clk_root, freq);
 
-       return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_attr, freq);
+       return q6prm_release_lpass_clock(dev, clk_id, clk_attr, clk_root, freq);
 }
 EXPORT_SYMBOL_GPL(q6prm_set_lpass_clock);
 
index 5eb056b942ce8d6c1d95a9ee49c27be5d8bae8d0..7958c9defd4922fe8a337008f09ae00e0ff9b8ae 100644 (file)
@@ -1661,10 +1661,14 @@ static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream)
        struct snd_pcm_hardware *hw = &runtime->hw;
        struct snd_soc_dai *dai;
        int stream = substream->stream;
+       u64 formats = hw->formats;
        int i;
 
        soc_pcm_hw_init(hw);
 
+       if (formats)
+               hw->formats &= formats;
+
        for_each_rtd_cpu_dais(fe, i, dai) {
                struct snd_soc_pcm_stream *cpu_stream;
 
index 3aea36c077c9d2262e36b2eb1d9a7c23181c1712..f3bdeba2841221f8b205109db46d53ab04a112f1 100644 (file)
@@ -196,12 +196,15 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)
                goto err;
        }
 
+       usleep_range(500, 1000);
+
        /* exit HDA controller reset */
        ret = hda_dsp_ctrl_link_reset(sdev, false);
        if (ret < 0) {
                dev_err(sdev->dev, "error: failed to exit HDA controller reset\n");
                goto err;
        }
+       usleep_range(1000, 1200);
 
        hda_codec_detect_mask(sdev);
 
index 68eb06f13a1fd2539bab66cf9c255d860e059caf..a6f2822401e03da1d3553f50fa4370955219f6e2 100644 (file)
@@ -392,6 +392,12 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
        snd_sof_dsp_update8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset,
                            SOF_HDA_VS_D0I3C_I3, value);
 
+       /*
+        * The value written to the D0I3C::I3 bit may not be taken into account immediately.
+        * A delay is recommended before checking if D0I3C::CIP is cleared
+        */
+       usleep_range(30, 40);
+
        /* Wait for cmd in progress to be cleared before exiting the function */
        ret = hda_dsp_wait_d0i3c_done(sdev);
        if (ret < 0) {
@@ -400,6 +406,12 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
        }
 
        reg = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, chip->d0i3_offset);
+       /* Confirm d0i3 state changed with paranoia check */
+       if ((reg ^ value) & SOF_HDA_VS_D0I3C_I3) {
+               dev_err(sdev->dev, "failed to update D0I3C!\n");
+               return -EIO;
+       }
+
        trace_sof_intel_D0I3C_updated(sdev, reg);
 
        return 0;
index 69279dcc92dc136630fed5a7ab3860a9f5540091..aff6cb573c270f9a4cf387c400a6c85c94757031 100644 (file)
@@ -78,6 +78,7 @@ static const struct sof_dev_desc glk_desc = {
        .nocodec_tplg_filename = "sof-glk-nocodec.tplg",
        .ops = &sof_apl_ops,
        .ops_init = sof_apl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 /* PCI IDs */
index 8db3f8d15b55e9f6f708b91a9f11b5fe136ca774..4c0c1c369dcd8a8ffb1fec3d9de2360730e9f0f2 100644 (file)
@@ -48,6 +48,7 @@ static const struct sof_dev_desc cnl_desc = {
        .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
        .ops = &sof_cnl_ops,
        .ops_init = sof_cnl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc cfl_desc = {
@@ -111,6 +112,7 @@ static const struct sof_dev_desc cml_desc = {
        .nocodec_tplg_filename = "sof-cnl-nocodec.tplg",
        .ops = &sof_cnl_ops,
        .ops_init = sof_cnl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 /* PCI IDs */
index d6cf75e357dbf07c9b1e89894cb8fa530d3e26a6..6785669113b3c2ee74f4d0315b4f3053a61ad6e8 100644 (file)
@@ -79,6 +79,7 @@ static const struct sof_dev_desc jsl_desc = {
        .nocodec_tplg_filename = "sof-jsl-nocodec.tplg",
        .ops = &sof_cnl_ops,
        .ops_init = sof_cnl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 /* PCI IDs */
index 6e4e6d4ef5a5649e781bbb78e053bb5b3f9edbb1..b183dc0014b4b5a102b57c63e0a787bc76b55d01 100644 (file)
@@ -46,6 +46,7 @@ static const struct sof_dev_desc mtl_desc = {
        .nocodec_tplg_filename = "sof-mtl-nocodec.tplg",
        .ops = &sof_mtl_ops,
        .ops_init = sof_mtl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 /* PCI IDs */
index 3a99dc444f92ea6b46014a4faaf9463fe4421c29..5b4bccf819658eeb356f2f58425c6ebb894f8436 100644 (file)
@@ -38,6 +38,7 @@ static struct sof_dev_desc skl_desc = {
        .nocodec_tplg_filename = "sof-skl-nocodec.tplg",
        .ops = &sof_skl_ops,
        .ops_init = sof_skl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static struct sof_dev_desc kbl_desc = {
@@ -61,6 +62,7 @@ static struct sof_dev_desc kbl_desc = {
        .nocodec_tplg_filename = "sof-kbl-nocodec.tplg",
        .ops = &sof_skl_ops,
        .ops_init = sof_skl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 /* PCI IDs */
index e80c4dfef85a58d71d0db6246199fe55c8b64336..22e769e0831d9349331e646ed5fbbfab1debf68a 100644 (file)
@@ -48,6 +48,7 @@ static const struct sof_dev_desc tgl_desc = {
        .nocodec_tplg_filename = "sof-tgl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc tglh_desc = {
@@ -110,6 +111,7 @@ static const struct sof_dev_desc ehl_desc = {
        .nocodec_tplg_filename = "sof-ehl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc adls_desc = {
@@ -141,6 +143,7 @@ static const struct sof_dev_desc adls_desc = {
        .nocodec_tplg_filename = "sof-adl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc adl_desc = {
@@ -172,6 +175,7 @@ static const struct sof_dev_desc adl_desc = {
        .nocodec_tplg_filename = "sof-adl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc adl_n_desc = {
@@ -203,6 +207,7 @@ static const struct sof_dev_desc adl_n_desc = {
        .nocodec_tplg_filename = "sof-adl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc rpls_desc = {
@@ -234,6 +239,7 @@ static const struct sof_dev_desc rpls_desc = {
        .nocodec_tplg_filename = "sof-rpl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 static const struct sof_dev_desc rpl_desc = {
@@ -265,6 +271,7 @@ static const struct sof_dev_desc rpl_desc = {
        .nocodec_tplg_filename = "sof-rpl-nocodec.tplg",
        .ops = &sof_tgl_ops,
        .ops_init = sof_tgl_ops_init,
+       .ops_free = hda_ops_free,
 };
 
 /* PCI IDs */
index 5b2b409752c585d103c6485e1db5efbdd0243b7d..8c22a00266c06a6ffd94be4e2e921450d721ce14 100644 (file)
@@ -75,11 +75,7 @@ static int tangier_pci_probe(struct snd_sof_dev *sdev)
 
        /* LPE base */
        base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
-       size = pci_resource_len(pci, desc->resindex_lpe_base);
-       if (size < PCI_BAR_SIZE) {
-               dev_err(sdev->dev, "error: I/O region is too small.\n");
-               return -ENODEV;
-       }
+       size = PCI_BAR_SIZE;
 
        dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
        sdev->bar[DSP_BAR] = devm_ioremap(sdev->dev, base, size);
index dceb78bfe17c68fc47efbc5c9611828d8efbc439..b1f425b39db94fd54b95bd6e9f3a6bc25538cf58 100644 (file)
@@ -2081,7 +2081,9 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
                break;
        case SOF_DAI_INTEL_ALH:
                if (data) {
-                       config->dai_index = data->dai_index;
+                       /* save the dai_index during hw_params and reuse it for hw_free */
+                       if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
+                               config->dai_index = data->dai_index;
                        config->alh.stream_id = data->dai_data;
                }
                break;
@@ -2089,7 +2091,30 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
                break;
        }
 
-       config->flags = flags;
+       /*
+        * The dai_config op is invoked several times and the flags argument varies as below:
+        * BE DAI hw_params: When the op is invoked during the BE DAI hw_params, flags contains
+        * SOF_DAI_CONFIG_FLAGS_HW_PARAMS along with quirks
+        * FE DAI hw_params: When invoked during FE DAI hw_params after the DAI widget has
+        * just been set up in the DSP, flags is set to SOF_DAI_CONFIG_FLAGS_HW_PARAMS with no
+        * quirks
+        * BE DAI trigger: When invoked during the BE DAI trigger, flags is set to
+        * SOF_DAI_CONFIG_FLAGS_PAUSE and contains no quirks
+        * BE DAI hw_free: When invoked during the BE DAI hw_free, flags is set to
+        * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
+        * FE DAI hw_free: When invoked during the FE DAI hw_free, flags is set to
+        * SOF_DAI_CONFIG_FLAGS_HW_FREE and contains no quirks
+        *
+        * The DAI_CONFIG IPC is sent to the DSP, only after the widget is set up during the FE
+        * DAI hw_params. But since the BE DAI hw_params precedes the FE DAI hw_params, the quirks
+        * need to be preserved when assigning the flags before sending the IPC.
+        * For the case of PAUSE/HW_FREE, since there are no quirks, flags can be used as is.
+        */
+
+       if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
+               config->flags |= flags;
+       else
+               config->flags = flags;
 
        /* only send the IPC if the widget is set up in the DSP */
        if (swidget->use_count > 0) {
@@ -2097,6 +2122,9 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
                                         &reply, sizeof(reply));
                if (ret < 0)
                        dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name);
+
+               /* clear the flags once the IPC has been sent even if it fails */
+               config->flags = SOF_DAI_CONFIG_FLAGS_NONE;
        }
 
        return ret;
index 3de64ea2dc9aa533c042097e20488630976e0c12..4493bbd7faf12bbda0a2e9ed8d4f6c869f83b0c8 100644 (file)
@@ -970,8 +970,9 @@ static void sof_ipc3_rx_msg(struct snd_sof_dev *sdev)
                return;
        }
 
-       if (hdr.size < sizeof(hdr)) {
-               dev_err(sdev->dev, "The received message size is invalid\n");
+       if (hdr.size < sizeof(hdr) || hdr.size > SOF_IPC_MSG_MAX_SIZE) {
+               dev_err(sdev->dev, "The received message size is invalid: %u\n",
+                       hdr.size);
                return;
        }
 
index 67bd2233fd9a675746ca91396ccddf25fb547f1c..9a71af1a613ac3800c9a5016de2a638cfac5d2d5 100644 (file)
@@ -97,7 +97,8 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
                }
 
                /* set curve type and duration from topology */
-               data.curve_duration = gain->data.curve_duration;
+               data.curve_duration_l = gain->data.curve_duration_l;
+               data.curve_duration_h = gain->data.curve_duration_h;
                data.curve_type = gain->data.curve_type;
 
                msg->data_ptr = &data;
index 3e27c7a48ebd39a3136063ee9d4daccf07047cb7..3a5394c3dd83bf35053bd5e398de7f345bd1c7ba 100644 (file)
@@ -107,7 +107,7 @@ static const struct sof_topology_token gain_tokens[] = {
                get_token_u32, offsetof(struct sof_ipc4_gain_data, curve_type)},
        {SOF_TKN_GAIN_RAMP_DURATION,
                SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
-               offsetof(struct sof_ipc4_gain_data, curve_duration)},
+               offsetof(struct sof_ipc4_gain_data, curve_duration_l)},
        {SOF_TKN_GAIN_VAL, SND_SOC_TPLG_TUPLE_TYPE_WORD,
                get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
 };
@@ -155,7 +155,7 @@ static void sof_ipc4_dbg_audio_format(struct device *dev,
        for (i = 0; i < num_format; i++, ptr = (u8 *)ptr + object_size) {
                fmt = ptr;
                dev_dbg(dev,
-                       " #%d: %uKHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n",
+                       " #%d: %uHz, %ubit (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x)\n",
                        i, fmt->sampling_frequency, fmt->bit_depth, fmt->ch_map,
                        fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg);
        }
@@ -692,7 +692,7 @@ static int sof_ipc4_widget_setup_comp_pga(struct snd_sof_widget *swidget)
 
        dev_dbg(scomp->dev,
                "pga widget %s: ramp type: %d, ramp duration %d, initial gain value: %#x, cpc %d\n",
-               swidget->widget->name, gain->data.curve_type, gain->data.curve_duration,
+               swidget->widget->name, gain->data.curve_type, gain->data.curve_duration_l,
                gain->data.init_val, gain->base_config.cpc);
 
        ret = sof_ipc4_widget_setup_msg(swidget, &gain->msg);
@@ -980,6 +980,7 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
 
                ipc4_copier = dai->private;
                if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) {
+                       struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data;
                        struct sof_ipc4_alh_configuration_blob *blob;
                        unsigned int group_id;
 
@@ -989,6 +990,9 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget)
                                           ALH_MULTI_GTW_BASE;
                                ida_free(&alh_group_ida, group_id);
                        }
+
+                       /* clear the node ID */
+                       copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
                }
        }
 
@@ -1801,6 +1805,16 @@ static int sof_ipc4_route_setup(struct snd_sof_dev *sdev, struct snd_sof_route *
        u32 header, extension;
        int ret;
 
+       if (!src_fw_module || !sink_fw_module) {
+               dev_err(sdev->dev,
+                       "cannot bind %s -> %s, no firmware module for: %s%s\n",
+                       src_widget->widget->name, sink_widget->widget->name,
+                       src_fw_module ? "" : " source",
+                       sink_fw_module ? "" : " sink");
+
+               return -ENODEV;
+       }
+
        sroute->src_queue_id = sof_ipc4_get_queue_id(src_widget, sink_widget,
                                                     SOF_PIN_TYPE_SOURCE);
        if (sroute->src_queue_id < 0) {
@@ -1940,8 +1954,15 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
                pipeline->skip_during_fe_trigger = true;
                fallthrough;
        case SOF_DAI_INTEL_ALH:
-               copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
-               copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
+               /*
+                * Do not clear the node ID when this op is invoked with
+                * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during
+                * unprepare.
+                */
+               if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+                       copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK;
+                       copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data);
+               }
                break;
        case SOF_DAI_INTEL_DMIC:
        case SOF_DAI_INTEL_SSP:
index 72529179ac22343063ca3ca1ce9873cd36ca75b3..123f1096f3261d46b0e1eda51376ce9b3c02e1d8 100644 (file)
@@ -46,7 +46,7 @@
 #define SOF_IPC4_NODE_INDEX_INTEL_SSP(x) (((x) & 0xf) << 4)
 
 /* Node ID for DMIC type DAI copiers */
-#define SOF_IPC4_NODE_INDEX_INTEL_DMIC(x) (((x) & 0x7) << 5)
+#define SOF_IPC4_NODE_INDEX_INTEL_DMIC(x) ((x) & 0x7)
 
 #define SOF_IPC4_GAIN_ALL_CHANNELS_MASK 0xffffffff
 #define SOF_IPC4_VOL_ZERO_DB   0x7fffffff
@@ -277,14 +277,16 @@ struct sof_ipc4_control_data {
  * @init_val: Initial value
  * @curve_type: Curve type
  * @reserved: reserved for future use
- * @curve_duration: Curve duration
+ * @curve_duration_l: Curve duration low part
+ * @curve_duration_h: Curve duration high part
  */
 struct sof_ipc4_gain_data {
        uint32_t channels;
        uint32_t init_val;
        uint32_t curve_type;
        uint32_t reserved;
-       uint32_t curve_duration;
+       uint32_t curve_duration_l;
+       uint32_t curve_duration_h;
 } __aligned(8);
 
 /**
index 8ede4b952997846bd61f614b143dbb0e6c583ebc..246b56d24a6f160258e5f4cd55ee8d76ec2db87b 100644 (file)
@@ -405,6 +405,9 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_
 static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
                                 size_t payload_bytes, bool set)
 {
+       const struct sof_dsp_power_state target_state = {
+                       .state = SOF_DSP_PM_D0,
+       };
        size_t payload_limit = sdev->ipc->max_payload_size;
        struct sof_ipc4_msg *ipc4_msg = data;
        struct sof_ipc4_msg tx = {{ 0 }};
@@ -435,6 +438,11 @@ static int sof_ipc4_set_get_data(struct snd_sof_dev *sdev, void *data,
 
        tx.extension |= SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(1);
 
+       /* ensure the DSP is in D0i0 before sending IPC */
+       ret = snd_sof_dsp_set_power_state(sdev, &target_state);
+       if (ret < 0)
+               return ret;
+
        /* Serialise IPC TX */
        mutex_lock(&sdev->ipc->tx_mutex);
 
index 8d3383085d12c4ffb8ff5c09417f1ec43937b378..85412aeb1ca16b0ed66d4db24a5e449be4370e57 100644 (file)
@@ -183,6 +183,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
        const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
        pm_message_t pm_state;
        u32 target_state = snd_sof_dsp_power_target(sdev);
+       u32 old_state = sdev->dsp_power_state.state;
        int ret;
 
        /* do nothing if dsp suspend callback is not set */
@@ -192,7 +193,12 @@ static int sof_suspend(struct device *dev, bool runtime_suspend)
        if (runtime_suspend && !sof_ops(sdev)->runtime_suspend)
                return 0;
 
-       if (tplg_ops && tplg_ops->tear_down_all_pipelines)
+       /* we need to tear down pipelines only if the DSP hardware is
+        * active, which happens for PCI devices. if the device is
+        * suspended, it is brought back to full power and then
+        * suspended again
+        */
+       if (tplg_ops && tplg_ops->tear_down_all_pipelines && (old_state == SOF_DSP_PM_D0))
                tplg_ops->tear_down_all_pipelines(sdev, false);
 
        if (sdev->fw_state != SOF_FW_BOOT_COMPLETE)
index 760621bfc80284a05c2ebed28579b29368a01f81..6de388a8d0b8df64e6653acc2df7e09510d50326 100644 (file)
@@ -50,9 +50,27 @@ static int sof_widget_free_unlocked(struct snd_sof_dev *sdev,
        /* reset route setup status for all routes that contain this widget */
        sof_reset_route_setup_status(sdev, swidget);
 
+       /* free DAI config and continue to free widget even if it fails */
+       if (WIDGET_IS_DAI(swidget->id)) {
+               struct snd_sof_dai_config_data data;
+               unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_FREE;
+
+               data.dai_data = DMA_CHAN_INVALID;
+
+               if (tplg_ops && tplg_ops->dai_config) {
+                       err = tplg_ops->dai_config(sdev, swidget, flags, &data);
+                       if (err < 0)
+                               dev_err(sdev->dev, "failed to free config for widget %s\n",
+                                       swidget->widget->name);
+               }
+       }
+
        /* continue to disable core even if IPC fails */
-       if (tplg_ops && tplg_ops->widget_free)
-               err = tplg_ops->widget_free(sdev, swidget);
+       if (tplg_ops && tplg_ops->widget_free) {
+               ret = tplg_ops->widget_free(sdev, swidget);
+               if (ret < 0 && !err)
+                       err = ret;
+       }
 
        /*
         * disable widget core. continue to route setup status and complete flag
@@ -151,8 +169,12 @@ static int sof_widget_setup_unlocked(struct snd_sof_dev *sdev,
 
        /* send config for DAI components */
        if (WIDGET_IS_DAI(swidget->id)) {
-               unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE;
+               unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS;
 
+               /*
+                * The config flags saved during BE DAI hw_params will be used for IPC3. IPC4 does
+                * not use the flags argument.
+                */
                if (tplg_ops && tplg_ops->dai_config) {
                        ret = tplg_ops->dai_config(sdev, swidget, flags, NULL);
                        if (ret < 0)
@@ -588,8 +610,8 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
        ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
                                        dir, SOF_WIDGET_SETUP);
        if (ret < 0) {
-               ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
-                                               dir, SOF_WIDGET_UNPREPARE);
+               sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
+                                         dir, SOF_WIDGET_UNPREPARE);
                return ret;
        }
 
index 4a62ccc71fcbffa005145fa43f601db69f8ef7b4..9f3a038fe21add2ae6ebbe02a41a029f9bdf8eac 100644 (file)
@@ -1388,14 +1388,15 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
        if (ret < 0) {
                dev_err(scomp->dev, "failed to parse component pin tokens for %s\n",
                        w->name);
-               return ret;
+               goto widget_free;
        }
 
        if (swidget->num_sink_pins > SOF_WIDGET_MAX_NUM_PINS ||
            swidget->num_source_pins > SOF_WIDGET_MAX_NUM_PINS) {
                dev_err(scomp->dev, "invalid pins for %s: [sink: %d, src: %d]\n",
                        swidget->widget->name, swidget->num_sink_pins, swidget->num_source_pins);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto widget_free;
        }
 
        if (swidget->num_sink_pins > 1) {
@@ -1404,7 +1405,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
                if (ret < 0) {
                        dev_err(scomp->dev, "failed to parse sink pin binding for %s\n",
                                w->name);
-                       return ret;
+                       goto widget_free;
                }
        }
 
@@ -1414,7 +1415,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
                if (ret < 0) {
                        dev_err(scomp->dev, "failed to parse source pin binding for %s\n",
                                w->name);
-                       return ret;
+                       goto widget_free;
                }
        }
 
@@ -1436,9 +1437,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
        case snd_soc_dapm_dai_out:
                dai = kzalloc(sizeof(*dai), GFP_KERNEL);
                if (!dai) {
-                       kfree(swidget);
-                       return -ENOMEM;
-
+                       ret = -ENOMEM;
+                       goto widget_free;
                }
 
                ret = sof_widget_parse_tokens(scomp, swidget, tw, token_list, token_list_size);
@@ -1496,8 +1496,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
                        tw->shift, swidget->id, tw->name,
                        strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0
                                ? tw->sname : "none");
-               kfree(swidget);
-               return ret;
+               goto widget_free;
        }
 
        if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) {
@@ -1518,10 +1517,7 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
                        if (ret) {
                                dev_err(scomp->dev, "widget event binding failed for %s\n",
                                        swidget->widget->name);
-                               kfree(swidget->private);
-                               kfree(swidget->tuples);
-                               kfree(swidget);
-                               return ret;
+                               goto free;
                        }
                }
        }
@@ -1532,10 +1528,8 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
 
                spipe = kzalloc(sizeof(*spipe), GFP_KERNEL);
                if (!spipe) {
-                       kfree(swidget->private);
-                       kfree(swidget->tuples);
-                       kfree(swidget);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto free;
                }
 
                spipe->pipe_widget = swidget;
@@ -1546,6 +1540,12 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
        w->dobj.private = swidget;
        list_add(&swidget->list, &sdev->widget_list);
        return ret;
+free:
+       kfree(swidget->private);
+       kfree(swidget->tuples);
+widget_free:
+       kfree(swidget);
+       return ret;
 }
 
 static int sof_route_unload(struct snd_soc_component *scomp,
index 419302e2057e8fbc67c6ee8d940ae9a4876369b2..647fa054d8b1da37a3ec8db6e4608ce8393d8a12 100644 (file)
@@ -455,8 +455,8 @@ static void push_back_to_ready_list(struct snd_usb_endpoint *ep,
  * This function is used both for implicit feedback endpoints and in low-
  * latency playback mode.
  */
-void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
-                                      bool in_stream_lock)
+int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
+                                     bool in_stream_lock)
 {
        bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep);
 
@@ -480,7 +480,7 @@ void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
                spin_unlock_irqrestore(&ep->lock, flags);
 
                if (ctx == NULL)
-                       return;
+                       break;
 
                /* copy over the length information */
                if (implicit_fb) {
@@ -495,11 +495,14 @@ void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
                        break;
                if (err < 0) {
                        /* push back to ready list again for -EAGAIN */
-                       if (err == -EAGAIN)
+                       if (err == -EAGAIN) {
                                push_back_to_ready_list(ep, ctx);
-                       else
+                               break;
+                       }
+
+                       if (!in_stream_lock)
                                notify_xrun(ep);
-                       return;
+                       return -EPIPE;
                }
 
                err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
@@ -507,13 +510,16 @@ void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
                        usb_audio_err(ep->chip,
                                      "Unable to submit urb #%d: %d at %s\n",
                                      ctx->index, err, __func__);
-                       notify_xrun(ep);
-                       return;
+                       if (!in_stream_lock)
+                               notify_xrun(ep);
+                       return -EPIPE;
                }
 
                set_bit(ctx->index, &ep->active_mask);
                atomic_inc(&ep->submitted_urbs);
        }
+
+       return 0;
 }
 
 /*
index 924f4351588ce9818fc93826483d91d0dc73f8bf..c09f68ce08b187258c25bc9d8853c5427a82a3b9 100644 (file)
@@ -52,7 +52,7 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
 int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
                                      struct snd_urb_ctx *ctx, int idx,
                                      unsigned int avail);
-void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
-                                      bool in_stream_lock);
+int snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
+                                     bool in_stream_lock);
 
 #endif /* __USBAUDIO_ENDPOINT_H */
index 405dc0bf6678c6bc94533315e063f51a32a576ae..4b1c5ba121f391db21a542a453147256d4055430 100644 (file)
@@ -39,8 +39,12 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
        case UAC_VERSION_1:
        default: {
                struct uac_format_type_i_discrete_descriptor *fmt = _fmt;
-               if (format >= 64)
-                       return 0; /* invalid format */
+               if (format >= 64) {
+                       usb_audio_info(chip,
+                                      "%u:%d: invalid format type 0x%llx is detected, processed as PCM\n",
+                                      fp->iface, fp->altsetting, format);
+                       format = UAC_FORMAT_TYPE_I_PCM;
+               }
                sample_width = fmt->bBitResolution;
                sample_bytes = fmt->bSubframeSize;
                format = 1ULL << format;
index d959da7a1afbab5bca4c92c3613025e48a84432d..eec5232f9fb290c7292d824893563e1bd8326032 100644 (file)
@@ -1639,7 +1639,7 @@ static int snd_usb_pcm_playback_ack(struct snd_pcm_substream *substream)
         * outputs here
         */
        if (!ep->active_mask)
-               snd_usb_queue_pending_output_urbs(ep, true);
+               return snd_usb_queue_pending_output_urbs(ep, true);
        return 0;
 }
 
index e497875fc7e3fecfbb419c7cd632383833bce07a..37e9f6804832641c176afe5ef150031748a77e9a 100644 (file)
@@ -39,7 +39,7 @@ help:
        @echo '  turbostat              - Intel CPU idle stats and freq reporting tool'
        @echo '  usb                    - USB testing tools'
        @echo '  virtio                 - vhost test module'
-       @echo '  vm                     - misc vm tools'
+       @echo '  mm                     - misc mm tools'
        @echo '  wmi                    - WMI interface examples'
        @echo '  x86_energy_perf_policy - Intel energy policy tool'
        @echo ''
@@ -69,7 +69,7 @@ acpi: FORCE
 cpupower: FORCE
        $(call descend,power/$@)
 
-cgroup counter firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE
+cgroup counter firewire hv guest bootconfig spi usb virtio mm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE
        $(call descend,$@)
 
 bpf/%: FORCE
@@ -118,7 +118,7 @@ kvm_stat: FORCE
 
 all: acpi cgroup counter cpupower gpio hv firewire \
                perf selftests bootconfig spi turbostat usb \
-               virtio vm bpf x86_energy_perf_policy \
+               virtio mm bpf x86_energy_perf_policy \
                tmon freefall iio objtool kvm_stat wmi \
                pci debugging tracing thermal thermometer thermal-engine
 
@@ -128,7 +128,7 @@ acpi_install:
 cpupower_install:
        $(call descend,power/$(@:_install=),install)
 
-cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install:
+cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install mm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install:
        $(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -158,7 +158,7 @@ kvm_stat_install:
 install: acpi_install cgroup_install counter_install cpupower_install gpio_install \
                hv_install firewire_install iio_install \
                perf_install selftests_install turbostat_install usb_install \
-               virtio_install vm_install bpf_install x86_energy_perf_policy_install \
+               virtio_install mm_install bpf_install x86_energy_perf_policy_install \
                tmon_install freefall_install objtool_install kvm_stat_install \
                wmi_install pci_install debugging_install intel-speed-select_install \
                tracing_install thermometer_install thermal-engine_install
@@ -169,7 +169,7 @@ acpi_clean:
 cpupower_clean:
        $(call descend,power/cpupower,clean)
 
-cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean:
+cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean mm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean:
        $(call descend,$(@:_clean=),clean)
 
 libapi_clean:
@@ -211,7 +211,7 @@ build_clean:
 
 clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \
                perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \
-               vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
+               mm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
                freefall_clean build_clean libbpf_clean libsubcmd_clean \
                gpio_clean objtool_clean leds_clean wmi_clean pci_clean firmware_clean debugging_clean \
                intel-speed-select_clean tracing_clean thermal_clean thermometer_clean thermal-engine_clean
index d4e32b3d484379631682aa2b01247803c053b2b4..00b4ba1e5cdf032f81aff9f728dcffea68571880 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef __ASM_LOONGARCH_BITSPERLONG_H
 #define __ASM_LOONGARCH_BITSPERLONG_H
 
-#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8)
+#define __BITS_PER_LONG (__SIZEOF_LONG__ * 8)
 
 #include <asm-generic/bitsperlong.h>
 
index 4f1c4b0c29e98a4ee06bb7fa06bc4ca0310eac6a..e0c25b75327ee70868aaac49e0dd46df9be1678e 100644 (file)
         7,    0,  EBX,     27, avx512er, AVX512 Exponent Reciproca instr
         7,    0,  EBX,     28, avx512cd, AVX512 Conflict Detection instr
         7,    0,  EBX,     29, sha, Intel Secure Hash Algorithm Extensions instr
-        7,    0,  EBX,     26, avx512bw, AVX512 Byte & Word instr
-        7,    0,  EBX,     28, avx512vl, AVX512 Vector Length Extentions (VL)
+        7,    0,  EBX,     30, avx512bw, AVX512 Byte & Word instr
+        7,    0,  EBX,     31, avx512vl, AVX512 Vector Length Extentions (VL)
         7,    0,  ECX,      0, prefetchwt1, X
         7,    0,  ECX,      1, avx512vbmi, AVX512 Vector Byte Manipulation Instructions
         7,    0,  ECX,      2, umip, User-mode Instruction Prevention
 # According to SDM
 # 40000000H - 4FFFFFFFH is invalid range
 
-
 # Leaf 80000001H
 # Extended Processor Signature and Feature Bits
 
+0x80000001,    0,  EAX,  27:20, extfamily, Extended family
+0x80000001,    0,  EAX,  19:16, extmodel, Extended model
+0x80000001,    0,  EAX,   11:8, basefamily, Description of Family
+0x80000001,    0,  EAX,   11:8, basemodel, Model numbers vary with product
+0x80000001,    0,  EAX,    3:0, stepping, Processor stepping (revision) for a specific model
+
+0x80000001,    0,  EBX,  31:28, pkgtype, Specifies the package type
+
 0x80000001,    0,  ECX,      0, lahf_lm, LAHF/SAHF available in 64-bit mode
+0x80000001,    0,  ECX,      1, cmplegacy, Core multi-processing legacy mode
+0x80000001,    0,  ECX,      2, svm, Indicates support for: VMRUN, VMLOAD, VMSAVE, CLGI, VMMCALL, and INVLPGA
+0x80000001,    0,  ECX,      3, extapicspace, Extended APIC register space
+0x80000001,    0,  ECX,      4, altmovecr8, Indicates support for LOCK MOV CR0 means MOV CR8
 0x80000001,    0,  ECX,      5, lzcnt, LZCNT
+0x80000001,    0,  ECX,      6, sse4a, EXTRQ, INSERTQ, MOVNTSS, and MOVNTSD instruction support
+0x80000001,    0,  ECX,      7, misalignsse, Misaligned SSE Mode
 0x80000001,    0,  ECX,      8, prefetchw, PREFETCHW
-
+0x80000001,    0,  ECX,      9, osvw, OS Visible Work-around support
+0x80000001,    0,  ECX,     10, ibs, Instruction Based Sampling
+0x80000001,    0,  ECX,     11, xop, Extended operation support
+0x80000001,    0,  ECX,     12, skinit, SKINIT and STGI support
+0x80000001,    0,  ECX,     13, wdt, Watchdog timer support
+0x80000001,    0,  ECX,     15, lwp, Lightweight profiling support
+0x80000001,    0,  ECX,     16, fma4, Four-operand FMA instruction support
+0x80000001,    0,  ECX,     17, tce, Translation cache extension
+0x80000001,    0,  ECX,     22, TopologyExtensions, Indicates support for Core::X86::Cpuid::CachePropEax0 and Core::X86::Cpuid::ExtApicId
+0x80000001,    0,  ECX,     23, perfctrextcore, Indicates support for Core::X86::Msr::PERF_CTL0 - 5 and Core::X86::Msr::PERF_CTR
+0x80000001,    0,  ECX,     24, perfctrextdf, Indicates support for Core::X86::Msr::DF_PERF_CTL and Core::X86::Msr::DF_PERF_CTR
+0x80000001,    0,  ECX,     26, databreakpointextension, Indicates data breakpoint support for Core::X86::Msr::DR0_ADDR_MASK, Core::X86::Msr::DR1_ADDR_MASK, Core::X86::Msr::DR2_ADDR_MASK and Core::X86::Msr::DR3_ADDR_MASK
+0x80000001,    0,  ECX,     27, perftsc, Performance time-stamp counter supported
+0x80000001,    0,  ECX,     28, perfctrextllc, Indicates support for L3 performance counter extensions
+0x80000001,    0,  ECX,     29, mwaitextended, MWAITX and MONITORX capability is supported
+0x80000001,    0,  ECX,     30, admskextn, Indicates support for address mask extension (to 32 bits and to all 4 DRs) for instruction breakpoints
+
+0x80000001,    0,  EDX,      0, fpu, x87 floating point unit on-chip
+0x80000001,    0,  EDX,      1, vme, Virtual-mode enhancements
+0x80000001,    0,  EDX,      2, de, Debugging extensions, IO breakpoints, CR4.DE
+0x80000001,    0,  EDX,      3, pse, Page-size extensions (4 MB pages)
+0x80000001,    0,  EDX,      4, tsc, Time stamp counter, RDTSC/RDTSCP instructions, CR4.TSD
+0x80000001,    0,  EDX,      5, msr, Model-specific registers (MSRs), with RDMSR and WRMSR instructions
+0x80000001,    0,  EDX,      6, pae, Physical-address extensions (PAE)
+0x80000001,    0,  EDX,      7, mce, Machine Check Exception, CR4.MCE
+0x80000001,    0,  EDX,      8, cmpxchg8b, CMPXCHG8B instruction
+0x80000001,    0,  EDX,      9, apic, advanced programmable interrupt controller (APIC) exists and is enabled
 0x80000001,    0,  EDX,     11, sysret, SYSCALL/SYSRET supported
+0x80000001,    0,  EDX,     12, mtrr, Memory-type range registers
+0x80000001,    0,  EDX,     13, pge, Page global extension, CR4.PGE
+0x80000001,    0,  EDX,     14, mca, Machine check architecture, MCG_CAP
+0x80000001,    0,  EDX,     15, cmov, Conditional move instructions, CMOV, FCOMI, FCMOV
+0x80000001,    0,  EDX,     16, pat, Page attribute table
+0x80000001,    0,  EDX,     17, pse36, Page-size extensions
 0x80000001,    0,  EDX,     20, exec_dis, Execute Disable Bit available
+0x80000001,    0,  EDX,     22, mmxext, AMD extensions to MMX instructions
+0x80000001,    0,  EDX,     23, mmx, MMX instructions
+0x80000001,    0,  EDX,     24, fxsr, FXSAVE and FXRSTOR instructions
+0x80000001,    0,  EDX,     25, ffxsr, FXSAVE and FXRSTOR instruction optimizations
 0x80000001,    0,  EDX,     26, 1gb_page, 1GB page supported
 0x80000001,    0,  EDX,     27, rdtscp, RDTSCP and IA32_TSC_AUX are available
-#0x80000001,    0,  EDX,     29, 64b, 64b Architecture supported
+0x80000001,    0,  EDX,     29, lm, 64b Architecture supported
+0x80000001,    0,  EDX,     30, threednowext, AMD extensions to 3DNow! instructions
+0x80000001,    0,  EDX,     31, threednow, 3DNow! instructions
 
 # Leaf 80000002H/80000003H/80000004H
 # Processor Brand String
index dae75511fef71fdc0871b4729c33c2fc7db29aa6..416f5b35dd8f4317f31a574407bed51e3f8640a7 100644 (file)
@@ -33,7 +33,7 @@ struct reg_desc {
        struct bits_desc descs[32];
 };
 
-enum {
+enum cpuid_reg {
        R_EAX = 0,
        R_EBX,
        R_ECX,
@@ -41,6 +41,10 @@ enum {
        NR_REGS
 };
 
+static const char * const reg_names[] = {
+       "EAX", "EBX", "ECX", "EDX",
+};
+
 struct subleaf {
        u32 index;
        u32 sub;
@@ -428,12 +432,18 @@ static void parse_text(void)
 
 
 /* Decode every eax/ebx/ecx/edx */
-static void decode_bits(u32 value, struct reg_desc *rdesc)
+static void decode_bits(u32 value, struct reg_desc *rdesc, enum cpuid_reg reg)
 {
        struct bits_desc *bdesc;
        int start, end, i;
        u32 mask;
 
+       if (!rdesc->nr) {
+               if (show_details)
+                       printf("\t %s: 0x%08x\n", reg_names[reg], value);
+               return;
+       }
+
        for (i = 0; i < rdesc->nr; i++) {
                bdesc = &rdesc->descs[i];
 
@@ -468,13 +478,21 @@ static void show_leaf(struct subleaf *leaf)
        if (!leaf)
                return;
 
-       if (show_raw)
+       if (show_raw) {
                leaf_print_raw(leaf);
+       } else {
+               if (show_details)
+                       printf("CPUID_0x%x_ECX[0x%x]:\n",
+                               leaf->index, leaf->sub);
+       }
+
+       decode_bits(leaf->eax, &leaf->info[R_EAX], R_EAX);
+       decode_bits(leaf->ebx, &leaf->info[R_EBX], R_EBX);
+       decode_bits(leaf->ecx, &leaf->info[R_ECX], R_ECX);
+       decode_bits(leaf->edx, &leaf->info[R_EDX], R_EDX);
 
-       decode_bits(leaf->eax, &leaf->info[R_EAX]);
-       decode_bits(leaf->ebx, &leaf->info[R_EBX]);
-       decode_bits(leaf->ecx, &leaf->info[R_ECX]);
-       decode_bits(leaf->edx, &leaf->info[R_EDX]);
+       if (!show_raw && show_details)
+               printf("\n");
 }
 
 static void show_func(struct cpuid_func *func)
index f68e2e9eef8b27223f753399dab743f370318d69..a2c484c243f5d9ba5da21fd932d802db1e23054e 100755 (executable)
@@ -87,10 +87,14 @@ xfail grep -i "error" $OUTFILE
 
 echo "Max node number check"
 
-echo -n > $TEMPCONF
-for i in `seq 1 1024` ; do
-   echo "node$i" >> $TEMPCONF
-done
+awk '
+BEGIN {
+  for (i = 0; i < 26; i += 1)
+      printf("%c\n", 65 + i % 26)
+  for (i = 26; i < 8192; i += 1)
+      printf("%c%c%c\n", 65 + i % 26, 65 + (i / 26) % 26, 65 + (i / 26 / 26))
+}
+' > $TEMPCONF
 xpass $BOOTCONF -a $TEMPCONF $INITRD
 
 echo "badnode" >> $TEMPCONF
index 25f2bb3a991d3003b3fee9314a767cb281876afb..332b983ead1e4aa9cef4db835198cc92d04ac29d 100644 (file)
@@ -20,7 +20,7 @@
  * Userspace note:
  * The same principle works for userspace, because 'error' pointers
  * fall down to the unused hole far from user space, as described
- * in Documentation/x86/x86_64/mm.rst for x86_64 arch:
+ * in Documentation/arch/x86/x86_64/mm.rst for x86_64 arch:
  *
  * 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm hole caused by [48:63] sign extension
  * ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole
diff --git a/tools/include/nolibc/.gitignore b/tools/include/nolibc/.gitignore
new file mode 100644 (file)
index 0000000..dea22ea
--- /dev/null
@@ -0,0 +1 @@
+sysroot
index cfd06764b5aeeae9c1843c50f6b7fd7fdfa91797..9839feafd38a14a45c73283fb979cd371a2d8fb7 100644 (file)
@@ -25,8 +25,8 @@ endif
 
 nolibc_arch := $(patsubst arm64,aarch64,$(ARCH))
 arch_file := arch-$(nolibc_arch).h
-all_files := ctype.h errno.h nolibc.h signal.h std.h stdio.h stdlib.h string.h \
-             sys.h time.h types.h unistd.h
+all_files := ctype.h errno.h nolibc.h signal.h stackprotector.h std.h stdint.h \
+             stdio.h stdlib.h string.h sys.h time.h types.h unistd.h
 
 # install all headers needed to support a bare-metal compiler
 all: headers
index e8d0cf545bf145db427191a75ac67fc599e6158c..2d98d78fd3f3a6459d7372dc51c65d1147b471ef 100644 (file)
@@ -181,6 +181,8 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
+#define __ARCH_SUPPORTS_STACK_PROTECTOR
+
 /* startup code */
 /*
  * i386 System V ABI mandates:
@@ -188,9 +190,12 @@ const unsigned long *_auxv __attribute__((weak));
  * 2) The deepest stack frame should be set to zero
  *
  */
-void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
+void __attribute__((weak,noreturn,optimize("omit-frame-pointer"),no_stack_protector)) _start(void)
 {
        __asm__ volatile (
+#ifdef NOLIBC_STACKPROTECTOR
+               "call __stack_chk_init\n"   // initialize stack protector
+#endif
                "pop %eax\n"                // argc   (first arg, %eax)
                "mov %esp, %ebx\n"          // argv[] (second arg, %ebx)
                "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
diff --git a/tools/include/nolibc/arch-loongarch.h b/tools/include/nolibc/arch-loongarch.h
new file mode 100644 (file)
index 0000000..029ee3c
--- /dev/null
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * LoongArch specific definitions for NOLIBC
+ * Copyright (C) 2023 Loongson Technology Corporation Limited
+ */
+
+#ifndef _NOLIBC_ARCH_LOONGARCH_H
+#define _NOLIBC_ARCH_LOONGARCH_H
+
+/* Syscalls for LoongArch :
+ *   - stack is 16-byte aligned
+ *   - syscall number is passed in a7
+ *   - arguments are in a0, a1, a2, a3, a4, a5
+ *   - the system call is performed by calling "syscall 0"
+ *   - syscall return comes in a0
+ *   - the arguments are cast to long and assigned into the target
+ *     registers which are then simply passed as registers to the asm code,
+ *     so that we don't have to experience issues with register constraints.
+ *
+ * On LoongArch, select() is not implemented so we have to use pselect6().
+ */
+#define __ARCH_WANT_SYS_PSELECT6
+
+#define my_syscall0(num)                                                      \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0");                                   \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "=r"(_arg1)                                                 \
+               : "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+#define my_syscall1(num, arg1)                                                \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "+r"(_arg1)                                                 \
+               : "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+#define my_syscall2(num, arg1, arg2)                                          \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
+       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "+r"(_arg1)                                                 \
+               : "r"(_arg2),                                                 \
+                 "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+#define my_syscall3(num, arg1, arg2, arg3)                                    \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
+       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
+       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "+r"(_arg1)                                                 \
+               : "r"(_arg2), "r"(_arg3),                                     \
+                 "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+#define my_syscall4(num, arg1, arg2, arg3, arg4)                              \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
+       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
+       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
+       register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "+r"(_arg1)                                                 \
+               : "r"(_arg2), "r"(_arg3), "r"(_arg4),                         \
+                 "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
+       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
+       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
+       register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
+       register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "+r"(_arg1)                                                 \
+               : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5),             \
+                 "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)                  \
+({                                                                            \
+       register long _num  __asm__ ("a7") = (num);                           \
+       register long _arg1 __asm__ ("a0") = (long)(arg1);                    \
+       register long _arg2 __asm__ ("a1") = (long)(arg2);                    \
+       register long _arg3 __asm__ ("a2") = (long)(arg3);                    \
+       register long _arg4 __asm__ ("a3") = (long)(arg4);                    \
+       register long _arg5 __asm__ ("a4") = (long)(arg5);                    \
+       register long _arg6 __asm__ ("a5") = (long)(arg6);                    \
+                                                                             \
+       __asm__  volatile (                                                   \
+               "syscall 0\n"                                                 \
+               : "+r"(_arg1)                                                 \
+               : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
+                 "r"(_num)                                                   \
+               : "memory", "$t0", "$t1", "$t2", "$t3",                       \
+                 "$t4", "$t5", "$t6", "$t7", "$t8"                           \
+       );                                                                    \
+       _arg1;                                                                \
+})
+
+char **environ __attribute__((weak));
+const unsigned long *_auxv __attribute__((weak));
+
+#if __loongarch_grlen == 32
+#define LONGLOG      "2"
+#define SZREG        "4"
+#define REG_L        "ld.w"
+#define LONG_S       "st.w"
+#define LONG_ADD     "add.w"
+#define LONG_ADDI    "addi.w"
+#define LONG_SLL     "slli.w"
+#define LONG_BSTRINS "bstrins.w"
+#else // __loongarch_grlen == 64
+#define LONGLOG      "3"
+#define SZREG        "8"
+#define REG_L        "ld.d"
+#define LONG_S       "st.d"
+#define LONG_ADD     "add.d"
+#define LONG_ADDI    "addi.d"
+#define LONG_SLL     "slli.d"
+#define LONG_BSTRINS "bstrins.d"
+#endif
+
+/* startup code */
+void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
+{
+       __asm__ volatile (
+               REG_L        " $a0, $sp, 0\n"         // argc (a0) was in the stack
+               LONG_ADDI    " $a1, $sp, "SZREG"\n"   // argv (a1) = sp + SZREG
+               LONG_SLL     " $a2, $a0, "LONGLOG"\n" // envp (a2) = SZREG*argc ...
+               LONG_ADDI    " $a2, $a2, "SZREG"\n"   //             + SZREG (skip null)
+               LONG_ADD     " $a2, $a2, $a1\n"       //             + argv
+
+               "move          $a3, $a2\n"            // iterate a3 over envp to find auxv (after NULL)
+               "0:\n"                                // do {
+               REG_L        " $a4, $a3, 0\n"         //   a4 = *a3;
+               LONG_ADDI    " $a3, $a3, "SZREG"\n"   //   a3 += sizeof(void*);
+               "bne           $a4, $zero, 0b\n"      // } while (a4);
+               "la.pcrel      $a4, _auxv\n"          // a4 = &_auxv
+               LONG_S       " $a3, $a4, 0\n"         // store a3 into _auxv
+
+               "la.pcrel      $a3, environ\n"        // a3 = &environ
+               LONG_S       " $a2, $a3, 0\n"         // store envp(a2) into environ
+               LONG_BSTRINS " $sp, $zero, 3, 0\n"    // sp must be 16-byte aligned
+               "bl            main\n"                // main() returns the status code, we'll exit with it.
+               "li.w          $a7, 93\n"             // NR_exit == 93
+               "syscall       0\n"
+       );
+       __builtin_unreachable();
+}
+
+#endif // _NOLIBC_ARCH_LOONGARCH_H
index 17f6751208e7e9d93229f1248bf0518c51f48985..f7f2a11d4c3b08fa9af028356da25d7038a381f1 100644 (file)
@@ -181,6 +181,8 @@ struct sys_stat_struct {
 char **environ __attribute__((weak));
 const unsigned long *_auxv __attribute__((weak));
 
+#define __ARCH_SUPPORTS_STACK_PROTECTOR
+
 /* startup code */
 /*
  * x86-64 System V ABI mandates:
@@ -191,6 +193,9 @@ const unsigned long *_auxv __attribute__((weak));
 void __attribute__((weak,noreturn,optimize("omit-frame-pointer"))) _start(void)
 {
        __asm__ volatile (
+#ifdef NOLIBC_STACKPROTECTOR
+               "call __stack_chk_init\n"   // initialize stack protector
+#endif
                "pop %rdi\n"                // argc   (first arg, %rdi)
                "mov %rsp, %rsi\n"          // argv[] (second arg, %rsi)
                "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
index 78b067a4fa47acbd12ebc55971ae16144e045aeb..2d5386a8d6aacc1a882e4e3b016b22c6dcfeb0e4 100644 (file)
@@ -29,6 +29,8 @@
 #include "arch-riscv.h"
 #elif defined(__s390x__)
 #include "arch-s390.h"
+#elif defined(__loongarch__)
+#include "arch-loongarch.h"
 #endif
 
 #endif /* _NOLIBC_ARCH_H */
index b2bc48d3cfe4b9321f5478162dc29a623c1fc497..04739a6293c4889da0e9804294f994f9dd78e701 100644 (file)
 #include "string.h"
 #include "time.h"
 #include "unistd.h"
+#include "stackprotector.h"
 
 /* Used by programs to avoid std includes */
 #define NOLIBC
diff --git a/tools/include/nolibc/stackprotector.h b/tools/include/nolibc/stackprotector.h
new file mode 100644 (file)
index 0000000..d119cbb
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * Stack protector support for NOLIBC
+ * Copyright (C) 2023 Thomas Weißschuh <linux@weissschuh.net>
+ */
+
+#ifndef _NOLIBC_STACKPROTECTOR_H
+#define _NOLIBC_STACKPROTECTOR_H
+
+#include "arch.h"
+
+#if defined(NOLIBC_STACKPROTECTOR)
+
+#if !defined(__ARCH_SUPPORTS_STACK_PROTECTOR)
+#error "nolibc does not support stack protectors on this arch"
+#endif
+
+#include "sys.h"
+#include "stdlib.h"
+
+/* The functions in this header are using raw syscall macros to avoid
+ * triggering stack protector errors themselves
+ */
+
+__attribute__((weak,noreturn,section(".text.nolibc_stack_chk")))
+void __stack_chk_fail(void)
+{
+       pid_t pid;
+       my_syscall3(__NR_write, STDERR_FILENO, "!!Stack smashing detected!!\n", 28);
+       pid = my_syscall0(__NR_getpid);
+       my_syscall2(__NR_kill, pid, SIGABRT);
+       for (;;);
+}
+
+__attribute__((weak,noreturn,section(".text.nolibc_stack_chk")))
+void __stack_chk_fail_local(void)
+{
+       __stack_chk_fail();
+}
+
+__attribute__((weak,section(".data.nolibc_stack_chk")))
+uintptr_t __stack_chk_guard;
+
+__attribute__((weak,no_stack_protector,section(".text.nolibc_stack_chk")))
+void __stack_chk_init(void)
+{
+       my_syscall3(__NR_getrandom, &__stack_chk_guard, sizeof(__stack_chk_guard), 0);
+       /* a bit more randomness in case getrandom() fails */
+       __stack_chk_guard ^= (uintptr_t) &__stack_chk_guard;
+}
+#endif // defined(NOLIBC_STACKPROTECTOR)
+
+#endif // _NOLIBC_STACKPROTECTOR_H
index 1747ae1253920ec03c6151c97df2f31ecc956158..933bc0be7e1c6be3b7909efc127f1d3b9c611135 100644 (file)
 #define NULL ((void *)0)
 #endif
 
-/* stdint types */
-typedef unsigned char       uint8_t;
-typedef   signed char        int8_t;
-typedef unsigned short     uint16_t;
-typedef   signed short      int16_t;
-typedef unsigned int       uint32_t;
-typedef   signed int        int32_t;
-typedef unsigned long long uint64_t;
-typedef   signed long long  int64_t;
-typedef unsigned long        size_t;
-typedef   signed long       ssize_t;
-typedef unsigned long     uintptr_t;
-typedef   signed long      intptr_t;
-typedef   signed long     ptrdiff_t;
+#include "stdint.h"
 
 /* those are commonly provided by sys/types.h */
 typedef unsigned int          dev_t;
diff --git a/tools/include/nolibc/stdint.h b/tools/include/nolibc/stdint.h
new file mode 100644 (file)
index 0000000..c1ce4f5
--- /dev/null
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * Standard definitions and types for NOLIBC
+ * Copyright (C) 2023 Vincent Dagonneau <v@vda.io>
+ */
+
+#ifndef _NOLIBC_STDINT_H
+#define _NOLIBC_STDINT_H
+
+typedef unsigned char       uint8_t;
+typedef   signed char        int8_t;
+typedef unsigned short     uint16_t;
+typedef   signed short      int16_t;
+typedef unsigned int       uint32_t;
+typedef   signed int        int32_t;
+typedef unsigned long long uint64_t;
+typedef   signed long long  int64_t;
+typedef unsigned long        size_t;
+typedef   signed long       ssize_t;
+typedef unsigned long     uintptr_t;
+typedef   signed long      intptr_t;
+typedef   signed long     ptrdiff_t;
+
+typedef   int8_t       int_least8_t;
+typedef  uint8_t      uint_least8_t;
+typedef  int16_t      int_least16_t;
+typedef uint16_t     uint_least16_t;
+typedef  int32_t      int_least32_t;
+typedef uint32_t     uint_least32_t;
+typedef  int64_t      int_least64_t;
+typedef uint64_t     uint_least64_t;
+
+typedef   int8_t        int_fast8_t;
+typedef  uint8_t       uint_fast8_t;
+typedef  ssize_t       int_fast16_t;
+typedef   size_t      uint_fast16_t;
+typedef  ssize_t       int_fast32_t;
+typedef   size_t      uint_fast32_t;
+typedef  ssize_t       int_fast64_t;
+typedef   size_t      uint_fast64_t;
+
+typedef  int64_t           intmax_t;
+typedef uint64_t          uintmax_t;
+
+/* limits of integral types */
+
+#define        INT8_MIN  (-128)
+#define       INT16_MIN  (-32767-1)
+#define       INT32_MIN  (-2147483647-1)
+#define       INT64_MIN  (-9223372036854775807LL-1)
+
+#define        INT8_MAX  (127)
+#define       INT16_MAX  (32767)
+#define       INT32_MAX  (2147483647)
+#define       INT64_MAX  (9223372036854775807LL)
+
+#define       UINT8_MAX  (255)
+#define      UINT16_MAX  (65535)
+#define      UINT32_MAX  (4294967295U)
+#define      UINT64_MAX  (18446744073709551615ULL)
+
+#define  INT_LEAST8_MIN  INT8_MIN
+#define INT_LEAST16_MIN  INT16_MIN
+#define INT_LEAST32_MIN  INT32_MIN
+#define INT_LEAST64_MIN  INT64_MIN
+
+#define  INT_LEAST8_MAX  INT8_MAX
+#define INT_LEAST16_MAX  INT16_MAX
+#define INT_LEAST32_MAX  INT32_MAX
+#define INT_LEAST64_MAX  INT64_MAX
+
+#define  UINT_LEAST8_MAX UINT8_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+
+#define SIZE_MAX         ((size_t)(__LONG_MAX__) * 2 + 1)
+#define INTPTR_MIN       (-__LONG_MAX__ - 1)
+#define INTPTR_MAX       __LONG_MAX__
+#define PTRDIFF_MIN      INTPTR_MIN
+#define PTRDIFF_MAX      INTPTR_MAX
+#define UINTPTR_MAX      SIZE_MAX
+
+#define  INT_FAST8_MIN   INT8_MIN
+#define INT_FAST16_MIN   INTPTR_MIN
+#define INT_FAST32_MIN   INTPTR_MIN
+#define INT_FAST64_MIN   INTPTR_MIN
+
+#define  INT_FAST8_MAX   INT8_MAX
+#define INT_FAST16_MAX   INTPTR_MAX
+#define INT_FAST32_MAX   INTPTR_MAX
+#define INT_FAST64_MAX   INTPTR_MAX
+
+#define  UINT_FAST8_MAX  UINT8_MAX
+#define UINT_FAST16_MAX  SIZE_MAX
+#define UINT_FAST32_MAX  SIZE_MAX
+#define UINT_FAST64_MAX  SIZE_MAX
+
+#endif /* _NOLIBC_STDINT_H */
index 96ac8afc5aeedc047eafaa46fb1a5b024865ca9f..6cbbb52836a00f74286a900196c962ccaec333db 100644 (file)
@@ -273,6 +273,12 @@ int vfprintf(FILE *stream, const char *fmt, va_list args)
        return written;
 }
 
+static __attribute__((unused))
+int vprintf(const char *fmt, va_list args)
+{
+       return vfprintf(stdout, fmt, args);
+}
+
 static __attribute__((unused, format(printf, 2, 3)))
 int fprintf(FILE *stream, const char *fmt, ...)
 {
index b5f8cd35c03be1dc42828f3ea422d47c3fbb94af..5d624dc63a424c3eef1e1099772c645fd80b6b7b 100644 (file)
@@ -11,7 +11,6 @@
 #include "std.h"
 
 /* system includes */
-#include <asm/fcntl.h>   // for O_*
 #include <asm/unistd.h>
 #include <asm/signal.h>  // for SIGCHLD
 #include <asm/ioctls.h>
@@ -20,6 +19,8 @@
 #include <linux/loop.h>
 #include <linux/time.h>
 #include <linux/auxvec.h>
+#include <linux/fcntl.h> // for O_* and AT_*
+#include <linux/stat.h>  // for statx()
 
 #include "arch.h"
 #include "errno.h"
@@ -410,6 +411,27 @@ int getdents64(int fd, struct linux_dirent64 *dirp, int count)
 }
 
 
+/*
+ * uid_t geteuid(void);
+ */
+
+static __attribute__((unused))
+uid_t sys_geteuid(void)
+{
+#ifdef __NR_geteuid32
+       return my_syscall0(__NR_geteuid32);
+#else
+       return my_syscall0(__NR_geteuid);
+#endif
+}
+
+static __attribute__((unused))
+uid_t geteuid(void)
+{
+       return sys_geteuid();
+}
+
+
 /*
  * pid_t getpgid(pid_t pid);
  */
@@ -544,6 +566,27 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
 }
 
 
+/*
+ * uid_t getuid(void);
+ */
+
+static __attribute__((unused))
+uid_t sys_getuid(void)
+{
+#ifdef __NR_getuid32
+       return my_syscall0(__NR_getuid32);
+#else
+       return my_syscall0(__NR_getuid);
+#endif
+}
+
+static __attribute__((unused))
+uid_t getuid(void)
+{
+       return sys_getuid();
+}
+
+
 /*
  * int ioctl(int fd, unsigned long req, void *value);
  */
@@ -1048,12 +1091,66 @@ pid_t setsid(void)
        return ret;
 }
 
+#if defined(__NR_statx)
+/*
+ * int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf);
+ */
+
+static __attribute__((unused))
+int sys_statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
+{
+       return my_syscall5(__NR_statx, fd, path, flags, mask, buf);
+}
+
+static __attribute__((unused))
+int statx(int fd, const char *path, int flags, unsigned int mask, struct statx *buf)
+{
+       int ret = sys_statx(fd, path, flags, mask, buf);
+
+       if (ret < 0) {
+               SET_ERRNO(-ret);
+               ret = -1;
+       }
+       return ret;
+}
+#endif
 
 /*
  * int stat(const char *path, struct stat *buf);
  * Warning: the struct stat's layout is arch-dependent.
  */
 
+#if defined(__NR_statx) && !defined(__NR_newfstatat) && !defined(__NR_stat)
+/*
+ * Maybe we can just use statx() when available for all architectures?
+ */
+static __attribute__((unused))
+int sys_stat(const char *path, struct stat *buf)
+{
+       struct statx statx;
+       long ret;
+
+       ret = sys_statx(AT_FDCWD, path, AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &statx);
+       buf->st_dev     = ((statx.stx_dev_minor & 0xff)
+                         | (statx.stx_dev_major << 8)
+                         | ((statx.stx_dev_minor & ~0xff) << 12));
+       buf->st_ino     = statx.stx_ino;
+       buf->st_mode    = statx.stx_mode;
+       buf->st_nlink   = statx.stx_nlink;
+       buf->st_uid     = statx.stx_uid;
+       buf->st_gid     = statx.stx_gid;
+       buf->st_rdev    = ((statx.stx_rdev_minor & 0xff)
+                         | (statx.stx_rdev_major << 8)
+                         | ((statx.stx_rdev_minor & ~0xff) << 12));
+       buf->st_size    = statx.stx_size;
+       buf->st_blksize = statx.stx_blksize;
+       buf->st_blocks  = statx.stx_blocks;
+       buf->st_atime   = statx.stx_atime.tv_sec;
+       buf->st_mtime   = statx.stx_mtime.tv_sec;
+       buf->st_ctime   = statx.stx_ctime.tv_sec;
+       return ret;
+}
+#else
 static __attribute__((unused))
 int sys_stat(const char *path, struct stat *buf)
 {
@@ -1083,6 +1180,7 @@ int sys_stat(const char *path, struct stat *buf)
        buf->st_ctime   = stat.st_ctime;
        return ret;
 }
+#endif
 
 static __attribute__((unused))
 int stat(const char *path, struct stat *buf)
index fbbc0e68c001b053a8d75f3d3bcfa3c7aaa2ab60..aedd7d9e3f64405be2ad1562092c4b7ea852363a 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "std.h"
 #include <linux/time.h>
+#include <linux/stat.h>
 
 
 /* Only the generic macros and types may be defined here. The arch-specific
  * the layout of sys_stat_struct must not be defined here.
  */
 
-/* stat flags (WARNING, octal here) */
+/* stat flags (WARNING, octal here). We need to check for an existing
+ * definition because linux/stat.h may omit to define those if it finds
+ * that any glibc header was already included.
+ */
+#if !defined(S_IFMT)
 #define S_IFDIR        0040000
 #define S_IFCHR        0020000
 #define S_IFBLK        0060000
 #define S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
 #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
 
+#define S_IRWXU 00700
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+
+#define S_IRWXG 00070
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+
+#define S_IRWXO 00007
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+#endif
+
 /* dirent types */
 #define DT_UNKNOWN     0x0
 #define DT_FIFO        0x1
 #define MAXPATHLEN     (PATH_MAX)
 #endif
 
-/* Special FD used by all the *at functions */
-#ifndef AT_FDCWD
-#define AT_FDCWD       (-100)
-#endif
-
 /* whence values for lseek() */
 #define SEEK_SET       0
 #define SEEK_CUR       1
@@ -81,6 +97,8 @@
 /* Macros used on waitpid()'s return status */
 #define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
 #define WIFEXITED(status)   (((status) & 0x7f) == 0)
+#define WTERMSIG(status)    ((status) & 0x7f)
+#define WIFSIGNALED(status) ((status) - 1 < 0xff)
 
 /* waitpid() flags */
 #define WNOHANG      1
index 1cfcd52106a420afc327ef8403afdd73da0efb10..ac7d53d986cd11ac84dd0a17e5a7055c779b2b10 100644 (file)
 #include "sys.h"
 
 
+#define STDIN_FILENO  0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+
 static __attribute__((unused))
 int msleep(unsigned int msecs)
 {
index b02c8e0f405757b4f62bf038ae199c8a9decfa68..1c7a0f6632c09e3368dc8b5d15cfc708e5c8cef0 100644 (file)
@@ -91,7 +91,6 @@
 
 /* a horrid kludge trying to make sure that this will fail on old kernels */
 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
-#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)      
 
 #ifndef O_NDELAY
 #define O_NDELAY       O_NONBLOCK
index 8c4e3e536c04285e155617cde126f2c4fce10e08..639524b59930bfcabcd0d352048a3fd4aa1da08b 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
 /* Do not edit directly, auto-generated from: */
 /*     Documentation/netlink/specs/netdev.yaml */
 /* YNL-GEN uapi header */
@@ -33,6 +33,8 @@ enum netdev_xdp_act {
        NETDEV_XDP_ACT_HW_OFFLOAD = 16,
        NETDEV_XDP_ACT_RX_SG = 32,
        NETDEV_XDP_ACT_NDO_XMIT_SG = 64,
+
+       NETDEV_XDP_ACT_MASK = 127,
 };
 
 enum {
index fbaf683353945d11b9c82a6577729c1e41eab93c..e4d05662a96ce38ba029f85960ff896046a22976 100644 (file)
@@ -20,8 +20,8 @@
 /* make sure libbpf doesn't use kernel-only integer typedefs */
 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
 
-/* prevent accidental re-addition of reallocarray()/strlcpy() */
-#pragma GCC poison reallocarray strlcpy
+/* prevent accidental re-addition of reallocarray() */
+#pragma GCC poison reallocarray
 
 #include "libbpf.h"
 #include "btf.h"
index 8e708523847094aac15c9f0e1971bb2ae2ce97bf..6dc8b3642458e5dcb64090b63ed9050517e32014 100644 (file)
@@ -28,9 +28,10 @@ Explanation of the Linux-Kernel Memory Consistency Model
   20. THE HAPPENS-BEFORE RELATION: hb
   21. THE PROPAGATES-BEFORE RELATION: pb
   22. RCU RELATIONS: rcu-link, rcu-gp, rcu-rscsi, rcu-order, rcu-fence, and rb
-  23. LOCKING
-  24. PLAIN ACCESSES AND DATA RACES
-  25. ODDS AND ENDS
+  23. SRCU READ-SIDE CRITICAL SECTIONS
+  24. LOCKING
+  25. PLAIN ACCESSES AND DATA RACES
+  26. ODDS AND ENDS
 
 
 
@@ -1848,14 +1849,169 @@ section in P0 both starts before P1's grace period does and ends
 before it does, and the critical section in P2 both starts after P1's
 grace period does and ends after it does.
 
-Addendum: The LKMM now supports SRCU (Sleepable Read-Copy-Update) in
-addition to normal RCU.  The ideas involved are much the same as
-above, with new relations srcu-gp and srcu-rscsi added to represent
-SRCU grace periods and read-side critical sections.  There is a
-restriction on the srcu-gp and srcu-rscsi links that can appear in an
-rcu-order sequence (the srcu-rscsi links must be paired with srcu-gp
-links having the same SRCU domain with proper nesting); the details
-are relatively unimportant.
+The LKMM supports SRCU (Sleepable Read-Copy-Update) in addition to
+normal RCU.  The ideas involved are much the same as above, with new
+relations srcu-gp and srcu-rscsi added to represent SRCU grace periods
+and read-side critical sections.  However, there are some significant
+differences between RCU read-side critical sections and their SRCU
+counterparts, as described in the next section.
+
+
+SRCU READ-SIDE CRITICAL SECTIONS
+--------------------------------
+
+The LKMM uses the srcu-rscsi relation to model SRCU read-side critical
+sections.  They differ from RCU read-side critical sections in the
+following respects:
+
+1.     Unlike the analogous RCU primitives, synchronize_srcu(),
+       srcu_read_lock(), and srcu_read_unlock() take a pointer to a
+       struct srcu_struct as an argument.  This structure is called
+       an SRCU domain, and calls linked by srcu-rscsi must have the
+       same domain.  Read-side critical sections and grace periods
+       associated with different domains are independent of one
+       another; the SRCU version of the RCU Guarantee applies only
+       to pairs of critical sections and grace periods having the
+       same domain.
+
+2.     srcu_read_lock() returns a value, called the index, which must
+       be passed to the matching srcu_read_unlock() call.  Unlike
+       rcu_read_lock() and rcu_read_unlock(), an srcu_read_lock()
+       call does not always have to match the next unpaired
+       srcu_read_unlock().  In fact, it is possible for two SRCU
+       read-side critical sections to overlap partially, as in the
+       following example (where s is an srcu_struct and idx1 and idx2
+       are integer variables):
+
+               idx1 = srcu_read_lock(&s);      // Start of first RSCS
+               idx2 = srcu_read_lock(&s);      // Start of second RSCS
+               srcu_read_unlock(&s, idx1);     // End of first RSCS
+               srcu_read_unlock(&s, idx2);     // End of second RSCS
+
+       The matching is determined entirely by the domain pointer and
+       index value.  By contrast, if the calls had been
+       rcu_read_lock() and rcu_read_unlock() then they would have
+       created two nested (fully overlapping) read-side critical
+       sections: an inner one and an outer one.
+
+3.     The srcu_down_read() and srcu_up_read() primitives work
+       exactly like srcu_read_lock() and srcu_read_unlock(), except
+       that matching calls don't have to execute on the same CPU.
+       (The names are meant to be suggestive of operations on
+       semaphores.)  Since the matching is determined by the domain
+       pointer and index value, these primitives make it possible for
+       an SRCU read-side critical section to start on one CPU and end
+       on another, so to speak.
+
+In order to account for these properties of SRCU, the LKMM models
+srcu_read_lock() as a special type of load event (which is
+appropriate, since it takes a memory location as argument and returns
+a value, just as a load does) and srcu_read_unlock() as a special type
+of store event (again appropriate, since it takes as arguments a
+memory location and a value).  These loads and stores are annotated as
+belonging to the "srcu-lock" and "srcu-unlock" event classes
+respectively.
+
+This approach allows the LKMM to tell whether two events are
+associated with the same SRCU domain, simply by checking whether they
+access the same memory location (i.e., they are linked by the loc
+relation).  It also gives a way to tell which unlock matches a
+particular lock, by checking for the presence of a data dependency
+from the load (srcu-lock) to the store (srcu-unlock).  For example,
+given the situation outlined earlier (with statement labels added):
+
+       A: idx1 = srcu_read_lock(&s);
+       B: idx2 = srcu_read_lock(&s);
+       C: srcu_read_unlock(&s, idx1);
+       D: srcu_read_unlock(&s, idx2);
+
+the LKMM will treat A and B as loads from s yielding values saved in
+idx1 and idx2 respectively.  Similarly, it will treat C and D as
+though they stored the values from idx1 and idx2 in s.  The end result
+is much as if we had written:
+
+       A: idx1 = READ_ONCE(s);
+       B: idx2 = READ_ONCE(s);
+       C: WRITE_ONCE(s, idx1);
+       D: WRITE_ONCE(s, idx2);
+
+except for the presence of the special srcu-lock and srcu-unlock
+annotations.  You can see at once that we have A ->data C and
+B ->data D.  These dependencies tell the LKMM that C is the
+srcu-unlock event matching srcu-lock event A, and D is the
+srcu-unlock event matching srcu-lock event B.
+
+This approach is admittedly a hack, and it has the potential to lead
+to problems.  For example, in:
+
+       idx1 = srcu_read_lock(&s);
+       srcu_read_unlock(&s, idx1);
+       idx2 = srcu_read_lock(&s);
+       srcu_read_unlock(&s, idx2);
+
+the LKMM will believe that idx2 must have the same value as idx1,
+since it reads from the immediately preceding store of idx1 in s.
+Fortunately this won't matter, assuming that litmus tests never do
+anything with SRCU index values other than pass them to
+srcu_read_unlock() or srcu_up_read() calls.
+
+However, sometimes it is necessary to store an index value in a
+shared variable temporarily.  In fact, this is the only way for
+srcu_down_read() to pass the index it gets to an srcu_up_read() call
+on a different CPU.  In more detail, we might have soething like:
+
+       struct srcu_struct s;
+       int x;
+
+       P0()
+       {
+               int r0;
+
+               A: r0 = srcu_down_read(&s);
+               B: WRITE_ONCE(x, r0);
+       }
+
+       P1()
+       {
+               int r1;
+
+               C: r1 = READ_ONCE(x);
+               D: srcu_up_read(&s, r1);
+       }
+
+Assuming that P1 executes after P0 and does read the index value
+stored in x, we can write this (using brackets to represent event
+annotations) as:
+
+       A[srcu-lock] ->data B[once] ->rf C[once] ->data D[srcu-unlock].
+
+The LKMM defines a carry-srcu-data relation to express this pattern;
+it permits an arbitrarily long sequence of
+
+       data ; rf
+
+pairs (that is, a data link followed by an rf link) to occur between
+an srcu-lock event and the final data dependency leading to the
+matching srcu-unlock event.  carry-srcu-data is complicated by the
+need to ensure that none of the intermediate store events in this
+sequence are instances of srcu-unlock.  This is necessary because in a
+pattern like the one above:
+
+       A: idx1 = srcu_read_lock(&s);
+       B: srcu_read_unlock(&s, idx1);
+       C: idx2 = srcu_read_lock(&s);
+       D: srcu_read_unlock(&s, idx2);
+
+the LKMM treats B as a store to the variable s and C as a load from
+that variable, creating an undesirable rf link from B to C:
+
+       A ->data B ->rf C ->data D.
+
+This would cause carry-srcu-data to mistakenly extend a data
+dependency from A to D, giving the impression that D was the
+srcu-unlock event matching A's srcu-lock.  To avoid such problems,
+carry-srcu-data does not accept sequences in which the ends of any of
+the intermediate ->data links (B above) is an srcu-unlock event.
 
 
 LOCKING
index 26554b1c5575e086578d1af42318bc461cb3587c..acac527328a1f092dc8aea877444020394153caa 100644 (file)
@@ -1028,32 +1028,7 @@ Limitations of the Linux-kernel memory model (LKMM) include:
                additional call_rcu() process to the site of the
                emulated rcu-barrier().
 
-       e.      Although sleepable RCU (SRCU) is now modeled, there
-               are some subtle differences between its semantics and
-               those in the Linux kernel.  For example, the kernel
-               might interpret the following sequence as two partially
-               overlapping SRCU read-side critical sections:
-
-                        1  r1 = srcu_read_lock(&my_srcu);
-                        2  do_something_1();
-                        3  r2 = srcu_read_lock(&my_srcu);
-                        4  do_something_2();
-                        5  srcu_read_unlock(&my_srcu, r1);
-                        6  do_something_3();
-                        7  srcu_read_unlock(&my_srcu, r2);
-
-               In contrast, LKMM will interpret this as a nested pair of
-               SRCU read-side critical sections, with the outer critical
-               section spanning lines 1-7 and the inner critical section
-               spanning lines 3-5.
-
-               This difference would be more of a concern had anyone
-               identified a reasonable use case for partially overlapping
-               SRCU read-side critical sections.  For more information
-               on the trickiness of such overlapping, please see:
-               https://paulmck.livejournal.com/40593.html
-
-       f.      Reader-writer locking is not modeled.  It can be
+       e.      Reader-writer locking is not modeled.  It can be
                emulated in litmus tests using atomic read-modify-write
                operations.
 
diff --git a/tools/memory-model/Documentation/locking.txt b/tools/memory-model/Documentation/locking.txt
new file mode 100644 (file)
index 0000000..65c898c
--- /dev/null
@@ -0,0 +1,298 @@
+Locking
+=======
+
+Locking is well-known and the common use cases are straightforward: Any
+CPU holding a given lock sees any changes previously seen or made by any
+CPU before it previously released that same lock.  This last sentence
+is the only part of this document that most developers will need to read.
+
+However, developers who would like to also access lock-protected shared
+variables outside of their corresponding locks should continue reading.
+
+
+Locking and Prior Accesses
+--------------------------
+
+The basic rule of locking is worth repeating:
+
+       Any CPU holding a given lock sees any changes previously seen
+       or made by any CPU before it previously released that same lock.
+
+Note that this statement is a bit stronger than "Any CPU holding a
+given lock sees all changes made by any CPU during the time that CPU was
+previously holding this same lock".  For example, consider the following
+pair of code fragments:
+
+       /* See MP+polocks.litmus. */
+       void CPU0(void)
+       {
+               WRITE_ONCE(x, 1);
+               spin_lock(&mylock);
+               WRITE_ONCE(y, 1);
+               spin_unlock(&mylock);
+       }
+
+       void CPU1(void)
+       {
+               spin_lock(&mylock);
+               r0 = READ_ONCE(y);
+               spin_unlock(&mylock);
+               r1 = READ_ONCE(x);
+       }
+
+The basic rule guarantees that if CPU0() acquires mylock before CPU1(),
+then both r0 and r1 must be set to the value 1.  This also has the
+consequence that if the final value of r0 is equal to 1, then the final
+value of r1 must also be equal to 1.  In contrast, the weaker rule would
+say nothing about the final value of r1.
+
+
+Locking and Subsequent Accesses
+-------------------------------
+
+The converse to the basic rule also holds:  Any CPU holding a given
+lock will not see any changes that will be made by any CPU after it
+subsequently acquires this same lock.  This converse statement is
+illustrated by the following litmus test:
+
+       /* See MP+porevlocks.litmus. */
+       void CPU0(void)
+       {
+               r0 = READ_ONCE(y);
+               spin_lock(&mylock);
+               r1 = READ_ONCE(x);
+               spin_unlock(&mylock);
+       }
+
+       void CPU1(void)
+       {
+               spin_lock(&mylock);
+               WRITE_ONCE(x, 1);
+               spin_unlock(&mylock);
+               WRITE_ONCE(y, 1);
+       }
+
+This converse to the basic rule guarantees that if CPU0() acquires
+mylock before CPU1(), then both r0 and r1 must be set to the value 0.
+This also has the consequence that if the final value of r1 is equal
+to 0, then the final value of r0 must also be equal to 0.  In contrast,
+the weaker rule would say nothing about the final value of r0.
+
+These examples show only a single pair of CPUs, but the effects of the
+locking basic rule extend across multiple acquisitions of a given lock
+across multiple CPUs.
+
+
+Double-Checked Locking
+----------------------
+
+It is well known that more than just a lock is required to make
+double-checked locking work correctly,  This litmus test illustrates
+one incorrect approach:
+
+       /* See Documentation/litmus-tests/locking/DCL-broken.litmus. */
+       void CPU0(void)
+       {
+               r0 = READ_ONCE(flag);
+               if (r0 == 0) {
+                       spin_lock(&lck);
+                       r1 = READ_ONCE(flag);
+                       if (r1 == 0) {
+                               WRITE_ONCE(data, 1);
+                               WRITE_ONCE(flag, 1);
+                       }
+                       spin_unlock(&lck);
+               }
+               r2 = READ_ONCE(data);
+       }
+       /* CPU1() is the exactly the same as CPU0(). */
+
+There are two problems.  First, there is no ordering between the first
+READ_ONCE() of "flag" and the READ_ONCE() of "data".  Second, there is
+no ordering between the two WRITE_ONCE() calls.  It should therefore be
+no surprise that "r2" can be zero, and a quick herd7 run confirms this.
+
+One way to fix this is to use smp_load_acquire() and smp_store_release()
+as shown in this corrected version:
+
+       /* See Documentation/litmus-tests/locking/DCL-fixed.litmus. */
+       void CPU0(void)
+       {
+               r0 = smp_load_acquire(&flag);
+               if (r0 == 0) {
+                       spin_lock(&lck);
+                       r1 = READ_ONCE(flag);
+                       if (r1 == 0) {
+                               WRITE_ONCE(data, 1);
+                               smp_store_release(&flag, 1);
+                       }
+                       spin_unlock(&lck);
+               }
+               r2 = READ_ONCE(data);
+       }
+       /* CPU1() is the exactly the same as CPU0(). */
+
+The smp_load_acquire() guarantees that its load from "flags" will
+be ordered before the READ_ONCE() from data, thus solving the first
+problem.  The smp_store_release() guarantees that its store will be
+ordered after the WRITE_ONCE() to "data", solving the second problem.
+The smp_store_release() pairs with the smp_load_acquire(), thus ensuring
+that the ordering provided by each actually takes effect.  Again, a
+quick herd7 run confirms this.
+
+In short, if you access a lock-protected variable without holding the
+corresponding lock, you will need to provide additional ordering, in
+this case, via the smp_load_acquire() and the smp_store_release().
+
+
+Ordering Provided by a Lock to CPUs Not Holding That Lock
+---------------------------------------------------------
+
+It is not necessarily the case that accesses ordered by locking will be
+seen as ordered by CPUs not holding that lock.  Consider this example:
+
+       /* See Z6.0+pooncelock+pooncelock+pombonce.litmus. */
+       void CPU0(void)
+       {
+               spin_lock(&mylock);
+               WRITE_ONCE(x, 1);
+               WRITE_ONCE(y, 1);
+               spin_unlock(&mylock);
+       }
+
+       void CPU1(void)
+       {
+               spin_lock(&mylock);
+               r0 = READ_ONCE(y);
+               WRITE_ONCE(z, 1);
+               spin_unlock(&mylock);
+       }
+
+       void CPU2(void)
+       {
+               WRITE_ONCE(z, 2);
+               smp_mb();
+               r1 = READ_ONCE(x);
+       }
+
+Counter-intuitive though it might be, it is quite possible to have
+the final value of r0 be 1, the final value of z be 2, and the final
+value of r1 be 0.  The reason for this surprising outcome is that CPU2()
+never acquired the lock, and thus did not fully benefit from the lock's
+ordering properties.
+
+Ordering can be extended to CPUs not holding the lock by careful use
+of smp_mb__after_spinlock():
+
+       /* See Z6.0+pooncelock+poonceLock+pombonce.litmus. */
+       void CPU0(void)
+       {
+               spin_lock(&mylock);
+               WRITE_ONCE(x, 1);
+               WRITE_ONCE(y, 1);
+               spin_unlock(&mylock);
+       }
+
+       void CPU1(void)
+       {
+               spin_lock(&mylock);
+               smp_mb__after_spinlock();
+               r0 = READ_ONCE(y);
+               WRITE_ONCE(z, 1);
+               spin_unlock(&mylock);
+       }
+
+       void CPU2(void)
+       {
+               WRITE_ONCE(z, 2);
+               smp_mb();
+               r1 = READ_ONCE(x);
+       }
+
+This addition of smp_mb__after_spinlock() strengthens the lock
+acquisition sufficiently to rule out the counter-intuitive outcome.
+In other words, the addition of the smp_mb__after_spinlock() prohibits
+the counter-intuitive result where the final value of r0 is 1, the final
+value of z is 2, and the final value of r1 is 0.
+
+
+No Roach-Motel Locking!
+-----------------------
+
+This example requires familiarity with the herd7 "filter" clause, so
+please read up on that topic in litmus-tests.txt.
+
+It is tempting to allow memory-reference instructions to be pulled
+into a critical section, but this cannot be allowed in the general case.
+For example, consider a spin loop preceding a lock-based critical section.
+Now, herd7 does not model spin loops, but we can emulate one with two
+loads, with a "filter" clause to constrain the first to return the
+initial value and the second to return the updated value, as shown below:
+
+       /* See Documentation/litmus-tests/locking/RM-fixed.litmus. */
+       void CPU0(void)
+       {
+               spin_lock(&lck);
+               r2 = atomic_inc_return(&y);
+               WRITE_ONCE(x, 1);
+               spin_unlock(&lck);
+       }
+
+       void CPU1(void)
+       {
+               r0 = READ_ONCE(x);
+               r1 = READ_ONCE(x);
+               spin_lock(&lck);
+               r2 = atomic_inc_return(&y);
+               spin_unlock(&lck);
+       }
+
+       filter (1:r0=0 /\ 1:r1=1)
+       exists (1:r2=1)
+
+The variable "x" is the control variable for the emulated spin loop.
+CPU0() sets it to "1" while holding the lock, and CPU1() emulates the
+spin loop by reading it twice, first into "1:r0" (which should get the
+initial value "0") and then into "1:r1" (which should get the updated
+value "1").
+
+The "filter" clause takes this into account, constraining "1:r0" to
+equal "0" and "1:r1" to equal 1.
+
+Then the "exists" clause checks to see if CPU1() acquired its lock first,
+which should not happen given the filter clause because CPU0() updates
+"x" while holding the lock.  And herd7 confirms this.
+
+But suppose that the compiler was permitted to reorder the spin loop
+into CPU1()'s critical section, like this:
+
+       /* See Documentation/litmus-tests/locking/RM-broken.litmus. */
+       void CPU0(void)
+       {
+               int r2;
+
+               spin_lock(&lck);
+               r2 = atomic_inc_return(&y);
+               WRITE_ONCE(x, 1);
+               spin_unlock(&lck);
+       }
+
+       void CPU1(void)
+       {
+               spin_lock(&lck);
+               r0 = READ_ONCE(x);
+               r1 = READ_ONCE(x);
+               r2 = atomic_inc_return(&y);
+               spin_unlock(&lck);
+       }
+
+       filter (1:r0=0 /\ 1:r1=1)
+       exists (1:r2=1)
+
+If "1:r0" is equal to "0", "1:r1" can never equal "1" because CPU0()
+cannot update "x" while CPU1() holds the lock.  And herd7 confirms this,
+showing zero executions matching the "filter" criteria.
+
+And this is why Linux-kernel lock and unlock primitives must prevent
+code from entering critical sections.  It is not sufficient to only
+prevent code from leaving them.
index 70a9073dec3e57a08faf6bb0b3d70dd11abc0138..ce068700939c559edc8c91b9a931a0feae82e159 100644 (file)
@@ -31,7 +31,8 @@ enum Barriers = 'wmb (*smp_wmb*) ||
                'before-atomic (*smp_mb__before_atomic*) ||
                'after-atomic (*smp_mb__after_atomic*) ||
                'after-spinlock (*smp_mb__after_spinlock*) ||
-               'after-unlock-lock (*smp_mb__after_unlock_lock*)
+               'after-unlock-lock (*smp_mb__after_unlock_lock*) ||
+               'after-srcu-read-unlock (*smp_mb__after_srcu_read_unlock*)
 instructions F[Barriers]
 
 (* SRCU *)
@@ -53,38 +54,31 @@ let rcu-rscs = let rec
        in matched
 
 (* Validate nesting *)
-flag ~empty Rcu-lock \ domain(rcu-rscs) as unbalanced-rcu-locking
-flag ~empty Rcu-unlock \ range(rcu-rscs) as unbalanced-rcu-locking
+flag ~empty Rcu-lock \ domain(rcu-rscs) as unmatched-rcu-lock
+flag ~empty Rcu-unlock \ range(rcu-rscs) as unmatched-rcu-unlock
 
 (* Compute matching pairs of nested Srcu-lock and Srcu-unlock *)
-let srcu-rscs = let rec
-           unmatched-locks = Srcu-lock \ domain(matched)
-       and unmatched-unlocks = Srcu-unlock \ range(matched)
-       and unmatched = unmatched-locks | unmatched-unlocks
-       and unmatched-po = ([unmatched] ; po ; [unmatched]) & loc
-       and unmatched-locks-to-unlocks =
-               ([unmatched-locks] ; po ; [unmatched-unlocks]) & loc
-       and matched = matched | (unmatched-locks-to-unlocks \
-               (unmatched-po ; unmatched-po))
-       in matched
+let carry-srcu-data = (data ; [~ Srcu-unlock] ; rf)*
+let srcu-rscs = ([Srcu-lock] ; carry-srcu-data ; data ; [Srcu-unlock]) & loc
 
 (* Validate nesting *)
-flag ~empty Srcu-lock \ domain(srcu-rscs) as unbalanced-srcu-locking
-flag ~empty Srcu-unlock \ range(srcu-rscs) as unbalanced-srcu-locking
+flag ~empty Srcu-lock \ domain(srcu-rscs) as unmatched-srcu-lock
+flag ~empty Srcu-unlock \ range(srcu-rscs) as unmatched-srcu-unlock
+flag ~empty (srcu-rscs^-1 ; srcu-rscs) \ id as multiple-srcu-matches
 
 (* Check for use of synchronize_srcu() inside an RCU critical section *)
 flag ~empty rcu-rscs & (po ; [Sync-srcu] ; po) as invalid-sleep
 
 (* Validate SRCU dynamic match *)
-flag ~empty different-values(srcu-rscs) as srcu-bad-nesting
+flag ~empty different-values(srcu-rscs) as srcu-bad-value-match
 
 (* Compute marked and plain memory accesses *)
 let Marked = (~M) | IW | Once | Release | Acquire | domain(rmw) | range(rmw) |
-               LKR | LKW | UL | LF | RL | RU
+               LKR | LKW | UL | LF | RL | RU | Srcu-lock | Srcu-unlock
 let Plain = M \ Marked
 
 (* Redefine dependencies to include those carried through plain accesses *)
-let carry-dep = (data ; rfi)*
+let carry-dep = (data ; [~ Srcu-unlock] ; rfi)*
 let addr = carry-dep ; addr
 let ctrl = carry-dep ; ctrl
 let data = carry-dep ; data
index 07f884f9b2bff045a68bfe17ca2c2a6d82d1cd71..adf3c4f412296269bb9f8127cd7e04f276479a57 100644 (file)
@@ -37,8 +37,20 @@ let mb = ([M] ; fencerel(Mb) ; [M]) |
        ([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) |
        ([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) |
        ([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) |
-       ([M] ; po ; [UL] ; (co | po) ; [LKW] ;
-               fencerel(After-unlock-lock) ; [M])
+(*
+ * Note: The po-unlock-lock-po relation only passes the lock to the direct
+ * successor, perhaps giving the impression that the ordering of the
+ * smp_mb__after_unlock_lock() fence only affects a single lock handover.
+ * However, in a longer sequence of lock handovers, the implicit
+ * A-cumulative release fences of lock-release ensure that any stores that
+ * propagate to one of the involved CPUs before it hands over the lock to
+ * the next CPU will also propagate to the final CPU handing over the lock
+ * to the CPU that executes the fence.  Therefore, all those stores are
+ * also affected by the fence.
+ *)
+       ([M] ; po-unlock-lock-po ;
+               [After-unlock-lock] ; po ; [M]) |
+       ([M] ; po? ; [Srcu-unlock] ; fencerel(After-srcu-read-unlock) ; [M])
 let gp = po ; [Sync-rcu | Sync-srcu] ; po?
 let strong-fence = mb | gp
 
@@ -69,8 +81,8 @@ let dep = addr | data
 let rwdep = (dep | ctrl) ; [W]
 let overwrite = co | fr
 let to-w = rwdep | (overwrite & int) | (addr ; [Plain] ; wmb)
-let to-r = addr | (dep ; [Marked] ; rfi)
-let ppo = to-r | to-w | fence | (po-unlock-lock-po & int)
+let to-r = (addr ; [R]) | (dep ; [Marked] ; rfi)
+let ppo = to-r | to-w | (fence & int) | (po-unlock-lock-po & int)
 
 (* Propagation: Ordering from release operations and strong fences. *)
 let A-cumul(r) = (rfe ; [Marked])? ; r
index ef0f3c1850dee2d212e0c69e8eb61e3b3b5b90e9..88a39601f52563b670876e3ef4950324dc66224a 100644 (file)
@@ -24,6 +24,7 @@ smp_mb__before_atomic() { __fence{before-atomic}; }
 smp_mb__after_atomic() { __fence{after-atomic}; }
 smp_mb__after_spinlock() { __fence{after-spinlock}; }
 smp_mb__after_unlock_lock() { __fence{after-unlock-lock}; }
+smp_mb__after_srcu_read_unlock() { __fence{after-srcu-read-unlock}; }
 barrier() { __fence{barrier}; }
 
 // Exchange
@@ -49,8 +50,10 @@ synchronize_rcu() { __fence{sync-rcu}; }
 synchronize_rcu_expedited() { __fence{sync-rcu}; }
 
 // SRCU
-srcu_read_lock(X)  __srcu{srcu-lock}(X)
-srcu_read_unlock(X,Y) { __srcu{srcu-unlock}(X,Y); }
+srcu_read_lock(X) __load{srcu-lock}(*X)
+srcu_read_unlock(X,Y) { __store{srcu-unlock}(*X,Y); }
+srcu_down_read(X) __load{srcu-lock}(*X)
+srcu_up_read(X,Y) { __store{srcu-unlock}(*X,Y); }
 synchronize_srcu(X)  { __srcu{sync-srcu}(X); }
 synchronize_srcu_expedited(X)  { __srcu{sync-srcu}(X); }
 
index c492a1ddad91d54a5b76e218a61a92d441ac8659..19c379cf069d2369db344673624a783834f9adce 100644 (file)
@@ -1,2 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-*.litmus.out
+*.litmus.*
index 6b52f365d73ac4ab99fe1270871f308a51ad2d76..53b5a492739d03ac8d30adc081e075b7ef635bb8 100644 (file)
@@ -36,9 +36,9 @@ let RU = try RU with emptyset
 (* Treat RL as a kind of LF: a read with no ordering properties *)
 let LF = LF | RL
 
-(* There should be no ordinary R or W accesses to spinlocks *)
-let ALL-LOCKS = LKR | LKW | UL | LF | RU
-flag ~empty [M \ IW] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
+(* There should be no ordinary R or W accesses to spinlocks or SRCU structs *)
+let ALL-LOCKS = LKR | LKW | UL | LF | RU | Srcu-lock | Srcu-unlock | Sync-srcu
+flag ~empty [M \ IW \ ALL-LOCKS] ; loc ; [ALL-LOCKS] as mixed-lock-accesses
 
 (* Link Lock-Reads to their RMW-partner Lock-Writes *)
 let lk-rmw = ([LKR] ; po-loc ; [LKW]) \ (po ; po)
index 095c7eb36f9f90a38c2acf50a49ec276fa02f097..fb39bd0fd1b9d2f8e099f83e8da36e8d63774e68 100644 (file)
@@ -27,6 +27,14 @@ checklitmushist.sh
 checklitmus.sh
 
        Check a single litmus test against its "Result:" expected result.
+       Not intended to for manual use.
+
+checktheselitmus.sh
+
+       Check the specified list of litmus tests against their "Result:"
+       expected results.  This takes optional parseargs.sh arguments,
+       followed by "--" followed by pathnames starting from the current
+       directory.
 
 cmplitmushist.sh
 
@@ -43,10 +51,10 @@ initlitmushist.sh
 
 judgelitmus.sh
 
-       Given a .litmus file and its .litmus.out herd7 output, check the
-       .litmus.out file against the .litmus file's "Result:" comment to
-       judge whether the test ran correctly.  Not normally run manually,
-       provided instead for use by other scripts.
+       Given a .litmus file and its herd7 output, check the output file
+       against the .litmus file's "Result:" comment to judge whether
+       the test ran correctly.  Not normally run manually, provided
+       instead for use by other scripts.
 
 newlitmushist.sh
 
@@ -68,3 +76,35 @@ runlitmushist.sh
 README
 
        This file
+
+Testing a change to LKMM might go as follows:
+
+       # Populate expected results without that change, and
+       # runs for about an hour on an 8-CPU x86 system:
+       scripts/initlitmushist.sh --timeout 10m --procs 10
+       # Incorporate the change:
+       git am -s -3 /path/to/patch # Or whatever it takes.
+
+       # Test the new version of LKMM as follows...
+
+       # Runs in seconds, good smoke test:
+       scripts/checkalllitmus.sh
+
+       # Compares results to those produced by initlitmushist.sh,
+       # and runs for about an hour on an 8-CPU x86 system:
+       scripts/checklitmushist.sh --timeout 10m --procs 10
+
+       # Checks results against Result tags, runs in minutes:
+       scripts/checkghlitmus.sh --timeout 10m --procs 10
+
+The checkghlitmus.sh should not report errors in cases where the
+checklitmushist.sh script did not also report a change.  However,
+this check is nevertheless valuable because it can find errors in the
+original version of LKMM.  Note however, that given the above procedure,
+an error in the original LKMM version that is fixed by the patch will
+be reported both as a mismatch by checklitmushist.sh and as an error
+by checkghlitmus.sh.  One exception to this rule of thumb is when the
+test fails completely on the original version of LKMM and passes on the
+new version.  In this case, checklitmushist.sh will report a mismatch
+and checkghlitmus.sh will report success.  This happens when the change
+to LKMM introduces a new primitive for which litmus tests already existed.
index 3c0c7fbbd223b77d173a070d167553edd350daec..2d3ee850a8399ee49f59342f2e13f0333c745f38 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: GPL-2.0+
 #
 # Run herd7 tests on all .litmus files in the litmus-tests directory
@@ -8,6 +8,11 @@
 # "^^^".  It also outputs verification results to a file whose name is
 # that of the specified litmus test, but with ".out" appended.
 #
+# If the --hw argument is specified, this script translates the .litmus
+# C-language file to the specified type of assembly and verifies that.
+# But in this case, litmus tests using complex synchronization (such as
+# locking, RCU, and SRCU) are cheerfully ignored.
+#
 # Usage:
 #      checkalllitmus.sh
 #
@@ -17,7 +22,7 @@
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
 
 . scripts/parseargs.sh
 
@@ -30,29 +35,23 @@ else
        exit 255
 fi
 
-# Create any new directories that have appeared in the github litmus
-# repo since the last run.
+# Create any new directories that have appeared in the litmus-tests
+# directory since the last run.
 if test "$LKMM_DESTDIR" != "."
 then
        find $litmusdir -type d -print |
        ( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh )
 fi
 
-# Find the checklitmus script.  If it is not where we expect it, then
-# assume that the caller has the PATH environment variable set
-# appropriately.
-if test -x scripts/checklitmus.sh
-then
-       clscript=scripts/checklitmus.sh
-else
-       clscript=checklitmus.sh
-fi
-
 # Run the script on all the litmus tests in the specified directory
 ret=0
 for i in $litmusdir/*.litmus
 do
-       if ! $clscript $i
+       if test -n "$LKMM_HW_MAP_FILE" && ! scripts/simpletest.sh $i
+       then
+               continue
+       fi
+       if ! scripts/checklitmus.sh $i
        then
                ret=1
        fi
index 6589fbb6f6538339c2a126288f75b8b476a3f0c3..d3dfb321259f223ef342733fe96dc65fa96d9624 100755 (executable)
@@ -10,6 +10,7 @@
 # parseargs.sh scripts for arguments.
 
 . scripts/parseargs.sh
+. scripts/hwfnseg.sh
 
 T=/tmp/checkghlitmus.sh.$$
 trap 'rm -rf $T' 0
@@ -32,19 +33,19 @@ then
        ( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh )
 fi
 
-# Create a list of the C-language litmus tests previously run.
-( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) |
-       sed -e 's/\.out$//' |
-       xargs -r egrep -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' |
+# Create a list of the specified litmus tests previously run.
+( cd $LKMM_DESTDIR; find litmus -name "*.litmus${hwfnseg}.out" -print ) |
+       sed -e "s/${hwfnseg}"'\.out$//' |
+       xargs -r grep -E -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' |
        xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already
 
 # Create a list of C-language litmus tests with "Result:" commands and
 # no more than the specified number of processes.
-find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C
-xargs < $T/list-C -r egrep -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' > $T/list-C-result
+find litmus -name '*.litmus' -print | mselect7 -arch C > $T/list-C
+xargs < $T/list-C -r grep -E -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' > $T/list-C-result
 xargs < $T/list-C-result -r grep -L "^P${LKMM_PROCS}" > $T/list-C-result-short
 
-# Form list of tests without corresponding .litmus.out files
+# Form list of tests without corresponding .out files
 sort $T/list-C-already $T/list-C-result-short | uniq -u > $T/list-C-needed
 
 # Run any needed tests.
index 11461ed40b5e456be0145e45d2ef4464895fed15..4c1d0cf0ddadcf93eb860c986167f013b354daf7 100755 (executable)
@@ -1,10 +1,8 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0+
 #
-# Run a herd7 test and invokes judgelitmus.sh to check the result against
-# a "Result:" comment within the litmus test.  It also outputs verification
-# results to a file whose name is that of the specified litmus test, but
-# with ".out" appended.
+# Invokes runlitmus.sh and judgelitmus.sh on its arguments to run the
+# specified litmus test and pass judgment on the results.
 #
 # Usage:
 #      checklitmus.sh file.litmus
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
 
-litmus=$1
-herdoptions=${LKMM_HERD_OPTIONS--conf linux-kernel.cfg}
-
-if test -f "$litmus" -a -r "$litmus"
-then
-       :
-else
-       echo ' --- ' error: \"$litmus\" is not a readable file
-       exit 255
-fi
-
-echo Herd options: $herdoptions > $LKMM_DESTDIR/$litmus.out
-/usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $litmus >> $LKMM_DESTDIR/$litmus.out 2>&1
-
-scripts/judgelitmus.sh $litmus
+scripts/runlitmus.sh $1
+scripts/judgelitmus.sh $1
index 1d210ffb7c8af6084518eabcf073864f1fed6a27..406ecfc0aee4ca8654ae4ebf4b8b168dd5e25bb0 100755 (executable)
@@ -12,7 +12,7 @@
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
 
 . scripts/parseargs.sh
 
diff --git a/tools/memory-model/scripts/checktheselitmus.sh b/tools/memory-model/scripts/checktheselitmus.sh
new file mode 100755 (executable)
index 0000000..10eeb5e
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Invokes checklitmus.sh on its arguments to run the specified litmus
+# test and pass judgment on the results.
+#
+# Usage:
+#      checktheselitmus.sh -- [ file1.litmus [ file2.litmus ... ] ]
+#
+# Run this in the directory containing the memory model, specifying the
+# pathname of the litmus test to check.  The usual parseargs.sh arguments
+# can be specified prior to the "--".
+#
+# This script is intended for use with pathnames that start from the
+# tools/memory-model directory.  If some of the pathnames instead start at
+# the root directory, they all must do so and the "--destdir /" parseargs.sh
+# argument must be specified prior to the "--".  Alternatively, some other
+# "--destdir" argument can be supplied as long as the needed subdirectories
+# are populated.
+#
+# Copyright IBM Corporation, 2018
+#
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
+
+. scripts/parseargs.sh
+
+ret=0
+for i in "$@"
+do
+       if scripts/checklitmus.sh $i
+       then
+               :
+       else
+               ret=1
+       fi
+done
+if test "$ret" -ne 0
+then
+       echo " ^^^ VERIFICATION MISMATCHES" 1>&2
+else
+       echo All litmus tests verified as was expected. 1>&2
+fi
+exit $ret
index 0f498aeeccf5ec6cc76fd2634aa1204db73bdce5..ca1ac8b646144ac95b0ae13d5534bbebcf411ea6 100755 (executable)
@@ -12,12 +12,49 @@ trap 'rm -rf $T' 0
 mkdir $T
 
 # comparetest oldpath newpath
+badmacnam=0
+timedout=0
 perfect=0
 obsline=0
 noobsline=0
 obsresult=0
 badcompare=0
 comparetest () {
+       if grep -q ': Unknown macro ' $1 || grep -q ': Unknown macro ' $2
+       then
+               if grep -q ': Unknown macro ' $1
+               then
+                       badname=`grep ': Unknown macro ' $1 |
+                               sed -e 's/^.*: Unknown macro //' |
+                               sed -e 's/ (User error).*$//'`
+                       echo 'Current LKMM version does not know "'$badname'"' $1
+               fi
+               if grep -q ': Unknown macro ' $2
+               then
+                       badname=`grep ': Unknown macro ' $2 |
+                               sed -e 's/^.*: Unknown macro //' |
+                               sed -e 's/ (User error).*$//'`
+                       echo 'Current LKMM version does not know "'$badname'"' $2
+               fi
+               badmacnam=`expr "$badmacnam" + 1`
+               return 0
+       elif grep -q '^Command exited with non-zero status 124' $1 ||
+            grep -q '^Command exited with non-zero status 124' $2
+       then
+               if grep -q '^Command exited with non-zero status 124' $1 &&
+                  grep -q '^Command exited with non-zero status 124' $2
+               then
+                       echo Both runs timed out: $2
+               elif grep -q '^Command exited with non-zero status 124' $1
+               then
+                       echo Old run timed out: $2
+               elif grep -q '^Command exited with non-zero status 124' $2
+               then
+                       echo New run timed out: $2
+               fi
+               timedout=`expr "$timedout" + 1`
+               return 0
+       fi
        grep -v 'maxresident)k\|minor)pagefaults\|^Time' $1 > $T/oldout
        grep -v 'maxresident)k\|minor)pagefaults\|^Time' $2 > $T/newout
        if cmp -s $T/oldout $T/newout && grep -q '^Observation' $1
@@ -38,7 +75,7 @@ comparetest () {
                        return 0
                fi
        else
-               echo Missing Observation line "(e.g., herd7 timeout)": $2
+               echo Missing Observation line "(e.g., syntax error)": $2
                noobsline=`expr "$noobsline" + 1`
                return 0
        fi
@@ -72,12 +109,20 @@ then
 fi
 if test "$noobsline" -ne 0
 then
-       echo Missing Observation line "(e.g., herd7 timeout)": $noobsline 1>&2
+       echo Missing Observation line "(e.g., syntax error)": $noobsline 1>&2
 fi
 if test "$obsresult" -ne 0
 then
        echo Matching Observation Always/Sometimes/Never result: $obsresult 1>&2
 fi
+if test "$timedout" -ne 0
+then
+       echo "!!!" Timed out: $timedout 1>&2
+fi
+if test "$badmacnam" -ne 0
+then
+       echo "!!!" Unknown primitive: $badmacnam 1>&2
+fi
 if test "$badcompare" -ne 0
 then
        echo "!!!" Result changed: $badcompare 1>&2
diff --git a/tools/memory-model/scripts/hwfnseg.sh b/tools/memory-model/scripts/hwfnseg.sh
new file mode 100755 (executable)
index 0000000..580c328
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Generate the hardware extension to the litmus-test filename, or the
+# empty string if this is an LKMM run.  The extension is placed in
+# the shell variable hwfnseg.
+#
+# Usage:
+#      . hwfnseg.sh
+#
+# Copyright IBM Corporation, 2019
+#
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
+
+if test -z "$LKMM_HW_MAP_FILE"
+then
+       hwfnseg=
+else
+       hwfnseg=".$LKMM_HW_MAP_FILE"
+fi
index 956b6957484d879351d312a1d217df11d9dfd9f2..31ea782955d3f0115ab740d9a0b064228f058878 100755 (executable)
@@ -60,7 +60,7 @@ fi
 
 # Create a list of the C-language litmus tests with no more than the
 # specified number of processes (per the --procs argument).
-find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C
+find litmus -name '*.litmus' -print | mselect7 -arch C > $T/list-C
 xargs < $T/list-C -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short
 
 scripts/runlitmushist.sh < $T/list-C-short
index 0cc63875e395d06fe890c0f711e748a6226f25ea..1ec5d89fcfbb2a2f6e93803882c94104b20d992d 100755 (executable)
@@ -1,9 +1,22 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0+
 #
-# Given a .litmus test and the corresponding .litmus.out file, check
-# the .litmus.out file against the "Result:" comment to judge whether
-# the test ran correctly.
+# Given a .litmus test and the corresponding litmus output file, check
+# the .litmus.out file against the "Result:" comment to judge whether the
+# test ran correctly.  If the --hw argument is omitted, check against the
+# LKMM output, which is assumed to be in file.litmus.out. If either a
+# "DATARACE" marker in the "Result:" comment or a "Flag data-race" marker
+# in the LKMM output is present, the other must also be as well, at least
+# for litmus tests having a "Result:" comment. In this case, a failure of
+# the Always/Sometimes/Never portion of the "Result:" prediction will be
+# noted, but forgiven.
+#
+# If the --hw argument is provided, this is assumed to be a hardware
+# test, and the output is assumed to be in file.litmus.HW.out, where
+# "HW" is the --hw argument. In addition, non-Sometimes verification
+# results will be noted, but forgiven.  Furthermore, if there is no
+# "Result:" comment but there is an LKMM .litmus.out file, the observation
+# in that file will be used to judge the assembly-language verification.
 #
 # Usage:
 #      judgelitmus.sh file.litmus
@@ -13,7 +26,7 @@
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
 
 litmus=$1
 
@@ -24,55 +37,120 @@ else
        echo ' --- ' error: \"$litmus\" is not a readable file
        exit 255
 fi
-if test -f "$LKMM_DESTDIR/$litmus".out -a -r "$LKMM_DESTDIR/$litmus".out
+if test -z "$LKMM_HW_MAP_FILE"
+then
+       litmusout=$litmus.out
+       lkmmout=
+else
+       litmusout="`echo $litmus |
+               sed -e 's/\.litmus$/.litmus.'${LKMM_HW_MAP_FILE}'/'`.out"
+       lkmmout=$litmus.out
+fi
+if test -f "$LKMM_DESTDIR/$litmusout" -a -r "$LKMM_DESTDIR/$litmusout"
 then
        :
 else
-       echo ' --- ' error: \"$LKMM_DESTDIR/$litmus\".out is not a readable file
+       echo ' --- ' error: \"$LKMM_DESTDIR/$litmusout is not a readable file
        exit 255
 fi
-if grep -q '^ \* Result: ' $litmus
+if grep -q '^Flag data-race$' "$LKMM_DESTDIR/$litmusout"
+then
+       datarace_modeled=1
+fi
+if grep -q '^[( ]\* Result: ' $litmus
+then
+       outcome=`grep -m 1 '^[( ]\* Result: ' $litmus | awk '{ print $3 }'`
+       if grep -m1 '^[( ]\* Result: .* DATARACE' $litmus
+       then
+               datarace_predicted=1
+       fi
+       if test -n "$datarace_predicted" -a -z "$datarace_modeled" -a -z "$LKMM_HW_MAP_FILE"
+       then
+               echo '!!! Predicted data race not modeled' $litmus
+               exit 252
+       elif test -z "$datarace_predicted" -a -n "$datarace_modeled"
+       then
+               # Note that hardware models currently don't model data races
+               echo '!!! Unexpected data race modeled' $litmus
+               exit 253
+       fi
+elif test -n "$LKMM_HW_MAP_FILE" && grep -q '^Observation' $LKMM_DESTDIR/$lkmmout > /dev/null 2>&1
 then
-       outcome=`grep -m 1 '^ \* Result: ' $litmus | awk '{ print $3 }'`
+       outcome=`grep -m 1 '^Observation ' $LKMM_DESTDIR/$lkmmout | awk '{ print $3 }'`
 else
        outcome=specified
 fi
 
-grep '^Observation' $LKMM_DESTDIR/$litmus.out
-if grep -q '^Observation' $LKMM_DESTDIR/$litmus.out
+grep '^Observation' $LKMM_DESTDIR/$litmusout
+if grep -q '^Observation' $LKMM_DESTDIR/$litmusout
 then
        :
+elif grep ': Unknown macro ' $LKMM_DESTDIR/$litmusout
+then
+       badname=`grep ': Unknown macro ' $LKMM_DESTDIR/$litmusout |
+               sed -e 's/^.*: Unknown macro //' |
+               sed -e 's/ (User error).*$//'`
+       badmsg=' !!! Current LKMM version does not know "'$badname'"'" $litmus"
+       echo $badmsg
+       if ! grep -q '!!!' $LKMM_DESTDIR/$litmusout
+       then
+               echo ' !!! '$badmsg >> $LKMM_DESTDIR/$litmusout 2>&1
+       fi
+       exit 254
+elif grep '^Command exited with non-zero status 124' $LKMM_DESTDIR/$litmusout
+then
+       echo ' !!! Timeout' $litmus
+       if ! grep -q '!!!' $LKMM_DESTDIR/$litmusout
+       then
+               echo ' !!! Timeout' >> $LKMM_DESTDIR/$litmusout 2>&1
+       fi
+       exit 124
 else
        echo ' !!! Verification error' $litmus
-       if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out
+       if ! grep -q '!!!' $LKMM_DESTDIR/$litmusout
        then
-               echo ' !!! Verification error' >> $LKMM_DESTDIR/$litmus.out 2>&1
+               echo ' !!! Verification error' >> $LKMM_DESTDIR/$litmusout 2>&1
        fi
        exit 255
 fi
 if test "$outcome" = DEADLOCK
 then
-       if grep '^Observation' $LKMM_DESTDIR/$litmus.out | grep -q 'Never 0 0$'
+       if grep '^Observation' $LKMM_DESTDIR/$litmusout | grep -q 'Never 0 0$'
        then
                ret=0
        else
                echo " !!! Unexpected non-$outcome verification" $litmus
-               if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out
+               if ! grep -q '!!!' $LKMM_DESTDIR/$litmusout
                then
-                       echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmus.out 2>&1
+                       echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmusout 2>&1
                fi
                ret=1
        fi
-elif grep '^Observation' $LKMM_DESTDIR/$litmus.out | grep -q $outcome || test "$outcome" = Maybe
+elif grep '^Observation' $LKMM_DESTDIR/$litmusout | grep -q 'Never 0 0$'
+then
+       echo " !!! Unexpected non-$outcome deadlock" $litmus
+       if ! grep -q '!!!' $LKMM_DESTDIR/$litmusout
+       then
+               echo " !!! Unexpected non-$outcome deadlock" $litmus >> $LKMM_DESTDIR/$litmusout 2>&1
+       fi
+       ret=1
+elif grep '^Observation' $LKMM_DESTDIR/$litmusout | grep -q $outcome || test "$outcome" = Maybe
 then
        ret=0
 else
-       echo " !!! Unexpected non-$outcome verification" $litmus
-       if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out
+       if test \( -n "$LKMM_HW_MAP_FILE" -a "$outcome" = Sometimes \) -o -n "$datarace_modeled"
        then
-               echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmus.out 2>&1
+               flag="--- Forgiven"
+               ret=0
+       else
+               flag="!!! Unexpected"
+               ret=1
+       fi
+       echo " $flag non-$outcome verification" $litmus
+       if ! grep -qe "$flag" $LKMM_DESTDIR/$litmusout
+       then
+               echo " $flag non-$outcome verification" >> $LKMM_DESTDIR/$litmusout 2>&1
        fi
-       ret=1
 fi
-tail -2 $LKMM_DESTDIR/$litmus.out | head -1
+tail -2 $LKMM_DESTDIR/$litmusout | head -1
 exit $ret
index 991f8f81488174b1c6b165efcc53cec167787138..25235e2049cf05bbc1aa870e822085b1204781c5 100755 (executable)
@@ -12,7 +12,7 @@
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
 
 . scripts/parseargs.sh
 
@@ -43,7 +43,7 @@ fi
 
 # Form full list of litmus tests with no more than the specified
 # number of processes (per the --procs argument).
-find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C-all
+find litmus -name '*.litmus' -print | mselect7 -arch C > $T/list-C-all
 xargs < $T/list-C-all -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short
 
 # Form list of new tests.  Note: This does not handle litmus-test deletion!
index 40f52080fdbd6eb9d82bc3f3bb647fe1da46ffb8..08ded59098607d44c829e6f0a58da8d12545ea46 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0+
 #
-# the corresponding .litmus.out file, and does not judge the result.
+# Parse arguments common to the various scripts.
 #
 # . scripts/parseargs.sh
 #
@@ -9,7 +9,7 @@
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
 
 T=/tmp/parseargs.sh.$$
 mkdir $T
@@ -27,6 +27,7 @@ initparam () {
 
 initparam LKMM_DESTDIR "."
 initparam LKMM_HERD_OPTIONS "-conf linux-kernel.cfg"
+initparam LKMM_HW_MAP_FILE ""
 initparam LKMM_JOBS `getconf _NPROCESSORS_ONLN`
 initparam LKMM_PROCS "3"
 initparam LKMM_TIMEOUT "1m"
@@ -37,10 +38,11 @@ usagehelp () {
        echo "Usage $scriptname [ arguments ]"
        echo "      --destdir path (place for .litmus.out, default by .litmus)"
        echo "      --herdopts -conf linux-kernel.cfg ..."
+       echo "      --hw AArch64"
        echo "      --jobs N (number of jobs, default one per CPU)"
        echo "      --procs N (litmus tests with at most this many processes)"
        echo "      --timeout N (herd7 timeout (e.g., 10s, 1m, 2hr, 1d, '')"
-       echo "Defaults: --destdir '$LKMM_DESTDIR_DEF' --herdopts '$LKMM_HERD_OPTIONS_DEF' --jobs '$LKMM_JOBS_DEF' --procs '$LKMM_PROCS_DEF' --timeout '$LKMM_TIMEOUT_DEF'"
+       echo "Defaults: --destdir '$LKMM_DESTDIR_DEF' --herdopts '$LKMM_HERD_OPTIONS_DEF' --hw '$LKMM_HW_MAP_FILE' --jobs '$LKMM_JOBS_DEF' --procs '$LKMM_PROCS_DEF' --timeout '$LKMM_TIMEOUT_DEF'"
        exit 1
 }
 
@@ -81,7 +83,7 @@ do
                        echo "Cannot create directory --destdir '$LKMM_DESTDIR'"
                        usage
                fi
-               if test -d "$LKMM_DESTDIR" -a -w "$LKMM_DESTDIR" -a -x "$LKMM_DESTDIR"
+               if test -d "$LKMM_DESTDIR" -a -x "$LKMM_DESTDIR"
                then
                        :
                else
@@ -95,6 +97,11 @@ do
                LKMM_HERD_OPTIONS="$2"
                shift
                ;;
+       --hw)
+               checkarg --hw "(.map file architecture name)" "$#" "$2" '^[A-Za-z0-9_-]\+' '^--'
+               LKMM_HW_MAP_FILE="$2"
+               shift
+               ;;
        -j[1-9]*)
                njobs="`echo $1 | sed -e 's/^-j//'`"
                trailchars="`echo $njobs | sed -e 's/[0-9]\+\(.*\)$/\1/'`"
@@ -106,7 +113,7 @@ do
                LKMM_JOBS="`echo $njobs | sed -e 's/^\([0-9]\+\).*$/\1/'`"
                ;;
        --jobs|--job|-j)
-               checkarg --jobs "(number)" "$#" "$2" '^[1-9][0-9]\+$' '^--'
+               checkarg --jobs "(number)" "$#" "$2" '^[1-9][0-9]*$' '^--'
                LKMM_JOBS="$2"
                shift
                ;;
@@ -120,6 +127,10 @@ do
                LKMM_TIMEOUT="$2"
                shift
                ;;
+       --)
+               shift
+               break
+               ;;
        *)
                echo Unknown argument $1
                usage
diff --git a/tools/memory-model/scripts/runlitmus.sh b/tools/memory-model/scripts/runlitmus.sh
new file mode 100755 (executable)
index 0000000..94608d4
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Without the -hw argument, runs a herd7 test and outputs verification
+# results to a file whose name is that of the specified litmus test,
+# but with ".out" appended.
+#
+# If the --hw argument is specified, this script translates the .litmus
+# C-language file to the specified type of assembly and verifies that.
+# But in this case, litmus tests using complex synchronization (such as
+# locking, RCU, and SRCU) are cheerfully ignored.
+#
+# Either way, return the status of the herd7 command.
+#
+# Usage:
+#      runlitmus.sh file.litmus
+#
+# Run this in the directory containing the memory model, specifying the
+# pathname of the litmus test to check.  The caller is expected to have
+# properly set up the LKMM environment variables.
+#
+# Copyright IBM Corporation, 2019
+#
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
+
+litmus=$1
+if test -f "$litmus" -a -r "$litmus"
+then
+       :
+else
+       echo ' !!! ' error: \"$litmus\" is not a readable file
+       exit 255
+fi
+
+if test -z "$LKMM_HW_MAP_FILE" -o ! -e $LKMM_DESTDIR/$litmus.out
+then
+       # LKMM run
+       herdoptions=${LKMM_HERD_OPTIONS--conf linux-kernel.cfg}
+       echo Herd options: $herdoptions > $LKMM_DESTDIR/$litmus.out
+       /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $litmus >> $LKMM_DESTDIR/$litmus.out 2>&1
+       ret=$?
+       if test -z "$LKMM_HW_MAP_FILE"
+       then
+               exit $ret
+       fi
+       echo " --- " Automatically generated LKMM output for '"'--hw $LKMM_HW_MAP_FILE'"' run
+fi
+
+# Hardware run
+
+T=/tmp/checklitmushw.sh.$$
+trap 'rm -rf $T' 0 2
+mkdir $T
+
+# Generate filenames
+mapfile="Linux2${LKMM_HW_MAP_FILE}.map"
+themefile="$T/${LKMM_HW_MAP_FILE}.theme"
+herdoptions="-model $LKMM_HW_CAT_FILE"
+hwlitmus=`echo $litmus | sed -e 's/\.litmus$/.litmus.'${LKMM_HW_MAP_FILE}'/'`
+hwlitmusfile=`echo $hwlitmus | sed -e 's,^.*/,,'`
+
+# Don't run on litmus tests with complex synchronization
+if ! scripts/simpletest.sh $litmus
+then
+       echo ' --- ' error: \"$litmus\" contains locking, RCU, or SRCU
+       exit 254
+fi
+
+# Generate the assembly code and run herd7 on it.
+gen_theme7 -n 10 -map $mapfile -call Linux.call > $themefile
+jingle7 -v -theme $themefile $litmus > $LKMM_DESTDIR/$hwlitmus 2> $T/$hwlitmusfile.jingle7.out
+if grep -q "Generated 0 tests" $T/$hwlitmusfile.jingle7.out
+then
+       echo ' !!! ' jingle7 failed, errors in $hwlitmus.err
+       cp $T/$hwlitmusfile.jingle7.out $LKMM_DESTDIR/$hwlitmus.err
+       exit 253
+fi
+/usr/bin/time $LKMM_TIMEOUT_CMD herd7 -unroll 0 $LKMM_DESTDIR/$hwlitmus > $LKMM_DESTDIR/$hwlitmus.out 2>&1
+
+exit $?
index 6ed376f495bb4eadc72504c66ba5f1ac9a2f9c2f..c6c2bdc67a502169700fbbe6731d75905ade312b 100755 (executable)
@@ -13,7 +13,9 @@
 #
 # Copyright IBM Corporation, 2018
 #
-# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
+
+. scripts/hwfnseg.sh
 
 T=/tmp/runlitmushist.sh.$$
 trap 'rm -rf $T' 0
@@ -30,15 +32,12 @@ fi
 # Prefixes for per-CPU scripts
 for ((i=0;i<$LKMM_JOBS;i++))
 do
-       echo dir="$LKMM_DESTDIR" > $T/$i.sh
        echo T=$T >> $T/$i.sh
-       echo herdoptions=\"$LKMM_HERD_OPTIONS\" >> $T/$i.sh
        cat << '___EOF___' >> $T/$i.sh
        runtest () {
-               echo ' ... ' /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $1 '>' $dir/$1.out '2>&1'
-               if /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $1 > $dir/$1.out 2>&1
+               if scripts/runlitmus.sh $1
                then
-                       if ! grep -q '^Observation ' $dir/$1.out
+                       if ! grep -q '^Observation ' $LKMM_DESTDIR/$1$2.out
                        then
                                echo ' !!! Herd failed, no Observation:' $1
                        fi
@@ -47,10 +46,16 @@ do
                        if test "$exitcode" -eq 124
                        then
                                exitmsg="timed out"
+                       elif test "$exitcode" -eq 253
+                       then
+                               exitmsg=
                        else
                                exitmsg="failed, exit code $exitcode"
                        fi
-                       echo ' !!! Herd' ${exitmsg}: $1
+                       if test -n "$exitmsg"
+                       then
+                               echo ' !!! Herd' ${exitmsg}: $1
+                       fi
                fi
        }
 ___EOF___
@@ -59,11 +64,13 @@ done
 awk -v q="'" -v b='\\' '
 {
        print "echo `grep " q "^P[0-9]" b "+(" q " " $0 " | tail -1 | sed -e " q "s/^P" b "([0-9]" b "+" b ")(.*$/" b "1/" q "` " $0
-}' | bash |
-sort -k1n |
-awk -v ncpu=$LKMM_JOBS -v t=$T '
+}' | sh | sort -k1n |
+awk -v dq='"' -v hwfnseg="$hwfnseg" -v ncpu="$LKMM_JOBS" -v t="$T" '
 {
-       print "runtest " $2 >> t "/" NR % ncpu ".sh";
+       print "if test -z " dq hwfnseg dq " || scripts/simpletest.sh " dq $2 dq
+       print "then"
+       print "\techo runtest " dq $2 dq " " hwfnseg " >> " t "/" NR % ncpu ".sh";
+       print "fi"
 }
 
 END {
diff --git a/tools/memory-model/scripts/simpletest.sh b/tools/memory-model/scripts/simpletest.sh
new file mode 100755 (executable)
index 0000000..7edc5d3
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Give zero status if this is a simple test and non-zero otherwise.
+# Simple tests do not contain locking, RCU, or SRCU.
+#
+# Usage:
+#      simpletest.sh file.litmus
+#
+# Copyright IBM Corporation, 2019
+#
+# Author: Paul E. McKenney <paulmck@linux.ibm.com>
+
+
+litmus=$1
+
+if test -f "$litmus" -a -r "$litmus"
+then
+       :
+else
+       echo ' --- ' error: \"$litmus\" is not a readable file
+       exit 255
+fi
+exclude="^[[:space:]]*\("
+exclude="${exclude}spin_lock(\|spin_unlock(\|spin_trylock(\|spin_is_locked("
+exclude="${exclude}\|rcu_read_lock(\|rcu_read_unlock("
+exclude="${exclude}\|synchronize_rcu(\|synchronize_rcu_expedited("
+exclude="${exclude}\|srcu_read_lock(\|srcu_read_unlock("
+exclude="${exclude}\|synchronize_srcu(\|synchronize_srcu_expedited("
+exclude="${exclude}\)"
+if grep -q $exclude $litmus
+then
+       exit 255
+fi
+exit 0
index 7c2ac124cdc83a21be7ba9bf010b5b1dd120af24..99798894b8790544b3dd83c222c9237af32b94a7 100644 (file)
@@ -857,7 +857,7 @@ int main(int argc, char **argv)
                        if (cull & CULL_PID || filter & FILTER_PID)
                                fprintf(fout, ", PID %d", list[i].pid);
                        if (cull & CULL_TGID || filter & FILTER_TGID)
-                               fprintf(fout, ", TGID %d", list[i].pid);
+                               fprintf(fout, ", TGID %d", list[i].tgid);
                        if (cull & CULL_COMM || filter & FILTER_COMM)
                                fprintf(fout, ", task_comm_name: %s", list[i].comm);
                        if (cull & CULL_ALLOCATOR) {
index a34d088f67432187c0d5b0e457788081d1ba5f95..d04450c2a44af866ef30cf6892a9d0d956c02b92 100644 (file)
@@ -138,10 +138,8 @@ class SpecEnumSet(SpecElement):
 
     def get_mask(self):
         mask = 0
-        idx = self.yaml.get('value-start', 0)
-        for _ in self.entries.values():
-            mask |= 1 << idx
-            idx += 1
+        for e in self.entries.values():
+            mask += e.user_value()
         return mask
 
 
@@ -276,6 +274,7 @@ class SpecFamily(SpecElement):
 
     Attributes:
         proto     protocol type (e.g. genetlink)
+        license   spec license (loaded from an SPDX tag on the spec)
 
         attr_sets  dict of attribute sets
         msgs       dict of all messages (index by name)
@@ -285,6 +284,13 @@ class SpecFamily(SpecElement):
     """
     def __init__(self, spec_path, schema_path=None):
         with open(spec_path, "r") as stream:
+            prefix = '# SPDX-License-Identifier: '
+            first = stream.readline().strip()
+            if not first.startswith(prefix):
+                raise Exception('SPDX license tag required in the spec')
+            self.license = first[len(prefix):]
+
+            stream.seek(0)
             spec = yaml.safe_load(stream)
 
         self._resolution_list = []
@@ -389,7 +395,8 @@ class SpecFamily(SpecElement):
     def resolve(self):
         self.resolve_up(super())
 
-        for elem in self.yaml['definitions']:
+        definitions = self.yaml.get('definitions', [])
+        for elem in definitions:
             if elem['type'] == 'enum' or elem['type'] == 'flags':
                 self.consts[elem['name']] = self.new_enum(elem)
             else:
index 90764a83c6461118d6dd9aeff19d16224bf87f9a..32536e1f9064bba576a267b5a02f6fe16a38d4a5 100644 (file)
@@ -200,7 +200,7 @@ def _genl_msg(nl_type, nl_flags, genl_cmd, genl_version, seq=None):
     if seq is None:
         seq = random.randint(1, 1024)
     nlmsg = struct.pack("HHII", nl_type, nl_flags, seq, 0)
-    genlmsg = struct.pack("bbH", genl_cmd, genl_version, 0)
+    genlmsg = struct.pack("BBH", genl_cmd, genl_version, 0)
     return nlmsg + genlmsg
 
 
@@ -264,7 +264,7 @@ class GenlMsg:
         self.hdr = nl_msg.raw[0:4]
         self.raw = nl_msg.raw[4:]
 
-        self.genl_cmd, self.genl_version, _ = struct.unpack("bbH", self.hdr)
+        self.genl_cmd, self.genl_version, _ = struct.unpack("BBH", self.hdr)
 
         self.raw_attrs = NlAttrs(self.raw)
 
@@ -358,7 +358,7 @@ class YnlFamily(SpecFamily):
                 raw >>= 1
                 i += 1
         else:
-            value = enum['entries'][raw - i]
+            value = enum.entries_by_val[raw - i].name
         rsp[attr_spec['name']] = value
 
     def _decode(self, attrs, space):
index 1bcc5354d8000725b52eeea7d77c8710afcf08c6..c16671a02621bfbbe8018985d614c4766ea7fed0 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
 
 import argparse
 import collections
@@ -1931,9 +1931,14 @@ def render_uapi(family, cw):
 
             if const.get('render-max', False):
                 cw.nl()
-                max_name = c_upper(name_pfx + 'max')
-                cw.p('__' + max_name + ',')
-                cw.p(max_name + ' = (__' + max_name + ' - 1)')
+                if const['type'] == 'flags':
+                    max_name = c_upper(name_pfx + 'mask')
+                    max_val = f' = {enum.get_mask()},'
+                    cw.p(max_name + max_val)
+                else:
+                    max_name = c_upper(name_pfx + 'max')
+                    cw.p('__' + max_name + ',')
+                    cw.p(max_name + ' = (__' + max_name + ' - 1)')
             cw.block_end(line=';')
             cw.nl()
         elif const['type'] == 'const':
@@ -2054,6 +2059,10 @@ def main():
 
     try:
         parsed = Family(args.spec)
+        if parsed.license != '((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)':
+            print('Spec license:', parsed.license)
+            print('License must be: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)')
+            os.sys.exit(1)
     except yaml.YAMLError as exc:
         print(exc)
         os.sys.exit(1)
@@ -2062,13 +2071,10 @@ def main():
     cw = CodeWriter(BaseNlLib(), out_file)
 
     _, spec_kernel = find_kernel_root(args.spec)
-    if args.mode == 'uapi':
-        cw.p('/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */')
+    if args.mode == 'uapi' or args.header:
+        cw.p(f'/* SPDX-License-Identifier: {parsed.license} */')
     else:
-        if args.header:
-            cw.p('/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */')
-        else:
-            cw.p('// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause')
+        cw.p(f'// SPDX-License-Identifier: {parsed.license}')
     cw.p("/* Do not edit directly, auto-generated from: */")
     cw.p(f"/*\t{spec_kernel} */")
     cw.p(f"/* YNL-GEN {args.mode} {'header' if args.header else 'source'} */")
index 8e53fc6735ef2668dcc51f571ec4b1eeb505b72f..744db4218e7ac0d4537d1268ea685a8dea21b904 100644 (file)
@@ -181,7 +181,7 @@ b) ORC (Oops Rewind Capability) unwind table generation
    band.  So it doesn't affect runtime performance and it can be
    reliable even when interrupts or exceptions are involved.
 
-   For more details, see Documentation/x86/orc-unwinder.rst.
+   For more details, see Documentation/arch/x86/orc-unwinder.rst.
 
 c) Higher live patching compatibility rate
 
index f937be1afe65ca9c968038c701b927dd4126f409..50ed63f701f106344f88afb4082972ec784d0230 100644 (file)
@@ -1284,9 +1284,9 @@ static const char *uaccess_safe_builtin[] = {
        "copy_mc_fragile_handle_tail",
        "copy_mc_enhanced_fast_string",
        "ftrace_likely_update", /* CONFIG_TRACE_BRANCH_PROFILING */
-       "clear_user_erms",
-       "clear_user_rep_good",
-       "clear_user_original",
+       "rep_stos_alternative",
+       "rep_movs_alternative",
+       "__copy_user_nocache",
        NULL
 };
 
index 52aa0351533c315e4c7bfd4e6a318642757c5e73..388c9e3ad0407b8b536dc69ffc6ea91d0ddd27f6 100644 (file)
@@ -97,7 +97,7 @@ static struct option long_options[] = {
 static void parse_options(int argc, char **argv)
 {
        int option_index = 0;
-       char *pathname;
+       char *pathname, *endptr;
        int opt;
 
        pathname = strdup(argv[0]);
@@ -125,11 +125,23 @@ static void parse_options(int argc, char **argv)
                        log_getinfo = 1;
                        break;
                case 'T':
-                       log_type = atoi(optarg);
+                       log_type = strtol(optarg, &endptr, 0);
+                       if (*endptr || (log_type != 0 && log_type != 1)) {
+                               printf("Number expected: type(0:execution, 1:history) - Quit.\n");
+                               exit(1);
+                       }
+
                        set_log_type = 1;
                        break;
                case 'L':
-                       log_level = atoi(optarg);
+                       log_level = strtol(optarg, &endptr, 0);
+                       if (*endptr ||
+                           (log_level != 0 && log_level != 1 &&
+                            log_level != 2 && log_level != 4)) {
+                               printf("Number expected: level(0, 1, 2, 4) - Quit.\n");
+                               exit(1);
+                       }
+
                        set_log_level = 1;
                        break;
                case 'R':
index 82c09cd25cc2189e405d4cbefed5665514fee50a..bf4ac24a1c7aa818dc3bb96d2e2e070613ebe03a 100755 (executable)
@@ -5556,9 +5556,8 @@ def executeSuspend(quiet=False):
                if not quiet:
                        pprint('CAPTURING TRACE')
                op = sv.writeDatafileHeader(sv.ftracefile, testdata)
-               fp = open(tp+'trace', 'r')
-               for line in fp:
-                       op.write(line)
+               fp = open(tp+'trace', 'rb')
+               op.write(ascii(fp.read()))
                op.close()
                sv.fsetVal('', 'trace')
                sv.platforminfo(cmdafter)
index c7b26a3603afecc8d7bc1f8d282a8857d979268e..8f08c3fd498d5b81185519728fc1c28a8a0d4d5f 100644 (file)
@@ -340,10 +340,12 @@ starts a new interval.
 must be run as root.
 Alternatively, non-root users can be enabled to run turbostat this way:
 
-# setcap cap_sys_admin,cap_sys_rawio,cap_sys_nice=+ep ./turbostat
+# setcap cap_sys_admin,cap_sys_rawio,cap_sys_nice=+ep path/to/turbostat
 
 # chmod +r /dev/cpu/*/msr
 
+# chmod +r /dev/cpu_dma_latency
+
 .B "turbostat "
 reads hardware counters, but doesn't write them.
 So it will not interfere with the OS or other programs, including
index aba460410dbd1b040942806edf676b01b163da8e..8a36ba5df9f90a0dc7c5ecd52b929de4d7b9eafb 100644 (file)
@@ -3,7 +3,7 @@
  * turbostat -- show CPU frequency and C-state residency
  * on modern Intel and AMD processors.
  *
- * Copyright (c) 2022 Intel Corporation.
+ * Copyright (c) 2023 Intel Corporation.
  * Len Brown <len.brown@intel.com>
  */
 
@@ -670,7 +670,7 @@ static int perf_instr_count_open(int cpu_num)
        /* counter for cpu_num, including user + kernel and all processes */
        fd = perf_event_open(&pea, -1, cpu_num, -1, 0);
        if (fd == -1) {
-               warn("cpu%d: perf instruction counter", cpu_num);
+               warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"", progname);
                BIC_NOT_PRESENT(BIC_IPC);
        }
 
@@ -2538,7 +2538,7 @@ static void dump_turbo_ratio_limits(int trl_msr_offset, int family, int model)
 
        get_msr(base_cpu, trl_msr_offset, &msr);
        fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n",
-               base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY" : "", msr);
+               base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY_" : "", msr);
 
        if (has_turbo_ratio_group_limits(family, model)) {
                get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
@@ -3502,9 +3502,6 @@ release_msr:
 /*
  * set_my_sched_priority(pri)
  * return previous
- *
- * if non-root, do this:
- * # /sbin/setcap cap_sys_rawio,cap_sys_nice=+ep /usr/bin/turbostat
  */
 int set_my_sched_priority(int priority)
 {
@@ -3518,7 +3515,7 @@ int set_my_sched_priority(int priority)
 
        retval = setpriority(PRIO_PROCESS, 0, priority);
        if (retval)
-               err(retval, "setpriority(%d)", priority);
+               errx(retval, "capget(CAP_SYS_NICE) failed,try \"# setcap cap_sys_nice=ep %s\"", progname);
 
        errno = 0;
        retval = getpriority(PRIO_PROCESS, 0);
@@ -4426,7 +4423,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
 
        fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
                "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
-               cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x2) ? "" : "No-");
+               cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x4) ? "" : "No-");
 
        return 0;
 }
@@ -5463,6 +5460,9 @@ unsigned int intel_model_duplicates(unsigned int model)
 
        case INTEL_FAM6_ICELAKE_D:
                return INTEL_FAM6_ICELAKE_X;
+
+       case INTEL_FAM6_EMERALDRAPIDS_X:
+               return INTEL_FAM6_SAPPHIRERAPIDS_X;
        }
        return model;
 }
@@ -5476,13 +5476,13 @@ void print_dev_latency(void)
 
        fd = open(path, O_RDONLY);
        if (fd < 0) {
-               warn("fopen %s\n", path);
+               warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", progname);
                return;
        }
 
        retval = read(fd, (void *)&value, sizeof(int));
        if (retval != sizeof(int)) {
-               warn("read %s\n", path);
+               warn("read failed %s", path);
                close(fd);
                return;
        }
@@ -5543,7 +5543,7 @@ void process_cpuid()
        edx_flags = edx;
 
        if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
-               warnx("get_msr(UCODE)\n");
+               warnx("get_msr(UCODE)");
 
        /*
         * check max extended function levels of CPUID.
@@ -6225,7 +6225,7 @@ int get_and_dump_counters(void)
 
 void print_version()
 {
-       fprintf(outf, "turbostat version 2022.10.04 - Len Brown <lenb@kernel.org>\n");
+       fprintf(outf, "turbostat version 2023.03.17 - Len Brown <lenb@kernel.org>\n");
 }
 
 #define COMMAND_LINE_SIZE 2048
old mode 100644 (file)
new mode 100755 (executable)
index e565697..08a39ad
@@ -1,11 +1,25 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0+
-#
-# Extract any RCU CPU stall warnings present in specified file.
-# Filter out clocksource lines.  Note that preceding-lines excludes the
-# initial line of the stall warning but trailing-lines includes it.
-#
-# Usage: extract-stall.sh dmesg-file [ preceding-lines [ trailing-lines ] ]
+
+usage() {
+       echo Extract any RCU CPU stall warnings present in specified file.
+       echo Filter out clocksource lines.  Note that preceding-lines excludes the
+       echo initial line of the stall warning but trailing-lines includes it.
+       echo
+       echo Usage: $(basename $0) dmesg-file [ preceding-lines [ trailing-lines ] ]
+       echo
+       echo Error: $1
+}
+
+# Terminate the script, if the argument is missing
+
+if test -f "$1" && test -r "$1"
+then
+       :
+else
+       usage "Console log file \"$1\" missing or unreadable."
+       exit 1
+fi
 
 echo $1
 preceding_lines="${2-3}"
index 741f15420467aecda526d84a62935a19ca4ec936..3905c43369c32245c2f3d8716403f450923aac27 100755 (executable)
@@ -123,7 +123,7 @@ def _suites_from_test_list(tests: List[str]) -> List[str]:
                parts = t.split('.', maxsplit=2)
                if len(parts) != 2:
                        raise ValueError(f'internal KUnit error, test name should be of the form "<suite>.<test>", got "{t}"')
-               suite, case = parts
+               suite, _ = parts
                if not suites or suites[-1] != suite:
                        suites.append(suite)
        return suites
@@ -269,7 +269,7 @@ def massage_argv(argv: Sequence[str]) -> Sequence[str]:
 def get_default_jobs() -> int:
        return len(os.sched_getaffinity(0))
 
-def add_common_opts(parser) -> None:
+def add_common_opts(parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--build_dir',
                            help='As in the make command, it specifies the build '
                            'directory.',
@@ -320,13 +320,13 @@ def add_common_opts(parser) -> None:
                            help='Additional QEMU arguments, e.g. "-smp 8"',
                            action='append', metavar='')
 
-def add_build_opts(parser) -> None:
+def add_build_opts(parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--jobs',
                            help='As in the make command, "Specifies  the number of '
                            'jobs (commands) to run simultaneously."',
                            type=int, default=get_default_jobs(), metavar='N')
 
-def add_exec_opts(parser) -> None:
+def add_exec_opts(parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--timeout',
                            help='maximum number of seconds to allow for all tests '
                            'to run. This does not include time taken to build the '
@@ -351,7 +351,7 @@ def add_exec_opts(parser) -> None:
                            type=str,
                            choices=['suite', 'test'])
 
-def add_parse_opts(parser) -> None:
+def add_parse_opts(parser: argparse.ArgumentParser) -> None:
        parser.add_argument('--raw_output', help='If set don\'t parse output from kernel. '
                            'By default, filters to just KUnit output. Use '
                            '--raw_output=all to show everything',
@@ -386,7 +386,7 @@ def tree_from_args(cli_args: argparse.Namespace) -> kunit_kernel.LinuxSourceTree
                        extra_qemu_args=qemu_args)
 
 
-def run_handler(cli_args):
+def run_handler(cli_args: argparse.Namespace) -> None:
        if not os.path.exists(cli_args.build_dir):
                os.mkdir(cli_args.build_dir)
 
@@ -405,7 +405,7 @@ def run_handler(cli_args):
                sys.exit(1)
 
 
-def config_handler(cli_args):
+def config_handler(cli_args: argparse.Namespace) -> None:
        if cli_args.build_dir and (
                        not os.path.exists(cli_args.build_dir)):
                os.mkdir(cli_args.build_dir)
@@ -421,7 +421,7 @@ def config_handler(cli_args):
                sys.exit(1)
 
 
-def build_handler(cli_args):
+def build_handler(cli_args: argparse.Namespace) -> None:
        linux = tree_from_args(cli_args)
        request = KunitBuildRequest(build_dir=cli_args.build_dir,
                                        make_options=cli_args.make_options,
@@ -434,7 +434,7 @@ def build_handler(cli_args):
                sys.exit(1)
 
 
-def exec_handler(cli_args):
+def exec_handler(cli_args: argparse.Namespace) -> None:
        linux = tree_from_args(cli_args)
        exec_request = KunitExecRequest(raw_output=cli_args.raw_output,
                                        build_dir=cli_args.build_dir,
@@ -450,10 +450,10 @@ def exec_handler(cli_args):
                sys.exit(1)
 
 
-def parse_handler(cli_args):
+def parse_handler(cli_args: argparse.Namespace) -> None:
        if cli_args.file is None:
-               sys.stdin.reconfigure(errors='backslashreplace')  # pytype: disable=attribute-error
-               kunit_output = sys.stdin
+               sys.stdin.reconfigure(errors='backslashreplace')  # type: ignore
+               kunit_output = sys.stdin  # type: Iterable[str]
        else:
                with open(cli_args.file, 'r', errors='backslashreplace') as f:
                        kunit_output = f.read().splitlines()
@@ -475,7 +475,7 @@ subcommand_handlers_map = {
 }
 
 
-def main(argv):
+def main(argv: Sequence[str]) -> None:
        parser = argparse.ArgumentParser(
                        description='Helps writing and running KUnit tests.')
        subparser = parser.add_subparsers(dest='subcommand')
index 48b5f34b2e5d7b0200f7de193e43f454cc7ac832..eb5dd01210b1b41b805779b0733134e6de31cd99 100644 (file)
@@ -8,7 +8,7 @@
 
 from dataclasses import dataclass
 import re
-from typing import Dict, Iterable, List, Set, Tuple
+from typing import Any, Dict, Iterable, List, Tuple
 
 CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
 CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
@@ -34,7 +34,7 @@ class Kconfig:
        def __init__(self) -> None:
                self._entries = {}  # type: Dict[str, str]
 
-       def __eq__(self, other) -> bool:
+       def __eq__(self, other: Any) -> bool:
                if not isinstance(other, self.__class__):
                        return False
                return self._entries == other._entries
index 53e90c3358348dbef24c2bdba395decf60b95ab2..f01f9410612965037e6510028351b566ac7ae382 100644 (file)
@@ -16,9 +16,9 @@ import shutil
 import signal
 import threading
 from typing import Iterator, List, Optional, Tuple
+from types import FrameType
 
 import kunit_config
-from kunit_printer import stdout
 import qemu_config
 
 KCONFIG_PATH = '.config'
@@ -57,7 +57,7 @@ class LinuxSourceTreeOperations:
        def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
                return base_kunitconfig
 
-       def make_olddefconfig(self, build_dir: str, make_options) -> None:
+       def make_olddefconfig(self, build_dir: str, make_options: Optional[List[str]]) -> None:
                command = ['make', 'ARCH=' + self._linux_arch, 'O=' + build_dir, 'olddefconfig']
                if self._cross_compile:
                        command += ['CROSS_COMPILE=' + self._cross_compile]
@@ -71,7 +71,7 @@ class LinuxSourceTreeOperations:
                except subprocess.CalledProcessError as e:
                        raise ConfigError(e.output.decode())
 
-       def make(self, jobs, build_dir: str, make_options) -> None:
+       def make(self, jobs: int, build_dir: str, make_options: Optional[List[str]]) -> None:
                command = ['make', 'ARCH=' + self._linux_arch, 'O=' + build_dir, '--jobs=' + str(jobs)]
                if make_options:
                        command.extend(make_options)
@@ -92,7 +92,7 @@ class LinuxSourceTreeOperations:
                if stderr:  # likely only due to build warnings
                        print(stderr.decode())
 
-       def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
+       def start(self, params: List[str], build_dir: str) -> subprocess.Popen[str]:
                raise RuntimeError('not implemented!')
 
 
@@ -106,13 +106,14 @@ class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations):
                self._kernel_path = qemu_arch_params.kernel_path
                self._kernel_command_line = qemu_arch_params.kernel_command_line + ' kunit_shutdown=reboot'
                self._extra_qemu_params = qemu_arch_params.extra_qemu_params
+               self._serial = qemu_arch_params.serial
 
        def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
                kconfig = kunit_config.parse_from_string(self._kconfig)
                kconfig.merge_in_entries(base_kunitconfig)
                return kconfig
 
-       def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
+       def start(self, params: List[str], build_dir: str) -> subprocess.Popen[str]:
                kernel_path = os.path.join(build_dir, self._kernel_path)
                qemu_command = ['qemu-system-' + self._qemu_arch,
                                '-nodefaults',
@@ -121,7 +122,7 @@ class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations):
                                '-append', ' '.join(params + [self._kernel_command_line]),
                                '-no-reboot',
                                '-nographic',
-                               '-serial', 'stdio'] + self._extra_qemu_params
+                               '-serial', self._serial] + self._extra_qemu_params
                # Note: shlex.join() does what we want, but requires python 3.8+.
                print('Running tests with:\n$', ' '.join(shlex.quote(arg) for arg in qemu_command))
                return subprocess.Popen(qemu_command,
@@ -133,7 +134,7 @@ class LinuxSourceTreeOperationsQemu(LinuxSourceTreeOperations):
 class LinuxSourceTreeOperationsUml(LinuxSourceTreeOperations):
        """An abstraction over command line operations performed on a source tree."""
 
-       def __init__(self, cross_compile=None):
+       def __init__(self, cross_compile: Optional[str]=None):
                super().__init__(linux_arch='um', cross_compile=cross_compile)
 
        def make_arch_config(self, base_kunitconfig: kunit_config.Kconfig) -> kunit_config.Kconfig:
@@ -141,7 +142,7 @@ class LinuxSourceTreeOperationsUml(LinuxSourceTreeOperations):
                kconfig.merge_in_entries(base_kunitconfig)
                return kconfig
 
-       def start(self, params: List[str], build_dir: str) -> subprocess.Popen:
+       def start(self, params: List[str], build_dir: str) -> subprocess.Popen[str]:
                """Runs the Linux UML binary. Must be named 'linux'."""
                linux_bin = os.path.join(build_dir, 'linux')
                params.extend(['mem=1G', 'console=tty', 'kunit_shutdown=halt'])
@@ -216,7 +217,7 @@ def _get_qemu_ops(config_path: str,
 
        if not hasattr(config, 'QEMU_ARCH'):
                raise ValueError('qemu_config module missing "QEMU_ARCH": ' + config_path)
-       params: qemu_config.QemuArchParams = config.QEMU_ARCH  # type: ignore
+       params: qemu_config.QemuArchParams = config.QEMU_ARCH
        if extra_qemu_args:
                params.extra_qemu_params.extend(extra_qemu_args)
        return params.linux_arch, LinuxSourceTreeOperationsQemu(
@@ -230,10 +231,10 @@ class LinuxSourceTree:
              build_dir: str,
              kunitconfig_paths: Optional[List[str]]=None,
              kconfig_add: Optional[List[str]]=None,
-             arch=None,
-             cross_compile=None,
-             qemu_config_path=None,
-             extra_qemu_args=None) -> None:
+             arch: Optional[str]=None,
+             cross_compile: Optional[str]=None,
+             qemu_config_path: Optional[str]=None,
+             extra_qemu_args: Optional[List[str]]=None) -> None:
                signal.signal(signal.SIGINT, self.signal_handler)
                if qemu_config_path:
                        self._arch, self._ops = _get_qemu_ops(qemu_config_path, extra_qemu_args, cross_compile)
@@ -276,7 +277,7 @@ class LinuxSourceTree:
                logging.error(message)
                return False
 
-       def build_config(self, build_dir: str, make_options) -> bool:
+       def build_config(self, build_dir: str, make_options: Optional[List[str]]) -> bool:
                kconfig_path = get_kconfig_path(build_dir)
                if build_dir and not os.path.exists(build_dir):
                        os.mkdir(build_dir)
@@ -304,7 +305,7 @@ class LinuxSourceTree:
                old_kconfig = kunit_config.parse_file(old_path)
                return old_kconfig != self._kconfig
 
-       def build_reconfig(self, build_dir: str, make_options) -> bool:
+       def build_reconfig(self, build_dir: str, make_options: Optional[List[str]]) -> bool:
                """Creates a new .config if it is not a subset of the .kunitconfig."""
                kconfig_path = get_kconfig_path(build_dir)
                if not os.path.exists(kconfig_path):
@@ -320,7 +321,7 @@ class LinuxSourceTree:
                os.remove(kconfig_path)
                return self.build_config(build_dir, make_options)
 
-       def build_kernel(self, jobs, build_dir: str, make_options) -> bool:
+       def build_kernel(self, jobs: int, build_dir: str, make_options: Optional[List[str]]) -> bool:
                try:
                        self._ops.make_olddefconfig(build_dir, make_options)
                        self._ops.make(jobs, build_dir, make_options)
@@ -329,7 +330,7 @@ class LinuxSourceTree:
                        return False
                return self.validate_config(build_dir)
 
-       def run_kernel(self, args=None, build_dir='', filter_glob='', timeout=None) -> Iterator[str]:
+       def run_kernel(self, args: Optional[List[str]]=None, build_dir: str='', filter_glob: str='', timeout: Optional[int]=None) -> Iterator[str]:
                if not args:
                        args = []
                if filter_glob:
@@ -340,7 +341,7 @@ class LinuxSourceTree:
                assert process.stdout is not None  # tell mypy it's set
 
                # Enforce the timeout in a background thread.
-               def _wait_proc():
+               def _wait_proc() -> None:
                        try:
                                process.wait(timeout=timeout)
                        except Exception as e:
@@ -366,6 +367,6 @@ class LinuxSourceTree:
                        waiter.join()
                        subprocess.call(['stty', 'sane'])
 
-       def signal_handler(self, unused_sig, unused_frame) -> None:
+       def signal_handler(self, unused_sig: int, unused_frame: Optional[FrameType]) -> None:
                logging.error('Build interruption occurred. Cleaning console.')
                subprocess.call(['stty', 'sane'])
index a225799f6b1b9e1e8346d10d8655fff8c8922518..fbc094f0567e660c098c0c10acb2b8281cf276f8 100644 (file)
@@ -12,7 +12,6 @@
 from __future__ import annotations
 from dataclasses import dataclass
 import re
-import sys
 import textwrap
 
 from enum import Enum, auto
index 5f1cc55ecdf5893e75e5b5f8a2bf2923ed8b40bc..015adf87dc2c773ac164d4979c2b3a7f96c63aa5 100644 (file)
@@ -15,7 +15,7 @@ _RESET = '\033[0;0m'
 class Printer:
        """Wraps a file object, providing utilities for coloring output, etc."""
 
-       def __init__(self, output: typing.IO):
+       def __init__(self, output: typing.IO[str]):
                self._output = output
                self._use_color = output.isatty()
 
index 0c2190514103faa78433fe5d2fb15139ae68293f..be35999bb84f14dd2909756fdfa8b0673fdd8f95 100755 (executable)
@@ -328,7 +328,7 @@ class KUnitParserTest(unittest.TestCase):
        def test_parse_subtest_header(self):
                ktap_log = test_data_path('test_parse_subtest_header.log')
                with open(ktap_log) as file:
-                       result = kunit_parser.parse_run_tests(file.readlines())
+                       kunit_parser.parse_run_tests(file.readlines())
                self.print_mock.assert_any_call(StrContains('suite (1 subtest)'))
 
        def test_show_test_output_on_failure(self):
index 0b6a80398cccb50fee5fe94def150c0761d96c20..b1fba9016eed00d010c853f2910c9624e01d4af5 100644 (file)
@@ -17,3 +17,4 @@ class QemuArchParams:
   kernel_path: str
   kernel_command_line: str
   extra_qemu_params: List[str]
+  serial: str = 'stdio'
diff --git a/tools/testing/kunit/qemu_configs/m68k.py b/tools/testing/kunit/qemu_configs/m68k.py
new file mode 100644 (file)
index 0000000..287fc38
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+from ..qemu_config import QemuArchParams
+
+QEMU_ARCH = QemuArchParams(linux_arch='m68k',
+                          kconfig='''
+CONFIG_VIRT=y''',
+                          qemu_arch='m68k',
+                          kernel_path='vmlinux',
+                          kernel_command_line='console=hvc0',
+                          extra_qemu_params=['-machine', 'virt'])
diff --git a/tools/testing/kunit/qemu_configs/sh.py b/tools/testing/kunit/qemu_configs/sh.py
new file mode 100644 (file)
index 0000000..78a474a
--- /dev/null
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+from ..qemu_config import QemuArchParams
+
+QEMU_ARCH = QemuArchParams(linux_arch='sh',
+                          kconfig='''
+CONFIG_CPU_SUBTYPE_SH7751R=y
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_SH_RTS7751R2D=y
+CONFIG_RTS7751R2D_PLUS=y
+CONFIG_SERIAL_SH_SCI=y''',
+                          qemu_arch='sh4',
+                          kernel_path='arch/sh/boot/zImage',
+                          kernel_command_line='console=ttySC1',
+                          serial='null',
+                          extra_qemu_params=[
+                                           '-machine', 'r2d',
+                                           '-serial', 'mon:stdio'])
index 066e6f938f6dcccc23dcaff4faa48a30e301f7f4..8208c3b3135efe8ef41712b1a6d22d3ea31ffc16 100755 (executable)
@@ -23,7 +23,7 @@ commands: Dict[str, Sequence[str]] = {
        'kunit_tool_test.py': ['./kunit_tool_test.py'],
        'kunit smoke test': ['./kunit.py', 'run', '--kunitconfig=lib/kunit', '--build_dir=kunit_run_checks'],
        'pytype': ['/bin/sh', '-c', 'pytype *.py'],
-       'mypy': ['/bin/sh', '-c', 'mypy *.py'],
+       'mypy': ['mypy', '--strict', '--exclude', '_test.py$', '--exclude', 'qemu_configs/', '.'],
 }
 
 # The user might not have mypy or pytype installed, skip them if so.
@@ -37,7 +37,7 @@ def main(argv: Sequence[str]) -> None:
        if argv:
                raise RuntimeError('This script takes no arguments')
 
-       future_to_name: Dict[futures.Future, str] = {}
+       future_to_name: Dict[futures.Future[None], str] = {}
        executor = futures.ThreadPoolExecutor(max_workers=len(commands))
        for name, argv in commands.items():
                if name in necessary_deps and shutil.which(necessary_deps[name]) is None:
@@ -73,7 +73,7 @@ def main(argv: Sequence[str]) -> None:
                sys.exit(1)
 
 
-def run_cmd(argv: Sequence[str]):
+def run_cmd(argv: Sequence[str]) -> None:
        subprocess.check_output(argv, stderr=subprocess.STDOUT, cwd=ABS_TOOL_PATH, timeout=TIMEOUT)
 
 
index 958ee9bdb3166df00ce3160160d2a546cb1353f0..4c89ff333f6f080eee71832a6e7e4e36d964ca4d 100644 (file)
@@ -108,6 +108,7 @@ static noinline void check_new_node(struct maple_tree *mt)
        MT_BUG_ON(mt, mn->slot[1] != NULL);
        MT_BUG_ON(mt, mas_allocated(&mas) != 0);
 
+       mn->parent = ma_parent_ptr(mn);
        ma_free_rcu(mn);
        mas.node = MAS_START;
        mas_nomem(&mas, GFP_KERNEL);
@@ -160,6 +161,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                MT_BUG_ON(mt, mas_allocated(&mas) != i);
                MT_BUG_ON(mt, !mn);
                MT_BUG_ON(mt, not_empty(mn));
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
        }
 
@@ -192,6 +194,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                MT_BUG_ON(mt, not_empty(mn));
                MT_BUG_ON(mt, mas_allocated(&mas) != i - 1);
                MT_BUG_ON(mt, !mn);
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
        }
 
@@ -210,6 +213,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                        mn = mas_pop_node(&mas);
                        MT_BUG_ON(mt, not_empty(mn));
                        MT_BUG_ON(mt, mas_allocated(&mas) != j - 1);
+                       mn->parent = ma_parent_ptr(mn);
                        ma_free_rcu(mn);
                }
                MT_BUG_ON(mt, mas_allocated(&mas) != 0);
@@ -233,6 +237,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                        MT_BUG_ON(mt, mas_allocated(&mas) != i - j);
                        mn = mas_pop_node(&mas);
                        MT_BUG_ON(mt, not_empty(mn));
+                       mn->parent = ma_parent_ptr(mn);
                        ma_free_rcu(mn);
                        MT_BUG_ON(mt, mas_allocated(&mas) != i - j - 1);
                }
@@ -269,6 +274,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                        mn = mas_pop_node(&mas); /* get the next node. */
                        MT_BUG_ON(mt, mn == NULL);
                        MT_BUG_ON(mt, not_empty(mn));
+                       mn->parent = ma_parent_ptr(mn);
                        ma_free_rcu(mn);
                }
                MT_BUG_ON(mt, mas_allocated(&mas) != 0);
@@ -294,6 +300,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                        mn = mas_pop_node(&mas2); /* get the next node. */
                        MT_BUG_ON(mt, mn == NULL);
                        MT_BUG_ON(mt, not_empty(mn));
+                       mn->parent = ma_parent_ptr(mn);
                        ma_free_rcu(mn);
                }
                MT_BUG_ON(mt, mas_allocated(&mas2) != 0);
@@ -334,10 +341,12 @@ static noinline void check_new_node(struct maple_tree *mt)
        MT_BUG_ON(mt, mas_allocated(&mas) != MAPLE_ALLOC_SLOTS + 2);
        mn = mas_pop_node(&mas);
        MT_BUG_ON(mt, not_empty(mn));
+       mn->parent = ma_parent_ptr(mn);
        ma_free_rcu(mn);
        for (i = 1; i <= MAPLE_ALLOC_SLOTS + 1; i++) {
                mn = mas_pop_node(&mas);
                MT_BUG_ON(mt, not_empty(mn));
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
        }
        MT_BUG_ON(mt, mas_allocated(&mas) != 0);
@@ -375,6 +384,7 @@ static noinline void check_new_node(struct maple_tree *mt)
                mas_node_count(&mas, i); /* Request */
                mas_nomem(&mas, GFP_KERNEL); /* Fill request */
                mn = mas_pop_node(&mas); /* get the next node. */
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
                mas_destroy(&mas);
 
@@ -382,10 +392,13 @@ static noinline void check_new_node(struct maple_tree *mt)
                mas_node_count(&mas, i); /* Request */
                mas_nomem(&mas, GFP_KERNEL); /* Fill request */
                mn = mas_pop_node(&mas); /* get the next node. */
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
                mn = mas_pop_node(&mas); /* get the next node. */
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
                mn = mas_pop_node(&mas); /* get the next node. */
+               mn->parent = ma_parent_ptr(mn);
                ma_free_rcu(mn);
                mas_destroy(&mas);
        }
@@ -35369,6 +35382,7 @@ static noinline void check_prealloc(struct maple_tree *mt)
        MT_BUG_ON(mt, allocated != 1 + height * 3);
        mn = mas_pop_node(&mas);
        MT_BUG_ON(mt, mas_allocated(&mas) != allocated - 1);
+       mn->parent = ma_parent_ptr(mn);
        ma_free_rcu(mn);
        MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0);
        mas_destroy(&mas);
@@ -35386,6 +35400,7 @@ static noinline void check_prealloc(struct maple_tree *mt)
        mas_destroy(&mas);
        allocated = mas_allocated(&mas);
        MT_BUG_ON(mt, allocated != 0);
+       mn->parent = ma_parent_ptr(mn);
        ma_free_rcu(mn);
 
        MT_BUG_ON(mt, mas_preallocate(&mas, GFP_KERNEL) != 0);
@@ -35756,6 +35771,7 @@ void farmer_tests(void)
        tree.ma_root = mt_mk_node(node, maple_leaf_64);
        mt_dump(&tree);
 
+       node->parent = ma_parent_ptr(node);
        ma_free_rcu(node);
 
        /* Check things that will make lockdep angry */
index 13a6837a0c6bc62902833292e10d055cafdbc6c1..97dcdaa656f6e6bcff0d765e66a638785a7393ca 100644 (file)
@@ -58,6 +58,7 @@ TARGETS += nsfs
 TARGETS += pidfd
 TARGETS += pid_namespace
 TARGETS += powerpc
+TARGETS += prctl
 TARGETS += proc
 TARGETS += pstore
 TARGETS += ptrace
index 5fd1424db37d82c399b4bfda72652e54c38dfe4c..c382f579fe94a73120e25233ab9da267557bd07b 100644 (file)
@@ -4,10 +4,15 @@
 # No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
 all:
 
-uname_M := $(shell uname -m 2>/dev/null || echo not)
-ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
+ARCH ?= $(shell uname -m 2>/dev/null || echo not)
+ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
 
-TEST_PROGS := run.sh
-TEST_FILES := basic.sh tbench.sh gitsource.sh
+ifeq (x86,$(ARCH))
+TEST_FILES += ../../../power/x86/amd_pstate_tracer/amd_pstate_trace.py
+TEST_FILES += ../../../power/x86/intel_pstate_tracer/intel_pstate_tracer.py
+endif
+
+TEST_PROGS += run.sh
+TEST_FILES += basic.sh tbench.sh gitsource.sh
 
 include ../lib.mk
index dbc1fe45599d6a70c5f1fd425254d7e1b2538370..5f2171f0116de323558e958f2f99dae14162f9d1 100755 (executable)
@@ -117,7 +117,7 @@ parse_gitsource()
        printf "Gitsource-$1-#$2 power consumption(J): $en_sum\n" | tee -a $OUTFILE_GIT.result
 
        # Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t
-       # senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
+       # seconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
        # and t is time measured in seconds(s). This means that performance per watt becomes
        #        1/t     1/t     1
        #       ----- = ----- = ---
@@ -175,7 +175,7 @@ gather_gitsource()
        printf "Gitsource-$1 avg power consumption(J): $avg_en\n" | tee -a $OUTFILE_GIT.result
 
        # Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t
-       # senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
+       # seconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J),
        # and t is time measured in seconds(s). This means that performance per watt becomes
        #        1/t     1/t     1
        #       ----- = ----- = ---
index 57cad57e59c0e7815cdd08027215ae1cdca5570b..de4d8e9c9565d0af58f764cbbd182644fa7a0091 100755 (executable)
@@ -244,7 +244,7 @@ prerequisite()
                if [ "$scaling_driver" != "$CURRENT_TEST" ]; then
                        echo "$0 # Skipped: Test can only run on $CURRENT_TEST driver or run comparative test."
                        echo "$0 # Please set X86_AMD_PSTATE enabled or run comparative test."
-                       echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
+                       echo "$0 # Current cpufreq scaling driver is $scaling_driver."
                        exit $ksft_skip
                fi
        else
@@ -252,7 +252,7 @@ prerequisite()
                        "tbench" | "gitsource")
                                if [ "$scaling_driver" != "$COMPARATIVE_TEST" ]; then
                                        echo "$0 # Skipped: Comparison test can only run on $COMPARISON_TEST driver."
-                                       echo "$0 # Current cpufreq scaling drvier is $scaling_driver."
+                                       echo "$0 # Current cpufreq scaling driver is $scaling_driver."
                                        exit $ksft_skip
                                fi
                                ;;
index 48f56c86ad4579970300940813c94340712b9ac0..b413b0af07f990c70c3c9ef94386eae62843bd68 100644 (file)
@@ -38,7 +38,7 @@ $(OUTPUT)/vec-syscfg: vec-syscfg.c $(OUTPUT)/rdvl.o
 $(OUTPUT)/vlset: vlset.c
 $(OUTPUT)/za-fork: za-fork.c $(OUTPUT)/za-fork-asm.o
        $(CC) -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
-               -include ../../../../include/nolibc/nolibc.h \
+               -include ../../../../include/nolibc/nolibc.h -I../..\
                -static -ffreestanding -Wall $^ -o $@
 $(OUTPUT)/za-ptrace: za-ptrace.c
 $(OUTPUT)/za-test: za-test.S $(OUTPUT)/asm-utils.o
index ff475c649e96698eab7c0613c131d4a2025d0b6d..b86cb1049497f39647566dcf03e39a96a69e2d23 100644 (file)
@@ -9,42 +9,9 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 
-#define EXPECTED_TESTS 1
-
-static void putstr(const char *str)
-{
-       write(1, str, strlen(str));
-}
-
-static void putnum(unsigned int num)
-{
-       char c;
-
-       if (num / 10)
-               putnum(num / 10);
-
-       c = '0' + (num % 10);
-       write(1, &c, 1);
-}
+#include "kselftest.h"
 
-static int tests_run;
-static int tests_passed;
-static int tests_failed;
-static int tests_skipped;
-
-static void print_summary(void)
-{
-       if (tests_passed + tests_failed + tests_skipped != EXPECTED_TESTS)
-               putstr("# UNEXPECTED TEST COUNT: ");
-
-       putstr("# Totals: pass:");
-       putnum(tests_passed);
-       putstr(" fail:");
-       putnum(tests_failed);
-       putstr(" xfail:0 xpass:0 skip:");
-       putnum(tests_skipped);
-       putstr(" error:0\n");
-}
+#define EXPECTED_TESTS 1
 
 int fork_test(void);
 int verify_fork(void);
@@ -63,22 +30,21 @@ int fork_test_c(void)
        if (newpid == 0) {
                /* In child */
                if (!verify_fork()) {
-                       putstr("# ZA state invalid in child\n");
+                       ksft_print_msg("ZA state invalid in child\n");
                        exit(0);
                } else {
                        exit(1);
                }
        }
        if (newpid < 0) {
-               putstr("# fork() failed: -");
-               putnum(-newpid);
-               putstr("\n");
+               ksft_print_msg("fork() failed: %d\n", newpid);
+
                return 0;
        }
 
        parent_result = verify_fork();
        if (!parent_result)
-               putstr("# ZA state invalid in parent\n");
+               ksft_print_msg("ZA state invalid in parent\n");
 
        for (;;) {
                waiting = waitpid(newpid, &child_status, 0);
@@ -86,18 +52,16 @@ int fork_test_c(void)
                if (waiting < 0) {
                        if (errno == EINTR)
                                continue;
-                       putstr("# waitpid() failed: ");
-                       putnum(errno);
-                       putstr("\n");
+                       ksft_print_msg("waitpid() failed: %d\n", errno);
                        return 0;
                }
                if (waiting != newpid) {
-                       putstr("# waitpid() returned wrong PID\n");
+                       ksft_print_msg("waitpid() returned wrong PID\n");
                        return 0;
                }
 
                if (!WIFEXITED(child_status)) {
-                       putstr("# child did not exit\n");
+                       ksft_print_msg("child did not exit\n");
                        return 0;
                }
 
@@ -105,29 +69,14 @@ int fork_test_c(void)
        }
 }
 
-#define run_test(name)                      \
-       if (name()) {                        \
-               tests_passed++;              \
-       } else {                             \
-               tests_failed++;              \
-               putstr("not ");              \
-       }                                    \
-       putstr("ok ");                       \
-       putnum(++tests_run);                 \
-       putstr(" " #name "\n");
-
 int main(int argc, char **argv)
 {
        int ret, i;
 
-       putstr("TAP version 13\n");
-       putstr("1..");
-       putnum(EXPECTED_TESTS);
-       putstr("\n");
+       ksft_print_header();
+       ksft_set_plan(EXPECTED_TESTS);
 
-       putstr("# PID: ");
-       putnum(getpid());
-       putstr("\n");
+       ksft_print_msg("PID: %d\n", getpid());
 
        /*
         * This test is run with nolibc which doesn't support hwcap and
@@ -136,21 +85,16 @@ int main(int argc, char **argv)
         */
        ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0);
        if (ret >= 0) {
-               run_test(fork_test);
+               ksft_test_result(fork_test(), "fork_test");
 
        } else {
-               putstr("# SME support not present\n");
-
+               ksft_print_msg("SME not supported\n");
                for (i = 0; i < EXPECTED_TESTS; i++) {
-                       putstr("ok ");
-                       putnum(i);
-                       putstr(" skipped\n");
+                       ksft_test_result_skip("fork_test\n");
                }
-
-               tests_skipped += EXPECTED_TESTS;
        }
 
-       print_summary();
+       ksft_finished();
 
        return 0;
 }
diff --git a/tools/testing/selftests/bpf/prog_tests/uninit_stack.c b/tools/testing/selftests/bpf/prog_tests/uninit_stack.c
new file mode 100644 (file)
index 0000000..e64c719
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <test_progs.h>
+#include "uninit_stack.skel.h"
+
+void test_uninit_stack(void)
+{
+       RUN_TESTS(uninit_stack);
+}
index 7271a18ab3e22d0d637ef0e00518a9afdee6539c..8251a0fc6ee94d80403298b9cb69fabf4c0bc4dc 100644 (file)
@@ -167,8 +167,7 @@ void test_xdp_do_redirect(void)
 
        if (!ASSERT_EQ(query_opts.feature_flags,
                       NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
-                      NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
-                      NETDEV_XDP_ACT_NDO_XMIT_SG,
+                      NETDEV_XDP_ACT_RX_SG,
                       "veth_src query_opts.feature_flags"))
                goto out;
 
@@ -176,11 +175,36 @@ void test_xdp_do_redirect(void)
        if (!ASSERT_OK(err, "veth_dst bpf_xdp_query"))
                goto out;
 
+       if (!ASSERT_EQ(query_opts.feature_flags,
+                      NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+                      NETDEV_XDP_ACT_RX_SG,
+                      "veth_dst query_opts.feature_flags"))
+               goto out;
+
+       /* Enable GRO */
+       SYS("ethtool -K veth_src gro on");
+       SYS("ethtool -K veth_dst gro on");
+
+       err = bpf_xdp_query(ifindex_src, XDP_FLAGS_DRV_MODE, &query_opts);
+       if (!ASSERT_OK(err, "veth_src bpf_xdp_query gro on"))
+               goto out;
+
        if (!ASSERT_EQ(query_opts.feature_flags,
                       NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
                       NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
                       NETDEV_XDP_ACT_NDO_XMIT_SG,
-                      "veth_dst query_opts.feature_flags"))
+                      "veth_src query_opts.feature_flags gro on"))
+               goto out;
+
+       err = bpf_xdp_query(ifindex_dst, XDP_FLAGS_DRV_MODE, &query_opts);
+       if (!ASSERT_OK(err, "veth_dst bpf_xdp_query gro on"))
+               goto out;
+
+       if (!ASSERT_EQ(query_opts.feature_flags,
+                      NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+                      NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG |
+                      NETDEV_XDP_ACT_NDO_XMIT_SG,
+                      "veth_dst query_opts.feature_flags gro on"))
                goto out;
 
        memcpy(skel->rodata->expect_dst, &pkt_udp.eth.h_dest, ETH_ALEN);
index aa4beae99f4f6ed6df6f2c60d9b8470f229dd1b7..8c5e98da9ae9f036889eda11508573b8e27fe751 100644 (file)
@@ -273,6 +273,8 @@ static int verify_xsk_metadata(struct xsk *xsk)
        if (!ASSERT_NEQ(meta->rx_hash, 0, "rx_hash"))
                return -1;
 
+       ASSERT_EQ(meta->rx_hash_type, 0, "rx_hash_type");
+
        xsk_ring_cons__release(&xsk->rx, 1);
        refill_rx(xsk, comp_addr);
 
index b3b326b8e2d1cb38cf374d18737529ce0fb7d9a4..6dab9cffda132b755c554fcddb67af752b22187a 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright (c) 2021 Facebook */
 #include "vmlinux.h"
 #include <bpf/bpf_helpers.h>
+#define vm_flags vm_start
 
 char _license[] SEC("license") = "GPL";
 
index 591104e79812ef2918c23f84b692790fe519f8fc..e96b901a733c5878d48de3dc1dcc3f4dd32f89af 100644 (file)
@@ -5,12 +5,10 @@
 #include <errno.h>
 #include <linux/capability.h>
 
-struct kernel_cap_struct {
-       __u64 val;
-} __attribute__((preserve_access_index));
+typedef struct { unsigned long long val; } kernel_cap_t;
 
 struct cred {
-       struct kernel_cap_struct cap_effective;
+       kernel_cap_t cap_effective;
 } __attribute__((preserve_access_index));
 
 char _license[] SEC("license") = "GPL";
@@ -18,8 +16,8 @@ char _license[] SEC("license") = "GPL";
 SEC("lsm.s/userns_create")
 int BPF_PROG(test_userns_create, const struct cred *cred, int ret)
 {
-       struct kernel_cap_struct caps = cred->cap_effective;
-       __u64 cap_mask = BIT_LL(CAP_SYS_ADMIN);
+       kernel_cap_t caps = cred->cap_effective;
+       __u64 cap_mask = 1ULL << CAP_SYS_ADMIN;
 
        if (ret)
                return 0;
index 98327bdbbfd24700900ac94667bb7e0269d9a1fd..8fba3f3649e227d521c84caac140ccf9dc5812a8 100644 (file)
@@ -5,12 +5,12 @@
 #include "bpf_misc.h"
 
 struct Small {
-       int x;
+       long x;
 };
 
 struct Big {
-       int x;
-       int y;
+       long x;
+       long y;
 };
 
 __noinline int foo(const struct Big *big)
@@ -22,7 +22,7 @@ __noinline int foo(const struct Big *big)
 }
 
 SEC("cgroup_skb/ingress")
-__failure __msg("invalid indirect read from stack")
+__failure __msg("invalid indirect access to stack")
 int global_func10(struct __sk_buff *skb)
 {
        const struct Small small = {.x = skb->len };
diff --git a/tools/testing/selftests/bpf/progs/uninit_stack.c b/tools/testing/selftests/bpf/progs/uninit_stack.c
new file mode 100644 (file)
index 0000000..8a40347
--- /dev/null
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+/* Read an uninitialized value from stack at a fixed offset */
+SEC("socket")
+__naked int read_uninit_stack_fixed_off(void *ctx)
+{
+       asm volatile ("                                 \
+               r0 = 0;                                 \
+               /* force stack depth to be 128 */       \
+               *(u64*)(r10 - 128) = r1;                \
+               r1 = *(u8 *)(r10 - 8 );                 \
+               r0 += r1;                               \
+               r1 = *(u8 *)(r10 - 11);                 \
+               r1 = *(u8 *)(r10 - 13);                 \
+               r1 = *(u8 *)(r10 - 15);                 \
+               r1 = *(u16*)(r10 - 16);                 \
+               r1 = *(u32*)(r10 - 32);                 \
+               r1 = *(u64*)(r10 - 64);                 \
+               /* read from a spill of a wrong size, it is a separate  \
+                * branch in check_stack_read_fixed_off()               \
+                */                                     \
+               *(u32*)(r10 - 72) = r1;                 \
+               r1 = *(u64*)(r10 - 72);                 \
+               r0 = 0;                                 \
+               exit;                                   \
+"
+                     ::: __clobber_all);
+}
+
+/* Read an uninitialized value from stack at a variable offset */
+SEC("socket")
+__naked int read_uninit_stack_var_off(void *ctx)
+{
+       asm volatile ("                                 \
+               call %[bpf_get_prandom_u32];            \
+               /* force stack depth to be 64 */        \
+               *(u64*)(r10 - 64) = r0;                 \
+               r0 = -r0;                               \
+               /* give r0 a range [-31, -1] */         \
+               if r0 s<= -32 goto exit_%=;             \
+               if r0 s>= 0 goto exit_%=;               \
+               /* access stack using r0 */             \
+               r1 = r10;                               \
+               r1 += r0;                               \
+               r2 = *(u8*)(r1 + 0);                    \
+exit_%=:       r0 = 0;                                 \
+               exit;                                   \
+"
+                     :
+                     : __imm(bpf_get_prandom_u32)
+                     : __clobber_all);
+}
+
+static __noinline void dummy(void) {}
+
+/* Pass a pointer to uninitialized stack memory to a helper.
+ * Passed memory block should be marked as STACK_MISC after helper call.
+ */
+SEC("socket")
+__log_level(7) __msg("fp-104=mmmmmmmm")
+__naked int helper_uninit_to_misc(void *ctx)
+{
+       asm volatile ("                                 \
+               /* force stack depth to be 128 */       \
+               *(u64*)(r10 - 128) = r1;                \
+               r1 = r10;                               \
+               r1 += -128;                             \
+               r2 = 32;                                \
+               call %[bpf_trace_printk];               \
+               /* Call to dummy() forces print_verifier_state(..., true),      \
+                * thus showing the stack state, matched by __msg().            \
+                */                                     \
+               call %[dummy];                          \
+               r0 = 0;                                 \
+               exit;                                   \
+"
+                     :
+                     : __imm(bpf_trace_printk),
+                       __imm(dummy)
+                     : __clobber_all);
+}
+
+char _license[] SEC("license") = "GPL";
index 4c55b4d79d3d44744b52b6485e0ecaa26e4a9b69..e1c787815e44bba5a9f1e41d4649f84f16f1510f 100644 (file)
@@ -12,10 +12,14 @@ struct {
        __type(value, __u32);
 } xsk SEC(".maps");
 
+__u64 pkts_skip = 0;
+__u64 pkts_fail = 0;
+__u64 pkts_redir = 0;
+
 extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx,
                                         __u64 *timestamp) __ksym;
-extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx,
-                                   __u32 *hash) __ksym;
+extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
+                                   enum xdp_rss_hash_type *rss_type) __ksym;
 
 SEC("xdp")
 int rx(struct xdp_md *ctx)
@@ -26,7 +30,7 @@ int rx(struct xdp_md *ctx)
        struct udphdr *udp = NULL;
        struct iphdr *iph = NULL;
        struct xdp_meta *meta;
-       int ret;
+       int err;
 
        data = (void *)(long)ctx->data;
        data_end = (void *)(long)ctx->data_end;
@@ -46,17 +50,20 @@ int rx(struct xdp_md *ctx)
                        udp = NULL;
        }
 
-       if (!udp)
+       if (!udp) {
+               __sync_add_and_fetch(&pkts_skip, 1);
                return XDP_PASS;
+       }
 
-       if (udp->dest != bpf_htons(9091))
+       /* Forwarding UDP:9091 to AF_XDP */
+       if (udp->dest != bpf_htons(9091)) {
+               __sync_add_and_fetch(&pkts_skip, 1);
                return XDP_PASS;
+       }
 
-       bpf_printk("forwarding UDP:9091 to AF_XDP");
-
-       ret = bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct xdp_meta));
-       if (ret != 0) {
-               bpf_printk("bpf_xdp_adjust_meta returned %d", ret);
+       err = bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct xdp_meta));
+       if (err) {
+               __sync_add_and_fetch(&pkts_fail, 1);
                return XDP_PASS;
        }
 
@@ -65,20 +72,19 @@ int rx(struct xdp_md *ctx)
        meta = data_meta;
 
        if (meta + 1 > data) {
-               bpf_printk("bpf_xdp_adjust_meta doesn't appear to work");
+               __sync_add_and_fetch(&pkts_fail, 1);
                return XDP_PASS;
        }
 
-       if (!bpf_xdp_metadata_rx_timestamp(ctx, &meta->rx_timestamp))
-               bpf_printk("populated rx_timestamp with %llu", meta->rx_timestamp);
-       else
+       err = bpf_xdp_metadata_rx_timestamp(ctx, &meta->rx_timestamp);
+       if (err)
                meta->rx_timestamp = 0; /* Used by AF_XDP as not avail signal */
 
-       if (!bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash))
-               bpf_printk("populated rx_hash with %u", meta->rx_hash);
-       else
-               meta->rx_hash = 0; /* Used by AF_XDP as not avail signal */
+       err = bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash, &meta->rx_hash_type);
+       if (err < 0)
+               meta->rx_hash_err = err; /* Used by AF_XDP as no hash signal */
 
+       __sync_add_and_fetch(&pkts_redir, 1);
        return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
 }
 
index 77678b03438970c7bbc6c1b3102739d9c9baf71f..d151d406a123efc004c1fb09f28844adccade711 100644 (file)
@@ -21,8 +21,8 @@ struct {
 
 extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx,
                                         __u64 *timestamp) __ksym;
-extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx,
-                                   __u32 *hash) __ksym;
+extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
+                                   enum xdp_rss_hash_type *rss_type) __ksym;
 
 SEC("xdp")
 int rx(struct xdp_md *ctx)
@@ -56,7 +56,7 @@ int rx(struct xdp_md *ctx)
        if (timestamp == 0)
                meta->rx_timestamp = 1;
 
-       bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash);
+       bpf_xdp_metadata_rx_hash(ctx, &meta->rx_hash, &meta->rx_hash_type);
 
        return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
 }
index cf69d05451c39b5873fb823491a1a8c4010f9b5d..85f88d9d7a78565d4239a6fb6a18ae6a36d03f6e 100644 (file)
@@ -5,17 +5,18 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
-extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx,
-                                   __u32 *hash) __ksym;
+extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
+                                   enum xdp_rss_hash_type *rss_type) __ksym;
 
 int called;
 
 SEC("freplace/rx")
 int freplace_rx(struct xdp_md *ctx)
 {
+       enum xdp_rss_hash_type type = 0;
        u32 hash = 0;
        /* Call _any_ metadata function to make sure we don't crash. */
-       bpf_xdp_metadata_rx_hash(ctx, &hash);
+       bpf_xdp_metadata_rx_hash(ctx, &hash, &type);
        called++;
        return XDP_PASS;
 }
index 9d993926bf0efb6a582077db5f751e496c98ef9e..289ed202ec66aec63d11e492a5ed60906e906500 100644 (file)
         * that fp-8 stack slot was unused in the fall-through
         * branch and will accept the program incorrectly
         */
-       BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 2, 2),
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_JMP_IMM(BPF_JGT, BPF_REG_0, 2, 2),
        BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
        BPF_JMP_IMM(BPF_JA, 0, 0, 0),
        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
        BPF_LD_MAP_FD(BPF_REG_1, 0),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .fixup_map_hash_48b = { 6 },
-       .errstr = "invalid indirect read from stack R2 off -8+0 size 8",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_XDP,
+       .fixup_map_hash_48b = { 7 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -8+0 size 8",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "calls: ctx read at start of subprog",
index a6c869a7319cd23a4ed5cae14e4aa0a80dad94c9..9c4885885aba0627b558136347267479e5436ea1 100644 (file)
 {
        "helper access to variable memory: stack, bitwise AND, zero included",
        .insns = {
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
-       BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
-       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
-       BPF_MOV64_IMM(BPF_REG_3, 0),
-       BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
+       /* set max stack size */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
+       /* set r3 to a random value */
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+       /* use bitwise AND to limit r3 range to [0, 64] */
+       BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 64),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
+       BPF_MOV64_IMM(BPF_REG_4, 0),
+       /* Call bpf_ringbuf_output(), it is one of a few helper functions with
+        * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
+        * For unpriv this should signal an error, because memory at &fp[-64] is
+        * not initialized.
+        */
+       BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
        BPF_EXIT_INSN(),
        },
-       .errstr = "invalid indirect read from stack R1 off -64+0 size 64",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .fixup_map_ringbuf = { 4 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "helper access to variable memory: stack, bitwise AND + JMP, wrong max",
 {
        "helper access to variable memory: stack, JMP, no min check",
        .insns = {
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
-       BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
-       BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
-       BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3),
-       BPF_MOV64_IMM(BPF_REG_3, 0),
-       BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
+       /* set max stack size */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
+       /* set r3 to a random value */
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+       /* use JMP to limit r3 range to [0, 64] */
+       BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 64, 6),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
+       BPF_MOV64_IMM(BPF_REG_4, 0),
+       /* Call bpf_ringbuf_output(), it is one of a few helper functions with
+        * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
+        * For unpriv this should signal an error, because memory at &fp[-64] is
+        * not initialized.
+        */
+       BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .errstr = "invalid indirect read from stack R1 off -64+0 size 64",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .fixup_map_ringbuf = { 4 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "helper access to variable memory: stack, JMP (signed), no min check",
 {
        "helper access to variable memory: 8 bytes leak",
        .insns = {
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
-       BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
+       /* set max stack size */
+       BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
+       /* set r3 to a random value */
+       BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
+       BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
+       BPF_LD_MAP_FD(BPF_REG_1, 0),
+       BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
+       /* Note: fp[-32] left uninitialized */
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
        BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
-       BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
-       BPF_MOV64_IMM(BPF_REG_3, 0),
-       BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
+       /* Limit r3 range to [1, 64] */
+       BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 63),
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1),
+       BPF_MOV64_IMM(BPF_REG_4, 0),
+       /* Call bpf_ringbuf_output(), it is one of a few helper functions with
+        * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
+        * For unpriv this should signal an error, because memory region [1, 64]
+        * at &fp[-64] is not fully initialized.
+        */
+       BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .errstr = "invalid indirect read from stack R1 off -64+32 size 64",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .fixup_map_ringbuf = { 3 },
+       .errstr_unpriv = "invalid indirect read from stack R2 off -64+32 size 64",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "helper access to variable memory: 8 bytes no leak (init memory)",
index 070893fb290074c0c68f1dae454993123eef5c02..02d9e004260b333944c29aed33e82c3d51e96a00 100644 (file)
                /* bpf_strtoul() */
                BPF_EMIT_CALL(BPF_FUNC_strtoul),
 
-               BPF_MOV64_IMM(BPF_REG_0, 1),
+               BPF_MOV64_IMM(BPF_REG_0, 0),
                BPF_EXIT_INSN(),
        },
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
-       .errstr = "invalid indirect read from stack R4 off -16+4 size 8",
+       .result_unpriv = REJECT,
+       .errstr_unpriv = "invalid indirect read from stack R4 off -16+4 size 8",
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "ARG_PTR_TO_LONG misaligned",
index d63fd8991b03aa9e9f3f2ec1b3f03419f8a1686c..745d6b5842fd4e15e79820ea4c4cfd0659b14386 100644 (file)
                BPF_EXIT_INSN(),
        },
        .fixup_map_hash_8b = { 3 },
-       .errstr = "invalid read from stack off -16+0 size 8",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_TRACEPOINT,
+       .errstr_unpriv = "invalid read from stack off -16+0 size 8",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "precision tracking for u32 spill/fill",
        BPF_EXIT_INSN(),
        },
        .flags = BPF_F_TEST_STATE_FREQ,
-       .errstr = "invalid read from stack off -8+1 size 8",
-       .result = REJECT,
+       .errstr_unpriv = "invalid read from stack off -8+1 size 8",
+       .result_unpriv = REJECT,
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
index d11d0b28be41672d35074d25c17a375b71be1061..108dd3ee1edda0cd9c326b85ed7b72b09b32cbd2 100644 (file)
        .prog_type = BPF_PROG_TYPE_SCHED_CLS,
        .result = ACCEPT,
 },
-{
-       "sk_storage_get(map, skb->sk, &stack_value, 1): partially init stack_value",
-       .insns = {
-       BPF_MOV64_IMM(BPF_REG_2, 0),
-       BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -8),
-       BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
-       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
-       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       BPF_MOV64_IMM(BPF_REG_4, 1),
-       BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
-       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -8),
-       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
-       BPF_LD_MAP_FD(BPF_REG_1, 0),
-       BPF_EMIT_CALL(BPF_FUNC_sk_storage_get),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       },
-       .fixup_sk_storage_map = { 14 },
-       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
-       .result = REJECT,
-       .errstr = "invalid indirect read from stack",
-},
 {
        "bpf_map_lookup_elem(smap, &key)",
        .insns = {
index 9bb302dade237f250c705ff10826e7d40b8ec42f..d1463bf4949afd10188f25938a66c49cb75a2129 100644 (file)
        BPF_MOV64_IMM(BPF_REG_0, 0),
        BPF_EXIT_INSN(),
        },
-       .result = REJECT,
-       .errstr = "invalid read from stack off -4+0 size 4",
-       .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+       .result_unpriv = REJECT,
+       .errstr_unpriv = "invalid read from stack off -4+0 size 4",
+       /* in privileged mode reads from uninitialized stack locations are permitted */
+       .result = ACCEPT,
 },
 {
        "Spill a u32 const scalar.  Refill as u16.  Offset to skb->data",
index d37f512fad16e3b8fa2d1f46fd2974a9a6937217..b183e26c03f10c09a824b4fb51a432bf0ddc32df 100644 (file)
        .result = REJECT,
        .prog_type = BPF_PROG_TYPE_LWT_IN,
 },
-{
-       "indirect variable-offset stack access, max_off+size > max_initialized",
-       .insns = {
-       /* Fill only the second from top 8 bytes of the stack. */
-       BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
-       /* Get an unknown value. */
-       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
-       /* Make it small and 4-byte aligned. */
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
-       BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
-       /* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
-        * which. fp-12 size 8 is partially uninitialized stack.
-        */
-       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
-       /* Dereference it indirectly. */
-       BPF_LD_MAP_FD(BPF_REG_1, 0),
-       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       },
-       .fixup_map_hash_8b = { 5 },
-       .errstr = "invalid indirect read from stack R2 var_off",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_LWT_IN,
-},
 {
        "indirect variable-offset stack access, min_off < min_initialized",
        .insns = {
        .result = ACCEPT,
        .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
 },
-{
-       "indirect variable-offset stack access, uninitialized",
-       .insns = {
-       BPF_MOV64_IMM(BPF_REG_2, 6),
-       BPF_MOV64_IMM(BPF_REG_3, 28),
-       /* Fill the top 16 bytes of the stack. */
-       BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0),
-       BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
-       /* Get an unknown value. */
-       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0),
-       /* Make it small and 4-byte aligned. */
-       BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4),
-       BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
-       /* Add it to fp.  We now have either fp-12 or fp-16, we don't know
-        * which, but either way it points to initialized stack.
-        */
-       BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
-       BPF_MOV64_IMM(BPF_REG_5, 8),
-       /* Dereference it indirectly. */
-       BPF_EMIT_CALL(BPF_FUNC_getsockopt),
-       BPF_MOV64_IMM(BPF_REG_0, 0),
-       BPF_EXIT_INSN(),
-       },
-       .errstr = "invalid indirect read from stack R4 var_off",
-       .result = REJECT,
-       .prog_type = BPF_PROG_TYPE_SOCK_OPS,
-},
 {
        "indirect variable-offset stack access, ok",
        .insns = {
index 1c8acb68b977cd04bda4096fdde12344b1a3c54a..987cf0db5ebc80f70b3c62d641bc878ed8ee1805 100644 (file)
@@ -141,7 +141,11 @@ static void verify_xdp_metadata(void *data)
        meta = data - sizeof(*meta);
 
        printf("rx_timestamp: %llu\n", meta->rx_timestamp);
-       printf("rx_hash: %u\n", meta->rx_hash);
+       if (meta->rx_hash_err < 0)
+               printf("No rx_hash err=%d\n", meta->rx_hash_err);
+       else
+               printf("rx_hash: 0x%X with RSS type:0x%X\n",
+                      meta->rx_hash, meta->rx_hash_type);
 }
 
 static void verify_skb_metadata(int fd)
@@ -212,7 +216,9 @@ static int verify_metadata(struct xsk *rx_xsk, int rxq, int server_fd)
        while (true) {
                errno = 0;
                ret = poll(fds, rxq + 1, 1000);
-               printf("poll: %d (%d)\n", ret, errno);
+               printf("poll: %d (%d) skip=%llu fail=%llu redir=%llu\n",
+                      ret, errno, bpf_obj->bss->pkts_skip,
+                      bpf_obj->bss->pkts_fail, bpf_obj->bss->pkts_redir);
                if (ret < 0)
                        break;
                if (ret == 0)
index f6780fbb0a214765a14a293cf7fb0654e4a32297..0c4624dc6f2f719183b21e7e0bd1fbc9e6b72164 100644 (file)
@@ -12,4 +12,8 @@
 struct xdp_meta {
        __u64 rx_timestamp;
        __u32 rx_hash;
+       union {
+               __u32 rx_hash_type;
+               __s32 rx_hash_err;
+       };
 };
index 1e616a8c6a9cfd8035c3dff13ab5204d73d3d059..f4f7c0aef702b916a6a6adfd3f41ecce71b40f4c 100644 (file)
@@ -98,6 +98,11 @@ static int alloc_anon_50M_check(const char *cgroup, void *arg)
        int ret = -1;
 
        buf = malloc(size);
+       if (buf == NULL) {
+               fprintf(stderr, "malloc() failed\n");
+               return -1;
+       }
+
        for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
                *ptr = 0;
 
@@ -211,6 +216,11 @@ static int alloc_anon_noexit(const char *cgroup, void *arg)
        char *buf, *ptr;
 
        buf = malloc(size);
+       if (buf == NULL) {
+               fprintf(stderr, "malloc() failed\n");
+               return -1;
+       }
+
        for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
                *ptr = 0;
 
@@ -778,6 +788,11 @@ static int alloc_anon_50M_check_swap(const char *cgroup, void *arg)
        int ret = -1;
 
        buf = malloc(size);
+       if (buf == NULL) {
+               fprintf(stderr, "malloc() failed\n");
+               return -1;
+       }
+
        for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
                *ptr = 0;
 
index 4fce46afe6db812fee6544caea897565994d28e0..e495f895a2cdd0bc5bfe77bb8cfdfdf20c0584ed 100644 (file)
@@ -129,7 +129,7 @@ int main(int argc, char *argv[])
        uid_t uid = getuid();
 
        ksft_print_header();
-       ksft_set_plan(17);
+       ksft_set_plan(18);
        test_clone3_supported();
 
        /* Just a simple clone3() should return 0.*/
@@ -198,5 +198,5 @@ int main(int argc, char *argv[])
        /* Do a clone3() in a new time namespace */
        test_clone3(CLONE_NEWTIME, 0, 0, CLONE3_ARGS_NO_TEST);
 
-       return !ksft_get_fail_cnt() ? ksft_exit_pass() : ksft_exit_fail();
+       ksft_finished();
 }
index 8e3b786a748f97bf7d288a25d97a614cd41210ca..03f92d7aeb19b970acfdb2d28ad882f630c12567 100644 (file)
@@ -8,10 +8,12 @@ TEST_PROGS := \
        dev_addr_lists.sh \
        mode-1-recovery-updelay.sh \
        mode-2-recovery-updelay.sh \
-       option_prio.sh
+       bond_options.sh \
+       bond-eth-type-change.sh
 
 TEST_FILES := \
        lag_lib.sh \
+       bond_topo_3d1c.sh \
        net_forwarding_lib.sh
 
 include ../../../lib.mk
diff --git a/tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh b/tools/testing/selftests/drivers/net/bonding/bond-eth-type-change.sh
new file mode 100755 (executable)
index 0000000..5cdd220
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test bond device ether type changing
+#
+
+ALL_TESTS="
+       bond_test_unsuccessful_enslave_type_change
+       bond_test_successful_enslave_type_change
+"
+REQUIRE_MZ=no
+NUM_NETIFS=0
+lib_dir=$(dirname "$0")
+source "$lib_dir"/net_forwarding_lib.sh
+
+bond_check_flags()
+{
+       local bonddev=$1
+
+       ip -d l sh dev "$bonddev" | grep -q "MASTER"
+       check_err $? "MASTER flag is missing from the bond device"
+
+       ip -d l sh dev "$bonddev" | grep -q "SLAVE"
+       check_err $? "SLAVE flag is missing from the bond device"
+}
+
+# test enslaved bond dev type change from ARPHRD_ETHER and back
+# this allows us to test both MASTER and SLAVE flags at once
+bond_test_enslave_type_change()
+{
+       local test_success=$1
+       local devbond0="test-bond0"
+       local devbond1="test-bond1"
+       local devbond2="test-bond2"
+       local nonethdev="test-noneth0"
+
+       # create a non-ARPHRD_ETHER device for testing (e.g. nlmon type)
+       ip link add name "$nonethdev" type nlmon
+       check_err $? "could not create a non-ARPHRD_ETHER device (nlmon)"
+       ip link add name "$devbond0" type bond
+       if [ $test_success -eq 1 ]; then
+               # we need devbond0 in active-backup mode to successfully enslave nonethdev
+               ip link set dev "$devbond0" type bond mode active-backup
+               check_err $? "could not change bond mode to active-backup"
+       fi
+       ip link add name "$devbond1" type bond
+       ip link add name "$devbond2" type bond
+       ip link set dev "$devbond0" master "$devbond1"
+       check_err $? "could not enslave $devbond0 to $devbond1"
+       # change bond type to non-ARPHRD_ETHER
+       ip link set dev "$nonethdev" master "$devbond0" 1>/dev/null 2>/dev/null
+       ip link set dev "$nonethdev" nomaster 1>/dev/null 2>/dev/null
+       # restore ARPHRD_ETHER type by enslaving such device
+       ip link set dev "$devbond2" master "$devbond0"
+       check_err $? "could not enslave $devbond2 to $devbond0"
+       ip link set dev "$devbond1" nomaster
+
+       bond_check_flags "$devbond0"
+
+       # clean up
+       ip link del dev "$devbond0"
+       ip link del dev "$devbond1"
+       ip link del dev "$devbond2"
+       ip link del dev "$nonethdev"
+}
+
+bond_test_unsuccessful_enslave_type_change()
+{
+       RET=0
+
+       bond_test_enslave_type_change 0
+       log_test "Change ether type of an enslaved bond device with unsuccessful enslave"
+}
+
+bond_test_successful_enslave_type_change()
+{
+       RET=0
+
+       bond_test_enslave_type_change 1
+       log_test "Change ether type of an enslaved bond device with successful enslave"
+}
+
+tests_run
+
+exit "$EXIT_STATUS"
diff --git a/tools/testing/selftests/drivers/net/bonding/bond_options.sh b/tools/testing/selftests/drivers/net/bonding/bond_options.sh
new file mode 100755 (executable)
index 0000000..db29a31
--- /dev/null
@@ -0,0 +1,264 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test bonding options with mode 1,5,6
+
+ALL_TESTS="
+       prio
+       arp_validate
+"
+
+REQUIRE_MZ=no
+NUM_NETIFS=0
+lib_dir=$(dirname "$0")
+source ${lib_dir}/net_forwarding_lib.sh
+source ${lib_dir}/bond_topo_3d1c.sh
+
+skip_prio()
+{
+       local skip=1
+
+       # check if iproute support prio option
+       ip -n ${s_ns} link set eth0 type bond_slave prio 10
+       [[ $? -ne 0 ]] && skip=0
+
+       # check if kernel support prio option
+       ip -n ${s_ns} -d link show eth0 | grep -q "prio 10"
+       [[ $? -ne 0 ]] && skip=0
+
+       return $skip
+}
+
+skip_ns()
+{
+       local skip=1
+
+       # check if iproute support ns_ip6_target option
+       ip -n ${s_ns} link add bond1 type bond ns_ip6_target ${g_ip6}
+       [[ $? -ne 0 ]] && skip=0
+
+       # check if kernel support ns_ip6_target option
+       ip -n ${s_ns} -d link show bond1 | grep -q "ns_ip6_target ${g_ip6}"
+       [[ $? -ne 0 ]] && skip=0
+
+       ip -n ${s_ns} link del bond1
+
+       return $skip
+}
+
+active_slave=""
+check_active_slave()
+{
+       local target_active_slave=$1
+       active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
+       test "$active_slave" = "$target_active_slave"
+       check_err $? "Current active slave is $active_slave but not $target_active_slave"
+}
+
+
+# Test bonding prio option
+prio_test()
+{
+       local param="$1"
+       RET=0
+
+       # create bond
+       bond_reset "${param}"
+
+       # check bonding member prio value
+       ip -n ${s_ns} link set eth0 type bond_slave prio 0
+       ip -n ${s_ns} link set eth1 type bond_slave prio 10
+       ip -n ${s_ns} link set eth2 type bond_slave prio 11
+       cmd_jq "ip -n ${s_ns} -d -j link show eth0" \
+               ".[].linkinfo.info_slave_data | select (.prio == 0)" "-e" &> /dev/null
+       check_err $? "eth0 prio is not 0"
+       cmd_jq "ip -n ${s_ns} -d -j link show eth1" \
+               ".[].linkinfo.info_slave_data | select (.prio == 10)" "-e" &> /dev/null
+       check_err $? "eth1 prio is not 10"
+       cmd_jq "ip -n ${s_ns} -d -j link show eth2" \
+               ".[].linkinfo.info_slave_data | select (.prio == 11)" "-e" &> /dev/null
+       check_err $? "eth2 prio is not 11"
+
+       bond_check_connection "setup"
+
+       # active slave should be the primary slave
+       check_active_slave eth1
+
+       # active slave should be the higher prio slave
+       ip -n ${s_ns} link set $active_slave down
+       bond_check_connection "fail over"
+       check_active_slave eth2
+
+       # when only 1 slave is up
+       ip -n ${s_ns} link set $active_slave down
+       bond_check_connection "only 1 slave up"
+       check_active_slave eth0
+
+       # when a higher prio slave change to up
+       ip -n ${s_ns} link set eth2 up
+       bond_check_connection "higher prio slave up"
+       case $primary_reselect in
+               "0")
+                       check_active_slave "eth2"
+                       ;;
+               "1")
+                       check_active_slave "eth0"
+                       ;;
+               "2")
+                       check_active_slave "eth0"
+                       ;;
+       esac
+       local pre_active_slave=$active_slave
+
+       # when the primary slave change to up
+       ip -n ${s_ns} link set eth1 up
+       bond_check_connection "primary slave up"
+       case $primary_reselect in
+               "0")
+                       check_active_slave "eth1"
+                       ;;
+               "1")
+                       check_active_slave "$pre_active_slave"
+                       ;;
+               "2")
+                       check_active_slave "$pre_active_slave"
+                       ip -n ${s_ns} link set $active_slave down
+                       bond_check_connection "pre_active slave down"
+                       check_active_slave "eth1"
+                       ;;
+       esac
+
+       # Test changing bond slave prio
+       if [[ "$primary_reselect" == "0" ]];then
+               ip -n ${s_ns} link set eth0 type bond_slave prio 1000000
+               ip -n ${s_ns} link set eth1 type bond_slave prio 0
+               ip -n ${s_ns} link set eth2 type bond_slave prio -50
+               ip -n ${s_ns} -d link show eth0 | grep -q 'prio 1000000'
+               check_err $? "eth0 prio is not 1000000"
+               ip -n ${s_ns} -d link show eth1 | grep -q 'prio 0'
+               check_err $? "eth1 prio is not 0"
+               ip -n ${s_ns} -d link show eth2 | grep -q 'prio -50'
+               check_err $? "eth3 prio is not -50"
+               check_active_slave "eth1"
+
+               ip -n ${s_ns} link set $active_slave down
+               bond_check_connection "change slave prio"
+               check_active_slave "eth0"
+       fi
+}
+
+prio_miimon()
+{
+       local primary_reselect
+       local mode=$1
+
+       for primary_reselect in 0 1 2; do
+               prio_test "mode $mode miimon 100 primary eth1 primary_reselect $primary_reselect"
+               log_test "prio" "$mode miimon primary_reselect $primary_reselect"
+       done
+}
+
+prio_arp()
+{
+       local primary_reselect
+       local mode=$1
+
+       for primary_reselect in 0 1 2; do
+               prio_test "mode active-backup arp_interval 100 arp_ip_target ${g_ip4} primary eth1 primary_reselect $primary_reselect"
+               log_test "prio" "$mode arp_ip_target primary_reselect $primary_reselect"
+       done
+}
+
+prio_ns()
+{
+       local primary_reselect
+       local mode=$1
+
+       if skip_ns; then
+               log_test_skip "prio ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
+               return 0
+       fi
+
+       for primary_reselect in 0 1 2; do
+               prio_test "mode active-backup arp_interval 100 ns_ip6_target ${g_ip6} primary eth1 primary_reselect $primary_reselect"
+               log_test "prio" "$mode ns_ip6_target primary_reselect $primary_reselect"
+       done
+}
+
+prio()
+{
+       local mode modes="active-backup balance-tlb balance-alb"
+
+       if skip_prio; then
+               log_test_skip "prio" "Current iproute or kernel doesn't support bond option 'prio'."
+               return 0
+       fi
+
+       for mode in $modes; do
+               prio_miimon $mode
+               prio_arp $mode
+               prio_ns $mode
+       done
+}
+
+arp_validate_test()
+{
+       local param="$1"
+       RET=0
+
+       # create bond
+       bond_reset "${param}"
+
+       bond_check_connection
+       [ $RET -ne 0 ] && log_test "arp_validate" "$retmsg"
+
+       # wait for a while to make sure the mii status stable
+       sleep 5
+       for i in $(seq 0 2); do
+               mii_status=$(cmd_jq "ip -n ${s_ns} -j -d link show eth$i" ".[].linkinfo.info_slave_data.mii_status")
+               if [ ${mii_status} != "UP" ]; then
+                       RET=1
+                       log_test "arp_validate" "interface eth$i mii_status $mii_status"
+               fi
+       done
+}
+
+arp_validate_arp()
+{
+       local mode=$1
+       local val
+       for val in $(seq 0 6); do
+               arp_validate_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} arp_validate $val"
+               log_test "arp_validate" "$mode arp_ip_target arp_validate $val"
+       done
+}
+
+arp_validate_ns()
+{
+       local mode=$1
+       local val
+
+       if skip_ns; then
+               log_test_skip "arp_validate ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
+               return 0
+       fi
+
+       for val in $(seq 0 6); do
+               arp_validate_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6} arp_validate $val"
+               log_test "arp_validate" "$mode ns_ip6_target arp_validate $val"
+       done
+}
+
+arp_validate()
+{
+       arp_validate_arp "active-backup"
+       arp_validate_ns "active-backup"
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh b/tools/testing/selftests/drivers/net/bonding/bond_topo_3d1c.sh
new file mode 100644 (file)
index 0000000..4045ca9
--- /dev/null
@@ -0,0 +1,143 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Topology for Bond mode 1,5,6 testing
+#
+#  +-------------------------------------+
+#  |                bond0                |
+#  |                  +                  |  Server
+#  |      eth0        | eth1   eth2      |  192.0.2.1/24
+#  |        +-------------------+        |  2001:db8::1/24
+#  |        |         |         |        |
+#  +-------------------------------------+
+#           |         |         |
+#  +-------------------------------------+
+#  |        |         |         |        |
+#  |    +---+---------+---------+---+    |  Gateway
+#  |    |            br0            |    |  192.0.2.254/24
+#  |    +-------------+-------------+    |  2001:db8::254/24
+#  |                  |                  |
+#  +-------------------------------------+
+#                     |
+#  +-------------------------------------+
+#  |                  |                  |  Client
+#  |                  +                  |  192.0.2.10/24
+#  |                eth0                 |  2001:db8::10/24
+#  +-------------------------------------+
+
+s_ns="s-$(mktemp -u XXXXXX)"
+c_ns="c-$(mktemp -u XXXXXX)"
+g_ns="g-$(mktemp -u XXXXXX)"
+s_ip4="192.0.2.1"
+c_ip4="192.0.2.10"
+g_ip4="192.0.2.254"
+s_ip6="2001:db8::1"
+c_ip6="2001:db8::10"
+g_ip6="2001:db8::254"
+
+gateway_create()
+{
+       ip netns add ${g_ns}
+       ip -n ${g_ns} link add br0 type bridge
+       ip -n ${g_ns} link set br0 up
+       ip -n ${g_ns} addr add ${g_ip4}/24 dev br0
+       ip -n ${g_ns} addr add ${g_ip6}/24 dev br0
+}
+
+gateway_destroy()
+{
+       ip -n ${g_ns} link del br0
+       ip netns del ${g_ns}
+}
+
+server_create()
+{
+       ip netns add ${s_ns}
+       ip -n ${s_ns} link add bond0 type bond mode active-backup miimon 100
+
+       for i in $(seq 0 2); do
+               ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns}
+
+               ip -n ${g_ns} link set s${i} up
+               ip -n ${g_ns} link set s${i} master br0
+               ip -n ${s_ns} link set eth${i} master bond0
+       done
+
+       ip -n ${s_ns} link set bond0 up
+       ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0
+       ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0
+       sleep 2
+}
+
+# Reset bond with new mode and options
+bond_reset()
+{
+       local param="$1"
+
+       ip -n ${s_ns} link set bond0 down
+       ip -n ${s_ns} link del bond0
+
+       ip -n ${s_ns} link add bond0 type bond $param
+       for i in $(seq 0 2); do
+               ip -n ${s_ns} link set eth$i master bond0
+       done
+
+       ip -n ${s_ns} link set bond0 up
+       ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0
+       ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0
+       sleep 2
+}
+
+server_destroy()
+{
+       for i in $(seq 0 2); do
+               ip -n ${s_ns} link del eth${i}
+       done
+       ip netns del ${s_ns}
+}
+
+client_create()
+{
+       ip netns add ${c_ns}
+       ip -n ${c_ns} link add eth0 type veth peer name c0 netns ${g_ns}
+
+       ip -n ${g_ns} link set c0 up
+       ip -n ${g_ns} link set c0 master br0
+
+       ip -n ${c_ns} link set eth0 up
+       ip -n ${c_ns} addr add ${c_ip4}/24 dev eth0
+       ip -n ${c_ns} addr add ${c_ip6}/24 dev eth0
+}
+
+client_destroy()
+{
+       ip -n ${c_ns} link del eth0
+       ip netns del ${c_ns}
+}
+
+setup_prepare()
+{
+       gateway_create
+       server_create
+       client_create
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       client_destroy
+       server_destroy
+       gateway_destroy
+}
+
+bond_check_connection()
+{
+       local msg=${1:-"check connection"}
+
+       sleep 2
+       ip netns exec ${s_ns} ping ${c_ip4} -c5 -i 0.1 &>/dev/null
+       check_err $? "${msg}: ping failed"
+       ip netns exec ${s_ns} ping6 ${c_ip6} -c5 -i 0.1 &>/dev/null
+       check_err $? "${msg}: ping6 failed"
+}
diff --git a/tools/testing/selftests/drivers/net/bonding/option_prio.sh b/tools/testing/selftests/drivers/net/bonding/option_prio.sh
deleted file mode 100755 (executable)
index c32eebf..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-#
-# Test bonding option prio
-#
-
-ALL_TESTS="
-       prio_arp_ip_target_test
-       prio_miimon_test
-"
-
-REQUIRE_MZ=no
-REQUIRE_JQ=no
-NUM_NETIFS=0
-lib_dir=$(dirname "$0")
-source "$lib_dir"/net_forwarding_lib.sh
-
-destroy()
-{
-       ip link del bond0 &>/dev/null
-       ip link del br0 &>/dev/null
-       ip link del veth0 &>/dev/null
-       ip link del veth1 &>/dev/null
-       ip link del veth2 &>/dev/null
-       ip netns del ns1 &>/dev/null
-       ip link del veth3 &>/dev/null
-}
-
-cleanup()
-{
-       pre_cleanup
-
-       destroy
-}
-
-skip()
-{
-        local skip=1
-       ip link add name bond0 type bond mode 1 miimon 100 &>/dev/null
-       ip link add name veth0 type veth peer name veth0_p
-       ip link set veth0 master bond0
-
-       # check if iproute support prio option
-       ip link set dev veth0 type bond_slave prio 10
-       [[ $? -ne 0 ]] && skip=0
-
-       # check if bonding support prio option
-       ip -d link show veth0 | grep -q "prio 10"
-       [[ $? -ne 0 ]] && skip=0
-
-       ip link del bond0 &>/dev/null
-       ip link del veth0
-
-       return $skip
-}
-
-active_slave=""
-check_active_slave()
-{
-       local target_active_slave=$1
-       active_slave="$(cat /sys/class/net/bond0/bonding/active_slave)"
-       test "$active_slave" = "$target_active_slave"
-       check_err $? "Current active slave is $active_slave but not $target_active_slave"
-}
-
-
-# Test bonding prio option with mode=$mode monitor=$monitor
-# and primary_reselect=$primary_reselect
-prio_test()
-{
-       RET=0
-
-       local monitor=$1
-       local mode=$2
-       local primary_reselect=$3
-
-       local bond_ip4="192.169.1.2"
-       local peer_ip4="192.169.1.1"
-       local bond_ip6="2009:0a:0b::02"
-       local peer_ip6="2009:0a:0b::01"
-
-
-       # create veths
-       ip link add name veth0 type veth peer name veth0_p
-       ip link add name veth1 type veth peer name veth1_p
-       ip link add name veth2 type veth peer name veth2_p
-
-       # create bond
-       if [[ "$monitor" == "miimon" ]];then
-               ip link add name bond0 type bond mode $mode miimon 100 primary veth1 primary_reselect $primary_reselect
-       elif [[ "$monitor" == "arp_ip_target" ]];then
-               ip link add name bond0 type bond mode $mode arp_interval 1000 arp_ip_target $peer_ip4 primary veth1 primary_reselect $primary_reselect
-       elif [[ "$monitor" == "ns_ip6_target" ]];then
-               ip link add name bond0 type bond mode $mode arp_interval 1000 ns_ip6_target $peer_ip6 primary veth1 primary_reselect $primary_reselect
-       fi
-       ip link set bond0 up
-       ip link set veth0 master bond0
-       ip link set veth1 master bond0
-       ip link set veth2 master bond0
-       # check bonding member prio value
-       ip link set dev veth0 type bond_slave prio 0
-       ip link set dev veth1 type bond_slave prio 10
-       ip link set dev veth2 type bond_slave prio 11
-       ip -d link show veth0 | grep -q 'prio 0'
-       check_err $? "veth0 prio is not 0"
-       ip -d link show veth1 | grep -q 'prio 10'
-       check_err $? "veth0 prio is not 10"
-       ip -d link show veth2 | grep -q 'prio 11'
-       check_err $? "veth0 prio is not 11"
-
-       ip link set veth0 up
-       ip link set veth1 up
-       ip link set veth2 up
-       ip link set veth0_p up
-       ip link set veth1_p up
-       ip link set veth2_p up
-
-       # prepare ping target
-       ip link add name br0 type bridge
-       ip link set br0 up
-       ip link set veth0_p master br0
-       ip link set veth1_p master br0
-       ip link set veth2_p master br0
-       ip link add name veth3 type veth peer name veth3_p
-       ip netns add ns1
-       ip link set veth3_p master br0 up
-       ip link set veth3 netns ns1 up
-       ip netns exec ns1 ip addr add $peer_ip4/24 dev veth3
-       ip netns exec ns1 ip addr add $peer_ip6/64 dev veth3
-       ip addr add $bond_ip4/24 dev bond0
-       ip addr add $bond_ip6/64 dev bond0
-       sleep 5
-
-       ping $peer_ip4 -c5 -I bond0 &>/dev/null
-       check_err $? "ping failed 1."
-       ping6 $peer_ip6 -c5 -I bond0 &>/dev/null
-       check_err $? "ping6 failed 1."
-
-       # active salve should be the primary slave
-       check_active_slave veth1
-
-       # active slave should be the higher prio slave
-       ip link set $active_slave down
-       ping $peer_ip4 -c5 -I bond0 &>/dev/null
-       check_err $? "ping failed 2."
-       check_active_slave veth2
-
-       # when only 1 slave is up
-       ip link set $active_slave down
-       ping $peer_ip4 -c5 -I bond0 &>/dev/null
-       check_err $? "ping failed 3."
-       check_active_slave veth0
-
-       # when a higher prio slave change to up
-       ip link set veth2 up
-       ping $peer_ip4 -c5 -I bond0 &>/dev/null
-       check_err $? "ping failed 4."
-       case $primary_reselect in
-               "0")
-                       check_active_slave "veth2"
-                       ;;
-               "1")
-                       check_active_slave "veth0"
-                       ;;
-               "2")
-                       check_active_slave "veth0"
-                       ;;
-       esac
-       local pre_active_slave=$active_slave
-
-       # when the primary slave change to up
-       ip link set veth1 up
-       ping $peer_ip4 -c5 -I bond0 &>/dev/null
-       check_err $? "ping failed 5."
-       case $primary_reselect in
-               "0")
-                       check_active_slave "veth1"
-                       ;;
-               "1")
-                       check_active_slave "$pre_active_slave"
-                       ;;
-               "2")
-                       check_active_slave "$pre_active_slave"
-                       ip link set $active_slave down
-                       ping $peer_ip4 -c5 -I bond0 &>/dev/null
-                       check_err $? "ping failed 6."
-                       check_active_slave "veth1"
-                       ;;
-       esac
-
-       # Test changing bond salve prio
-       if [[ "$primary_reselect" == "0" ]];then
-               ip link set dev veth0 type bond_slave prio 1000000
-               ip link set dev veth1 type bond_slave prio 0
-               ip link set dev veth2 type bond_slave prio -50
-               ip -d link show veth0 | grep -q 'prio 1000000'
-               check_err $? "veth0 prio is not 1000000"
-               ip -d link show veth1 | grep -q 'prio 0'
-               check_err $? "veth1 prio is not 0"
-               ip -d link show veth2 | grep -q 'prio -50'
-               check_err $? "veth3 prio is not -50"
-               check_active_slave "veth1"
-
-               ip link set $active_slave down
-               ping $peer_ip4 -c5 -I bond0 &>/dev/null
-               check_err $? "ping failed 7."
-               check_active_slave "veth0"
-       fi
-
-       cleanup
-
-       log_test "prio_test" "Test bonding option 'prio' with mode=$mode monitor=$monitor and primary_reselect=$primary_reselect"
-}
-
-prio_miimon_test()
-{
-       local mode
-       local primary_reselect
-
-       for mode in 1 5 6; do
-               for primary_reselect in 0 1 2; do
-                       prio_test "miimon" $mode $primary_reselect
-               done
-       done
-}
-
-prio_arp_ip_target_test()
-{
-       local primary_reselect
-
-       for primary_reselect in 0 1 2; do
-               prio_test "arp_ip_target" 1 $primary_reselect
-       done
-}
-
-if skip;then
-       log_test_skip "option_prio.sh" "Current iproute doesn't support 'prio'."
-       exit 0
-fi
-
-trap cleanup EXIT
-
-tests_run
-
-exit "$EXIT_STATUS"
index 33a0dbd26bd342c4159df46de49177c5ef66e068..829be379545adacd3efc7c7e3a729954c2e20eef 100644 (file)
 #ifndef __KSELFTEST_H
 #define __KSELFTEST_H
 
+#ifndef NOLIBC
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <stdio.h>
+#endif
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
index cfa36f38794844078b8f429f845b427831b326c4..9b004905d1d3141c19051055c51a7900cbbdbea1 100644 (file)
@@ -180,9 +180,7 @@ static void host_test_system_suspend(void)
 
        enter_guest(source);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
-                   "Unhandled exit reason: %u (%s)",
-                   run->exit_reason, exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(source, KVM_EXIT_SYSTEM_EVENT);
        TEST_ASSERT(run->system_event.type == KVM_SYSTEM_EVENT_SUSPEND,
                    "Unhandled system event: %u (expected: %u)",
                    run->system_event.type, KVM_SYSTEM_EVENT_SUSPEND);
index 80d6416f3012e6c8605b1e5fb07a21085a0f7cd7..a6e9f215ce700c9cf3ef44093697998b3d36b5a2 100644 (file)
@@ -63,6 +63,15 @@ void test_assert(bool exp, const char *exp_str,
                    #a, #b, #a, (unsigned long) __a, #b, (unsigned long) __b); \
 } while (0)
 
+#define TEST_ASSERT_KVM_EXIT_REASON(vcpu, expected) do {               \
+       __u32 exit_reason = (vcpu)->run->exit_reason;                   \
+                                                                       \
+       TEST_ASSERT(exit_reason == (expected),                          \
+                   "Wanted KVM exit reason: %u (%s), got: %u (%s)",    \
+                   (expected), exit_reason_str((expected)),            \
+                   exit_reason, exit_reason_str(exit_reason));         \
+} while (0)
+
 #define TEST_FAIL(fmt, ...) do { \
        TEST_ASSERT(false, fmt, ##__VA_ARGS__); \
        __builtin_unreachable(); \
index 53ffa43c90db1b0d8eb16b956ae7aaeddffe051a..90387ddcb2a9de8e63f0a1b853975895efe46bab 100644 (file)
@@ -1063,6 +1063,8 @@ uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr);
 
 uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
                       uint64_t a3);
+uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1);
+void xen_hypercall(uint64_t nr, uint64_t a0, void *a1);
 
 void __vm_xsave_require_permission(int bit, const char *name);
 
index 3ea24a5f4c43ecf12921340005ecefff7e819596..8ec20ac33de022012c7935314f1e6c1b28792f17 100644 (file)
@@ -1815,38 +1815,53 @@ void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
                vcpu_dump(stream, vcpu, indent + 2);
 }
 
+#define KVM_EXIT_STRING(x) {KVM_EXIT_##x, #x}
+
 /* Known KVM exit reasons */
 static struct exit_reason {
        unsigned int reason;
        const char *name;
 } exit_reasons_known[] = {
-       {KVM_EXIT_UNKNOWN, "UNKNOWN"},
-       {KVM_EXIT_EXCEPTION, "EXCEPTION"},
-       {KVM_EXIT_IO, "IO"},
-       {KVM_EXIT_HYPERCALL, "HYPERCALL"},
-       {KVM_EXIT_DEBUG, "DEBUG"},
-       {KVM_EXIT_HLT, "HLT"},
-       {KVM_EXIT_MMIO, "MMIO"},
-       {KVM_EXIT_IRQ_WINDOW_OPEN, "IRQ_WINDOW_OPEN"},
-       {KVM_EXIT_SHUTDOWN, "SHUTDOWN"},
-       {KVM_EXIT_FAIL_ENTRY, "FAIL_ENTRY"},
-       {KVM_EXIT_INTR, "INTR"},
-       {KVM_EXIT_SET_TPR, "SET_TPR"},
-       {KVM_EXIT_TPR_ACCESS, "TPR_ACCESS"},
-       {KVM_EXIT_S390_SIEIC, "S390_SIEIC"},
-       {KVM_EXIT_S390_RESET, "S390_RESET"},
-       {KVM_EXIT_DCR, "DCR"},
-       {KVM_EXIT_NMI, "NMI"},
-       {KVM_EXIT_INTERNAL_ERROR, "INTERNAL_ERROR"},
-       {KVM_EXIT_OSI, "OSI"},
-       {KVM_EXIT_PAPR_HCALL, "PAPR_HCALL"},
-       {KVM_EXIT_DIRTY_RING_FULL, "DIRTY_RING_FULL"},
-       {KVM_EXIT_X86_RDMSR, "RDMSR"},
-       {KVM_EXIT_X86_WRMSR, "WRMSR"},
-       {KVM_EXIT_XEN, "XEN"},
-       {KVM_EXIT_HYPERV, "HYPERV"},
+       KVM_EXIT_STRING(UNKNOWN),
+       KVM_EXIT_STRING(EXCEPTION),
+       KVM_EXIT_STRING(IO),
+       KVM_EXIT_STRING(HYPERCALL),
+       KVM_EXIT_STRING(DEBUG),
+       KVM_EXIT_STRING(HLT),
+       KVM_EXIT_STRING(MMIO),
+       KVM_EXIT_STRING(IRQ_WINDOW_OPEN),
+       KVM_EXIT_STRING(SHUTDOWN),
+       KVM_EXIT_STRING(FAIL_ENTRY),
+       KVM_EXIT_STRING(INTR),
+       KVM_EXIT_STRING(SET_TPR),
+       KVM_EXIT_STRING(TPR_ACCESS),
+       KVM_EXIT_STRING(S390_SIEIC),
+       KVM_EXIT_STRING(S390_RESET),
+       KVM_EXIT_STRING(DCR),
+       KVM_EXIT_STRING(NMI),
+       KVM_EXIT_STRING(INTERNAL_ERROR),
+       KVM_EXIT_STRING(OSI),
+       KVM_EXIT_STRING(PAPR_HCALL),
+       KVM_EXIT_STRING(S390_UCONTROL),
+       KVM_EXIT_STRING(WATCHDOG),
+       KVM_EXIT_STRING(S390_TSCH),
+       KVM_EXIT_STRING(EPR),
+       KVM_EXIT_STRING(SYSTEM_EVENT),
+       KVM_EXIT_STRING(S390_STSI),
+       KVM_EXIT_STRING(IOAPIC_EOI),
+       KVM_EXIT_STRING(HYPERV),
+       KVM_EXIT_STRING(ARM_NISV),
+       KVM_EXIT_STRING(X86_RDMSR),
+       KVM_EXIT_STRING(X86_WRMSR),
+       KVM_EXIT_STRING(DIRTY_RING_FULL),
+       KVM_EXIT_STRING(AP_RESET_HOLD),
+       KVM_EXIT_STRING(X86_BUS_LOCK),
+       KVM_EXIT_STRING(XEN),
+       KVM_EXIT_STRING(RISCV_SBI),
+       KVM_EXIT_STRING(RISCV_CSR),
+       KVM_EXIT_STRING(NOTIFY),
 #ifdef KVM_EXIT_MEMORY_NOT_PRESENT
-       {KVM_EXIT_MEMORY_NOT_PRESENT, "MEMORY_NOT_PRESENT"},
+       KVM_EXIT_STRING(MEMORY_NOT_PRESENT),
 #endif
 };
 
index cdb7daeed5fd956a1076c39d35bad166d09ac788..2c432fa164f194ade8a3d51a79f27c8dbb0e32ee 100644 (file)
@@ -35,8 +35,7 @@ static uint64_t diag318_handler(void)
        vcpu_run(vcpu);
        run = vcpu->run;
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
-                   "DIAGNOSE 0x0318 instruction was not intercepted");
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s390_sieic.icptcode == ICPT_INSTRUCTION,
                    "Unexpected intercept code: 0x%x", run->s390_sieic.icptcode);
        TEST_ASSERT((run->s390_sieic.ipa & 0xff00) == IPA0_DIAG,
index 5c22fa4c2825efb1d51df880fea85dbb4dcce036..b772193f6c186d659b8053e9703ff6abe6754ee7 100644 (file)
@@ -165,26 +165,33 @@ size_t get_trans_hugepagesz(void)
 size_t get_def_hugetlb_pagesz(void)
 {
        char buf[64];
-       const char *tag = "Hugepagesize:";
+       const char *hugepagesize = "Hugepagesize:";
+       const char *hugepages_total = "HugePages_Total:";
        FILE *f;
 
        f = fopen("/proc/meminfo", "r");
        TEST_ASSERT(f != NULL, "Error in opening /proc/meminfo");
 
        while (fgets(buf, sizeof(buf), f) != NULL) {
-               if (strstr(buf, tag) == buf) {
+               if (strstr(buf, hugepages_total) == buf) {
+                       unsigned long long total = strtoull(buf + strlen(hugepages_total), NULL, 10);
+                       if (!total) {
+                               fprintf(stderr, "HUGETLB is not enabled in /proc/sys/vm/nr_hugepages\n");
+                               exit(KSFT_SKIP);
+                       }
+               }
+               if (strstr(buf, hugepagesize) == buf) {
                        fclose(f);
-                       return strtoull(buf + strlen(tag), NULL, 10) << 10;
+                       return strtoull(buf + strlen(hugepagesize), NULL, 10) << 10;
                }
        }
 
-       if (feof(f))
-               TEST_FAIL("HUGETLB is not configured in host kernel");
-       else
-               TEST_FAIL("Error in reading /proc/meminfo");
+       if (feof(f)) {
+               fprintf(stderr, "HUGETLB is not configured in host kernel");
+               exit(KSFT_SKIP);
+       }
 
-       fclose(f);
-       return 0;
+       TEST_FAIL("Error in reading /proc/meminfo");
 }
 
 #define ANON_FLAGS     (MAP_PRIVATE | MAP_ANONYMOUS)
index ae1e573d94ce71d6832d15c3eeb191d938f693e6..c39a4353ba194c13257e1aaae62c0ee6889c776d 100644 (file)
@@ -1139,21 +1139,36 @@ const struct kvm_cpuid_entry2 *get_cpuid_entry(const struct kvm_cpuid2 *cpuid,
        return NULL;
 }
 
+#define X86_HYPERCALL(inputs...)                                       \
+({                                                                     \
+       uint64_t r;                                                     \
+                                                                       \
+       asm volatile("test %[use_vmmcall], %[use_vmmcall]\n\t"          \
+                    "jnz 1f\n\t"                                       \
+                    "vmcall\n\t"                                       \
+                    "jmp 2f\n\t"                                       \
+                    "1: vmmcall\n\t"                                   \
+                    "2:"                                               \
+                    : "=a"(r)                                          \
+                    : [use_vmmcall] "r" (host_cpu_is_amd), inputs);    \
+                                                                       \
+       r;                                                              \
+})
+
 uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2,
                       uint64_t a3)
 {
-       uint64_t r;
-
-       asm volatile("test %[use_vmmcall], %[use_vmmcall]\n\t"
-                    "jnz 1f\n\t"
-                    "vmcall\n\t"
-                    "jmp 2f\n\t"
-                    "1: vmmcall\n\t"
-                    "2:"
-                    : "=a"(r)
-                    : "a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3),
-                      [use_vmmcall] "r" (host_cpu_is_amd));
-       return r;
+       return X86_HYPERCALL("a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3));
+}
+
+uint64_t __xen_hypercall(uint64_t nr, uint64_t a0, void *a1)
+{
+       return X86_HYPERCALL("a"(nr), "D"(a0), "S"(a1));
+}
+
+void xen_hypercall(uint64_t nr, uint64_t a0, void *a1)
+{
+       GUEST_ASSERT(!__xen_hypercall(nr, a0, a1));
 }
 
 const struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(void)
index 2ddde41c44ba994904c1e73228528da2182c49a8..636a70ddac1ea36151cb57a0dfd74ddcca33de14 100644 (file)
@@ -126,10 +126,7 @@ void test_req_and_verify_all_valid_regs(struct kvm_vcpu *vcpu)
        run->kvm_valid_regs = TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
-                   "Unexpected exit reason: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s390_sieic.icptcode == 4 &&
                    (run->s390_sieic.ipa >> 8) == 0x83 &&
                    (run->s390_sieic.ipb >> 16) == 0x501,
@@ -165,10 +162,7 @@ void test_set_and_verify_various_reg_values(struct kvm_vcpu *vcpu)
 
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
-                   "Unexpected exit reason: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s.regs.gprs[11] == 0xBAD1DEA + 1,
                    "r11 sync regs value incorrect 0x%llx.",
                    run->s.regs.gprs[11]);
@@ -200,10 +194,7 @@ void test_clear_kvm_dirty_regs_bits(struct kvm_vcpu *vcpu)
        run->s.regs.diag318 = 0x4B1D;
        rv = _vcpu_run(vcpu);
        TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_S390_SIEIC,
-                   "Unexpected exit reason: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_S390_SIEIC);
        TEST_ASSERT(run->s.regs.gprs[11] != 0xDEADBEEF,
                    "r11 sync regs value incorrect 0x%llx.",
                    run->s.regs.gprs[11]);
index 2ef1d1b72ce43194894386df947b0a2def9b2f49..a849ce23ca97560eed95b3ba44b0492a2bc17902 100644 (file)
@@ -308,7 +308,6 @@ static void test_delete_memory_region(void)
 static void test_zero_memory_regions(void)
 {
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        struct kvm_vm *vm;
 
        pr_info("Testing KVM_RUN with zero added memory regions\n");
@@ -318,10 +317,7 @@ static void test_zero_memory_regions(void)
 
        vm_ioctl(vm, KVM_SET_NR_MMU_PAGES, (void *)64ul);
        vcpu_run(vcpu);
-
-       run = vcpu->run;
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR,
-                   "Unexpected exit_reason = %u\n", run->exit_reason);
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR);
 
        kvm_vm_free(vm);
 }
index bd72c6eb3b670a4f49dab41f67d97cadfd3278c3..b646cdb5055adb3ab9f3f03e68381d422ed5e27d 100644 (file)
@@ -241,7 +241,6 @@ int main(int argc, char *argv[])
        struct kvm_regs regs1, regs2;
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct kvm_x86_state *state;
        int xsave_restore_size;
        vm_vaddr_t amx_cfg, tiledata, xsavedata;
@@ -268,7 +267,6 @@ int main(int argc, char *argv[])
                    "KVM should enumerate max XSAVE size when XSAVE is supported");
        xsave_restore_size = kvm_cpu_property(X86_PROPERTY_XSTATE_MAX_SIZE);
 
-       run = vcpu->run;
        vcpu_regs_get(vcpu, &regs1);
 
        /* Register #NM handler */
@@ -291,10 +289,7 @@ int main(int argc, char *argv[])
 
        for (stage = 1; ; stage++) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
@@ -350,7 +345,6 @@ int main(int argc, char *argv[])
                /* Restore state in a new VM.  */
                vcpu = vm_recreate_with_one_vcpu(vm);
                vcpu_load_state(vcpu, state);
-               run = vcpu->run;
                kvm_x86_state_cleanup(state);
 
                memset(&regs2, 0, sizeof(regs2));
index 1027a671c7d3aaceb3971ec3b10ca28227cb29d6..624dc725e14dc0d3170b7fbe6414c92907102027 100644 (file)
@@ -50,7 +50,6 @@ static void guest_code(void)
 int main(int argc, char *argv[])
 {
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        struct kvm_vm *vm;
        struct kvm_sregs sregs;
        struct ucall uc;
@@ -58,15 +57,10 @@ int main(int argc, char *argv[])
        TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_XSAVE));
 
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
-       run = vcpu->run;
 
        while (1) {
                vcpu_run(vcpu);
-
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Unexpected exit reason: %u (%s),\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_SYNC:
index 7ef99c3359a0db8eda4bde8026fc831a62f33a93..f6b295e0b2d2bb2ef7d8f3f9359df5125c17069d 100644 (file)
@@ -204,7 +204,7 @@ int main(void)
        vcpu_guest_debug_set(vcpu, &debug);
 
        vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, "KVM_EXIT_IO");
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        cmd = get_ucall(vcpu, &uc);
        TEST_ASSERT(cmd == UCALL_DONE, "UCALL_DONE");
 
index e43a7df25f2c53321cfdc776de2b7fa87d992276..0a1573d52882b7b127307a829b0d1dc4d1af6560 100644 (file)
@@ -24,10 +24,7 @@ static inline void handle_flds_emulation_failure_exit(struct kvm_vcpu *vcpu)
        uint8_t *insn_bytes;
        uint64_t flags;
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR,
-                   "Unexpected exit reason: %u (%s)",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR);
 
        TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION,
                    "Unexpected suberror: %u",
index 2ee0af0d449efcab6f14b4242f43ce40eeb7995c..f25749eaa6a84bb16f0405fdf8847ace33ce04ce 100644 (file)
@@ -207,13 +207,11 @@ int main(void)
 {
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct ucall uc;
        vm_vaddr_t tsc_page_gva;
        int stage;
 
        vm = vm_create_with_one_vcpu(&vcpu, guest_main);
-       run = vcpu->run;
 
        vcpu_set_hv_cpuid(vcpu);
 
@@ -227,10 +225,7 @@ int main(void)
 
        for (stage = 1;; stage++) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index af29e5776d4034e90efc6a772596f703ff580ced..7bde0c4dfdbd18b769a2580c68c2e789a7a692a6 100644 (file)
@@ -237,7 +237,6 @@ int main(int argc, char *argv[])
 
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct ucall uc;
        int stage;
 
@@ -266,13 +265,8 @@ int main(int argc, char *argv[])
        pr_info("Running L1 which uses EVMCS to run L2\n");
 
        for (stage = 1;; stage++) {
-               run = vcpu->run;
-
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index c5e3b39edd0797b71fa3c0b386514b3fcac4ebe6..78606de9385dae2b4ff88fb9ddd69bc83c5a8962 100644 (file)
@@ -122,7 +122,6 @@ static void guest_test_msrs_access(void)
 {
        struct kvm_cpuid2 *prev_cpuid = NULL;
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        struct kvm_vm *vm;
        struct ucall uc;
        int stage = 0;
@@ -151,8 +150,6 @@ static void guest_test_msrs_access(void)
                vm_init_descriptor_tables(vm);
                vcpu_init_descriptor_tables(vcpu);
 
-               run = vcpu->run;
-
                /* TODO: Make this entire test easier to maintain. */
                if (stage >= 21)
                        vcpu_enable_cap(vcpu, KVM_CAP_HYPERV_SYNIC2, 0);
@@ -494,9 +491,7 @@ static void guest_test_msrs_access(void)
                         msr->idx, msr->write ? "write" : "read");
 
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "unexpected exit reason: %u (%s)",
-                           run->exit_reason, exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
@@ -518,7 +513,6 @@ static void guest_test_hcalls_access(void)
 {
        struct kvm_cpuid2 *prev_cpuid = NULL;
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        struct kvm_vm *vm;
        struct ucall uc;
        int stage = 0;
@@ -550,8 +544,6 @@ static void guest_test_hcalls_access(void)
                        vcpu_init_cpuid(vcpu, prev_cpuid);
                }
 
-               run = vcpu->run;
-
                switch (stage) {
                case 0:
                        vcpu_set_cpuid_feature(vcpu, HV_MSR_HYPERCALL_AVAILABLE);
@@ -669,9 +661,7 @@ static void guest_test_hcalls_access(void)
                pr_debug("Stage %d: testing hcall: 0x%lx\n", stage, hcall->control);
 
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "unexpected exit reason: %u (%s)",
-                           run->exit_reason, exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index 0cbb0e646ef8d7e7e804b730c773dcfd497a0658..6feb5ddb031dac66aeabe18b7733f8639f29af63 100644 (file)
@@ -243,7 +243,6 @@ int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
        struct kvm_vcpu *vcpu[3];
-       unsigned int exit_reason;
        vm_vaddr_t hcall_page;
        pthread_t threads[2];
        int stage = 1, r;
@@ -283,10 +282,7 @@ int main(int argc, char *argv[])
        while (true) {
                vcpu_run(vcpu[0]);
 
-               exit_reason = vcpu[0]->run->exit_reason;
-               TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                           "unexpected exit reason: %u (%s)",
-                           exit_reason, exit_reason_str(exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu[0], KVM_EXIT_IO);
 
                switch (get_ucall(vcpu[0], &uc)) {
                case UCALL_SYNC:
index 68a7d354ea070a290cb818f7877fd712d0e7b1ea..e446d76d1c0c38f7ed41ff0ed3dfc736b6b3693c 100644 (file)
@@ -156,7 +156,6 @@ int main(int argc, char *argv[])
        vm_vaddr_t hcall_page;
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct ucall uc;
        int stage;
 
@@ -165,7 +164,6 @@ int main(int argc, char *argv[])
        /* Create VM */
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
        vcpu_set_hv_cpuid(vcpu);
-       run = vcpu->run;
        vcpu_alloc_svm(vm, &nested_gva);
        vcpu_alloc_hyperv_test_pages(vm, &hv_pages_gva);
 
@@ -177,10 +175,7 @@ int main(int argc, char *argv[])
 
        for (stage = 1;; stage++) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index 68f97ff720a74f8eeb3c3a4d12daa84d24696954..4758b6ef5618e387d3a838908e78d2e51af79fa7 100644 (file)
@@ -542,18 +542,13 @@ static void *vcpu_thread(void *arg)
        struct ucall uc;
        int old;
        int r;
-       unsigned int exit_reason;
 
        r = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
        TEST_ASSERT(!r, "pthread_setcanceltype failed on vcpu_id=%u with errno=%d",
                    vcpu->id, r);
 
        vcpu_run(vcpu);
-       exit_reason = vcpu->run->exit_reason;
-
-       TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                   "vCPU %u exited with unexpected exit reason %u-%s, expected KVM_EXIT_IO",
-                   vcpu->id, exit_reason, exit_reason_str(exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        switch (get_ucall(vcpu, &uc)) {
        case UCALL_ABORT:
@@ -587,7 +582,6 @@ int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
        struct kvm_vcpu *vcpu[3];
-       unsigned int exit_reason;
        pthread_t threads[2];
        vm_vaddr_t test_data_page, gva;
        vm_paddr_t gpa;
@@ -657,11 +651,7 @@ int main(int argc, char *argv[])
 
        while (true) {
                vcpu_run(vcpu[0]);
-               exit_reason = vcpu[0]->run->exit_reason;
-
-               TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                           "unexpected exit reason: %u (%s)",
-                           exit_reason, exit_reason_str(exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu[0], KVM_EXIT_IO);
 
                switch (get_ucall(vcpu[0], &uc)) {
                case UCALL_SYNC:
index 813ce282cf5612b72e9909c7f825f94dfb2bc231..1778704360a6634ee7df3dfacd8f63fd3d236cab 100644 (file)
@@ -105,7 +105,6 @@ static void setup_clock(struct kvm_vm *vm, struct test_case *test_case)
 static void enter_guest(struct kvm_vcpu *vcpu)
 {
        struct kvm_clock_data start, end;
-       struct kvm_run *run = vcpu->run;
        struct kvm_vm *vm = vcpu->vm;
        struct ucall uc;
        int i;
@@ -118,9 +117,7 @@ static void enter_guest(struct kvm_vcpu *vcpu)
                vcpu_run(vcpu);
                vm_ioctl(vm, KVM_GET_CLOCK, &end);
 
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "unexpected exit reason: %u (%s)",
-                           run->exit_reason, exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_SYNC:
index 619655c1a1f39fbf950149a13d9feec57f8f6ea8..f774a9e62858f3a35736591223db35c4acceacba 100644 (file)
@@ -111,14 +111,11 @@ static void pr_hcall(struct ucall *uc)
 
 static void enter_guest(struct kvm_vcpu *vcpu)
 {
-       struct kvm_run *run = vcpu->run;
        struct ucall uc;
 
        while (true) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "unexpected exit reason: %u (%s)",
-                           run->exit_reason, exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_PR_MSR:
index 016070cad36edb59405b4b10d42b7b398911d125..72812644d7f5ea6b212f525376ca7a5a3f74648f 100644 (file)
@@ -64,7 +64,6 @@ int main(int argc, char *argv[])
 {
        uint64_t disabled_quirks;
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        struct kvm_vm *vm;
        struct ucall uc;
        int testcase;
@@ -74,18 +73,12 @@ int main(int argc, char *argv[])
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
        vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_MWAIT);
 
-       run = vcpu->run;
-
        vm_init_descriptor_tables(vm);
        vcpu_init_descriptor_tables(vcpu);
 
        while (1) {
                vcpu_run(vcpu);
-
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Unexpected exit reason: %u (%s),\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_SYNC:
index ac33835f78f45afa2a1bc2d387bf03c18025efc5..6502aa23c2f84b81d4187a42b7ec057b5354311a 100644 (file)
@@ -166,12 +166,9 @@ static void __attribute__((__flatten__)) l1_guest_code(void *test_data)
 
 static void assert_ucall_vector(struct kvm_vcpu *vcpu, int vector)
 {
-       struct kvm_run *run = vcpu->run;
        struct ucall uc;
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason, exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        switch (get_ucall(vcpu, &uc)) {
        case UCALL_SYNC:
index 310a104d94f06ab0533ef5fc4cfef0e675a65e07..c9a07963d68aaedcc6b45d4e00e932e5981645b0 100644 (file)
@@ -36,15 +36,12 @@ static void guest_code(void)
 
 static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu)
 {
-       struct kvm_run *run = vcpu->run;
        struct ucall uc;
 
        vm_enable_cap(vcpu->vm, KVM_CAP_MSR_PLATFORM_INFO, true);
        vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                       "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
-                       run->exit_reason,
-                       exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
+
        get_ucall(vcpu, &uc);
        TEST_ASSERT(uc.cmd == UCALL_SYNC,
                        "Received ucall other than UCALL_SYNC: %lu\n", uc.cmd);
@@ -56,14 +53,9 @@ static void test_msr_platform_info_enabled(struct kvm_vcpu *vcpu)
 
 static void test_msr_platform_info_disabled(struct kvm_vcpu *vcpu)
 {
-       struct kvm_run *run = vcpu->run;
-
        vm_enable_cap(vcpu->vm, KVM_CAP_MSR_PLATFORM_INFO, false);
        vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-                       "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
-                       run->exit_reason,
-                       exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN);
 }
 
 int main(int argc, char *argv[])
index bad7ef8c5b92e991f6e3d689c98c1c9139e31ca0..2feef25ba69134ea132e9fb441e5fca732de67bc 100644 (file)
@@ -151,14 +151,10 @@ static void amd_guest_code(void)
  */
 static uint64_t run_vcpu_to_sync(struct kvm_vcpu *vcpu)
 {
-       struct kvm_run *run = vcpu->run;
        struct ucall uc;
 
        vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        get_ucall(vcpu, &uc);
        TEST_ASSERT(uc.cmd == UCALL_SYNC,
                    "Received ucall other than UCALL_SYNC: %lu", uc.cmd);
index cb38a478e1f62aec9e52ca861baddfaf07b03ee8..e18b86666e1fc2d9814c287f81fae95dc9dadfa4 100644 (file)
@@ -133,7 +133,6 @@ int main(int argc, char *argv[])
        struct kvm_vcpu *vcpu;
        struct kvm_regs regs;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct kvm_x86_state *state;
        int stage, stage_reported;
 
@@ -142,8 +141,6 @@ int main(int argc, char *argv[])
        /* Create VM */
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
 
-       run = vcpu->run;
-
        vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, SMRAM_GPA,
                                    SMRAM_MEMSLOT, SMRAM_PAGES, 0);
        TEST_ASSERT(vm_phy_pages_alloc(vm, SMRAM_PAGES, SMRAM_GPA, SMRAM_MEMSLOT)
@@ -169,10 +166,7 @@ int main(int argc, char *argv[])
 
        for (stage = 1;; stage++) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                memset(&regs, 0, sizeof(regs));
                vcpu_regs_get(vcpu, &regs);
@@ -208,7 +202,6 @@ int main(int argc, char *argv[])
 
                vcpu = vm_recreate_with_one_vcpu(vm);
                vcpu_load_state(vcpu, state);
-               run = vcpu->run;
                kvm_x86_state_cleanup(state);
        }
 
index ea578971fb9f9278893ed115a63dbfa417979727..4c4925a8ab4523452326a417634764f85fce19ca 100644 (file)
@@ -158,14 +158,12 @@ int main(int argc, char *argv[])
        struct kvm_regs regs1, regs2;
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct kvm_x86_state *state;
        struct ucall uc;
        int stage;
 
        /* Create VM */
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
-       run = vcpu->run;
 
        vcpu_regs_get(vcpu, &regs1);
 
@@ -183,10 +181,7 @@ int main(int argc, char *argv[])
 
        for (stage = 1;; stage++) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
@@ -214,7 +209,6 @@ int main(int argc, char *argv[])
                /* Restore state in a new VM.  */
                vcpu = vm_recreate_with_one_vcpu(vm);
                vcpu_load_state(vcpu, state);
-               run = vcpu->run;
                kvm_x86_state_cleanup(state);
 
                memset(&regs2, 0, sizeof(regs2));
index 4a07ba227b9954cbe99dc10b84bea96e78e80f22..32bef39bec2178068238a2de650f87179acc22f6 100644 (file)
@@ -85,7 +85,6 @@ static void l1_guest_code(struct svm_test_data *svm)
 int main(int argc, char *argv[])
 {
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        vm_vaddr_t svm_gva;
        struct kvm_vm *vm;
        struct ucall uc;
@@ -103,13 +102,8 @@ int main(int argc, char *argv[])
        vcpu_alloc_svm(vm, &svm_gva);
        vcpu_args_set(vcpu, 1, svm_gva);
 
-       run = vcpu->run;
-
        vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        switch (get_ucall(vcpu, &uc)) {
        case UCALL_ABORT:
index e73fcdef47bbe910a4643a33404c17c28635097d..d6fcdcc3af3144b6805cf3d9530614b03476ac79 100644 (file)
@@ -42,7 +42,6 @@ static void l1_guest_code(struct svm_test_data *svm, struct idt_entry *idt)
 int main(int argc, char *argv[])
 {
        struct kvm_vcpu *vcpu;
-       struct kvm_run *run;
        vm_vaddr_t svm_gva;
        struct kvm_vm *vm;
 
@@ -55,13 +54,9 @@ int main(int argc, char *argv[])
        vcpu_alloc_svm(vm, &svm_gva);
 
        vcpu_args_set(vcpu, 2, svm_gva, vm->idt);
-       run = vcpu->run;
 
        vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-                   "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN);
 
        kvm_vm_free(vm);
 }
index b34980d45648a68de61051cd521f49b21e8fa719..4e2479716da6eb5b567151593beac16c419a8220 100644 (file)
@@ -176,16 +176,12 @@ static void run_test(bool is_nmi)
        memset(&debug, 0, sizeof(debug));
        vcpu_guest_debug_set(vcpu, &debug);
 
-       struct kvm_run *run = vcpu->run;
        struct ucall uc;
 
        alarm(2);
        vcpu_run(vcpu);
        alarm(0);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        switch (get_ucall(vcpu, &uc)) {
        case UCALL_ABORT:
index c3ac45df748325151aae1f7c27e994be924c171c..8a62cca28cfbb377af77b31b985b3e8694430edf 100644 (file)
@@ -47,14 +47,10 @@ int main(int argc, char *argv[])
        vcpu_args_set(vcpu, 1, svm_gva);
 
        for (;;) {
-               volatile struct kvm_run *run = vcpu->run;
                struct ucall uc;
 
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index d2f9b5bdfab20b6c3eae23afc249049b61af343d..2da89fdc2471a7f95983c66b1c744a5365ad007c 100644 (file)
@@ -132,10 +132,7 @@ int main(int argc, char *argv[])
        /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
        run->kvm_valid_regs = TEST_SYNC_FIELDS;
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        vcpu_regs_get(vcpu, &regs);
        compare_regs(&regs, &run->s.regs.regs);
@@ -154,10 +151,7 @@ int main(int argc, char *argv[])
        run->kvm_valid_regs = TEST_SYNC_FIELDS;
        run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS;
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(run->s.regs.regs.rbx == 0xBAD1DEA + 1,
                    "rbx sync regs value incorrect 0x%llx.",
                    run->s.regs.regs.rbx);
@@ -181,10 +175,7 @@ int main(int argc, char *argv[])
        run->kvm_dirty_regs = 0;
        run->s.regs.regs.rbx = 0xDEADBEEF;
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF,
                    "rbx sync regs value incorrect 0x%llx.",
                    run->s.regs.regs.rbx);
@@ -199,10 +190,7 @@ int main(int argc, char *argv[])
        regs.rbx = 0xBAC0;
        vcpu_regs_set(vcpu, &regs);
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(run->s.regs.regs.rbx == 0xAAAA,
                    "rbx sync regs value incorrect 0x%llx.",
                    run->s.regs.regs.rbx);
@@ -219,10 +207,7 @@ int main(int argc, char *argv[])
        run->kvm_dirty_regs = TEST_SYNC_FIELDS;
        run->s.regs.regs.rbx = 0xBBBB;
        rv = _vcpu_run(vcpu);
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(run->s.regs.regs.rbx == 0xBBBB,
                    "rbx sync regs value incorrect 0x%llx.",
                    run->s.regs.regs.rbx);
index ead5d878a71c458348d9e86100016bc8bd2a72b4..56306a19144a7db90a7f0906aede46e75ee346a1 100644 (file)
@@ -89,9 +89,7 @@ int main(void)
        run = vcpu->run;
        vcpu_run(vcpu);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Expected KVM_EXIT_IO, got: %u (%s)\n",
-                   run->exit_reason, exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT,
                    "Expected IN from port %d from L2, got port %d",
                    ARBITRARY_IO_PORT, run->io.port);
@@ -111,10 +109,7 @@ int main(void)
 
 
        if (has_svm) {
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
-                           "Got exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN);
        } else {
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_DONE:
index 47139aab74084b29ba356dd9ddd4d76edb0105eb..5b669818e39aaa2313d0887c0324aca4b628ed3c 100644 (file)
@@ -64,14 +64,10 @@ static void *run_vcpu(void *_cpu_nr)
        pthread_spin_unlock(&create_lock);
 
        for (;;) {
-               volatile struct kvm_run *run = vcpu->run;
                 struct ucall uc;
 
                vcpu_run(vcpu);
-                TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                            "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                            run->exit_reason,
-                            exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                 case UCALL_DONE:
index a897c7fd8abe464d57a2927f5526b3f6f7044d62..85f34ca7e49e531c11e09f700738d0eec2a0e0fa 100644 (file)
@@ -137,15 +137,11 @@ static void guest_gp_handler(struct ex_regs *regs)
 
 static void run_vcpu_expect_gp(struct kvm_vcpu *vcpu)
 {
-       unsigned int exit_reason;
        struct ucall uc;
 
        vcpu_run(vcpu);
 
-       exit_reason = vcpu->run->exit_reason;
-       TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                   "exited with unexpected exit reason %u-%s, expected KVM_EXIT_IO",
-                   exit_reason, exit_reason_str(exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
        TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC,
                    "Expect UCALL_SYNC\n");
        TEST_ASSERT(uc.args[1] == SYNC_GP, "#GP is expected.");
@@ -182,7 +178,6 @@ static void *run_ucna_injection(void *arg)
        struct ucall uc;
        int old;
        int r;
-       unsigned int exit_reason;
 
        r = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
        TEST_ASSERT(r == 0,
@@ -191,10 +186,7 @@ static void *run_ucna_injection(void *arg)
 
        vcpu_run(params->vcpu);
 
-       exit_reason = params->vcpu->run->exit_reason;
-       TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                   "unexpected exit reason %u-%s, expected KVM_EXIT_IO",
-                   exit_reason, exit_reason_str(exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO);
        TEST_ASSERT(get_ucall(params->vcpu, &uc) == UCALL_SYNC,
                    "Expect UCALL_SYNC\n");
        TEST_ASSERT(uc.args[1] == SYNC_FIRST_UCNA, "Injecting first UCNA.");
@@ -204,10 +196,7 @@ static void *run_ucna_injection(void *arg)
        inject_ucna(params->vcpu, FIRST_UCNA_ADDR);
        vcpu_run(params->vcpu);
 
-       exit_reason = params->vcpu->run->exit_reason;
-       TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                   "unexpected exit reason %u-%s, expected KVM_EXIT_IO",
-                   exit_reason, exit_reason_str(exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO);
        TEST_ASSERT(get_ucall(params->vcpu, &uc) == UCALL_SYNC,
                    "Expect UCALL_SYNC\n");
        TEST_ASSERT(uc.args[1] == SYNC_SECOND_UCNA, "Injecting second UCNA.");
@@ -217,10 +206,7 @@ static void *run_ucna_injection(void *arg)
        inject_ucna(params->vcpu, SECOND_UCNA_ADDR);
        vcpu_run(params->vcpu);
 
-       exit_reason = params->vcpu->run->exit_reason;
-       TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                   "unexpected exit reason %u-%s, expected KVM_EXIT_IO",
-                   exit_reason, exit_reason_str(exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(params->vcpu, KVM_EXIT_IO);
        if (get_ucall(params->vcpu, &uc) == UCALL_ABORT) {
                TEST_ASSERT(false, "vCPU assertion failure: %s.\n",
                            (const char *)uc.args[0]);
index 91076c9787b41e322a1b3c3de2c35b066295d710..0cb51fa42773b23278448b66174f05052a407465 100644 (file)
@@ -63,11 +63,7 @@ int main(int argc, char *argv[])
 
        while (1) {
                vcpu_run(vcpu);
-
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Unexpected exit reason: %u (%s),\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                if (get_ucall(vcpu, &uc))
                        break;
index 25fa55344a10efb23b972e41d1f62262ee928e70..3533dc2fbfeeb136b217eb79e819e2e374e2b0cd 100644 (file)
@@ -410,10 +410,7 @@ static void process_rdmsr(struct kvm_vcpu *vcpu, uint32_t msr_index)
 
        check_for_guest_assert(vcpu);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_X86_RDMSR,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_X86_RDMSR);
        TEST_ASSERT(run->msr.index == msr_index,
                        "Unexpected msr (0x%04x), expected 0x%04x",
                        run->msr.index, msr_index);
@@ -445,10 +442,7 @@ static void process_wrmsr(struct kvm_vcpu *vcpu, uint32_t msr_index)
 
        check_for_guest_assert(vcpu);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_X86_WRMSR,
-                   "Unexpected exit reason: %u (%s),\n",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_X86_WRMSR);
        TEST_ASSERT(run->msr.index == msr_index,
                        "Unexpected msr (0x%04x), expected 0x%04x",
                        run->msr.index, msr_index);
@@ -472,15 +466,11 @@ static void process_wrmsr(struct kvm_vcpu *vcpu, uint32_t msr_index)
 
 static void process_ucall_done(struct kvm_vcpu *vcpu)
 {
-       struct kvm_run *run = vcpu->run;
        struct ucall uc;
 
        check_for_guest_assert(vcpu);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s)",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_DONE,
                    "Unexpected ucall command: %lu, expected UCALL_DONE (%d)",
@@ -489,15 +479,11 @@ static void process_ucall_done(struct kvm_vcpu *vcpu)
 
 static uint64_t process_ucall(struct kvm_vcpu *vcpu)
 {
-       struct kvm_run *run = vcpu->run;
        struct ucall uc = {};
 
        check_for_guest_assert(vcpu);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Unexpected exit reason: %u (%s)",
-                   run->exit_reason,
-                   exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        switch (get_ucall(vcpu, &uc)) {
        case UCALL_SYNC:
index 5abecf06329eaccd2ac85e0fb6b57075d5628f15..2bed5fb3a0d6e51aa63f9732d77dac330378d2c8 100644 (file)
@@ -96,21 +96,14 @@ int main(int argc, char *argv[])
 
                vcpu_run(vcpu);
                if (apic_access_addr == high_gpa) {
-                       TEST_ASSERT(run->exit_reason ==
-                                   KVM_EXIT_INTERNAL_ERROR,
-                                   "Got exit reason other than KVM_EXIT_INTERNAL_ERROR: %u (%s)\n",
-                                   run->exit_reason,
-                                   exit_reason_str(run->exit_reason));
+                       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR);
                        TEST_ASSERT(run->internal.suberror ==
                                    KVM_INTERNAL_ERROR_EMULATION,
                                    "Got internal suberror other than KVM_INTERNAL_ERROR_EMULATION: %u\n",
                                    run->internal.suberror);
                        break;
                }
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index d79651b027402d6f349eb594a03fdc425ce3843a..dad988351493e089bf0f9b62d7604d89b65137a7 100644 (file)
@@ -64,10 +64,7 @@ int main(int argc, char *argv[])
                struct ucall uc;
 
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                if (run->io.port == PORT_L0_EXIT)
                        break;
index f0456fb031b1ef465c9f6177af630599e5d92daf..e4ad5fef52ffc5b08ec8d3f445b518b52229e672 100644 (file)
@@ -73,7 +73,6 @@ int main(int argc, char *argv[])
 
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct ucall uc;
        bool done = false;
 
@@ -84,7 +83,6 @@ int main(int argc, char *argv[])
        vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
        vmx = vcpu_alloc_vmx(vm, &vmx_pages_gva);
        vcpu_args_set(vcpu, 1, vmx_pages_gva);
-       run = vcpu->run;
 
        /* Add an extra memory slot for testing dirty logging */
        vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
@@ -117,10 +115,7 @@ int main(int argc, char *argv[])
        while (!done) {
                memset(host_test_mem, 0xaa, TEST_MEM_PAGES * 4096);
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Unexpected exit reason: %u (%s),\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index ccdfa5dc1a4dc6fdc5876575dfb6240c3beff536..be0bdb8c6f78c27a3fa573ea87f66ddc58bf79c8 100644 (file)
@@ -26,9 +26,7 @@ static void __run_vcpu_with_invalid_state(struct kvm_vcpu *vcpu)
 
        vcpu_run(vcpu);
 
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_INTERNAL_ERROR,
-                   "Expected KVM_EXIT_INTERNAL_ERROR, got %d (%s)\n",
-                   run->exit_reason, exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_INTERNAL_ERROR);
        TEST_ASSERT(run->emulation_failure.suberror == KVM_INTERNAL_ERROR_EMULATION,
                    "Expected emulation failure, got %d\n",
                    run->emulation_failure.suberror);
index 6bfb4bb471ca2b68f7cdaeeece7b93ba4d6d33db..a100ee5f000936e8e397d2112071b19f18192ff5 100644 (file)
@@ -74,9 +74,7 @@ int main(int argc, char *argv[])
         * The first exit to L0 userspace should be an I/O access from L2.
         * Running L1 should launch L2 without triggering an exit to userspace.
         */
-       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                   "Expected KVM_EXIT_IO, got: %u (%s)\n",
-                   run->exit_reason, exit_reason_str(run->exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        TEST_ASSERT(run->io.port == ARBITRARY_IO_PORT,
                    "Expected IN from port %d from L2, got port %d",
index 465a9434d61c2b9d7cc3611d719e32598365f00b..d427eb146bc5818e8d96a93da7c00a1b485bcf81 100644 (file)
@@ -183,14 +183,10 @@ int main(int argc, char *argv[])
        vcpu_ioctl(vcpu, KVM_SET_TSC_KHZ, (void *) (tsc_khz / l1_scale_factor));
 
        for (;;) {
-               volatile struct kvm_run *run = vcpu->run;
                struct ucall uc;
 
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index 0efdc05969a56395db7774821c9023fb93928d9c..affc32800158415225e2a5c0cd2d75ce0f727e30 100644 (file)
@@ -157,7 +157,6 @@ int main(int argc, char *argv[])
 
        struct kvm_regs regs1, regs2;
        struct kvm_vm *vm;
-       struct kvm_run *run;
        struct kvm_vcpu *vcpu;
        struct kvm_x86_state *state;
        struct ucall uc;
@@ -173,7 +172,6 @@ int main(int argc, char *argv[])
 
        /* Create VM */
        vm = vm_create_with_one_vcpu(&vcpu, guest_code);
-       run = vcpu->run;
 
        vcpu_regs_get(vcpu, &regs1);
 
@@ -182,10 +180,7 @@ int main(int argc, char *argv[])
 
        for (stage = 1;; stage++) {
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Stage %d: unexpected exit reason: %u (%s),\n",
-                           stage, run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
@@ -237,7 +232,6 @@ int main(int argc, char *argv[])
                /* Restore state in a new VM.  */
                vcpu = vm_recreate_with_one_vcpu(vm);
                vcpu_load_state(vcpu, state);
-               run = vcpu->run;
                kvm_x86_state_cleanup(state);
 
                memset(&regs2, 0, sizeof(regs2));
index ff8ecdf32ae07d9e448e32af6839943a1ed3d51b..2ceb5c78c442710166c2ecc1243d812cb1839793 100644 (file)
@@ -131,14 +131,10 @@ int main(int argc, char *argv[])
        vcpu_args_set(vcpu, 1, vmx_pages_gva);
 
        for (;;) {
-               volatile struct kvm_run *run = vcpu->run;
                struct ucall uc;
 
                vcpu_run(vcpu);
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index 3d272d7f961ef1948e65e588f0d6cad30e7ebe70..67ac2a3292efd4e5a4ff24073af25849ce375dd9 100644 (file)
@@ -198,7 +198,6 @@ static void *vcpu_thread(void *arg)
        struct ucall uc;
        int old;
        int r;
-       unsigned int exit_reason;
 
        r = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
        TEST_ASSERT(r == 0,
@@ -207,11 +206,8 @@ static void *vcpu_thread(void *arg)
 
        fprintf(stderr, "vCPU thread running vCPU %u\n", vcpu->id);
        vcpu_run(vcpu);
-       exit_reason = vcpu->run->exit_reason;
 
-       TEST_ASSERT(exit_reason == KVM_EXIT_IO,
-                   "vCPU %u exited with unexpected exit reason %u-%s, expected KVM_EXIT_IO",
-                   vcpu->id, exit_reason, exit_reason_str(exit_reason));
+       TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
        if (get_ucall(vcpu, &uc) == UCALL_ABORT) {
                TEST_ASSERT(false,
index 5a3bf8f6141761ef81750d7ba04ae46768a7f874..05898ad9f4d992b3c7eba0a9ec677b21315689e6 100644 (file)
@@ -26,6 +26,9 @@
 #define DUMMY_REGION_GPA       (SHINFO_REGION_GPA + (3 * PAGE_SIZE))
 #define DUMMY_REGION_SLOT      11
 
+#define DUMMY_REGION_GPA_2     (SHINFO_REGION_GPA + (4 * PAGE_SIZE))
+#define DUMMY_REGION_SLOT_2    12
+
 #define SHINFO_ADDR    (SHINFO_REGION_GPA)
 #define VCPU_INFO_ADDR (SHINFO_REGION_GPA + 0x40)
 #define PVTIME_ADDR    (SHINFO_REGION_GPA + PAGE_SIZE)
 #define EVTCHN_TEST2 66
 #define EVTCHN_TIMER 13
 
+enum {
+       TEST_INJECT_VECTOR = 0,
+       TEST_RUNSTATE_runnable,
+       TEST_RUNSTATE_blocked,
+       TEST_RUNSTATE_offline,
+       TEST_RUNSTATE_ADJUST,
+       TEST_RUNSTATE_DATA,
+       TEST_STEAL_TIME,
+       TEST_EVTCHN_MASKED,
+       TEST_EVTCHN_UNMASKED,
+       TEST_EVTCHN_SLOWPATH,
+       TEST_EVTCHN_SEND_IOCTL,
+       TEST_EVTCHN_HCALL,
+       TEST_EVTCHN_HCALL_SLOWPATH,
+       TEST_EVTCHN_HCALL_EVENTFD,
+       TEST_TIMER_SETUP,
+       TEST_TIMER_WAIT,
+       TEST_TIMER_RESTORE,
+       TEST_POLL_READY,
+       TEST_POLL_TIMEOUT,
+       TEST_POLL_MASKED,
+       TEST_POLL_WAKE,
+       TEST_TIMER_PAST,
+       TEST_LOCKING_SEND_RACE,
+       TEST_LOCKING_POLL_RACE,
+       TEST_LOCKING_POLL_TIMEOUT,
+       TEST_DONE,
+
+       TEST_GUEST_SAW_IRQ,
+};
+
 #define XEN_HYPERCALL_MSR      0x40000000
 
 #define MIN_STEAL_TIME         50000
@@ -144,7 +178,7 @@ static void evtchn_handler(struct ex_regs *regs)
        vi->evtchn_pending_sel = 0;
        guest_saw_irq = true;
 
-       GUEST_SYNC(0x20);
+       GUEST_SYNC(TEST_GUEST_SAW_IRQ);
 }
 
 static void guest_wait_for_irq(void)
@@ -165,41 +199,41 @@ static void guest_code(void)
        );
 
        /* Trigger an interrupt injection */
-       GUEST_SYNC(0);
+       GUEST_SYNC(TEST_INJECT_VECTOR);
 
        guest_wait_for_irq();
 
        /* Test having the host set runstates manually */
-       GUEST_SYNC(RUNSTATE_runnable);
+       GUEST_SYNC(TEST_RUNSTATE_runnable);
        GUEST_ASSERT(rs->time[RUNSTATE_runnable] != 0);
        GUEST_ASSERT(rs->state == 0);
 
-       GUEST_SYNC(RUNSTATE_blocked);
+       GUEST_SYNC(TEST_RUNSTATE_blocked);
        GUEST_ASSERT(rs->time[RUNSTATE_blocked] != 0);
        GUEST_ASSERT(rs->state == 0);
 
-       GUEST_SYNC(RUNSTATE_offline);
+       GUEST_SYNC(TEST_RUNSTATE_offline);
        GUEST_ASSERT(rs->time[RUNSTATE_offline] != 0);
        GUEST_ASSERT(rs->state == 0);
 
        /* Test runstate time adjust */
-       GUEST_SYNC(4);
+       GUEST_SYNC(TEST_RUNSTATE_ADJUST);
        GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x5a);
        GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x6b6b);
 
        /* Test runstate time set */
-       GUEST_SYNC(5);
+       GUEST_SYNC(TEST_RUNSTATE_DATA);
        GUEST_ASSERT(rs->state_entry_time >= 0x8000);
        GUEST_ASSERT(rs->time[RUNSTATE_runnable] == 0);
        GUEST_ASSERT(rs->time[RUNSTATE_blocked] == 0x6b6b);
        GUEST_ASSERT(rs->time[RUNSTATE_offline] == 0x5a);
 
        /* sched_yield() should result in some 'runnable' time */
-       GUEST_SYNC(6);
+       GUEST_SYNC(TEST_STEAL_TIME);
        GUEST_ASSERT(rs->time[RUNSTATE_runnable] >= MIN_STEAL_TIME);
 
        /* Attempt to deliver a *masked* interrupt */
-       GUEST_SYNC(7);
+       GUEST_SYNC(TEST_EVTCHN_MASKED);
 
        /* Wait until we see the bit set */
        struct shared_info *si = (void *)SHINFO_VADDR;
@@ -207,71 +241,65 @@ static void guest_code(void)
                __asm__ __volatile__ ("rep nop" : : : "memory");
 
        /* Now deliver an *unmasked* interrupt */
-       GUEST_SYNC(8);
+       GUEST_SYNC(TEST_EVTCHN_UNMASKED);
 
        guest_wait_for_irq();
 
        /* Change memslots and deliver an interrupt */
-       GUEST_SYNC(9);
+       GUEST_SYNC(TEST_EVTCHN_SLOWPATH);
 
        guest_wait_for_irq();
 
        /* Deliver event channel with KVM_XEN_HVM_EVTCHN_SEND */
-       GUEST_SYNC(10);
+       GUEST_SYNC(TEST_EVTCHN_SEND_IOCTL);
 
        guest_wait_for_irq();
 
-       GUEST_SYNC(11);
+       GUEST_SYNC(TEST_EVTCHN_HCALL);
 
        /* Our turn. Deliver event channel (to ourselves) with
         * EVTCHNOP_send hypercall. */
-       unsigned long rax;
        struct evtchn_send s = { .port = 127 };
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_event_channel_op),
-                             "D" (EVTCHNOP_send),
-                             "S" (&s));
+       xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
+
+       guest_wait_for_irq();
+
+       GUEST_SYNC(TEST_EVTCHN_HCALL_SLOWPATH);
 
-       GUEST_ASSERT(rax == 0);
+       /*
+        * Same again, but this time the host has messed with memslots so it
+        * should take the slow path in kvm_xen_set_evtchn().
+        */
+       xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
 
        guest_wait_for_irq();
 
-       GUEST_SYNC(12);
+       GUEST_SYNC(TEST_EVTCHN_HCALL_EVENTFD);
 
        /* Deliver "outbound" event channel to an eventfd which
         * happens to be one of our own irqfds. */
        s.port = 197;
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_event_channel_op),
-                             "D" (EVTCHNOP_send),
-                             "S" (&s));
-
-       GUEST_ASSERT(rax == 0);
+       xen_hypercall(__HYPERVISOR_event_channel_op, EVTCHNOP_send, &s);
 
        guest_wait_for_irq();
 
-       GUEST_SYNC(13);
+       GUEST_SYNC(TEST_TIMER_SETUP);
 
        /* Set a timer 100ms in the future. */
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_set_timer_op),
-                             "D" (rs->state_entry_time + 100000000));
-       GUEST_ASSERT(rax == 0);
+       xen_hypercall(__HYPERVISOR_set_timer_op,
+                     rs->state_entry_time + 100000000, NULL);
 
-       GUEST_SYNC(14);
+       GUEST_SYNC(TEST_TIMER_WAIT);
 
        /* Now wait for the timer */
        guest_wait_for_irq();
 
-       GUEST_SYNC(15);
+       GUEST_SYNC(TEST_TIMER_RESTORE);
 
        /* The host has 'restored' the timer. Just wait for it. */
        guest_wait_for_irq();
 
-       GUEST_SYNC(16);
+       GUEST_SYNC(TEST_POLL_READY);
 
        /* Poll for an event channel port which is already set */
        u32 ports[1] = { EVTCHN_TIMER };
@@ -281,65 +309,41 @@ static void guest_code(void)
                .timeout = 0,
        };
 
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_sched_op),
-                             "D" (SCHEDOP_poll),
-                             "S" (&p));
+       xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
 
-       GUEST_ASSERT(rax == 0);
-
-       GUEST_SYNC(17);
+       GUEST_SYNC(TEST_POLL_TIMEOUT);
 
        /* Poll for an unset port and wait for the timeout. */
        p.timeout = 100000000;
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_sched_op),
-                             "D" (SCHEDOP_poll),
-                             "S" (&p));
-
-       GUEST_ASSERT(rax == 0);
+       xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
 
-       GUEST_SYNC(18);
+       GUEST_SYNC(TEST_POLL_MASKED);
 
        /* A timer will wake the masked port we're waiting on, while we poll */
        p.timeout = 0;
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_sched_op),
-                             "D" (SCHEDOP_poll),
-                             "S" (&p));
-
-       GUEST_ASSERT(rax == 0);
+       xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
 
-       GUEST_SYNC(19);
+       GUEST_SYNC(TEST_POLL_WAKE);
 
        /* A timer wake an *unmasked* port which should wake us with an
         * actual interrupt, while we're polling on a different port. */
        ports[0]++;
        p.timeout = 0;
-       __asm__ __volatile__ ("vmcall" :
-                             "=a" (rax) :
-                             "a" (__HYPERVISOR_sched_op),
-                             "D" (SCHEDOP_poll),
-                             "S" (&p));
-
-       GUEST_ASSERT(rax == 0);
+       xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
 
        guest_wait_for_irq();
 
-       GUEST_SYNC(20);
+       GUEST_SYNC(TEST_TIMER_PAST);
 
        /* Timer should have fired already */
        guest_wait_for_irq();
 
-       GUEST_SYNC(21);
+       GUEST_SYNC(TEST_LOCKING_SEND_RACE);
        /* Racing host ioctls */
 
        guest_wait_for_irq();
 
-       GUEST_SYNC(22);
+       GUEST_SYNC(TEST_LOCKING_POLL_RACE);
        /* Racing vmcall against host ioctl */
 
        ports[0] = 0;
@@ -360,24 +364,19 @@ wait_for_timer:
         * timer IRQ is dropped due to an invalid event channel.
         */
        for (i = 0; i < 100 && !guest_saw_irq; i++)
-               asm volatile("vmcall"
-                            : "=a" (rax)
-                            : "a" (__HYPERVISOR_sched_op),
-                              "D" (SCHEDOP_poll),
-                              "S" (&p)
-                            : "memory");
+               __xen_hypercall(__HYPERVISOR_sched_op, SCHEDOP_poll, &p);
 
        /*
         * Re-send the timer IRQ if it was (likely) dropped due to the timer
         * expiring while the event channel was invalid.
         */
        if (!guest_saw_irq) {
-               GUEST_SYNC(23);
+               GUEST_SYNC(TEST_LOCKING_POLL_TIMEOUT);
                goto wait_for_timer;
        }
        guest_saw_irq = false;
 
-       GUEST_SYNC(24);
+       GUEST_SYNC(TEST_DONE);
 }
 
 static int cmp_timespec(struct timespec *a, struct timespec *b)
@@ -623,15 +622,10 @@ int main(int argc, char *argv[])
        bool evtchn_irq_expected = false;
 
        for (;;) {
-               volatile struct kvm_run *run = vcpu->run;
                struct ucall uc;
 
                vcpu_run(vcpu);
-
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
@@ -647,25 +641,26 @@ int main(int argc, char *argv[])
                                            "runstate times don't add up");
 
                        switch (uc.args[1]) {
-                       case 0:
+                       case TEST_INJECT_VECTOR:
                                if (verbose)
                                        printf("Delivering evtchn upcall\n");
                                evtchn_irq_expected = true;
                                vinfo->evtchn_upcall_pending = 1;
                                break;
 
-                       case RUNSTATE_runnable...RUNSTATE_offline:
+                       case TEST_RUNSTATE_runnable...TEST_RUNSTATE_offline:
                                TEST_ASSERT(!evtchn_irq_expected, "Event channel IRQ not seen");
                                if (!do_runstate_tests)
                                        goto done;
                                if (verbose)
                                        printf("Testing runstate %s\n", runstate_names[uc.args[1]]);
                                rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT;
-                               rst.u.runstate.state = uc.args[1];
+                               rst.u.runstate.state = uc.args[1] + RUNSTATE_runnable -
+                                       TEST_RUNSTATE_runnable;
                                vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst);
                                break;
 
-                       case 4:
+                       case TEST_RUNSTATE_ADJUST:
                                if (verbose)
                                        printf("Testing RUNSTATE_ADJUST\n");
                                rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST;
@@ -680,7 +675,7 @@ int main(int argc, char *argv[])
                                vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst);
                                break;
 
-                       case 5:
+                       case TEST_RUNSTATE_DATA:
                                if (verbose)
                                        printf("Testing RUNSTATE_DATA\n");
                                rst.type = KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA;
@@ -692,7 +687,7 @@ int main(int argc, char *argv[])
                                vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &rst);
                                break;
 
-                       case 6:
+                       case TEST_STEAL_TIME:
                                if (verbose)
                                        printf("Testing steal time\n");
                                /* Yield until scheduler delay exceeds target */
@@ -702,7 +697,7 @@ int main(int argc, char *argv[])
                                } while (get_run_delay() < rundelay);
                                break;
 
-                       case 7:
+                       case TEST_EVTCHN_MASKED:
                                if (!do_eventfd_tests)
                                        goto done;
                                if (verbose)
@@ -712,7 +707,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 8:
+                       case TEST_EVTCHN_UNMASKED:
                                if (verbose)
                                        printf("Testing unmasked event channel\n");
                                /* Unmask that, but deliver the other one */
@@ -723,7 +718,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 9:
+                       case TEST_EVTCHN_SLOWPATH:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                shinfo->evtchn_pending[1] = 0;
@@ -736,7 +731,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 10:
+                       case TEST_EVTCHN_SEND_IOCTL:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                if (!do_evtchn_tests)
@@ -756,7 +751,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 11:
+                       case TEST_EVTCHN_HCALL:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                shinfo->evtchn_pending[1] = 0;
@@ -767,7 +762,20 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 12:
+                       case TEST_EVTCHN_HCALL_SLOWPATH:
+                               TEST_ASSERT(!evtchn_irq_expected,
+                                           "Expected event channel IRQ but it didn't happen");
+                               shinfo->evtchn_pending[0] = 0;
+
+                               if (verbose)
+                                       printf("Testing guest EVTCHNOP_send direct to evtchn after memslot change\n");
+                               vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+                                                           DUMMY_REGION_GPA_2, DUMMY_REGION_SLOT_2, 1, 0);
+                               evtchn_irq_expected = true;
+                               alarm(1);
+                               break;
+
+                       case TEST_EVTCHN_HCALL_EVENTFD:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                shinfo->evtchn_pending[0] = 0;
@@ -778,7 +786,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 13:
+                       case TEST_TIMER_SETUP:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                shinfo->evtchn_pending[1] = 0;
@@ -787,7 +795,7 @@ int main(int argc, char *argv[])
                                        printf("Testing guest oneshot timer\n");
                                break;
 
-                       case 14:
+                       case TEST_TIMER_WAIT:
                                memset(&tmr, 0, sizeof(tmr));
                                tmr.type = KVM_XEN_VCPU_ATTR_TYPE_TIMER;
                                vcpu_ioctl(vcpu, KVM_XEN_VCPU_GET_ATTR, &tmr);
@@ -801,7 +809,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 15:
+                       case TEST_TIMER_RESTORE:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                shinfo->evtchn_pending[0] = 0;
@@ -815,7 +823,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 16:
+                       case TEST_POLL_READY:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
 
@@ -825,14 +833,14 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 17:
+                       case TEST_POLL_TIMEOUT:
                                if (verbose)
                                        printf("Testing SCHEDOP_poll timeout\n");
                                shinfo->evtchn_pending[0] = 0;
                                alarm(1);
                                break;
 
-                       case 18:
+                       case TEST_POLL_MASKED:
                                if (verbose)
                                        printf("Testing SCHEDOP_poll wake on masked event\n");
 
@@ -841,7 +849,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 19:
+                       case TEST_POLL_WAKE:
                                shinfo->evtchn_pending[0] = shinfo->evtchn_mask[0] = 0;
                                if (verbose)
                                        printf("Testing SCHEDOP_poll wake on unmasked event\n");
@@ -858,7 +866,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 20:
+                       case TEST_TIMER_PAST:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                /* Read timer and check it is no longer pending */
@@ -875,7 +883,7 @@ int main(int argc, char *argv[])
                                alarm(1);
                                break;
 
-                       case 21:
+                       case TEST_LOCKING_SEND_RACE:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
                                alarm(0);
@@ -897,7 +905,7 @@ int main(int argc, char *argv[])
                                        __vm_ioctl(vm, KVM_XEN_HVM_EVTCHN_SEND, &uxe);
                                break;
 
-                       case 22:
+                       case TEST_LOCKING_POLL_RACE:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
 
@@ -912,7 +920,7 @@ int main(int argc, char *argv[])
                                vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &tmr);
                                break;
 
-                       case 23:
+                       case TEST_LOCKING_POLL_TIMEOUT:
                                /*
                                 * Optional and possibly repeated sync point.
                                 * Injecting the timer IRQ may fail if the
@@ -934,7 +942,7 @@ int main(int argc, char *argv[])
                                                         SHINFO_RACE_TIMEOUT * 1000000000ULL;
                                vcpu_ioctl(vcpu, KVM_XEN_VCPU_SET_ATTR, &tmr);
                                break;
-                       case 24:
+                       case TEST_DONE:
                                TEST_ASSERT(!evtchn_irq_expected,
                                            "Expected event channel IRQ but it didn't happen");
 
@@ -945,7 +953,7 @@ int main(int argc, char *argv[])
                                TEST_ASSERT(ret == 0, "pthread_join() failed: %s", strerror(ret));
                                goto done;
 
-                       case 0x20:
+                       case TEST_GUEST_SAW_IRQ:
                                TEST_ASSERT(evtchn_irq_expected, "Unexpected event channel IRQ");
                                evtchn_irq_expected = false;
                                break;
index 88914d48c65ed8fb5270c5d96ae45c9c55faee5d..c94cde3b523f2b14a4f61986c835ad5503a95337 100644 (file)
@@ -122,10 +122,7 @@ int main(int argc, char *argv[])
                        continue;
                }
 
-               TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
-                           run->exit_reason,
-                           exit_reason_str(run->exit_reason));
+               TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 
                switch (get_ucall(vcpu, &uc)) {
                case UCALL_ABORT:
index f7900e75d2306d2ff79d930e78a1c9110c69b48b..05400462c77996a71a439dfd7946904cbff06aa0 100644 (file)
@@ -10,12 +10,14 @@ endif
 CLANG_TARGET_FLAGS_arm          := arm-linux-gnueabi
 CLANG_TARGET_FLAGS_arm64        := aarch64-linux-gnu
 CLANG_TARGET_FLAGS_hexagon      := hexagon-linux-musl
+CLANG_TARGET_FLAGS_i386         := i386-linux-gnu
 CLANG_TARGET_FLAGS_m68k         := m68k-linux-gnu
 CLANG_TARGET_FLAGS_mips         := mipsel-linux-gnu
 CLANG_TARGET_FLAGS_powerpc      := powerpc64le-linux-gnu
 CLANG_TARGET_FLAGS_riscv        := riscv64-linux-gnu
 CLANG_TARGET_FLAGS_s390         := s390x-linux-gnu
 CLANG_TARGET_FLAGS_x86          := x86_64-linux-gnu
+CLANG_TARGET_FLAGS_x86_64       := x86_64-linux-gnu
 CLANG_TARGET_FLAGS              := $(CLANG_TARGET_FLAGS_$(ARCH))
 
 ifeq ($(CROSS_COMPILE),)
index f466a099f1bf75c5d39f810a165fdcf9bc104706..bc91bef5d254e5770d29188aae81f1259829b511 100644 (file)
@@ -163,9 +163,8 @@ TEST_F(mdwe, mprotect_WRITE_EXEC)
 
 TEST_F(mdwe, mmap_FIXED)
 {
-       void *p, *p2;
+       void *p;
 
-       p2 = mmap(NULL, self->size, PROT_READ | PROT_EXEC, self->flags, 0, 0);
        self->p = mmap(NULL, self->size, PROT_READ, self->flags, 0, 0);
        ASSERT_NE(self->p, MAP_FAILED);
 
index 582669ca38e9dd98ea2236577e5a4313ea887742..c6a8c732b802176dea234feb34ec13d6a73d6fc8 100644 (file)
@@ -18,6 +18,7 @@
 #include <grp.h>
 #include <stdbool.h>
 #include <stdarg.h>
+#include <linux/mount.h>
 
 #include "../kselftest_harness.h"
 
index a6911cae368c77b49f0083def57bbfdac75463b5..80f06aa620345815171f8f708043ddbbc1beabcb 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 bind_bhash
 bind_timewait
+bind_wildcard
 csum
 cmsg_sender
 diag_uid
index 6cd8993454d7e0b647e5db3fb80526b18de0ce6f..80fbfe0330f6ec726b60b71761ca64df6e9d5b2f 100644 (file)
@@ -80,6 +80,7 @@ TEST_GEN_FILES += sctp_hello
 TEST_GEN_FILES += csum
 TEST_GEN_FILES += nat6to4.o
 TEST_GEN_FILES += ip_local_port_range
+TEST_GEN_FILES += bind_wildcard
 
 TEST_FILES := settings
 
diff --git a/tools/testing/selftests/net/bind_wildcard.c b/tools/testing/selftests/net/bind_wildcard.c
new file mode 100644 (file)
index 0000000..58edfc1
--- /dev/null
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright Amazon.com Inc. or its affiliates. */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "../kselftest_harness.h"
+
+FIXTURE(bind_wildcard)
+{
+       struct sockaddr_in addr4;
+       struct sockaddr_in6 addr6;
+       int expected_errno;
+};
+
+FIXTURE_VARIANT(bind_wildcard)
+{
+       const __u32 addr4_const;
+       const struct in6_addr *addr6_const;
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_any)
+{
+       .addr4_const = INADDR_ANY,
+       .addr6_const = &in6addr_any,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_any_v6_local)
+{
+       .addr4_const = INADDR_ANY,
+       .addr6_const = &in6addr_loopback,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_any)
+{
+       .addr4_const = INADDR_LOOPBACK,
+       .addr6_const = &in6addr_any,
+};
+
+FIXTURE_VARIANT_ADD(bind_wildcard, v4_local_v6_local)
+{
+       .addr4_const = INADDR_LOOPBACK,
+       .addr6_const = &in6addr_loopback,
+};
+
+FIXTURE_SETUP(bind_wildcard)
+{
+       self->addr4.sin_family = AF_INET;
+       self->addr4.sin_port = htons(0);
+       self->addr4.sin_addr.s_addr = htonl(variant->addr4_const);
+
+       self->addr6.sin6_family = AF_INET6;
+       self->addr6.sin6_port = htons(0);
+       self->addr6.sin6_addr = *variant->addr6_const;
+
+       if (variant->addr6_const == &in6addr_any)
+               self->expected_errno = EADDRINUSE;
+       else
+               self->expected_errno = 0;
+}
+
+FIXTURE_TEARDOWN(bind_wildcard)
+{
+}
+
+void bind_sockets(struct __test_metadata *_metadata,
+                 FIXTURE_DATA(bind_wildcard) *self,
+                 struct sockaddr *addr1, socklen_t addrlen1,
+                 struct sockaddr *addr2, socklen_t addrlen2)
+{
+       int fd[2];
+       int ret;
+
+       fd[0] = socket(addr1->sa_family, SOCK_STREAM, 0);
+       ASSERT_GT(fd[0], 0);
+
+       ret = bind(fd[0], addr1, addrlen1);
+       ASSERT_EQ(ret, 0);
+
+       ret = getsockname(fd[0], addr1, &addrlen1);
+       ASSERT_EQ(ret, 0);
+
+       ((struct sockaddr_in *)addr2)->sin_port = ((struct sockaddr_in *)addr1)->sin_port;
+
+       fd[1] = socket(addr2->sa_family, SOCK_STREAM, 0);
+       ASSERT_GT(fd[1], 0);
+
+       ret = bind(fd[1], addr2, addrlen2);
+       if (self->expected_errno) {
+               ASSERT_EQ(ret, -1);
+               ASSERT_EQ(errno, self->expected_errno);
+       } else {
+               ASSERT_EQ(ret, 0);
+       }
+
+       close(fd[1]);
+       close(fd[0]);
+}
+
+TEST_F(bind_wildcard, v4_v6)
+{
+       bind_sockets(_metadata, self,
+                    (struct sockaddr *)&self->addr4, sizeof(self->addr6),
+                    (struct sockaddr *)&self->addr6, sizeof(self->addr6));
+}
+
+TEST_F(bind_wildcard, v6_v4)
+{
+       bind_sockets(_metadata, self,
+                    (struct sockaddr *)&self->addr6, sizeof(self->addr6),
+                    (struct sockaddr *)&self->addr4, sizeof(self->addr4));
+}
+
+TEST_HARNESS_MAIN
index cc9fd55ab8699b0c3092ea2708ee2a363e846195..2529226ce87ca2afc86b6d96d9d0d5886864a0cd 100644 (file)
@@ -48,3 +48,4 @@ CONFIG_BAREUDP=m
 CONFIG_IPV6_IOAM6_LWTUNNEL=y
 CONFIG_CRYPTO_SM4_GENERIC=y
 CONFIG_AMT=m
+CONFIG_IP_SCTP=m
index 2b5d6ff8737388f60b9b8cef771368e8dd49d81b..2d84c7a0be6b21e7f3fbbc5472e88d1f28220a75 100755 (executable)
@@ -59,6 +59,8 @@ class devlink_ports(object):
         assert stderr == ""
         ports = json.loads(stdout)['port']
 
+        validate_devlink_output(ports, 'flavour')
+
         for port in ports:
             if dev in port:
                 if ports[port]['flavour'] == 'physical':
@@ -220,6 +222,27 @@ def split_splittable_port(port, k, lanes, dev):
     unsplit(port.bus_info)
 
 
+def validate_devlink_output(devlink_data, target_property=None):
+    """
+    Determine if test should be skipped by checking:
+      1. devlink_data contains values
+      2. The target_property exist in devlink_data
+    """
+    skip_reason = None
+    if any(devlink_data.values()):
+        if target_property:
+            skip_reason = "{} not found in devlink output, test skipped".format(target_property)
+            for key in devlink_data:
+                if target_property in devlink_data[key]:
+                    skip_reason = None
+    else:
+        skip_reason = 'devlink output is empty, test skipped'
+
+    if skip_reason:
+        print(skip_reason)
+        sys.exit(KSFT_SKIP)
+
+
 def make_parser():
     parser = argparse.ArgumentParser(description='A test for port splitting.')
     parser.add_argument('--dev',
@@ -240,12 +263,9 @@ def main(cmdline=None):
         stdout, stderr = run_command(cmd)
         assert stderr == ""
 
+        validate_devlink_output(json.loads(stdout))
         devs = json.loads(stdout)['dev']
-        if devs:
-            dev = list(devs.keys())[0]
-        else:
-            print("no devlink device was found, test skipped")
-            sys.exit(KSFT_SKIP)
+        dev = list(devs.keys())[0]
 
     cmd = "devlink dev show %s" % dev
     stdout, stderr = run_command(cmd)
@@ -255,6 +275,7 @@ def main(cmdline=None):
 
     ports = devlink_ports(dev)
 
+    found_max_lanes = False
     for port in ports.if_names:
         max_lanes = get_max_lanes(port.name)
 
@@ -277,6 +298,11 @@ def main(cmdline=None):
                 split_splittable_port(port, lane, max_lanes, dev)
 
                 lane //= 2
+        found_max_lanes = True
+
+    if not found_max_lanes:
+        print(f"Test not started, no port of device {dev} reports max_lanes")
+        sys.exit(KSFT_SKIP)
 
 
 if __name__ == "__main__":
index 66c5be25c13d03892d878b4f58154f657daa54c9..b1eb7bce599dc0e76078df68df84c9ce117eac8e 100755 (executable)
@@ -240,7 +240,7 @@ check_expected_one()
        fi
 
        stdbuf -o0 -e0 printf "\tExpected value for '%s': '%s', got '%s'.\n" \
-               "${var}" "${!var}" "${!exp}"
+               "${var}" "${!exp}" "${!var}"
        return 1
 }
 
@@ -913,6 +913,7 @@ test_listener()
                $client4_port > /dev/null 2>&1 &
        local listener_pid=$!
 
+       sleep 0.5
        verify_listener_events $client_evts $LISTENER_CREATED $AF_INET 10.0.2.2 $client4_port
 
        # ADD_ADDR from client to server machine reusing the subflow port
@@ -928,6 +929,7 @@ test_listener()
        # Delete the listener from the client ns, if one was created
        kill_wait $listener_pid
 
+       sleep 0.5
        verify_listener_events $client_evts $LISTENER_CLOSED $AF_INET 10.0.2.2 $client4_port
 }
 
index 3243c90d449e6ec2bea681c37974287b7939f55a..5d467d1993cb12a8d225654b4dde833fd23755ba 100644 (file)
@@ -62,7 +62,7 @@ class OvsDatapath(GenericNetlinkSocket):
         nla_map = (
             ("OVS_DP_ATTR_UNSPEC", "none"),
             ("OVS_DP_ATTR_NAME", "asciiz"),
-            ("OVS_DP_ATTR_UPCALL_PID", "uint32"),
+            ("OVS_DP_ATTR_UPCALL_PID", "array(uint32)"),
             ("OVS_DP_ATTR_STATS", "dpstats"),
             ("OVS_DP_ATTR_MEGAFLOW_STATS", "megaflowstats"),
             ("OVS_DP_ATTR_USER_FEATURES", "uint32"),
index 0fd0d2db3abc1baf3c7834b24547a297145f80f9..a26c5624429fb1a029d1d472921154e73a7ea86b 100755 (executable)
@@ -60,6 +60,7 @@ ip link set dev $VETH up
 ip -n $NETNS link set dev $VETH up
 chk_rps "changing rps_default_mask affect newly created devices" "" $VETH 3
 chk_rps "changing rps_default_mask don't affect newly child netns[II]" $NETNS $VETH 0
+ip link del dev $VETH
 ip netns del $NETNS
 
 setup
index 8fe61d3e3cce0a8f4beda0640f05f49ffc5eb721..bbce57420465cd81e94c61e478eb914ea29685ec 100644 (file)
@@ -1,6 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for nolibc tests
 include ../../../scripts/Makefile.include
+# We need this for the "cc-option" macro.
+include ../../../build/Build.include
 
 # we're in ".../tools/testing/selftests/nolibc"
 ifeq ($(srctree),)
@@ -13,52 +15,56 @@ ARCH = $(SUBARCH)
 endif
 
 # kernel image names by architecture
-IMAGE_i386    = arch/x86/boot/bzImage
-IMAGE_x86_64  = arch/x86/boot/bzImage
-IMAGE_x86     = arch/x86/boot/bzImage
-IMAGE_arm64   = arch/arm64/boot/Image
-IMAGE_arm     = arch/arm/boot/zImage
-IMAGE_mips    = vmlinuz
-IMAGE_riscv   = arch/riscv/boot/Image
-IMAGE_s390    = arch/s390/boot/bzImage
-IMAGE         = $(IMAGE_$(ARCH))
-IMAGE_NAME    = $(notdir $(IMAGE))
+IMAGE_i386       = arch/x86/boot/bzImage
+IMAGE_x86_64     = arch/x86/boot/bzImage
+IMAGE_x86        = arch/x86/boot/bzImage
+IMAGE_arm64      = arch/arm64/boot/Image
+IMAGE_arm        = arch/arm/boot/zImage
+IMAGE_mips       = vmlinuz
+IMAGE_riscv      = arch/riscv/boot/Image
+IMAGE_s390       = arch/s390/boot/bzImage
+IMAGE_loongarch  = arch/loongarch/boot/vmlinuz.efi
+IMAGE            = $(IMAGE_$(ARCH))
+IMAGE_NAME       = $(notdir $(IMAGE))
 
 # default kernel configurations that appear to be usable
-DEFCONFIG_i386    = defconfig
-DEFCONFIG_x86_64  = defconfig
-DEFCONFIG_x86     = defconfig
-DEFCONFIG_arm64   = defconfig
-DEFCONFIG_arm     = multi_v7_defconfig
-DEFCONFIG_mips    = malta_defconfig
-DEFCONFIG_riscv   = defconfig
-DEFCONFIG_s390    = defconfig
-DEFCONFIG         = $(DEFCONFIG_$(ARCH))
+DEFCONFIG_i386       = defconfig
+DEFCONFIG_x86_64     = defconfig
+DEFCONFIG_x86        = defconfig
+DEFCONFIG_arm64      = defconfig
+DEFCONFIG_arm        = multi_v7_defconfig
+DEFCONFIG_mips       = malta_defconfig
+DEFCONFIG_riscv      = defconfig
+DEFCONFIG_s390       = defconfig
+DEFCONFIG_loongarch  = defconfig
+DEFCONFIG            = $(DEFCONFIG_$(ARCH))
 
 # optional tests to run (default = all)
 TEST =
 
 # QEMU_ARCH: arch names used by qemu
-QEMU_ARCH_i386    = i386
-QEMU_ARCH_x86_64  = x86_64
-QEMU_ARCH_x86     = x86_64
-QEMU_ARCH_arm64   = aarch64
-QEMU_ARCH_arm     = arm
-QEMU_ARCH_mips    = mipsel  # works with malta_defconfig
-QEMU_ARCH_riscv   = riscv64
-QEMU_ARCH_s390    = s390x
-QEMU_ARCH         = $(QEMU_ARCH_$(ARCH))
+QEMU_ARCH_i386       = i386
+QEMU_ARCH_x86_64     = x86_64
+QEMU_ARCH_x86        = x86_64
+QEMU_ARCH_arm64      = aarch64
+QEMU_ARCH_arm        = arm
+QEMU_ARCH_mips       = mipsel  # works with malta_defconfig
+QEMU_ARCH_riscv      = riscv64
+QEMU_ARCH_s390       = s390x
+QEMU_ARCH_loongarch  = loongarch64
+QEMU_ARCH            = $(QEMU_ARCH_$(ARCH))
 
 # QEMU_ARGS : some arch-specific args to pass to qemu
-QEMU_ARGS_i386    = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_x86_64  = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_x86     = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_arm64   = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_arm     = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_mips    = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_riscv   = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS_s390    = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
-QEMU_ARGS         = $(QEMU_ARGS_$(ARCH))
+QEMU_ARGS_i386       = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_x86_64     = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_x86        = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_arm64      = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_arm        = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_mips       = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_riscv      = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_s390       = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS_loongarch  = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
+QEMU_ARGS            = $(QEMU_ARGS_$(ARCH))
 
 # OUTPUT is only set when run from the main makefile, otherwise
 # it defaults to this nolibc directory.
@@ -70,8 +76,16 @@ else
 Q=@
 endif
 
+CFLAGS_STACKPROTECTOR = -DNOLIBC_STACKPROTECTOR \
+                       $(call cc-option,-mstack-protector-guard=global) \
+                       $(call cc-option,-fstack-protector-all)
+CFLAGS_STKP_i386 = $(CFLAGS_STACKPROTECTOR)
+CFLAGS_STKP_x86_64 = $(CFLAGS_STACKPROTECTOR)
+CFLAGS_STKP_x86 = $(CFLAGS_STACKPROTECTOR)
 CFLAGS_s390 = -m64
-CFLAGS  ?= -Os -fno-ident -fno-asynchronous-unwind-tables $(CFLAGS_$(ARCH))
+CFLAGS  ?= -Os -fno-ident -fno-asynchronous-unwind-tables \
+               $(call cc-option,-fno-stack-protector) \
+               $(CFLAGS_STKP_$(ARCH)) $(CFLAGS_$(ARCH))
 LDFLAGS := -s
 
 help:
index c4a0c915139cd6eb34c8f0225f924c9aeb48d152..21bacc928bf7b260518496fcecd0cf2960628a27 100644 (file)
@@ -130,111 +130,111 @@ static int pad_spc(int llen, int cnt, const char *fmt, ...)
  */
 
 #define EXPECT_ZR(cond, expr)                          \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0)
 
 static int expect_zr(int expr, int llen)
 {
        int ret = !(expr == 0);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_NZ(cond, expr, val)                     \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0)
 
 static int expect_nz(int expr, int llen)
 {
        int ret = !(expr != 0);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_EQ(cond, expr, val)                             \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0)
 
-static int expect_eq(int expr, int llen, int val)
+static int expect_eq(uint64_t expr, int llen, uint64_t val)
 {
        int ret = !(expr == val);
 
-       llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       llen += printf(" = %lld ", expr);
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_NE(cond, expr, val)                             \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0)
 
 static int expect_ne(int expr, int llen, int val)
 {
        int ret = !(expr != val);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_GE(cond, expr, val)                             \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0)
 
 static int expect_ge(int expr, int llen, int val)
 {
        int ret = !(expr >= val);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_GT(cond, expr, val)                             \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0)
 
 static int expect_gt(int expr, int llen, int val)
 {
        int ret = !(expr > val);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_LE(cond, expr, val)                             \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0)
 
 static int expect_le(int expr, int llen, int val)
 {
        int ret = !(expr <= val);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_LT(cond, expr, val)                             \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0)
 
 static int expect_lt(int expr, int llen, int val)
 {
        int ret = !(expr < val);
 
        llen += printf(" = %d ", expr);
-       pad_spc(llen, 40, ret ? "[FAIL]\n" : " [OK]\n");
+       pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n");
        return ret;
 }
 
 
 #define EXPECT_SYSZR(cond, expr)                               \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0)
 
 static int expect_syszr(int expr, int llen)
 {
@@ -243,17 +243,17 @@ static int expect_syszr(int expr, int llen)
        if (expr) {
                ret = 1;
                llen += printf(" = %d %s ", expr, errorname(errno));
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
                llen += printf(" = %d ", expr);
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_SYSEQ(cond, expr, val)                          \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0)
 
 static int expect_syseq(int expr, int llen, int val)
 {
@@ -262,17 +262,17 @@ static int expect_syseq(int expr, int llen, int val)
        if (expr != val) {
                ret = 1;
                llen += printf(" = %d %s ", expr, errorname(errno));
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
                llen += printf(" = %d ", expr);
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_SYSNE(cond, expr, val)                          \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0)
 
 static int expect_sysne(int expr, int llen, int val)
 {
@@ -281,17 +281,17 @@ static int expect_sysne(int expr, int llen, int val)
        if (expr == val) {
                ret = 1;
                llen += printf(" = %d %s ", expr, errorname(errno));
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
                llen += printf(" = %d ", expr);
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_SYSER(cond, expr, expret, experr)                       \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr(expr, expret, experr, llen); } while (0)
 
 static int expect_syserr(int expr, int expret, int experr, int llen)
 {
@@ -302,16 +302,16 @@ static int expect_syserr(int expr, int expret, int experr, int llen)
        if (expr != expret || _errno != experr) {
                ret = 1;
                llen += printf(" != (%d %s) ", expret, errorname(experr));
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_PTRZR(cond, expr)                               \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0)
 
 static int expect_ptrzr(const void *expr, int llen)
 {
@@ -320,16 +320,16 @@ static int expect_ptrzr(const void *expr, int llen)
        llen += printf(" = <%p> ", expr);
        if (expr) {
                ret = 1;
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_PTRNZ(cond, expr)                               \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0)
 
 static int expect_ptrnz(const void *expr, int llen)
 {
@@ -338,16 +338,16 @@ static int expect_ptrnz(const void *expr, int llen)
        llen += printf(" = <%p> ", expr);
        if (!expr) {
                ret = 1;
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_STRZR(cond, expr)                               \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0)
 
 static int expect_strzr(const char *expr, int llen)
 {
@@ -356,16 +356,16 @@ static int expect_strzr(const char *expr, int llen)
        llen += printf(" = <%s> ", expr);
        if (expr) {
                ret = 1;
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_STRNZ(cond, expr)                               \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0)
 
 static int expect_strnz(const char *expr, int llen)
 {
@@ -374,16 +374,16 @@ static int expect_strnz(const char *expr, int llen)
        llen += printf(" = <%s> ", expr);
        if (!expr) {
                ret = 1;
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_STREQ(cond, expr, cmp)                          \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0)
 
 static int expect_streq(const char *expr, int llen, const char *cmp)
 {
@@ -392,16 +392,16 @@ static int expect_streq(const char *expr, int llen, const char *cmp)
        llen += printf(" = <%s> ", expr);
        if (strcmp(expr, cmp) != 0) {
                ret = 1;
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
 
 
 #define EXPECT_STRNE(cond, expr, cmp)                          \
-       do { if (!cond) pad_spc(llen, 40, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0)
+       do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0)
 
 static int expect_strne(const char *expr, int llen, const char *cmp)
 {
@@ -410,9 +410,9 @@ static int expect_strne(const char *expr, int llen, const char *cmp)
        llen += printf(" = <%s> ", expr);
        if (strcmp(expr, cmp) == 0) {
                ret = 1;
-               llen += pad_spc(llen, 40, "[FAIL]\n");
+               llen += pad_spc(llen, 64, "[FAIL]\n");
        } else {
-               llen += pad_spc(llen, 40, " [OK]\n");
+               llen += pad_spc(llen, 64, " [OK]\n");
        }
        return ret;
 }
@@ -477,6 +477,7 @@ static int test_getpagesize(void)
 int run_syscall(int min, int max)
 {
        struct stat stat_buf;
+       int euid0;
        int proc;
        int test;
        int tmp;
@@ -486,6 +487,9 @@ int run_syscall(int min, int max)
        /* <proc> indicates whether or not /proc is mounted */
        proc = stat("/proc", &stat_buf) == 0;
 
+       /* this will be used to skip certain tests that can't be run unprivileged */
+       euid0 = geteuid() == 0;
+
        for (test = min; test >= 0 && test <= max; test++) {
                int llen = 0; // line length
 
@@ -511,7 +515,7 @@ int run_syscall(int min, int max)
                CASE_TEST(chmod_net);         EXPECT_SYSZR(proc, chmod("/proc/self/net", 0555)); break;
                CASE_TEST(chmod_self);        EXPECT_SYSER(proc, chmod("/proc/self", 0555), -1, EPERM); break;
                CASE_TEST(chown_self);        EXPECT_SYSER(proc, chown("/proc/self", 0, 0), -1, EPERM); break;
-               CASE_TEST(chroot_root);       EXPECT_SYSZR(1, chroot("/")); break;
+               CASE_TEST(chroot_root);       EXPECT_SYSZR(euid0, chroot("/")); break;
                CASE_TEST(chroot_blah);       EXPECT_SYSER(1, chroot("/proc/self/blah"), -1, ENOENT); break;
                CASE_TEST(chroot_exe);        EXPECT_SYSER(proc, chroot("/proc/self/exe"), -1, ENOTDIR); break;
                CASE_TEST(close_m1);          EXPECT_SYSER(1, close(-1), -1, EBADF); break;
@@ -536,7 +540,7 @@ int run_syscall(int min, int max)
                CASE_TEST(ioctl_tiocinq);     EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
                CASE_TEST(link_root1);        EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break;
                CASE_TEST(link_blah);         EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break;
-               CASE_TEST(link_dir);          EXPECT_SYSER(1, link("/", "/blah"), -1, EPERM); break;
+               CASE_TEST(link_dir);          EXPECT_SYSER(euid0, link("/", "/blah"), -1, EPERM); break;
                CASE_TEST(link_cross);        EXPECT_SYSER(proc, link("/proc/self/net", "/blah"), -1, EXDEV); break;
                CASE_TEST(lseek_m1);          EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break;
                CASE_TEST(lseek_0);           EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break;
@@ -602,6 +606,59 @@ int run_stdlib(int min, int max)
                CASE_TEST(memcmp_e0_20);       EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x20", 4), 0); break;
                CASE_TEST(memcmp_80_e0);       EXPECT_LT(1, memcmp("aaa\x80", "aaa\xe0", 4), 0); break;
                CASE_TEST(memcmp_e0_80);       EXPECT_GT(1, memcmp("aaa\xe0", "aaa\x80", 4), 0); break;
+               CASE_TEST(limit_int8_max);          EXPECT_EQ(1, INT8_MAX,         (int8_t)          0x7f); break;
+               CASE_TEST(limit_int8_min);          EXPECT_EQ(1, INT8_MIN,         (int8_t)          0x80); break;
+               CASE_TEST(limit_uint8_max);         EXPECT_EQ(1, UINT8_MAX,        (uint8_t)         0xff); break;
+               CASE_TEST(limit_int16_max);         EXPECT_EQ(1, INT16_MAX,        (int16_t)         0x7fff); break;
+               CASE_TEST(limit_int16_min);         EXPECT_EQ(1, INT16_MIN,        (int16_t)         0x8000); break;
+               CASE_TEST(limit_uint16_max);        EXPECT_EQ(1, UINT16_MAX,       (uint16_t)        0xffff); break;
+               CASE_TEST(limit_int32_max);         EXPECT_EQ(1, INT32_MAX,        (int32_t)         0x7fffffff); break;
+               CASE_TEST(limit_int32_min);         EXPECT_EQ(1, INT32_MIN,        (int32_t)         0x80000000); break;
+               CASE_TEST(limit_uint32_max);        EXPECT_EQ(1, UINT32_MAX,       (uint32_t)        0xffffffff); break;
+               CASE_TEST(limit_int64_max);         EXPECT_EQ(1, INT64_MAX,        (int64_t)         0x7fffffffffffffff); break;
+               CASE_TEST(limit_int64_min);         EXPECT_EQ(1, INT64_MIN,        (int64_t)         0x8000000000000000); break;
+               CASE_TEST(limit_uint64_max);        EXPECT_EQ(1, UINT64_MAX,       (uint64_t)        0xffffffffffffffff); break;
+               CASE_TEST(limit_int_least8_max);    EXPECT_EQ(1, INT_LEAST8_MAX,   (int_least8_t)    0x7f); break;
+               CASE_TEST(limit_int_least8_min);    EXPECT_EQ(1, INT_LEAST8_MIN,   (int_least8_t)    0x80); break;
+               CASE_TEST(limit_uint_least8_max);   EXPECT_EQ(1, UINT_LEAST8_MAX,  (uint_least8_t)   0xff); break;
+               CASE_TEST(limit_int_least16_max);   EXPECT_EQ(1, INT_LEAST16_MAX,  (int_least16_t)   0x7fff); break;
+               CASE_TEST(limit_int_least16_min);   EXPECT_EQ(1, INT_LEAST16_MIN,  (int_least16_t)   0x8000); break;
+               CASE_TEST(limit_uint_least16_max);  EXPECT_EQ(1, UINT_LEAST16_MAX, (uint_least16_t)  0xffff); break;
+               CASE_TEST(limit_int_least32_max);   EXPECT_EQ(1, INT_LEAST32_MAX,  (int_least32_t)   0x7fffffff); break;
+               CASE_TEST(limit_int_least32_min);   EXPECT_EQ(1, INT_LEAST32_MIN,  (int_least32_t)   0x80000000); break;
+               CASE_TEST(limit_uint_least32_max);  EXPECT_EQ(1, UINT_LEAST32_MAX, (uint_least32_t)  0xffffffffU); break;
+               CASE_TEST(limit_int_least64_min);   EXPECT_EQ(1, INT_LEAST64_MIN,  (int_least64_t)   0x8000000000000000LL); break;
+               CASE_TEST(limit_int_least64_max);   EXPECT_EQ(1, INT_LEAST64_MAX,  (int_least64_t)   0x7fffffffffffffffLL); break;
+               CASE_TEST(limit_uint_least64_max);  EXPECT_EQ(1, UINT_LEAST64_MAX, (uint_least64_t)  0xffffffffffffffffULL); break;
+               CASE_TEST(limit_int_fast8_max);     EXPECT_EQ(1, INT_FAST8_MAX,    (int_fast8_t)     0x7f); break;
+               CASE_TEST(limit_int_fast8_min);     EXPECT_EQ(1, INT_FAST8_MIN,    (int_fast8_t)     0x80); break;
+               CASE_TEST(limit_uint_fast8_max);    EXPECT_EQ(1, UINT_FAST8_MAX,   (uint_fast8_t)    0xff); break;
+               CASE_TEST(limit_int_fast16_min);    EXPECT_EQ(1, INT_FAST16_MIN,   (int_fast16_t)    INTPTR_MIN); break;
+               CASE_TEST(limit_int_fast16_max);    EXPECT_EQ(1, INT_FAST16_MAX,   (int_fast16_t)    INTPTR_MAX); break;
+               CASE_TEST(limit_uint_fast16_max);   EXPECT_EQ(1, UINT_FAST16_MAX,  (uint_fast16_t)   UINTPTR_MAX); break;
+               CASE_TEST(limit_int_fast32_min);    EXPECT_EQ(1, INT_FAST32_MIN,   (int_fast32_t)    INTPTR_MIN); break;
+               CASE_TEST(limit_int_fast32_max);    EXPECT_EQ(1, INT_FAST32_MAX,   (int_fast32_t)    INTPTR_MAX); break;
+               CASE_TEST(limit_uint_fast32_max);   EXPECT_EQ(1, UINT_FAST32_MAX,  (uint_fast32_t)   UINTPTR_MAX); break;
+               CASE_TEST(limit_int_fast64_min);    EXPECT_EQ(1, INT_FAST64_MIN,   (int_fast64_t)    INTPTR_MIN); break;
+               CASE_TEST(limit_int_fast64_max);    EXPECT_EQ(1, INT_FAST64_MAX,   (int_fast64_t)    INTPTR_MAX); break;
+               CASE_TEST(limit_uint_fast64_max);   EXPECT_EQ(1, UINT_FAST64_MAX,  (uint_fast64_t)   UINTPTR_MAX); break;
+#if __SIZEOF_LONG__ == 8
+               CASE_TEST(limit_intptr_min);        EXPECT_EQ(1, INTPTR_MIN,       (intptr_t)        0x8000000000000000LL); break;
+               CASE_TEST(limit_intptr_max);        EXPECT_EQ(1, INTPTR_MAX,       (intptr_t)        0x7fffffffffffffffLL); break;
+               CASE_TEST(limit_uintptr_max);       EXPECT_EQ(1, UINTPTR_MAX,      (uintptr_t)       0xffffffffffffffffULL); break;
+               CASE_TEST(limit_ptrdiff_min);       EXPECT_EQ(1, PTRDIFF_MIN,      (ptrdiff_t)       0x8000000000000000LL); break;
+               CASE_TEST(limit_ptrdiff_max);       EXPECT_EQ(1, PTRDIFF_MAX,      (ptrdiff_t)       0x7fffffffffffffffLL); break;
+               CASE_TEST(limit_size_max);          EXPECT_EQ(1, SIZE_MAX,         (size_t)          0xffffffffffffffffULL); break;
+#elif __SIZEOF_LONG__ == 4
+               CASE_TEST(limit_intptr_min);        EXPECT_EQ(1, INTPTR_MIN,       (intptr_t)        0x80000000); break;
+               CASE_TEST(limit_intptr_max);        EXPECT_EQ(1, INTPTR_MAX,       (intptr_t)        0x7fffffff); break;
+               CASE_TEST(limit_uintptr_max);       EXPECT_EQ(1, UINTPTR_MAX,      (uintptr_t)       0xffffffffU); break;
+               CASE_TEST(limit_ptrdiff_min);       EXPECT_EQ(1, PTRDIFF_MIN,      (ptrdiff_t)       0x80000000); break;
+               CASE_TEST(limit_ptrdiff_max);       EXPECT_EQ(1, PTRDIFF_MAX,      (ptrdiff_t)       0x7fffffff); break;
+               CASE_TEST(limit_size_max);          EXPECT_EQ(1, SIZE_MAX,         (size_t)          0xffffffffU); break;
+#else
+# warning "__SIZEOF_LONG__ is undefined"
+#endif /* __SIZEOF_LONG__ */
                case __LINE__:
                        return ret; /* must be last */
                /* note: do not set any defaults so as to permit holes above */
@@ -610,6 +667,63 @@ int run_stdlib(int min, int max)
        return ret;
 }
 
+#if defined(__clang__)
+__attribute__((optnone))
+#elif defined(__GNUC__)
+__attribute__((optimize("O0")))
+#endif
+static int smash_stack(void)
+{
+       char buf[100];
+
+       for (size_t i = 0; i < 200; i++)
+               buf[i] = 'P';
+
+       return 1;
+}
+
+static int run_protection(int min, int max)
+{
+       pid_t pid;
+       int llen = 0, status;
+
+       llen += printf("0 -fstackprotector ");
+
+#if !defined(NOLIBC_STACKPROTECTOR)
+       llen += printf("not supported");
+       pad_spc(llen, 64, "[SKIPPED]\n");
+       return 0;
+#endif
+
+       pid = -1;
+       pid = fork();
+
+       switch (pid) {
+       case -1:
+               llen += printf("fork()");
+               pad_spc(llen, 64, "[FAIL]\n");
+               return 1;
+
+       case 0:
+               close(STDOUT_FILENO);
+               close(STDERR_FILENO);
+
+               smash_stack();
+               return 1;
+
+       default:
+               pid = waitpid(pid, &status, 0);
+
+               if (pid == -1 || !WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT) {
+                       llen += printf("waitpid()");
+                       pad_spc(llen, 64, "[FAIL]\n");
+                       return 1;
+               }
+               pad_spc(llen, 64, " [OK]\n");
+               return 0;
+       }
+}
+
 /* prepare what needs to be prepared for pid 1 (stdio, /dev, /proc, etc) */
 int prepare(void)
 {
@@ -660,10 +774,11 @@ int prepare(void)
 }
 
 /* This is the definition of known test names, with their functions */
-static struct test test_names[] = {
+static const struct test test_names[] = {
        /* add new tests here */
-       { .name = "syscall",   .func = run_syscall  },
-       { .name = "stdlib",    .func = run_stdlib   },
+       { .name = "syscall",    .func = run_syscall    },
+       { .name = "stdlib",     .func = run_stdlib     },
+       { .name = "protection", .func = run_protection },
        { 0 }
 };
 
index 91af2b631bc96037875a0e6bdb3dd8305229e412..7a657b25f686d38e125a82d15a5279285bfd83ad 100644 (file)
@@ -2,3 +2,4 @@
 disable-tsc-ctxt-sw-stress-test
 disable-tsc-on-off-stress-test
 disable-tsc-test
+set-anon-vma-name-test
index c7923b205222dd0361a8971426780fde5498c19a..c058b81eeb41860b8dd915a72146340f253c0f18 100644 (file)
@@ -5,7 +5,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
 
 ifeq ($(ARCH),x86)
 TEST_PROGS := disable-tsc-ctxt-sw-stress-test disable-tsc-on-off-stress-test \
-               disable-tsc-test
+               disable-tsc-test set-anon-vma-name-test
 all: $(TEST_PROGS)
 
 include ../lib.mk
diff --git a/tools/testing/selftests/prctl/config b/tools/testing/selftests/prctl/config
new file mode 100644 (file)
index 0000000..c6ed03c
--- /dev/null
@@ -0,0 +1 @@
+CONFIG_ANON_VMA_NAME=y
diff --git a/tools/testing/selftests/prctl/set-anon-vma-name-test.c b/tools/testing/selftests/prctl/set-anon-vma-name-test.c
new file mode 100644 (file)
index 0000000..26d853c
--- /dev/null
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This test covers the anonymous VMA naming functionality through prctl calls
+ */
+
+#include <errno.h>
+#include <sys/prctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#include "../kselftest_harness.h"
+
+#define AREA_SIZE 1024
+
+#define GOOD_NAME "goodname"
+#define BAD_NAME "badname\1"
+
+#ifndef PR_SET_VMA
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
+#endif
+
+
+int rename_vma(unsigned long addr, unsigned long size, char *name)
+{
+       int res;
+
+       res = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, size, name);
+       if (res < 0)
+               return -errno;
+       return res;
+}
+
+int was_renaming_successful(char *target_name, unsigned long ptr)
+{
+       FILE *maps_file;
+
+       char line_buf[512], name[128], mode[8];
+       unsigned long start_addr, end_addr, offset;
+       unsigned int major_id, minor_id, node_id;
+
+       char target_buf[128];
+       int res = 0, sscanf_res;
+
+       // The entry name in maps will be in format [anon:<target_name>]
+       sprintf(target_buf, "[anon:%s]", target_name);
+       maps_file = fopen("/proc/self/maps", "r");
+       if (!maps_file) {
+               printf("## /proc/self/maps file opening error\n");
+               return 0;
+       }
+
+       // Parse the maps file to find the entry we renamed
+       while (fgets(line_buf, sizeof(line_buf), maps_file)) {
+               sscanf_res = sscanf(line_buf, "%lx-%lx %7s %lx %u:%u %u %s", &start_addr,
+                                       &end_addr, mode, &offset, &major_id,
+                                       &minor_id, &node_id, name);
+               if (sscanf_res == EOF) {
+                       res = 0;
+                       printf("## EOF while parsing the maps file\n");
+                       break;
+               }
+               if (!strcmp(name, target_buf) && start_addr == ptr) {
+                       res = 1;
+                       break;
+               }
+       }
+       fclose(maps_file);
+       return res;
+}
+
+FIXTURE(vma) {
+       void *ptr_anon, *ptr_not_anon;
+};
+
+FIXTURE_SETUP(vma) {
+       self->ptr_anon = mmap(NULL, AREA_SIZE, PROT_READ | PROT_WRITE,
+                                       MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+       ASSERT_NE(self->ptr_anon, NULL);
+       self->ptr_not_anon = mmap(NULL, AREA_SIZE, PROT_READ | PROT_WRITE,
+                                       MAP_PRIVATE, 0, 0);
+       ASSERT_NE(self->ptr_not_anon, NULL);
+}
+
+FIXTURE_TEARDOWN(vma) {
+       munmap(self->ptr_anon, AREA_SIZE);
+       munmap(self->ptr_not_anon, AREA_SIZE);
+}
+
+TEST_F(vma, renaming) {
+       TH_LOG("Try to rename the VMA with correct parameters");
+       EXPECT_GE(rename_vma((unsigned long)self->ptr_anon, AREA_SIZE, GOOD_NAME), 0);
+       EXPECT_TRUE(was_renaming_successful(GOOD_NAME, (unsigned long)self->ptr_anon));
+
+       TH_LOG("Try to pass invalid name (with non-printable character \\1) to rename the VMA");
+       EXPECT_EQ(rename_vma((unsigned long)self->ptr_anon, AREA_SIZE, BAD_NAME), -EINVAL);
+
+       TH_LOG("Try to rename non-anonynous VMA");
+       EXPECT_EQ(rename_vma((unsigned long) self->ptr_not_anon, AREA_SIZE, GOOD_NAME), -EINVAL);
+}
+
+TEST_HARNESS_MAIN
index 781f7a50fc3f196b95ec31019e744681e60cdd9b..f335eec5067e91f7017fca10f311470b51c53fb0 100644 (file)
@@ -13,7 +13,9 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-// Test that values in /proc/uptime increment monotonically.
+// Test that boottime value in /proc/uptime and CLOCK_BOOTTIME increment
+// monotonically. We don't test idle time monotonicity due to broken iowait
+// task counting, cf: comment above get_cpu_idle_time_us()
 #undef NDEBUG
 #include <assert.h>
 #include <stdint.h>
 
 int main(void)
 {
-       uint64_t start, u0, u1, i0, i1;
+       uint64_t start, u0, u1, c0, c1;
        int fd;
 
        fd = open("/proc/uptime", O_RDONLY);
        assert(fd >= 0);
 
-       proc_uptime(fd, &u0, &i0);
+       u0 = proc_uptime(fd);
        start = u0;
+       c0 = clock_boottime();
+
        do {
-               proc_uptime(fd, &u1, &i1);
+               u1 = proc_uptime(fd);
+               c1 = clock_boottime();
+
+               /* Is /proc/uptime monotonic ? */
                assert(u1 >= u0);
-               assert(i1 >= i0);
+
+               /* Is CLOCK_BOOTTIME monotonic ? */
+               assert(c1 >= c0);
+
+               /* Is CLOCK_BOOTTIME VS /proc/uptime monotonic ? */
+               assert(c0 >= u0);
+
                u0 = u1;
-               i0 = i1;
+               c0 = c1;
        } while (u1 - start < 100);
 
        return 0;
index 7d0aa22bdc12b29b9adf2581b021f84d5ee7b9c2..ae453daa96c1911038ccaa6082db6cc7bd7adf63 100644 (file)
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-// Test that values in /proc/uptime increment monotonically
-// while shifting across CPUs.
+// Test that boottime value in /proc/uptime and CLOCK_BOOTTIME increment
+// monotonically while shifting across CPUs. We don't test idle time
+// monotonicity due to broken iowait task counting, cf: comment above
+// get_cpu_idle_time_us()
 #undef NDEBUG
 #include <assert.h>
 #include <errno.h>
@@ -42,10 +44,10 @@ static inline int sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned lo
 
 int main(void)
 {
+       uint64_t u0, u1, c0, c1;
        unsigned int len;
        unsigned long *m;
        unsigned int cpu;
-       uint64_t u0, u1, i0, i1;
        int fd;
 
        /* find out "nr_cpu_ids" */
@@ -60,7 +62,9 @@ int main(void)
        fd = open("/proc/uptime", O_RDONLY);
        assert(fd >= 0);
 
-       proc_uptime(fd, &u0, &i0);
+       u0 = proc_uptime(fd);
+       c0 = clock_boottime();
+
        for (cpu = 0; cpu < len * 8; cpu++) {
                memset(m, 0, len);
                m[cpu / (8 * sizeof(unsigned long))] |= 1UL << (cpu % (8 * sizeof(unsigned long)));
@@ -68,11 +72,20 @@ int main(void)
                /* CPU might not exist, ignore error */
                sys_sched_setaffinity(0, len, m);
 
-               proc_uptime(fd, &u1, &i1);
+               u1 = proc_uptime(fd);
+               c1 = clock_boottime();
+
+               /* Is /proc/uptime monotonic ? */
                assert(u1 >= u0);
-               assert(i1 >= i0);
+
+               /* Is CLOCK_BOOTTIME monotonic ? */
+               assert(c1 >= c0);
+
+               /* Is CLOCK_BOOTTIME VS /proc/uptime monotonic ? */
+               assert(c0 >= u0);
+
                u0 = u1;
-               i0 = i1;
+               c0 = c1;
        }
 
        return 0;
index dc6a42b1d6b077998a31a7b6d5bed1bba64a43f5..730cce4a3d73ec36ee4aec506c2778844bbc0b18 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <time.h>
 
 #include "proc.h"
 
-static void proc_uptime(int fd, uint64_t *uptime, uint64_t *idle)
+static uint64_t clock_boottime(void)
+{
+       struct timespec ts;
+       int err;
+
+       err = clock_gettime(CLOCK_BOOTTIME, &ts);
+       assert(err >= 0);
+
+       return (ts.tv_sec * 100) + (ts.tv_nsec / 10000000);
+}
+
+static uint64_t proc_uptime(int fd)
 {
        uint64_t val1, val2;
        char buf[64], *p;
@@ -43,18 +55,6 @@ static void proc_uptime(int fd, uint64_t *uptime, uint64_t *idle)
        assert(p[3] == ' ');
 
        val2 = (p[1] - '0') * 10 + p[2] - '0';
-       *uptime = val1 * 100 + val2;
-
-       p += 4;
-
-       val1 = xstrtoull(p, &p);
-       assert(p[0] == '.');
-       assert('0' <= p[1] && p[1] <= '9');
-       assert('0' <= p[2] && p[2] <= '9');
-       assert(p[3] == '\n');
-
-       val2 = (p[1] - '0') * 10 + p[2] - '0';
-       *idle = val1 * 100 + val2;
 
-       assert(p + 4 == buf + rv);
+       return val1 * 100 + val2;
 }
index 792318aaa30cd209c9269f71e4d34e8ddc22e592..b7dde152e75a9a2f75bfa1961117d2d9bb775824 100644 (file)
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 get_syscall_info
+get_set_sud
 peeksiginfo
 vmaccess
index 96ffa94afb9136237649b019a20a44a628b4654a..1c631740a730af922ddfe8363aff7fb4948bf55b 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 CFLAGS += -std=c99 -pthread -Wall $(KHDR_INCLUDES)
 
-TEST_GEN_PROGS := get_syscall_info peeksiginfo vmaccess
+TEST_GEN_PROGS := get_syscall_info peeksiginfo vmaccess get_set_sud
 
 include ../lib.mk
diff --git a/tools/testing/selftests/ptrace/get_set_sud.c b/tools/testing/selftests/ptrace/get_set_sud.c
new file mode 100644 (file)
index 0000000..5297b10
--- /dev/null
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include "../kselftest_harness.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include <sys/prctl.h>
+
+#include "linux/ptrace.h"
+
+static int sys_ptrace(int request, pid_t pid, void *addr, void *data)
+{
+       return syscall(SYS_ptrace, request, pid, addr, data);
+}
+
+TEST(get_set_sud)
+{
+       struct ptrace_sud_config config;
+       pid_t child;
+       int ret = 0;
+       int status;
+
+       child = fork();
+       ASSERT_GE(child, 0);
+       if (child == 0) {
+               ASSERT_EQ(0, sys_ptrace(PTRACE_TRACEME, 0, 0, 0)) {
+                       TH_LOG("PTRACE_TRACEME: %m");
+               }
+               kill(getpid(), SIGSTOP);
+               _exit(1);
+       }
+
+       waitpid(child, &status, 0);
+
+       memset(&config, 0xff, sizeof(config));
+       config.mode = PR_SYS_DISPATCH_ON;
+
+       ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
+                        (void *)sizeof(config), &config);
+
+       ASSERT_EQ(ret, 0);
+       ASSERT_EQ(config.mode, PR_SYS_DISPATCH_OFF);
+       ASSERT_EQ(config.selector, 0);
+       ASSERT_EQ(config.offset, 0);
+       ASSERT_EQ(config.len, 0);
+
+       config.mode = PR_SYS_DISPATCH_ON;
+       config.selector = 0;
+       config.offset = 0x400000;
+       config.len = 0x1000;
+
+       ret = sys_ptrace(PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG, child,
+                        (void *)sizeof(config), &config);
+
+       ASSERT_EQ(ret, 0);
+
+       memset(&config, 1, sizeof(config));
+       ret = sys_ptrace(PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG, child,
+                        (void *)sizeof(config), &config);
+
+       ASSERT_EQ(ret, 0);
+       ASSERT_EQ(config.mode, PR_SYS_DISPATCH_ON);
+       ASSERT_EQ(config.selector, 0);
+       ASSERT_EQ(config.offset, 0x400000);
+       ASSERT_EQ(config.len, 0x1000);
+
+       kill(child, SIGKILL);
+}
+
+TEST_HARNESS_MAIN
index 54900657eb442f81835e7e7c8f1647f8bedceb2d..a6884f66dc0130b5970544065a28745e73a26cc1 100644 (file)
@@ -151,7 +151,7 @@ out:
 
 int main(int argc, char *argv[])
 {
-       siginfo_t siginfo[SIGNR];
+       siginfo_t siginfo;
        int i, exit_code = 1;
        sigset_t blockmask;
        pid_t child;
@@ -176,13 +176,13 @@ int main(int argc, char *argv[])
 
        /* Send signals in process-wide and per-thread queues */
        for (i = 0; i < SIGNR; i++) {
-               siginfo->si_code = TEST_SICODE_SHARE;
-               siginfo->si_int = i;
-               sys_rt_sigqueueinfo(child, SIGRTMIN, siginfo);
+               siginfo.si_code = TEST_SICODE_SHARE;
+               siginfo.si_int = i;
+               sys_rt_sigqueueinfo(child, SIGRTMIN, &siginfo);
 
-               siginfo->si_code = TEST_SICODE_PRIV;
-               siginfo->si_int = i;
-               sys_rt_tgsigqueueinfo(child, child, SIGRTMIN, siginfo);
+               siginfo.si_code = TEST_SICODE_PRIV;
+               siginfo.si_int = i;
+               sys_rt_tgsigqueueinfo(child, child, SIGRTMIN, &siginfo);
        }
 
        if (sys_ptrace(PTRACE_ATTACH, child, NULL, NULL) == -1)
index 8a968fbda02c9e5e452281dd59017681f4b97f60..88ca4e36848908272a9947c07ff6b6afc8224578 100755 (executable)
@@ -193,7 +193,7 @@ do
        qemu_cmd_dir="`dirname "$i"`"
        kernel_dir="`echo $qemu_cmd_dir | sed -e 's/\.[0-9]\+$//'`"
        jitter_dir="`dirname "$kernel_dir"`"
-       kvm-transform.sh "$kernel_dir/bzImage" "$qemu_cmd_dir/console.log" "$jitter_dir" $dur "$bootargs" < $T/qemu-cmd > $i
+       kvm-transform.sh "$kernel_dir/bzImage" "$qemu_cmd_dir/console.log" "$jitter_dir" "$dur" "$bootargs" < $T/qemu-cmd > $i
        if test -n "$arg_remote"
        then
                echo "# TORTURE_KCONFIG_GDB_ARG=''" >> $i
diff --git a/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh b/tools/testing/selftests/rcutorture/bin/srcu_lockdep.sh
new file mode 100755 (executable)
index 0000000..2e63ef0
--- /dev/null
@@ -0,0 +1,78 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Run SRCU-lockdep tests and report any that fail to meet expectations.
+#
+# Copyright (C) 2021 Meta Platforms, Inc.
+#
+# Authors: Paul E. McKenney <paulmck@kernel.org>
+
+usage () {
+       echo "Usage: $scriptname optional arguments:"
+       echo "       --datestamp string"
+       exit 1
+}
+
+ds=`date +%Y.%m.%d-%H.%M.%S`-srcu_lockdep
+scriptname="$0"
+
+T="`mktemp -d ${TMPDIR-/tmp}/srcu_lockdep.sh.XXXXXX`"
+trap 'rm -rf $T' 0
+
+RCUTORTURE="`pwd`/tools/testing/selftests/rcutorture"; export RCUTORTURE
+PATH=${RCUTORTURE}/bin:$PATH; export PATH
+. functions.sh
+
+while test $# -gt 0
+do
+       case "$1" in
+       --datestamp)
+               checkarg --datestamp "(relative pathname)" "$#" "$2" '^[a-zA-Z0-9._/-]*$' '^--'
+               ds=$2
+               shift
+               ;;
+       *)
+               echo Unknown argument $1
+               usage
+               ;;
+       esac
+       shift
+done
+
+err=
+nerrs=0
+for d in 0 1
+do
+       for t in 0 1 2
+       do
+               for c in 1 2 3
+               do
+                       err=
+                       val=$((d*1000+t*10+c))
+                       tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 5s --configs "SRCU-P" --bootargs "rcutorture.test_srcu_lockdep=$val" --trust-make --datestamp "$ds/$val" > "$T/kvm.sh.out" 2>&1
+                       ret=$?
+                       mv "$T/kvm.sh.out" "$RCUTORTURE/res/$ds/$val"
+                       if test "$d" -ne 0 && test "$ret" -eq 0
+                       then
+                               err=1
+                               echo -n Unexpected success for > "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+                       fi
+                       if test "$d" -eq 0 && test "$ret" -ne 0
+                       then
+                               err=1
+                               echo -n Unexpected failure for > "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+                       fi
+                       if test -n "$err"
+                       then
+                               grep "rcu_torture_init_srcu_lockdep: test_srcu_lockdep = " "$RCUTORTURE/res/$ds/$val/SRCU-P/console.log" | sed -e 's/^.*rcu_torture_init_srcu_lockdep://' >> "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+                               cat "$RCUTORTURE/res/$ds/$val/kvm.sh.err"
+                               nerrs=$((nerrs+1))
+                       fi
+               done
+       done
+done
+if test "$nerrs" -ne 0
+then
+       exit 1
+fi
+exit 0
index 130d0de4c3bbd3e5c4133823f5bfb7650a0a4f06..5a2ae2264403f063ad596c80d6ee824739bcb687 100755 (executable)
@@ -497,16 +497,16 @@ fi
 
 if test "$do_clocksourcewd" = "yes"
 then
-       torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000"
+       torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 tsc=watchdog"
        torture_set "clocksourcewd-1" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --kconfig "CONFIG_TEST_CLOCKSOURCE_WATCHDOG=y" --trust-make
 
-       torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 clocksource.max_cswd_read_retries=1"
+       torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 clocksource.max_cswd_read_retries=1 tsc=watchdog"
        torture_set "clocksourcewd-2" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --kconfig "CONFIG_TEST_CLOCKSOURCE_WATCHDOG=y" --trust-make
 
        # In case our work is already done...
        if test "$do_rcutorture" != "yes"
        then
-               torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000"
+               torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 tsc=watchdog"
                torture_set "clocksourcewd-3" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --trust-make
        fi
 fi
index 41bae5824339453c7a0b3a9fc6db60ba98588bc5..28e23d05d5a5574b14a17cb65397fef6b47ccf55 100644 (file)
@@ -5,3 +5,5 @@ LOCK04
 LOCK05
 LOCK06
 LOCK07
+LOCK08
+LOCK09
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK08 b/tools/testing/selftests/rcutorture/configs/lock/LOCK08
new file mode 100644 (file)
index 0000000..1d1da14
--- /dev/null
@@ -0,0 +1,6 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot
new file mode 100644 (file)
index 0000000..b8b6cae
--- /dev/null
@@ -0,0 +1 @@
+locktorture.torture_type=mutex_lock locktorture.nested_locks=8
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK09 b/tools/testing/selftests/rcutorture/configs/lock/LOCK09
new file mode 100644 (file)
index 0000000..1d1da14
--- /dev/null
@@ -0,0 +1,6 @@
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT_NONE=n
+CONFIG_PREEMPT_VOLUNTARY=n
+CONFIG_PREEMPT=y
diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot
new file mode 100644 (file)
index 0000000..fd5eff1
--- /dev/null
@@ -0,0 +1 @@
+locktorture.torture_type=rtmutex_lock locktorture.nested_locks=8
index 8ae41d5f81a3e941e5f5cbf1bc295ed75b4ba3ad..04831ef1f9b55421063775b3a543f9a2f0cc6536 100644 (file)
@@ -15,3 +15,4 @@ CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_RCU_BOOST=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
 CONFIG_RCU_EXPERT=y
+CONFIG_BOOTPARAM_HOTPLUG_CPU0=y
index ae395981b5e5e7c03499bd3d9140c6de8b034690..dc4985064b3adb31f8db2d6ffc65a283774ac6df 100644 (file)
@@ -15,3 +15,4 @@ CONFIG_DEBUG_LOCK_ALLOC=n
 CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
 CONFIG_RCU_EXPERT=y
 CONFIG_RCU_EQS_DEBUG=y
+CONFIG_RCU_LAZY=y
index 42acb1a64ce10b2b1460143cd44c39ec4021b4c4..3f5fb66f16df7b4c4ab6247f69a7a76e5ff7406f 100644 (file)
@@ -71,9 +71,5 @@ CONFIG_TASKS_RCU
 
        These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP.
 
-CONFIG_SRCU
-
-       Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable.
-
 
 boot parameters ignored: TBD
index 68ff856d36f0bc52720f31dae88bea29d01470bb..8a4fe8693be63e5ae2ad40dea0ed68fd07fd4bf0 100644 (file)
@@ -48,7 +48,7 @@ static int perf_event_open_llc_miss(pid_t pid, int cpu_no)
        return 0;
 }
 
-static int initialize_llc_perf(void)
+static void initialize_llc_perf(void)
 {
        memset(&pea_llc_miss, 0, sizeof(struct perf_event_attr));
        memset(&rf_cqm, 0, sizeof(struct read_format));
@@ -59,8 +59,6 @@ static int initialize_llc_perf(void)
        pea_llc_miss.config = PERF_COUNT_HW_CACHE_MISSES;
 
        rf_cqm.nr = 1;
-
-       return 0;
 }
 
 static int reset_enable_llc_perf(pid_t pid, int cpu_no)
@@ -79,7 +77,7 @@ static int reset_enable_llc_perf(pid_t pid, int cpu_no)
 
 /*
  * get_llc_perf:       llc cache miss through perf events
- * @cpu_no:            CPU number that the benchmark PID is binded to
+ * @llc_perf_miss:     LLC miss counter that is filled on success
  *
  * Perf events like HW_CACHE_MISSES could be used to validate number of
  * cache lines allocated.
@@ -234,20 +232,19 @@ int cat_val(struct resctrl_val_param *param)
        if (ret)
                return ret;
 
-       if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) {
-               ret = initialize_llc_perf();
-               if (ret)
-                       return ret;
-       }
+       if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)))
+               initialize_llc_perf();
 
        /* Test runs until the callback setup() tells the test to stop. */
        while (1) {
                if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR))) {
                        ret = param->setup(1, param);
-                       if (ret) {
+                       if (ret == END_OF_TESTS) {
                                ret = 0;
                                break;
                        }
+                       if (ret < 0)
+                               break;
                        ret = reset_enable_llc_perf(bm_pid, param->cpu_no);
                        if (ret)
                                break;
index 1c5e90c632548100c92c803432d154678c9ba98d..fb1443f888c4c90beabca9c93649ce3458c7a7a5 100644 (file)
@@ -40,7 +40,7 @@ static int cat_setup(int num, ...)
 
        /* Run NUM_OF_RUNS times */
        if (p->num_of_runs >= NUM_OF_RUNS)
-               return -1;
+               return END_OF_TESTS;
 
        if (p->num_of_runs == 0) {
                sprintf(schemata, "%lx", p->mask);
@@ -103,7 +103,6 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
        unsigned long l_mask, l_mask_1;
        int ret, pipefd[2], sibling_cpu_no;
        char pipe_message;
-       pid_t bm_pid;
 
        cache_size = 0;
 
@@ -145,7 +144,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
        struct resctrl_val_param param = {
                .resctrl_val    = CAT_STR,
                .cpu_no         = cpu_no,
-               .mum_resctrlfs  = 0,
+               .mum_resctrlfs  = false,
                .setup          = cat_setup,
        };
 
@@ -167,6 +166,7 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
                return errno;
        }
 
+       fflush(stdout);
        bm_pid = fork();
 
        /* Set param values for child thread which will be allocated bitmask
@@ -180,28 +180,31 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
                strcpy(param.filename, RESULT_FILE_NAME1);
                param.num_of_runs = 0;
                param.cpu_no = sibling_cpu_no;
+       } else {
+               ret = signal_handler_register();
+               if (ret) {
+                       kill(bm_pid, SIGKILL);
+                       goto out;
+               }
        }
 
        remove(param.filename);
 
        ret = cat_val(&param);
-       if (ret)
-               return ret;
-
-       ret = check_results(&param);
-       if (ret)
-               return ret;
+       if (ret == 0)
+               ret = check_results(&param);
 
        if (bm_pid == 0) {
                /* Tell parent that child is ready */
                close(pipefd[0]);
                pipe_message = 1;
                if (write(pipefd[1], &pipe_message, sizeof(pipe_message)) <
-                   sizeof(pipe_message)) {
-                       close(pipefd[1]);
+                   sizeof(pipe_message))
+                       /*
+                        * Just print the error message.
+                        * Let while(1) run and wait for itself to be killed.
+                        */
                        perror("# failed signaling parent process");
-                       return errno;
-               }
 
                close(pipefd[1]);
                while (1)
@@ -219,11 +222,13 @@ int cat_perf_miss_val(int cpu_no, int n, char *cache_type)
                }
                close(pipefd[0]);
                kill(bm_pid, SIGKILL);
+               signal_handler_unregister();
        }
 
+out:
        cat_test_cleanup();
        if (bm_pid)
                umount_resctrlfs();
 
-       return 0;
+       return ret;
 }
index 8968e36db99d79cca16e99321e4f79e72bad4e24..af71b21412710b8d2ea511e36569225f9dd64f7e 100644 (file)
@@ -32,7 +32,7 @@ static int cmt_setup(int num, ...)
 
        /* Run NUM_OF_RUNS times */
        if (p->num_of_runs >= NUM_OF_RUNS)
-               return -1;
+               return END_OF_TESTS;
 
        p->num_of_runs++;
 
@@ -82,12 +82,11 @@ void cmt_test_cleanup(void)
 
 int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
 {
-       int ret, mum_resctrlfs;
+       int ret;
 
        cache_size = 0;
-       mum_resctrlfs = 1;
 
-       ret = remount_resctrlfs(mum_resctrlfs);
+       ret = remount_resctrlfs(true);
        if (ret)
                return ret;
 
@@ -118,7 +117,7 @@ int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
                .ctrlgrp        = "c1",
                .mongrp         = "m1",
                .cpu_no         = cpu_no,
-               .mum_resctrlfs  = 0,
+               .mum_resctrlfs  = false,
                .filename       = RESULT_FILE_NAME,
                .mask           = ~(long_mask << n) & long_mask,
                .span           = cache_size * n / count_of_bits,
@@ -133,13 +132,12 @@ int cmt_resctrl_val(int cpu_no, int n, char **benchmark_cmd)
 
        ret = resctrl_val(benchmark_cmd, &param);
        if (ret)
-               return ret;
+               goto out;
 
        ret = check_results(&param, n);
-       if (ret)
-               return ret;
 
+out:
        cmt_test_cleanup();
 
-       return 0;
+       return ret;
 }
index 56ccbeae0638d57fda0e99d4eaa70ae6b742e370..341cc93ca84c4b86535c4fb58043ed52af96ae2e 100644 (file)
@@ -14,7 +14,6 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <inttypes.h>
-#include <malloc.h>
 #include <string.h>
 
 #include "resctrl.h"
@@ -33,14 +32,6 @@ static void sb(void)
 #endif
 }
 
-static void ctrl_handler(int signo)
-{
-       free(startptr);
-       printf("\nEnding\n");
-       sb();
-       exit(EXIT_SUCCESS);
-}
-
 static void cl_flush(void *p)
 {
 #if defined(__i386) || defined(__x86_64)
@@ -64,10 +55,14 @@ static void mem_flush(void *p, size_t s)
 
 static void *malloc_and_init_memory(size_t s)
 {
+       void *p = NULL;
        uint64_t *p64;
        size_t s64;
+       int ret;
 
-       void *p = memalign(PAGE_SIZE, s);
+       ret = posix_memalign(&p, PAGE_SIZE, s);
+       if (ret < 0)
+               return NULL;
 
        p64 = (uint64_t *)p;
        s64 = s / sizeof(uint64_t);
@@ -198,12 +193,6 @@ int run_fill_buf(unsigned long span, int malloc_and_init_memory,
        unsigned long long cache_size = span;
        int ret;
 
-       /* set up ctrl-c handler */
-       if (signal(SIGINT, ctrl_handler) == SIG_ERR)
-               printf("Failed to catch SIGINT!\n");
-       if (signal(SIGHUP, ctrl_handler) == SIG_ERR)
-               printf("Failed to catch SIGHUP!\n");
-
        ret = fill_cache(cache_size, malloc_and_init_memory, memflush, op,
                         resctrl_val);
        if (ret) {
index 1a1bdb6180cf2ac32c2f30bf5ff7245f4dc5922f..cde3781a9ab0504aaddd916248247ac556a9b739 100644 (file)
@@ -28,6 +28,7 @@ static int mba_setup(int num, ...)
        struct resctrl_val_param *p;
        char allocation_str[64];
        va_list param;
+       int ret;
 
        va_start(param, num);
        p = va_arg(param, struct resctrl_val_param *);
@@ -41,20 +42,24 @@ static int mba_setup(int num, ...)
                return 0;
 
        if (allocation < ALLOCATION_MIN || allocation > ALLOCATION_MAX)
-               return -1;
+               return END_OF_TESTS;
 
        sprintf(allocation_str, "%d", allocation);
 
-       write_schemata(p->ctrlgrp, allocation_str, p->cpu_no, p->resctrl_val);
+       ret = write_schemata(p->ctrlgrp, allocation_str, p->cpu_no,
+                            p->resctrl_val);
+       if (ret < 0)
+               return ret;
+
        allocation -= ALLOCATION_STEP;
 
        return 0;
 }
 
-static void show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
+static bool show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
 {
        int allocation, runs;
-       bool failed = false;
+       bool ret = false;
 
        ksft_print_msg("Results are displayed in (MB)\n");
        /* Memory bandwidth from 100% down to 10% */
@@ -90,13 +95,15 @@ static void show_mba_info(unsigned long *bw_imc, unsigned long *bw_resc)
                ksft_print_msg("avg_bw_imc: %lu\n", avg_bw_imc);
                ksft_print_msg("avg_bw_resc: %lu\n", avg_bw_resc);
                if (avg_diff_per > MAX_DIFF_PERCENT)
-                       failed = true;
+                       ret = true;
        }
 
        ksft_print_msg("%s Check schemata change using MBA\n",
-                      failed ? "Fail:" : "Pass:");
-       if (failed)
+                      ret ? "Fail:" : "Pass:");
+       if (ret)
                ksft_print_msg("At least one test failed\n");
+
+       return ret;
 }
 
 static int check_results(void)
@@ -132,9 +139,7 @@ static int check_results(void)
 
        fclose(fp);
 
-       show_mba_info(bw_imc, bw_resc);
-
-       return 0;
+       return show_mba_info(bw_imc, bw_resc);
 }
 
 void mba_test_cleanup(void)
@@ -149,7 +154,7 @@ int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd)
                .ctrlgrp        = "c1",
                .mongrp         = "m1",
                .cpu_no         = cpu_no,
-               .mum_resctrlfs  = 1,
+               .mum_resctrlfs  = true,
                .filename       = RESULT_FILE_NAME,
                .bw_report      = bw_report,
                .setup          = mba_setup
@@ -160,13 +165,12 @@ int mba_schemata_change(int cpu_no, char *bw_report, char **benchmark_cmd)
 
        ret = resctrl_val(benchmark_cmd, &param);
        if (ret)
-               return ret;
+               goto out;
 
        ret = check_results();
-       if (ret)
-               return ret;
 
+out:
        mba_test_cleanup();
 
-       return 0;
+       return ret;
 }
index 8392e5c55ed02599dd15446f27acce245faca90a..538d35a6485acd0c885896104e03b0f34a82ae33 100644 (file)
@@ -89,23 +89,24 @@ static int check_results(int span)
 static int mbm_setup(int num, ...)
 {
        struct resctrl_val_param *p;
-       static int num_of_runs;
        va_list param;
        int ret = 0;
 
-       /* Run NUM_OF_RUNS times */
-       if (num_of_runs++ >= NUM_OF_RUNS)
-               return -1;
-
        va_start(param, num);
        p = va_arg(param, struct resctrl_val_param *);
        va_end(param);
 
+       /* Run NUM_OF_RUNS times */
+       if (p->num_of_runs >= NUM_OF_RUNS)
+               return END_OF_TESTS;
+
        /* Set up shemata with 100% allocation on the first run. */
-       if (num_of_runs == 0)
+       if (p->num_of_runs == 0)
                ret = write_schemata(p->ctrlgrp, "100", p->cpu_no,
                                     p->resctrl_val);
 
+       p->num_of_runs++;
+
        return ret;
 }
 
@@ -122,7 +123,7 @@ int mbm_bw_change(int span, int cpu_no, char *bw_report, char **benchmark_cmd)
                .mongrp         = "m1",
                .span           = span,
                .cpu_no         = cpu_no,
-               .mum_resctrlfs  = 1,
+               .mum_resctrlfs  = true,
                .filename       = RESULT_FILE_NAME,
                .bw_report      =  bw_report,
                .setup          = mbm_setup
@@ -133,13 +134,12 @@ int mbm_bw_change(int span, int cpu_no, char *bw_report, char **benchmark_cmd)
 
        ret = resctrl_val(benchmark_cmd, &param);
        if (ret)
-               return ret;
+               goto out;
 
        ret = check_results(span);
-       if (ret)
-               return ret;
 
+out:
        mbm_test_cleanup();
 
-       return 0;
+       return ret;
 }
index f0ded31fb3c7cbf05540480cfe64ef7000d52e1d..87e39456dee082166ac96398c792b9729114684e 100644 (file)
@@ -28,7 +28,7 @@
 #define MB                     (1024 * 1024)
 #define RESCTRL_PATH           "/sys/fs/resctrl"
 #define PHYS_ID_PATH           "/sys/devices/system/cpu/cpu"
-#define CBM_MASK_PATH          "/sys/fs/resctrl/info"
+#define INFO_PATH              "/sys/fs/resctrl/info"
 #define L3_PATH                        "/sys/fs/resctrl/info/L3"
 #define MB_PATH                        "/sys/fs/resctrl/info/MB"
 #define L3_MON_PATH            "/sys/fs/resctrl/info/L3_MON"
@@ -37,6 +37,8 @@
 #define ARCH_INTEL     1
 #define ARCH_AMD       2
 
+#define END_OF_TESTS   1
+
 #define PARENT_EXIT(err_msg)                   \
        do {                                    \
                perror(err_msg);                \
@@ -62,7 +64,7 @@ struct resctrl_val_param {
        char            mongrp[64];
        int             cpu_no;
        unsigned long   span;
-       int             mum_resctrlfs;
+       bool            mum_resctrlfs;
        char            filename[64];
        char            *bw_report;
        unsigned long   mask;
@@ -107,6 +109,8 @@ void mba_test_cleanup(void);
 int get_cbm_mask(char *cache_type, char *cbm_mask);
 int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size);
 void ctrlc_handler(int signum, siginfo_t *info, void *ptr);
+int signal_handler_register(void);
+void signal_handler_unregister(void);
 int cat_val(struct resctrl_val_param *param);
 void cat_test_cleanup(void);
 int cat_perf_miss_val(int cpu_no, int no_of_bits, char *cache_type);
index df0d8d8526fc6c91b7b622776c78d41e9d0ab7c0..9b9751206e1c134d5ea8610b5ec5f95aae2ef8db 100644 (file)
@@ -77,7 +77,7 @@ static void run_mbm_test(bool has_ben, char **benchmark_cmd, int span,
 
        ksft_print_msg("Starting MBM BW change ...\n");
 
-       if (!validate_resctrl_feature_request(MBM_STR)) {
+       if (!validate_resctrl_feature_request(MBM_STR) || (get_vendor() != ARCH_INTEL)) {
                ksft_test_result_skip("Hardware does not support MBM or MBM is disabled\n");
                return;
        }
@@ -88,7 +88,6 @@ static void run_mbm_test(bool has_ben, char **benchmark_cmd, int span,
        ksft_test_result(!res, "MBM: bw change\n");
        if ((get_vendor() == ARCH_INTEL) && res)
                ksft_print_msg("Intel MBM may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
-       mbm_test_cleanup();
 }
 
 static void run_mba_test(bool has_ben, char **benchmark_cmd, int span,
@@ -98,7 +97,7 @@ static void run_mba_test(bool has_ben, char **benchmark_cmd, int span,
 
        ksft_print_msg("Starting MBA Schemata change ...\n");
 
-       if (!validate_resctrl_feature_request(MBA_STR)) {
+       if (!validate_resctrl_feature_request(MBA_STR) || (get_vendor() != ARCH_INTEL)) {
                ksft_test_result_skip("Hardware does not support MBA or MBA is disabled\n");
                return;
        }
@@ -107,7 +106,6 @@ static void run_mba_test(bool has_ben, char **benchmark_cmd, int span,
                sprintf(benchmark_cmd[1], "%d", span);
        res = mba_schemata_change(cpu_no, bw_report, benchmark_cmd);
        ksft_test_result(!res, "MBA: schemata change\n");
-       mba_test_cleanup();
 }
 
 static void run_cmt_test(bool has_ben, char **benchmark_cmd, int cpu_no)
@@ -126,7 +124,6 @@ static void run_cmt_test(bool has_ben, char **benchmark_cmd, int cpu_no)
        ksft_test_result(!res, "CMT: test\n");
        if ((get_vendor() == ARCH_INTEL) && res)
                ksft_print_msg("Intel CMT may be inaccurate when Sub-NUMA Clustering is enabled. Check BIOS configuration.\n");
-       cmt_test_cleanup();
 }
 
 static void run_cat_test(int cpu_no, int no_of_bits)
@@ -142,7 +139,6 @@ static void run_cat_test(int cpu_no, int no_of_bits)
 
        res = cat_perf_miss_val(cpu_no, no_of_bits, "L3");
        ksft_test_result(!res, "CAT: test\n");
-       cat_test_cleanup();
 }
 
 int main(int argc, char **argv)
@@ -258,10 +254,10 @@ int main(int argc, char **argv)
 
        ksft_set_plan(tests ? : 4);
 
-       if ((get_vendor() == ARCH_INTEL) && mbm_test)
+       if (mbm_test)
                run_mbm_test(has_ben, benchmark_cmd, span, cpu_no, bw_report);
 
-       if ((get_vendor() == ARCH_INTEL) && mba_test)
+       if (mba_test)
                run_mba_test(has_ben, benchmark_cmd, span, cpu_no, bw_report);
 
        if (cmt_test)
@@ -272,5 +268,5 @@ int main(int argc, char **argv)
 
        umount_resctrlfs();
 
-       return ksft_exit_pass();
+       ksft_finished();
 }
index b32b96356ec70a79136b44b9d3b045894ba9c0b1..ab1eab1e7ff63e838416c67aec1e1469a193639d 100644 (file)
@@ -476,6 +476,45 @@ void ctrlc_handler(int signum, siginfo_t *info, void *ptr)
        exit(EXIT_SUCCESS);
 }
 
+/*
+ * Register CTRL-C handler for parent, as it has to kill
+ * child process before exiting.
+ */
+int signal_handler_register(void)
+{
+       struct sigaction sigact;
+       int ret = 0;
+
+       sigact.sa_sigaction = ctrlc_handler;
+       sigemptyset(&sigact.sa_mask);
+       sigact.sa_flags = SA_SIGINFO;
+       if (sigaction(SIGINT, &sigact, NULL) ||
+           sigaction(SIGTERM, &sigact, NULL) ||
+           sigaction(SIGHUP, &sigact, NULL)) {
+               perror("# sigaction");
+               ret = -1;
+       }
+       return ret;
+}
+
+/*
+ * Reset signal handler to SIG_DFL.
+ * Non-Value return because the caller should keep
+ * the error code of other path even if sigaction fails.
+ */
+void signal_handler_unregister(void)
+{
+       struct sigaction sigact;
+
+       sigact.sa_handler = SIG_DFL;
+       sigemptyset(&sigact.sa_mask);
+       if (sigaction(SIGINT, &sigact, NULL) ||
+           sigaction(SIGTERM, &sigact, NULL) ||
+           sigaction(SIGHUP, &sigact, NULL)) {
+               perror("# sigaction");
+       }
+}
+
 /*
  * print_results_bw:   the memory bandwidth results are stored in a file
  * @filename:          file that stores the results
@@ -629,6 +668,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
         * Fork to start benchmark, save child's pid so that it can be killed
         * when needed
         */
+       fflush(stdout);
        bm_pid = fork();
        if (bm_pid == -1) {
                perror("# Unable to fork");
@@ -670,39 +710,28 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
 
        ksft_print_msg("Benchmark PID: %d\n", bm_pid);
 
-       /*
-        * Register CTRL-C handler for parent, as it has to kill benchmark
-        * before exiting
-        */
-       sigact.sa_sigaction = ctrlc_handler;
-       sigemptyset(&sigact.sa_mask);
-       sigact.sa_flags = SA_SIGINFO;
-       if (sigaction(SIGINT, &sigact, NULL) ||
-           sigaction(SIGTERM, &sigact, NULL) ||
-           sigaction(SIGHUP, &sigact, NULL)) {
-               perror("# sigaction");
-               ret = errno;
+       ret = signal_handler_register();
+       if (ret)
                goto out;
-       }
 
        value.sival_ptr = benchmark_cmd;
 
        /* Taskset benchmark to specified cpu */
        ret = taskset_benchmark(bm_pid, param->cpu_no);
        if (ret)
-               goto out;
+               goto unregister;
 
        /* Write benchmark to specified control&monitoring grp in resctrl FS */
        ret = write_bm_pid_to_resctrl(bm_pid, param->ctrlgrp, param->mongrp,
                                      resctrl_val);
        if (ret)
-               goto out;
+               goto unregister;
 
        if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) ||
            !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) {
                ret = initialize_mem_bw_imc();
                if (ret)
-                       goto out;
+                       goto unregister;
 
                initialize_mem_bw_resctrl(param->ctrlgrp, param->mongrp,
                                          param->cpu_no, resctrl_val);
@@ -717,7 +746,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
                    sizeof(pipe_message)) {
                        perror("# failed reading message from child process");
                        close(pipefd[0]);
-                       goto out;
+                       goto unregister;
                }
        }
        close(pipefd[0]);
@@ -726,7 +755,7 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
        if (sigqueue(bm_pid, SIGUSR1, value) == -1) {
                perror("# sigqueue SIGUSR1 to child");
                ret = errno;
-               goto out;
+               goto unregister;
        }
 
        /* Give benchmark enough time to fully run */
@@ -734,32 +763,29 @@ int resctrl_val(char **benchmark_cmd, struct resctrl_val_param *param)
 
        /* Test runs until the callback setup() tells the test to stop. */
        while (1) {
+               ret = param->setup(1, param);
+               if (ret == END_OF_TESTS) {
+                       ret = 0;
+                       break;
+               }
+               if (ret < 0)
+                       break;
+
                if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) ||
                    !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) {
-                       ret = param->setup(1, param);
-                       if (ret) {
-                               ret = 0;
-                               break;
-                       }
-
                        ret = measure_vals(param, &bw_resc_start);
                        if (ret)
                                break;
                } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) {
-                       ret = param->setup(1, param);
-                       if (ret) {
-                               ret = 0;
-                               break;
-                       }
                        sleep(1);
                        ret = measure_cache_vals(param, bm_pid);
                        if (ret)
                                break;
-               } else {
-                       break;
                }
        }
 
+unregister:
+       signal_handler_unregister();
 out:
        kill(bm_pid, SIGKILL);
        umount_resctrlfs();
index 6f543e470ad4aacc999cf946bca301754b9c65c9..fb00245dee92e8b035d881cbe556cd09023de939 100644 (file)
@@ -210,7 +210,7 @@ int get_cbm_mask(char *cache_type, char *cbm_mask)
        if (!cbm_mask)
                return -1;
 
-       sprintf(cbm_mask_path, "%s/%s/cbm_mask", CBM_MASK_PATH, cache_type);
+       sprintf(cbm_mask_path, "%s/%s/cbm_mask", INFO_PATH, cache_type);
 
        fp = fopen(cbm_mask_path, "r");
        if (!fp) {
@@ -498,6 +498,7 @@ int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
        FILE *fp;
 
        if (strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) &&
+           strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) &&
            strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) &&
            strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
                return -ENOENT;
@@ -523,7 +524,8 @@ int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
        if (!strncmp(resctrl_val, CAT_STR, sizeof(CAT_STR)) ||
            !strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR)))
                sprintf(schema, "%s%d%c%s", "L3:", resource_id, '=', schemata);
-       if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)))
+       if (!strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR)) ||
+           !strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)))
                sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata);
 
        fp = fopen(controlgroup, "w");
@@ -676,6 +678,7 @@ int filter_dmesg(void)
                perror("pipe");
                return ret;
        }
+       fflush(stdout);
        pid = fork();
        if (pid == 0) {
                close(pipefds[0]);
index 25e0d95d37133177fe52e2cce64f01ba73f2712c..3e1619b6bf2da5156a8e53dfba7aeab60b4d03a8 100644 (file)
@@ -334,6 +334,12 @@ int main(int argc, char *argv[])
        validate(get_cs_cookie(pid) != 0);
        validate(get_cs_cookie(pid) == get_cs_cookie(procs[pidx].thr_tids[0]));
 
+       validate(_prctl(PR_SCHED_CORE, PR_SCHED_CORE_MAX, 0, PIDTYPE_PGID, 0) < 0
+               && errno == EINVAL);
+
+       validate(_prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_TO, 0, PIDTYPE_PGID, 1) < 0
+               && errno == EINVAL);
+
        if (errors) {
                printf("TESTS FAILED. errors: %d\n", errors);
                res = 10;
diff --git a/tools/testing/selftests/sigaltstack/current_stack_pointer.h b/tools/testing/selftests/sigaltstack/current_stack_pointer.h
new file mode 100644 (file)
index 0000000..ea9bdf3
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#if __alpha__
+register unsigned long sp asm("$30");
+#elif __arm__ || __aarch64__ || __csky__ || __m68k__ || __mips__ || __riscv
+register unsigned long sp asm("sp");
+#elif __i386__
+register unsigned long sp asm("esp");
+#elif __loongarch64
+register unsigned long sp asm("$sp");
+#elif __ppc__
+register unsigned long sp asm("r1");
+#elif __s390x__
+register unsigned long sp asm("%15");
+#elif __sh__
+register unsigned long sp asm("r15");
+#elif __x86_64__
+register unsigned long sp asm("rsp");
+#elif __XTENSA__
+register unsigned long sp asm("a1");
+#else
+#error "implement current_stack_pointer equivalent"
+#endif
index c53b070755b65eb9f4454c795ad31521020ba284..98d37cb744fb28f628e628bcfb27bb24a714ac87 100644 (file)
@@ -20,6 +20,7 @@
 #include <sys/auxv.h>
 
 #include "../kselftest.h"
+#include "current_stack_pointer.h"
 
 #ifndef SS_AUTODISARM
 #define SS_AUTODISARM  (1U << 31)
@@ -46,12 +47,6 @@ void my_usr1(int sig, siginfo_t *si, void *u)
        stack_t stk;
        struct stk_data *p;
 
-#if __s390x__
-       register unsigned long sp asm("%15");
-#else
-       register unsigned long sp asm("sp");
-#endif
-
        if (sp < (unsigned long)sstack ||
                        sp >= (unsigned long)sstack + stack_size) {
                ksft_exit_fail_msg("SP is not on sigaltstack\n");
index 0ba500056e635be0f5d4ca88827a163c053cc31c..8a17c0e8d82b3727d866b9d9f587d038b9a27c36 100644 (file)
@@ -188,6 +188,80 @@ static int check_timer_create(int which)
        return 0;
 }
 
+int remain;
+__thread int got_signal;
+
+static void *distribution_thread(void *arg)
+{
+       while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
+       return NULL;
+}
+
+static void distribution_handler(int nr)
+{
+       if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED))
+               __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED);
+}
+
+/*
+ * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID
+ * timer signals. This primarily tests that the kernel does not favour any one.
+ */
+static int check_timer_distribution(void)
+{
+       int err, i;
+       timer_t id;
+       const int nthreads = 10;
+       pthread_t threads[nthreads];
+       struct itimerspec val = {
+               .it_value.tv_sec = 0,
+               .it_value.tv_nsec = 1000 * 1000,
+               .it_interval.tv_sec = 0,
+               .it_interval.tv_nsec = 1000 * 1000,
+       };
+
+       printf("Check timer_create() per process signal distribution... ");
+       fflush(stdout);
+
+       remain = nthreads + 1;  /* worker threads + this thread */
+       signal(SIGALRM, distribution_handler);
+       err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
+       if (err < 0) {
+               perror("Can't create timer\n");
+               return -1;
+       }
+       err = timer_settime(id, 0, &val, NULL);
+       if (err < 0) {
+               perror("Can't set timer\n");
+               return -1;
+       }
+
+       for (i = 0; i < nthreads; i++) {
+               if (pthread_create(&threads[i], NULL, distribution_thread, NULL)) {
+                       perror("Can't create thread\n");
+                       return -1;
+               }
+       }
+
+       /* Wait for all threads to receive the signal. */
+       while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
+
+       for (i = 0; i < nthreads; i++) {
+               if (pthread_join(threads[i], NULL)) {
+                       perror("Can't join thread\n");
+                       return -1;
+               }
+       }
+
+       if (timer_delete(id)) {
+               perror("Can't delete timer\n");
+               return -1;
+       }
+
+       printf("[OK]\n");
+       return 0;
+}
+
 int main(int argc, char **argv)
 {
        printf("Testing posix timers. False negative may happen on CPU execution \n");
@@ -217,5 +291,8 @@ int main(int argc, char **argv)
        if (check_timer_create(CLOCK_PROCESS_CPUTIME_ID) < 0)
                return ksft_exit_fail();
 
+       if (check_timer_distribution() < 0)
+               return ksft_exit_fail();
+
        return ksft_exit_pass();
 }
index 625e42901237c0c47db7bb129ff9921e3633bfde..d884fd69dd510bce52c684f496eb68b9d5ba866b 100644 (file)
 #include <sys/auxv.h>
 #include <sys/mman.h>
 #include <sys/shm.h>
+#include <sys/ptrace.h>
 #include <sys/syscall.h>
 #include <sys/wait.h>
+#include <sys/uio.h>
 
 #include "../kselftest.h" /* For __cpuid_count() */
 
@@ -583,6 +585,13 @@ static void test_dynamic_state(void)
        _exit(0);
 }
 
+static inline int __compare_tiledata_state(struct xsave_buffer *xbuf1, struct xsave_buffer *xbuf2)
+{
+       return memcmp(&xbuf1->bytes[xtiledata.xbuf_offset],
+                     &xbuf2->bytes[xtiledata.xbuf_offset],
+                     xtiledata.size);
+}
+
 /*
  * Save current register state and compare it to @xbuf1.'
  *
@@ -599,9 +608,7 @@ static inline bool __validate_tiledata_regs(struct xsave_buffer *xbuf1)
                fatal_error("failed to allocate XSAVE buffer\n");
 
        xsave(xbuf2, XFEATURE_MASK_XTILEDATA);
-       ret = memcmp(&xbuf1->bytes[xtiledata.xbuf_offset],
-                    &xbuf2->bytes[xtiledata.xbuf_offset],
-                    xtiledata.size);
+       ret = __compare_tiledata_state(xbuf1, xbuf2);
 
        free(xbuf2);
 
@@ -826,6 +833,99 @@ static void test_context_switch(void)
        free(finfo);
 }
 
+/* Ptrace test */
+
+/*
+ * Make sure the ptracee has the expanded kernel buffer on the first
+ * use. Then, initialize the state before performing the state
+ * injection from the ptracer.
+ */
+static inline void ptracee_firstuse_tiledata(void)
+{
+       load_rand_tiledata(stashed_xsave);
+       init_xtiledata();
+}
+
+/*
+ * Ptracer injects the randomized tile data state. It also reads
+ * before and after that, which will execute the kernel's state copy
+ * functions. So, the tester is advised to double-check any emitted
+ * kernel messages.
+ */
+static void ptracer_inject_tiledata(pid_t target)
+{
+       struct xsave_buffer *xbuf;
+       struct iovec iov;
+
+       xbuf = alloc_xbuf();
+       if (!xbuf)
+               fatal_error("unable to allocate XSAVE buffer");
+
+       printf("\tRead the init'ed tiledata via ptrace().\n");
+
+       iov.iov_base = xbuf;
+       iov.iov_len = xbuf_size;
+
+       memset(stashed_xsave, 0, xbuf_size);
+
+       if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
+               fatal_error("PTRACE_GETREGSET");
+
+       if (!__compare_tiledata_state(stashed_xsave, xbuf))
+               printf("[OK]\tThe init'ed tiledata was read from ptracee.\n");
+       else
+               printf("[FAIL]\tThe init'ed tiledata was not read from ptracee.\n");
+
+       printf("\tInject tiledata via ptrace().\n");
+
+       load_rand_tiledata(xbuf);
+
+       memcpy(&stashed_xsave->bytes[xtiledata.xbuf_offset],
+              &xbuf->bytes[xtiledata.xbuf_offset],
+              xtiledata.size);
+
+       if (ptrace(PTRACE_SETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
+               fatal_error("PTRACE_SETREGSET");
+
+       if (ptrace(PTRACE_GETREGSET, target, (uint32_t)NT_X86_XSTATE, &iov))
+               fatal_error("PTRACE_GETREGSET");
+
+       if (!__compare_tiledata_state(stashed_xsave, xbuf))
+               printf("[OK]\tTiledata was correctly written to ptracee.\n");
+       else
+               printf("[FAIL]\tTiledata was not correctly written to ptracee.\n");
+}
+
+static void test_ptrace(void)
+{
+       pid_t child;
+       int status;
+
+       child = fork();
+       if (child < 0) {
+               err(1, "fork");
+       } else if (!child) {
+               if (ptrace(PTRACE_TRACEME, 0, NULL, NULL))
+                       err(1, "PTRACE_TRACEME");
+
+               ptracee_firstuse_tiledata();
+
+               raise(SIGTRAP);
+               _exit(0);
+       }
+
+       do {
+               wait(&status);
+       } while (WSTOPSIG(status) != SIGTRAP);
+
+       ptracer_inject_tiledata(child);
+
+       ptrace(PTRACE_DETACH, child, NULL, NULL);
+       wait(&status);
+       if (!WIFEXITED(status) || WEXITSTATUS(status))
+               err(1, "ptrace test");
+}
+
 int main(void)
 {
        /* Check hardware availability at first */
@@ -846,6 +946,8 @@ int main(void)
        ctxtswtest_config.num_threads = 5;
        test_context_switch();
 
+       test_ptrace();
+
        clearhandler(SIGILL);
        free_stashed_xsave();
 
index 67e9f9df3a8c4eae6421fe23b8bcef89319140ea..12b97c92fbb20dcf68adfc5d03eca7dc8dd1c0c4 100644 (file)
@@ -860,6 +860,199 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
        close(fd);
 }
 
+#define INV_BUF_TEST_DATA_LEN 512
+
+static void test_inv_buf_client(const struct test_opts *opts, bool stream)
+{
+       unsigned char data[INV_BUF_TEST_DATA_LEN] = {0};
+       ssize_t ret;
+       int fd;
+
+       if (stream)
+               fd = vsock_stream_connect(opts->peer_cid, 1234);
+       else
+               fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
+
+       if (fd < 0) {
+               perror("connect");
+               exit(EXIT_FAILURE);
+       }
+
+       control_expectln("SENDDONE");
+
+       /* Use invalid buffer here. */
+       ret = recv(fd, NULL, sizeof(data), 0);
+       if (ret != -1) {
+               fprintf(stderr, "expected recv(2) failure, got %zi\n", ret);
+               exit(EXIT_FAILURE);
+       }
+
+       if (errno != ENOMEM) {
+               fprintf(stderr, "unexpected recv(2) errno %d\n", errno);
+               exit(EXIT_FAILURE);
+       }
+
+       ret = recv(fd, data, sizeof(data), MSG_DONTWAIT);
+
+       if (stream) {
+               /* For SOCK_STREAM we must continue reading. */
+               if (ret != sizeof(data)) {
+                       fprintf(stderr, "expected recv(2) success, got %zi\n", ret);
+                       exit(EXIT_FAILURE);
+               }
+               /* Don't check errno in case of success. */
+       } else {
+               /* For SOCK_SEQPACKET socket's queue must be empty. */
+               if (ret != -1) {
+                       fprintf(stderr, "expected recv(2) failure, got %zi\n", ret);
+                       exit(EXIT_FAILURE);
+               }
+
+               if (errno != EAGAIN) {
+                       fprintf(stderr, "unexpected recv(2) errno %d\n", errno);
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       control_writeln("DONE");
+
+       close(fd);
+}
+
+static void test_inv_buf_server(const struct test_opts *opts, bool stream)
+{
+       unsigned char data[INV_BUF_TEST_DATA_LEN] = {0};
+       ssize_t res;
+       int fd;
+
+       if (stream)
+               fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
+       else
+               fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
+
+       if (fd < 0) {
+               perror("accept");
+               exit(EXIT_FAILURE);
+       }
+
+       res = send(fd, data, sizeof(data), 0);
+       if (res != sizeof(data)) {
+               fprintf(stderr, "unexpected send(2) result %zi\n", res);
+               exit(EXIT_FAILURE);
+       }
+
+       control_writeln("SENDDONE");
+
+       control_expectln("DONE");
+
+       close(fd);
+}
+
+static void test_stream_inv_buf_client(const struct test_opts *opts)
+{
+       test_inv_buf_client(opts, true);
+}
+
+static void test_stream_inv_buf_server(const struct test_opts *opts)
+{
+       test_inv_buf_server(opts, true);
+}
+
+static void test_seqpacket_inv_buf_client(const struct test_opts *opts)
+{
+       test_inv_buf_client(opts, false);
+}
+
+static void test_seqpacket_inv_buf_server(const struct test_opts *opts)
+{
+       test_inv_buf_server(opts, false);
+}
+
+#define HELLO_STR "HELLO"
+#define WORLD_STR "WORLD"
+
+static void test_stream_virtio_skb_merge_client(const struct test_opts *opts)
+{
+       ssize_t res;
+       int fd;
+
+       fd = vsock_stream_connect(opts->peer_cid, 1234);
+       if (fd < 0) {
+               perror("connect");
+               exit(EXIT_FAILURE);
+       }
+
+       /* Send first skbuff. */
+       res = send(fd, HELLO_STR, strlen(HELLO_STR), 0);
+       if (res != strlen(HELLO_STR)) {
+               fprintf(stderr, "unexpected send(2) result %zi\n", res);
+               exit(EXIT_FAILURE);
+       }
+
+       control_writeln("SEND0");
+       /* Peer reads part of first skbuff. */
+       control_expectln("REPLY0");
+
+       /* Send second skbuff, it will be appended to the first. */
+       res = send(fd, WORLD_STR, strlen(WORLD_STR), 0);
+       if (res != strlen(WORLD_STR)) {
+               fprintf(stderr, "unexpected send(2) result %zi\n", res);
+               exit(EXIT_FAILURE);
+       }
+
+       control_writeln("SEND1");
+       /* Peer reads merged skbuff packet. */
+       control_expectln("REPLY1");
+
+       close(fd);
+}
+
+static void test_stream_virtio_skb_merge_server(const struct test_opts *opts)
+{
+       unsigned char buf[64];
+       ssize_t res;
+       int fd;
+
+       fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
+       if (fd < 0) {
+               perror("accept");
+               exit(EXIT_FAILURE);
+       }
+
+       control_expectln("SEND0");
+
+       /* Read skbuff partially. */
+       res = recv(fd, buf, 2, 0);
+       if (res != 2) {
+               fprintf(stderr, "expected recv(2) returns 2 bytes, got %zi\n", res);
+               exit(EXIT_FAILURE);
+       }
+
+       control_writeln("REPLY0");
+       control_expectln("SEND1");
+
+       res = recv(fd, buf + 2, sizeof(buf) - 2, 0);
+       if (res != 8) {
+               fprintf(stderr, "expected recv(2) returns 8 bytes, got %zi\n", res);
+               exit(EXIT_FAILURE);
+       }
+
+       res = recv(fd, buf, sizeof(buf) - 8 - 2, MSG_DONTWAIT);
+       if (res != -1) {
+               fprintf(stderr, "expected recv(2) failure, got %zi\n", res);
+               exit(EXIT_FAILURE);
+       }
+
+       if (memcmp(buf, HELLO_STR WORLD_STR, strlen(HELLO_STR WORLD_STR))) {
+               fprintf(stderr, "pattern mismatch\n");
+               exit(EXIT_FAILURE);
+       }
+
+       control_writeln("REPLY1");
+
+       close(fd);
+}
+
 static struct test_case test_cases[] = {
        {
                .name = "SOCK_STREAM connection reset",
@@ -920,6 +1113,21 @@ static struct test_case test_cases[] = {
                .run_client = test_seqpacket_bigmsg_client,
                .run_server = test_seqpacket_bigmsg_server,
        },
+       {
+               .name = "SOCK_STREAM test invalid buffer",
+               .run_client = test_stream_inv_buf_client,
+               .run_server = test_stream_inv_buf_server,
+       },
+       {
+               .name = "SOCK_SEQPACKET test invalid buffer",
+               .run_client = test_seqpacket_inv_buf_client,
+               .run_server = test_seqpacket_inv_buf_server,
+       },
+       {
+               .name = "SOCK_STREAM virtio skb merge",
+               .run_client = test_stream_virtio_skb_merge_client,
+               .run_server = test_stream_virtio_skb_merge_server,
+       },
        {},
 };
 
index 075588c4da0815227ccb95609d477477d99203a4..9934d48d9a55772f4c49ad513f8f8c651370d736 100644 (file)
@@ -2,3 +2,4 @@
 *.d
 virtio_test
 vringh_test
+virtio-trace/trace-agent
index b64845b823abde33b051563585d4c718a051a501..4fb9368bf7519b36e8c49ac78ad3ffa9ef15d496 100644 (file)
@@ -61,7 +61,7 @@ and
       id=channel0,name=agent-ctl-path\
  ##data path##
      -chardev pipe,id=charchannel1,path=/tmp/virtio-trace/trace-path-cpu0\
-     -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel0,\
+     -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,\
       id=channel1,name=trace-path-cpu0\
       ...
 
index ee01e40e8bc65e06ba3b74e3f50d5aaa485bcea1..61230532fef10f7261db75e5757a8b2c4366d2d9 100644 (file)
@@ -353,6 +353,12 @@ static int cpio_mkfile(const char *name, const char *location,
                buf.st_mtime = 0xffffffff;
        }
 
+       if (buf.st_mtime < 0) {
+               fprintf(stderr, "%s: Timestamp negative, clipping.\n",
+                       location);
+               buf.st_mtime = 0;
+       }
+
        if (buf.st_size > 0xffffffff) {
                fprintf(stderr, "%s: Size exceeds maximum cpio file size\n",
                        location);
@@ -602,10 +608,10 @@ int main (int argc, char *argv[])
        /*
         * Timestamps after 2106-02-07 06:28:15 UTC have an ascii hex time_t
         * representation that exceeds 8 chars and breaks the cpio header
-        * specification.
+        * specification. Negative timestamps similarly exceed 8 chars.
         */
-       if (default_mtime > 0xffffffff) {
-               fprintf(stderr, "ERROR: Timestamp too large for cpio format\n");
+       if (default_mtime > 0xffffffff || default_mtime < 0) {
+               fprintf(stderr, "ERROR: Timestamp out of range for cpio format\n");
                exit(1);
        }
 
index 2a3ed401ce4653377d55de9b02ccfa9e6086f3f3..b0af834ffa95092540d0aee1e39602c3907d84bb 100644 (file)
@@ -55,6 +55,15 @@ irqfd_inject(struct work_struct *work)
                            irqfd->gsi, 1, false);
 }
 
+static void irqfd_resampler_notify(struct kvm_kernel_irqfd_resampler *resampler)
+{
+       struct kvm_kernel_irqfd *irqfd;
+
+       list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link,
+                                srcu_read_lock_held(&resampler->kvm->irq_srcu))
+               eventfd_signal(irqfd->resamplefd, 1);
+}
+
 /*
  * Since resampler irqfds share an IRQ source ID, we de-assert once
  * then notify all of the resampler irqfds using this GSI.  We can't
@@ -65,7 +74,6 @@ irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian)
 {
        struct kvm_kernel_irqfd_resampler *resampler;
        struct kvm *kvm;
-       struct kvm_kernel_irqfd *irqfd;
        int idx;
 
        resampler = container_of(kian,
@@ -76,11 +84,7 @@ irqfd_resampler_ack(struct kvm_irq_ack_notifier *kian)
                    resampler->notifier.gsi, 0, false);
 
        idx = srcu_read_lock(&kvm->irq_srcu);
-
-       list_for_each_entry_srcu(irqfd, &resampler->list, resampler_link,
-           srcu_read_lock_held(&kvm->irq_srcu))
-               eventfd_signal(irqfd->resamplefd, 1);
-
+       irqfd_resampler_notify(resampler);
        srcu_read_unlock(&kvm->irq_srcu, idx);
 }
 
@@ -96,8 +100,12 @@ irqfd_resampler_shutdown(struct kvm_kernel_irqfd *irqfd)
        synchronize_srcu(&kvm->irq_srcu);
 
        if (list_empty(&resampler->list)) {
-               list_del(&resampler->link);
+               list_del_rcu(&resampler->link);
                kvm_unregister_irq_ack_notifier(kvm, &resampler->notifier);
+               /*
+                * synchronize_srcu(&kvm->irq_srcu) already called
+                * in kvm_unregister_irq_ack_notifier().
+                */
                kvm_set_irq(kvm, KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID,
                            resampler->notifier.gsi, 0, false);
                kfree(resampler);
@@ -369,7 +377,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
                        resampler->notifier.irq_acked = irqfd_resampler_ack;
                        INIT_LIST_HEAD(&resampler->link);
 
-                       list_add(&resampler->link, &kvm->irqfds.resampler_list);
+                       list_add_rcu(&resampler->link, &kvm->irqfds.resampler_list);
                        kvm_register_irq_ack_notifier(kvm,
                                                      &resampler->notifier);
                        irqfd->resampler = resampler;
@@ -644,6 +652,31 @@ void kvm_irq_routing_update(struct kvm *kvm)
        spin_unlock_irq(&kvm->irqfds.lock);
 }
 
+bool kvm_notify_irqfd_resampler(struct kvm *kvm,
+                               unsigned int irqchip,
+                               unsigned int pin)
+{
+       struct kvm_kernel_irqfd_resampler *resampler;
+       int gsi, idx;
+
+       idx = srcu_read_lock(&kvm->irq_srcu);
+       gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin);
+       if (gsi != -1) {
+               list_for_each_entry_srcu(resampler,
+                                        &kvm->irqfds.resampler_list, link,
+                                        srcu_read_lock_held(&kvm->irq_srcu)) {
+                       if (resampler->notifier.gsi == gsi) {
+                               irqfd_resampler_notify(resampler);
+                               srcu_read_unlock(&kvm->irq_srcu, idx);
+                               return true;
+                       }
+               }
+       }
+       srcu_read_unlock(&kvm->irq_srcu, idx);
+
+       return false;
+}
+
 /*
  * create a host-wide workqueue for issuing deferred shutdown requests
  * aggregated from all vm* instances. We need our own isolated
index d255964ec331ef5c9aebf90243990ef4da0aec2b..b1679d08a216099a379df472a6cc52c268e4e51d 100644 (file)
@@ -4479,7 +4479,6 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
 #endif
 #ifdef CONFIG_HAVE_KVM_IRQFD
        case KVM_CAP_IRQFD:
-       case KVM_CAP_IRQFD_RESAMPLE:
 #endif
        case KVM_CAP_IOEVENTFD_ANY_LENGTH:
        case KVM_CAP_CHECK_EXTENSION_VM: